CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
255 lines
6.1 KiB
Markdown
255 lines
6.1 KiB
Markdown
# IR Converter - Converting Strings to IRList
|
|
|
|
StinkyTofu provides the 'StinkyIRConverter' class to programmatically convert MLIR-style instruction strings to 'IRList' objects.
|
|
|
|
> **Note:** For detailed information about error codes, see [Error Codes](error-codes.md).
|
|
|
|
## Basic Usage
|
|
|
|
'''cpp
|
|
#include "stinkytofu/core/stinkytofu.hpp"
|
|
|
|
using namespace stinkytofu;
|
|
|
|
std::string irText = R"(
|
|
v[0:3] = "st.ds_load_b128"(v40) { issueCycles = 4, latencyCycles = 56 }
|
|
v[4:7] = "st.ds_load_b128"(v40) { issueCycles = 4, latencyCycles = 56 }
|
|
)";
|
|
|
|
// Create converter with default architecture (gfx1250)
|
|
StinkyIRConverter converter;
|
|
|
|
// Convert string to IRList
|
|
IRList* irlist = converter.convertToIRList(irText);
|
|
|
|
if(irlist) {
|
|
// Successfully converted, use the IRList
|
|
std::cout << "Converted " << irlist->size() << " instructions\n";
|
|
} else {
|
|
std::cerr << "Conversion failed\n";
|
|
}
|
|
'''
|
|
|
|
## Custom Architecture
|
|
|
|
You can specify a different target architecture:
|
|
|
|
'''cpp
|
|
// For gfx1250
|
|
std::array<int, 3> arch = {12, 5, 0};
|
|
StinkyIRConverter converter(arch);
|
|
|
|
IRList* irlist = converter.convertToIRList(irText);
|
|
'''
|
|
|
|
## Accessing the PassContext
|
|
|
|
After conversion, you can access the 'PassContext' to run optimization passes:
|
|
|
|
'''cpp
|
|
StinkyIRConverter converter;
|
|
IRList* irlist = converter.convertToIRList(irText);
|
|
|
|
if(irlist) {
|
|
PassContext* ctx = converter.getPassContext();
|
|
if(ctx) {
|
|
// Run passes on the IR
|
|
PassManager pm;
|
|
pm.addPass(std::make_unique<SomeOptimizationPass>());
|
|
pm.run(*ctx);
|
|
}
|
|
}
|
|
'''
|
|
|
|
## Using the Static Method
|
|
|
|
For more control, use the static 'populateFunctionFromString' method:
|
|
|
|
'''cpp
|
|
// Create your own PassContext
|
|
auto ctx = PassContext::create(GfxArchID::gfx1250);
|
|
IRList& irlist = ctx->getIRList();
|
|
|
|
// Populate it with instructions from string
|
|
std::string irText = /* ... */;
|
|
GfxArchID arch = GfxArchID::gfx1250;
|
|
|
|
StinkyErrorCode result = StinkyIRConverter::populateFunctionFromString(
|
|
irText, irlist, *ctx, arch);
|
|
|
|
if(result == StinkyErrorCode::SUCCESS) {
|
|
// Successfully populated
|
|
std::cout << "Populated " << irlist.size() << " instructions\n";
|
|
} else {
|
|
// Handle error
|
|
std::cerr << "Error: " << static_cast<int>(result) << "\n";
|
|
}
|
|
'''
|
|
|
|
## Complete Example
|
|
|
|
Here's a complete example showing conversion and assembly emission:
|
|
|
|
'''cpp
|
|
#include "stinkytofu/core/stinkytofu.hpp"
|
|
#include "stinkytofu/serialization/asm/StinkyAsmEmitter.hpp"
|
|
#include <iostream>
|
|
|
|
using namespace stinkytofu;
|
|
|
|
int main() {
|
|
// IR text with two ds_read instructions
|
|
std::string irText = R"(
|
|
v[0:3] = "st.ds_load_b128"(v40) { issueCycles = 4, latencyCycles = 52 }
|
|
v[4:7] = "st.ds_load_b128"(v40) { issueCycles = 4, latencyCycles = 52 }
|
|
)";
|
|
|
|
// Convert to IRList
|
|
StinkyIRConverter converter;
|
|
IRList* irlist = converter.convertToIRList(irText);
|
|
|
|
if(!irlist) {
|
|
std::cerr << "Failed to convert IR\n";
|
|
return 1;
|
|
}
|
|
|
|
std::cout << "Converted " << irlist->size() << " instructions\n";
|
|
|
|
// Emit as assembly
|
|
StinkyAsmEmitter emitter;
|
|
std::string assembly = emitter.emit(*irlist);
|
|
|
|
std::cout << "\nGenerated Assembly:\n" << assembly << std::endl;
|
|
|
|
return 0;
|
|
}
|
|
'''
|
|
|
|
### Expected Output
|
|
|
|
'''
|
|
Converted 2 instructions
|
|
|
|
Generated Assembly:
|
|
// ==================================================
|
|
// StinkyTofu Assembly Output
|
|
// Instructions: 2
|
|
// ==================================================
|
|
|
|
ds_read_b128 v[0:3], v[40] // issue=4 latency=52
|
|
ds_read_b128 v[4:7], v[40] // issue=4 latency=52
|
|
'''
|
|
|
|
## IR Format
|
|
|
|
The IR string should follow the MLIR-style StinkyTofu format:
|
|
|
|
'''
|
|
destRegs = "st.mnemonic"(srcRegs) { attributes }
|
|
'''
|
|
|
|
### Examples
|
|
|
|
**Simple instruction:**
|
|
'''
|
|
v[0] = "st.v_mov_b32"(v1)
|
|
'''
|
|
|
|
**Multiple destinations:**
|
|
'''
|
|
v[0:3] = "st.ds_load_b128"(v40)
|
|
'''
|
|
|
|
**With attributes:**
|
|
'''
|
|
v[0:3] = "st.ds_load_b128"(v40) { issueCycles = 4, latencyCycles = 52 }
|
|
'''
|
|
|
|
**Multiple source registers:**
|
|
'''
|
|
acc[0:15] = "st.v_mfma_f32_16x16x16_f16"(v6:7, v22:23, acc0:15)
|
|
'''
|
|
|
|
## Error Handling
|
|
|
|
Always check the return value:
|
|
|
|
'''cpp
|
|
StinkyIRConverter converter;
|
|
IRList* irlist = converter.convertToIRList(irText);
|
|
|
|
if(!irlist) {
|
|
std::cerr << "Conversion failed. Possible reasons:\n"
|
|
<< " - Invalid IR syntax\n"
|
|
<< " - Unsupported instruction mnemonic\n"
|
|
<< " - Invalid register format\n";
|
|
return 1;
|
|
}
|
|
'''
|
|
|
|
For the static method, check the error code:
|
|
|
|
'''cpp
|
|
StinkyErrorCode result = StinkyIRConverter::populateFunctionFromString(
|
|
irText, irlist, *ctx, arch);
|
|
|
|
switch(result) {
|
|
case StinkyErrorCode::SUCCESS:
|
|
// Success
|
|
break;
|
|
case StinkyErrorCode::PASSCTX_EMPTY:
|
|
std::cerr << "PassContext is empty or invalid\n";
|
|
break;
|
|
default:
|
|
std::cerr << "Unknown error\n";
|
|
break;
|
|
}
|
|
'''
|
|
|
|
## Integration with Optimization Passes
|
|
|
|
After converting IR, you can run optimization passes:
|
|
|
|
'''cpp
|
|
// Convert IR
|
|
StinkyIRConverter converter;
|
|
IRList* irlist = converter.convertToIRList(irText);
|
|
|
|
if(irlist) {
|
|
PassContext* ctx = converter.getPassContext();
|
|
if(ctx) {
|
|
// Create pass manager and add passes. The public API exposes passes
|
|
// through factory functions (the concrete pass types are not installed).
|
|
PassManager pm;
|
|
pm.addPass(createStinkyDAGSchedulerPass());
|
|
pm.addPass(createStinkyWaitCntInsertionPass());
|
|
|
|
// Run the passes
|
|
pm.run(*ctx);
|
|
|
|
// Emit optimized assembly
|
|
StinkyAsmEmitter emitter;
|
|
std::string optimizedAsm = emitter.emit(*irlist);
|
|
std::cout << optimizedAsm << std::endl;
|
|
}
|
|
}
|
|
'''
|
|
|
|
## Thread Safety
|
|
|
|
'StinkyIRConverter' is not thread-safe. If you need to convert IR in multiple threads, create a separate converter instance for each thread:
|
|
|
|
'''cpp
|
|
// In each thread:
|
|
void processIRInThread(const std::string& irText) {
|
|
StinkyIRConverter converter; // Thread-local instance
|
|
IRList* irlist = converter.convertToIRList(irText);
|
|
// ... process irlist ...
|
|
}
|
|
'''
|
|
|
|
## See Also
|
|
|
|
- [Assembly Emitter Guide](asm-emitter.md) - Converting IR to assembly code
|
|
- [Error Codes Reference](error-codes.md) - Error codes and handling
|