Skip to content

dr2chase/midway

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

26 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Midway: SIMD Source-to-Source Rewriter

midway is a CLI tool that automatically generates vector-size-specific SIMD code from Go written to use a "scalable SIMD" API, provided in midway/simd/mocks.go. This is a prototype for both an API and for a compiler transformation, and a step towards a more general solution for writing SIMD code in Go across architectures and cpu variants with a variety of vector widths. The intent is that the generated code for different vector widths (for example, AVX and AVX-512, or ARM SVE's scalable vector lengths) will all be present in a single binary that chooses the right implementation at runtime. The tool is not yet general purpose; it is specialized for the API provided in midway/simd/mocks.go, which are amd64-specific.

Overview

The tool operates on Go files marked with //go:build midway. It performs two main transformations:

  1. Dispatcher Generation: Rewrites the original file in a new ..._simd_<arch>.go, replacing functions dependent on SIMD types with a switch statement that calls the appropriate architecture-specific implementation based on midway.MaxVectorSize(). The build tag is updated to !midway so it compiles as standard Go (and the originals, tagged "midway", are ignored).
  2. Specialization: Generates specialized implementation files (e.g., ..._simd128_<arch>.go, ..._simd256_<arch>.go) where abstract simd types are replaced with concrete archsimd types (e.g., simd.Int32s becomes archsimd.Int32x4 for 128-bit, archsimd.Int32x8 for 256-bit).

Installation

go install github.com/dr2chase/midway/cmd/midway

Usage

Run the tool on/in a directory containing midway-tagged files:

midway [-dir <directory>] [other options]
go mod tidy # fill in entry for github.com/dr2chase/midway/midway

Flags

  • arch: Comma-separated lists of architectures to rewrite for. Default is "amd64".
  • -dir string: Directory to process (default: current directory ".").
  • -a2s string: Comma-separated list mapping architectures to lists of vector sizes (e.g., "amd64:128,256,512;wasm:128"). Default is "amd64:128,256,512;wasm:128".
  • -prefix string: Prefix for the archsimd package path (default: "simd").
  • -midway string: Package path for midway helpers (default: "github.com/dr2chase/midway/midway").

Example

Input (example.go):

//go:build midway

package example

import "github.com/dr2chase/midway/simd"

func Add(a, b simd.Int32s) simd.Int32s {
	return a // Implementation
}

Command:

midway -dir . -arch amd64 -sizes amd64:128,256

Output:

  1. Refactored example_simd_amd64.go (Dispatcher):

    //go:build !midway
    
    package example
    
    import "github.com/dr2chase/midway/midway"
    
    func Add(a, b simd.Int32s) simd.Int32s {
        switch midway.MaxVectorSize() {
        case 256:
            return Add_simd256(a, b)
        case 128:
            return Add_simd128(a, b)
        default:
            panic("unsupported vector size")
        }
    }
  2. Generated example_simd128_amd64.go:

    //go:build !midway
    
    package example
    
    import (
        "simd/archsimd"
        "github.com/dr2chase/midway/midway"
    )
    
    func Add_simd128(a, b archsimd.Int32x4) archsimd.Int32x4 {
        midway.Assert128()
        return a
    }
  3. Generated example_simd256_amd64.go: Similar to 128-bit, but using archsimd.Int32x8.

Development

The project includes test data in testdata/simple (hand-validated, won't run) and testdata/ip (runs, for GOARCH=amd64 and GOEXPERIMENT=simd) demonstrating various usage patterns, including:

  • Dependent types and aliases.
  • Dependent struct fields.
  • Global variables.
  • Generic functions (instantiated with SIMD types).
  • Midway files that are architecture-build tagged.

Known issues

Top-level initialized SIMD variables probably don't work yet.

Mocks.go is autogenerated from signatures in go1.26/simd/archsimd and there may be unanticipated semantic mismatches.

It would be better to combine the dispatch and specialized code all into a single file; there are no conflicts, and doing otherwise is just messy.

About

This is a source-to-source prototype of a proposed within-compiler implementation of "scalable simd" (i.e., riscv and arm64 sve)..

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages