tiny.choir.dialects.gpu.dialect.GpuDialect
Defined in dialects.gpu.dialect.
API (282)
Actions
Public operations.
ActiveMaskOp.createActiveMaskOp.getResultAllSyncOp.createAllSyncOp.getMaskAllSyncOp.getPredicateAllSyncOp.getResultAnySyncOp.createAnySyncOp.getMaskAnySyncOp.getPredicateAnySyncOp.getResultAtomicAddOp.createAtomicAddOp.getIndexAtomicAddOp.getMemrefAtomicAddOp.getOrderingAtomicAddOp.getResultAtomicAddOp.getScopeAtomicAddOp.getValAtomicCasOp.createAtomicCasOp.getDesiredAtomicCasOp.getExpectedAtomicCasOp.getIndexAtomicCasOp.getMemrefAtomicCasOp.getOrderingAtomicCasOp.getResultAtomicCasOp.getScopeAtomicLoadOp.createAtomicLoadOp.getIndexAtomicLoadOp.getMemrefAtomicLoadOp.getOrderingAtomicLoadOp.getResultAtomicMaxOp.createAtomicMaxOp.getIndexAtomicMaxOp.getMemrefAtomicMaxOp.getResultAtomicMaxOp.getValAtomicStoreOp.createAtomicStoreOp.getIndexAtomicStoreOp.getMemrefAtomicStoreOp.getOrderingAtomicStoreOp.getValueBallotSyncOp.createBallotSyncOp.getMaskBallotSyncOp.getPredicateBallotSyncOp.getResultBarrierOp.createBarrierOp.getScopeBlockDimOp.createBlockDimOp.getDimensionBlockDimOp.getResultBlockIdxOp.createBlockIdxOp.getDimensionBlockIdxOp.getResultCpAsyncCommitOp.createCpAsyncSharedOp.createCpAsyncSharedOp.getBytesCpAsyncSharedOp.getDstCpAsyncSharedOp.getDstIndexCpAsyncSharedOp.getSrcCpAsyncSharedOp.getSrcIndexCpAsyncWaitOp.createCpAsyncWaitOp.getGroupsFenceOp.createFenceOp.getOrderingFenceOp.getScopeFuncOp.createFuncOp.createKernelFuncOp.getArgumentFuncOp.getArgumentsFuncOp.getBodyFuncOp.getEntryBlockFuncOp.getNameFuncOp.getNumArgumentsFuncOp.getNumResultsFuncOp.getResultTypesFuncOp.isKernelGlobalIdxOp.createGlobalIdxOp.getDimensionGlobalIdxOp.getResultGridDimOp.createGridDimOp.getDimensionGridDimOp.getResultLaneIdOp.createLaneIdOp.getResultLaunchOp.createLaunchOp.getBlockDimLaunchOp.getGridDimLaunchOp.getKernelArgsLaunchOp.getKernelNameLaunchOp.getNumKernelArgsMatchAllOp.createMatchAllOp.getAllEqualResultMatchAllOp.getMaskResultMatchAllOp.getValueMatchAnyOp.createMatchAnyOp.getResultMatchAnyOp.getValueMemcpyAsyncOp.createMemcpyAsyncOp.getDstMemcpyAsyncOp.getEventMemcpyAsyncOp.getNumBytesMemcpyAsyncOp.getSrcMemcpyAsyncOp.getStreamMmaSyncOp.createMmaSyncOp.getAMmaSyncOp.getBMmaSyncOp.getCMmaSyncOp.getDMmaSyncOp.getShapeModuleOp.createModuleOp.getBodyModuleOp.getBodyBlockShflSyncOp.createShflSyncOp.getLaneOrDeltaShflSyncOp.getMaskShflSyncOp.getModeShflSyncOp.getResultShflSyncOp.getSrcSyncWarpOp.createSyncWarpOp.getMaskThreadIdxOp.createThreadIdxOp.getDimensionThreadIdxOp.getResultTmaCommitGroupOp.createTmaCreateDescriptorOp.createTmaCreateDescriptorOp.getBoxShapeTmaCreateDescriptorOp.getResultTmaCreateDescriptorOp.getTensorTmaLoadOp.createTmaLoadOp.getBarrierTmaLoadOp.getCoordsTmaLoadOp.getDescriptorTmaLoadOp.getSharedMemTmaWaitGroupOp.createTmaWaitGroupOp.getCountWarpIdOp.createWarpIdOp.getResultWarpReduceOp.createWarpReduceOp.getMaskWarpReduceOp.getOpKindWarpReduceOp.getResultWarpReduceOp.getValueWarpScanOp.createWarpScanOp.getMaskWarpScanOp.getOpKindWarpScanOp.getResultWarpScanOp.getValueWarpScanOp.isInclusiveYieldOp.createYieldOp.getOperandsgetMBarrierTypegetTmaDescriptorType
Types and contracts
Public types and contracts.
ActiveMaskOpAllSyncOpAnySyncOpAtomicAddOpAtomicCasOpAtomicLoadOpAtomicMaxOpAtomicStoreOpBallotSyncOpBarrierOpBlockDimOpBlockIdxOpCpAsyncCommitOpCpAsyncSharedOpCpAsyncWaitOpDpdxOpDpdyOpFenceOpFragCoordOpFrontFacingOpFuncOpFwidthOpGlobalIdxOpGridDimOpInstanceIndexOpLaneIdOpLaunchOpMatchAllOpMatchAnyOpMemcpyAsyncOpMmaSyncOpModuleOpPositionOpPushConstantOpSampleLodOpSampleOpSampledTextureOpShflSyncOpStageInputOpStageOutputOpSyncWarpOpThreadIdxOpTmaCommitGroupOpTmaCreateDescriptorOpTmaLoadOpTmaWaitGroupOpUniformOpVertexIndexOpWarpIdOpWarpReduceOpWarpScanOpYieldOp
Values and defaults
Public values and defaults.
ActiveMaskOp.operation_nameActiveMaskOp.operation_specAllSyncOp.operation_nameAllSyncOp.operation_specAnySyncOp.operation_nameAnySyncOp.operation_specAtomicAddOp.operation_nameAtomicAddOp.operation_specAtomicCasOp.operation_nameAtomicCasOp.operation_specAtomicLoadOp.operation_nameAtomicLoadOp.operation_specAtomicMaxOp.operation_nameAtomicMaxOp.operation_specAtomicStoreOp.operation_nameAtomicStoreOp.operation_specBallotSyncOp.operation_nameBallotSyncOp.operation_specBarrierOp.operation_nameBarrierOp.operation_specBlockDimOp.operation_nameBlockDimOp.operation_specBlockIdxOp.operation_nameBlockIdxOp.operation_specCpAsyncCommitOp.operation_nameCpAsyncCommitOp.operation_specCpAsyncSharedOp.operation_nameCpAsyncSharedOp.operation_specCpAsyncWaitOp.operation_nameCpAsyncWaitOp.operation_specFenceOp.operation_nameFenceOp.operation_specFuncOp.operation_nameFuncOp.operation_specGlobalIdxOp.operation_nameGlobalIdxOp.operation_specGridDimOp.operation_nameGridDimOp.operation_specLaneIdOp.operation_nameLaneIdOp.operation_specLaunchOp.operation_nameLaunchOp.operation_specMatchAllOp.operation_nameMatchAllOp.operation_specMatchAnyOp.operation_nameMatchAnyOp.operation_specMemcpyAsyncOp.operation_nameMemcpyAsyncOp.operation_specMmaSyncOp.operation_nameMmaSyncOp.operation_specModuleOp.operation_nameModuleOp.operation_specShflSyncOp.operation_nameShflSyncOp.operation_specSyncWarpOp.operation_nameSyncWarpOp.operation_specThreadIdxOp.operation_nameThreadIdxOp.operation_specTmaCommitGroupOp.operation_nameTmaCommitGroupOp.operation_specTmaCreateDescriptorOp.operation_nameTmaCreateDescriptorOp.operation_specTmaLoadOp.operation_nameTmaLoadOp.operation_specTmaWaitGroupOp.operation_nameTmaWaitGroupOp.operation_specWarpIdOp.operation_nameWarpIdOp.operation_specWarpReduceOp.operation_nameWarpReduceOp.operation_specWarpScanOp.operation_nameWarpScanOp.operation_specYieldOp.operation_nameYieldOp.operation_specmma_sync_a_countmma_sync_acc_countmma_sync_b_countnamespec
Source
Source: lib/choir/src/dialects/gpu/dialect.zig:20
zig
pub const GpuDialect = struct { pub const name = "gpu"; const op_specs = ir.dialects.opSpec.dialect(@This()); pub const spec = ir.dialects.dialectSpec(@This(), .{ .types = ir.dialects.typeNames(type_specs), }); const symbol_table_trait = ir.dialects.trait(ir.traits.SymbolTable); const func_symbol_vtable = interfaces.SymbolOpInterface.VTable{ .getSymbolName = getFuncSymbolName, .setSymbolName = setFuncSymbolName, .isDeclaration = isFuncDeclaration, }; const type_specs = struct { pub const tma_desc = type_names.tma_desc; pub const mbarrier = type_names.mbarrier; pub const sampled_texture = type_names.sampled_texture; }; pub const StageInputOp = stage.StageInputOp; pub const StageOutputOp = stage.StageOutputOp; pub const PositionOp = stage.PositionOp; pub const FragCoordOp = stage.FragCoordOp; pub const VertexIndexOp = stage.VertexIndexOp; pub const InstanceIndexOp = stage.InstanceIndexOp; pub const FrontFacingOp = stage.FrontFacingOp; pub const SampledTextureOp = stage.SampledTextureOp; pub const SampleOp = stage.SampleOp; pub const SampleLodOp = stage.SampleLodOp; pub const DpdxOp = stage.DpdxOp; pub const DpdyOp = stage.DpdyOp; pub const FwidthOp = stage.FwidthOp; pub const PushConstantOp = stage.PushConstantOp; pub const UniformOp = stage.UniformOp; pub const ModuleOp = struct { op: *ir.Operation, pub const operation_spec = op_specs.define(.{ .mnemonic = "module", .operands = 0, .results = 0, .regions = .{"body"}, .successors = 0, .dynamic_traits = .{symbol_table_trait}, }); pub const operation_name = operation_spec.name; pub fn create(ctx: *ir.Context, loc: ir.Location) !ModuleOp { try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); var state = ir.Operation.State.init(operation_name, loc); var body = ir.context.initRegion(ctx); defer body.deinit(); var body_builder = ir.OperationBuilder.init(ctx); _ = try body_builder.createBlock(&body, &.{}, &.{}); var regions = [_]*ir.Region{&body}; state.addRegionBodies(®ions); const op = try builder.create(state); errdefer op.erase(); return .{ .op = op }; } pub fn getBody(self: ModuleOp) *ir.Region { return self.op.getRegion(0).?; } pub fn getBodyBlock(self: ModuleOp) *ir.Block { return self.getBody().getEntryBlock().?; } }; pub const FuncOp = struct { op: *ir.Operation, pub const operation_spec = op_specs.define(.{ .mnemonic = "func", .operands = 0, .regions = .{"body"}, .successors = 0, .attrs = &.{ "kernel", ir.SymbolTable.symbol_attr_names.sym_visibility }, .required_attrs = &.{"sym_name"}, .interfaces = &.{ interfaces.SymbolOpInterface.entry(&func_symbol_vtable), effects.EffectOpInterface.entryFor(.{ .facts = &.{.{ .region = .{ .index = 0, .execution = .latent, .may_diverge = false, .captures = false, } }} }), }, }); pub const operation_name = operation_spec.name; pub fn create( ctx: *ir.Context, loc: ir.Location, func_name: []const u8, input_types: []const ir.Type, result_types: []const ir.Type, ) !FuncOp { try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); var state = ir.Operation.State.init(operation_name, loc); state.addTypes(result_types); var body = ir.context.initRegion(ctx); defer body.deinit(); var body_builder = ir.OperationBuilder.init(ctx); _ = try body_builder.createBlockWithLoc(&body, input_types, loc); var regions = [_]*ir.Region{&body}; state.addRegionBodies(®ions); const op = try builder.create(state); errdefer op.erase(); const name_attr = try func.FuncDialect.getSymNameAttr(ctx, func_name); try op.setAttr("sym_name", name_attr); return .{ .op = op }; } pub fn createKernel( ctx: *ir.Context, loc: ir.Location, kernel_name: []const u8, input_types: []const ir.Type, ) !FuncOp { var func_op = try create(ctx, loc, kernel_name, input_types, &.{}); errdefer func_op.op.erase(); const kernel_attr = try func.FuncDialect.getKernelAttr(ctx); try func_op.op.setAttr("kernel", kernel_attr); return func_op; } pub fn getName(self: FuncOp) ?[]const u8 { return ir.SymbolTable.getSymbolName(self.op); } pub fn isKernel(self: FuncOp) bool { return self.op.getAttr("kernel") != null; } pub fn getBody(self: FuncOp) *ir.Region { return self.op.getRegion(0).?; } pub fn getEntryBlock(self: FuncOp) *ir.Block { return self.getBody().getEntryBlock().?; } pub fn getArguments(self: FuncOp) []*ir.Value { return self.getEntryBlock().arguments.items; } pub fn getNumArguments(self: FuncOp) usize { return self.getEntryBlock().arguments.items.len; } pub fn getArgument(self: FuncOp, index: usize) *ir.Value { return self.getEntryBlock().arguments.items[index]; } pub fn getResultTypes(self: FuncOp) []const ir.Type { return self.op.getResultTypes(); } pub fn getNumResults(self: FuncOp) usize { return self.op.results.items.len; } }; pub const YieldOp = struct { op: *ir.Operation, pub const operation_spec = op_specs.terminator(.{ .mnemonic = "yield" }); pub const operation_name = operation_spec.name; pub fn create( ctx: *ir.Context, loc: ir.Location, operands: []const *ir.Value, ) !YieldOp { try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); var state = ir.Operation.State.init(operation_name, loc); state.addOperands(operands); const op = try builder.create(state); errdefer op.erase(); return .{ .op = op }; } pub fn getOperands(self: YieldOp) []const *ir.Value { return self.op.getOperandValues(); } }; pub const LaunchOp = struct { op: *ir.Operation, const dim_attr_keys = struct { pub const grid_x = "grid_x"; pub const grid_y = "grid_y"; pub const grid_z = "grid_z"; pub const block_x = "block_x"; pub const block_y = "block_y"; pub const block_z = "block_z"; }; pub const operation_spec = op_specs.leaf(.{ .mnemonic = "launch", .interfaces = &.{gpuEffects(.launch, &.{}, &.{})}, .operands = ir.dialects.shape.any(), .results = 0, .required_attrs = &.{ dim_attr_keys.block_x, dim_attr_keys.block_y, dim_attr_keys.block_z, dim_attr_keys.grid_x, dim_attr_keys.grid_y, dim_attr_keys.grid_z, "kernel", "num_kernel_args", }, }); pub const operation_name = operation_spec.name; fn setDimAttr(op: *ir.Operation, ctx: *ir.Context, key: []const u8, value: u32) !void { const attr = try ctx.getI64Attr(@intCast(value)); try op.setAttr(key, attr); } fn getDimAttr(op: *const ir.Operation, key: []const u8) ?u32 { const int_attr = op.getAttrAs(ir.Attribute.IntegerAttr, key) orelse return null; const raw = int_attr.getUnsignedValue(); if (raw > std.math.maxInt(u32)) return null; return @intCast(raw); } pub fn create( ctx: *ir.Context, loc: ir.Location, kernel_name: []const u8, kernel_args: []const *ir.Value, grid_dim: [3]u32, block_dim: [3]u32, ) !LaunchOp { try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); var state = ir.Operation.State.init(operation_name, loc); var all_operands: std.ArrayList(*ir.Value) = .empty; const allocator = ir.context.transientAllocator(ctx); defer all_operands.deinit(allocator); for (kernel_args) |arg| { try all_operands.append(allocator, arg); } state.addOperands(all_operands.items); const op = try builder.create(state); errdefer op.erase(); const kernel_attr = try func.FuncDialect.getSymNameAttr(ctx, kernel_name); try op.setAttr("kernel", kernel_attr); var buf: [16]u8 = undefined; const num_args_str = try ir.format.intPayload(buf[0..], kernel_args.len); const num_args_attr = try ctx.getDialectAttr("gpu.num_kernel_args", num_args_str); try op.setAttr("num_kernel_args", num_args_attr); try setDimAttr(op, ctx, dim_attr_keys.grid_x, grid_dim[0]); try setDimAttr(op, ctx, dim_attr_keys.grid_y, grid_dim[1]); try setDimAttr(op, ctx, dim_attr_keys.grid_z, grid_dim[2]); try setDimAttr(op, ctx, dim_attr_keys.block_x, block_dim[0]); try setDimAttr(op, ctx, dim_attr_keys.block_y, block_dim[1]); try setDimAttr(op, ctx, dim_attr_keys.block_z, block_dim[2]); return .{ .op = op }; } pub fn getKernelName(self: LaunchOp) ?[]const u8 { if (self.op.getAttr("kernel")) |attr| { return func.FuncDialect.getSymNameValue(attr); } return null; } pub fn getNumKernelArgs(self: LaunchOp) usize { const dialect_attr = self.op.getAttrAs(ir.Attribute.DialectAttr, "num_kernel_args") orelse return 0; return std.fmt.parseInt(usize, dialect_attr.payload, 10) catch 0; } pub fn getKernelArgs(self: LaunchOp) []const *ir.Value { const num_args = self.getNumKernelArgs(); return self.op.getOperandValues()[0..num_args]; } pub fn getGridDim(self: LaunchOp) ?[3]u32 { const gx = getDimAttr(self.op, dim_attr_keys.grid_x) orelse return null; const gy = getDimAttr(self.op, dim_attr_keys.grid_y) orelse return null; const gz = getDimAttr(self.op, dim_attr_keys.grid_z) orelse return null; return .{ gx, gy, gz }; } pub fn getBlockDim(self: LaunchOp) ?[3]u32 { const bx = getDimAttr(self.op, dim_attr_keys.block_x) orelse return null; const by = getDimAttr(self.op, dim_attr_keys.block_y) orelse return null; const bz = getDimAttr(self.op, dim_attr_keys.block_z) orelse return null; return .{ bx, by, bz }; } }; pub const ThreadIdxOp = struct { op: *ir.Operation, pub const operation_spec = dimIndexSpec("thread_idx"); pub const operation_name = operation_spec.name; pub fn create(ctx: *ir.Context, loc: ir.Location, dim: Dimension) !ThreadIdxOp { const arith = choir.dialects.arith; try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); const index_type = try arith.ArithDialect.getIndexType(ctx); var state = ir.Operation.State.init(operation_name, loc); state.addTypes(&.{index_type}); const op = try builder.create(state); errdefer op.erase(); try setDimensionAttr(op, ctx, dim); return .{ .op = op }; } pub fn getResult(self: *const ThreadIdxOp) *ir.Value { return self.op.getResult(0).?; } pub fn getDimension(self: ThreadIdxOp) ?Dimension { return getDimensionAttr(self.op); } }; pub const BlockIdxOp = struct { op: *ir.Operation, pub const operation_spec = dimIndexSpec("block_idx"); pub const operation_name = operation_spec.name; pub fn create(ctx: *ir.Context, loc: ir.Location, dim: Dimension) !BlockIdxOp { const arith = choir.dialects.arith; try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); const index_type = try arith.ArithDialect.getIndexType(ctx); var state = ir.Operation.State.init(operation_name, loc); state.addTypes(&.{index_type}); const op = try builder.create(state); errdefer op.erase(); try setDimensionAttr(op, ctx, dim); return .{ .op = op }; } pub fn getResult(self: *const BlockIdxOp) *ir.Value { return self.op.getResult(0).?; } pub fn getDimension(self: BlockIdxOp) ?Dimension { return getDimensionAttr(self.op); } }; pub const BlockDimOp = struct { op: *ir.Operation, pub const operation_spec = dimIndexSpec("block_dim"); pub const operation_name = operation_spec.name; pub fn create(ctx: *ir.Context, loc: ir.Location, dim: Dimension) !BlockDimOp { const arith = choir.dialects.arith; try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); const index_type = try arith.ArithDialect.getIndexType(ctx); var state = ir.Operation.State.init(operation_name, loc); state.addTypes(&.{index_type}); const op = try builder.create(state); errdefer op.erase(); try setDimensionAttr(op, ctx, dim); return .{ .op = op }; } pub fn getResult(self: *const BlockDimOp) *ir.Value { return self.op.getResult(0).?; } pub fn getDimension(self: BlockDimOp) ?Dimension { return getDimensionAttr(self.op); } }; pub const GridDimOp = struct { op: *ir.Operation, pub const operation_spec = dimIndexSpec("grid_dim"); pub const operation_name = operation_spec.name; pub fn create(ctx: *ir.Context, loc: ir.Location, dim: Dimension) !GridDimOp { const arith = choir.dialects.arith; try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); const index_type = try arith.ArithDialect.getIndexType(ctx); var state = ir.Operation.State.init(operation_name, loc); state.addTypes(&.{index_type}); const op = try builder.create(state); errdefer op.erase(); try setDimensionAttr(op, ctx, dim); return .{ .op = op }; } pub fn getResult(self: *const GridDimOp) *ir.Value { return self.op.getResult(0).?; } pub fn getDimension(self: GridDimOp) ?Dimension { return getDimensionAttr(self.op); } }; pub const GlobalIdxOp = struct { op: *ir.Operation, pub const operation_spec = dimIndexSpec("global_idx"); pub const operation_name = operation_spec.name; pub fn create(ctx: *ir.Context, loc: ir.Location, dim: Dimension) !GlobalIdxOp { const arith = choir.dialects.arith; try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); const index_type = try arith.ArithDialect.getIndexType(ctx); var state = ir.Operation.State.init(operation_name, loc); state.addTypes(&.{index_type}); const op = try builder.create(state); errdefer op.erase(); try setDimensionAttr(op, ctx, dim); return .{ .op = op }; } pub fn getResult(self: *const GlobalIdxOp) *ir.Value { return self.op.getResult(0).?; } pub fn getDimension(self: GlobalIdxOp) ?Dimension { return getDimensionAttr(self.op); } }; pub const LaneIdOp = struct { op: *ir.Operation, pub const operation_spec = indexSpec("lane_id"); pub const operation_name = operation_spec.name; pub fn create(ctx: *ir.Context, loc: ir.Location) !LaneIdOp { const arith = choir.dialects.arith; try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); const index_type = try arith.ArithDialect.getIndexType(ctx); var state = ir.Operation.State.init(operation_name, loc); state.addTypes(&.{index_type}); const op = try builder.create(state); errdefer op.erase(); return .{ .op = op }; } pub fn getResult(self: *const LaneIdOp) *ir.Value { return self.op.getResult(0).?; } }; pub const WarpIdOp = struct { op: *ir.Operation, pub const operation_spec = indexSpec("warp_id"); pub const operation_name = operation_spec.name; pub fn create(ctx: *ir.Context, loc: ir.Location) !WarpIdOp { const arith = choir.dialects.arith; try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); const index_type = try arith.ArithDialect.getIndexType(ctx); var state = ir.Operation.State.init(operation_name, loc); state.addTypes(&.{index_type}); const op = try builder.create(state); errdefer op.erase(); return .{ .op = op }; } pub fn getResult(self: *const WarpIdOp) *ir.Value { return self.op.getResult(0).?; } }; pub const BarrierOp = struct { op: *ir.Operation, pub const operation_spec = op_specs.leaf(.{ .mnemonic = "barrier", .interfaces = &.{gpuEffects(.synchronize, &.{}, &.{})}, .operands = 0, .results = 0, .required_attrs = &.{"scope"}, }); pub const operation_name = operation_spec.name; pub fn create(ctx: *ir.Context, loc: ir.Location, scope: Scope) !BarrierOp { try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); const state = ir.Operation.State.init(operation_name, loc); const op = try builder.create(state); errdefer op.erase(); try setScopeAttr(op, ctx, scope); return .{ .op = op }; } pub fn getScope(self: BarrierOp) ?Scope { return getScopeAttr(self.op); } }; pub const FenceOp = struct { op: *ir.Operation, pub const operation_spec = op_specs.leaf(.{ .mnemonic = "fence", .interfaces = &.{gpuEffects(.synchronize, &.{}, &.{})}, .operands = 0, .results = 0, .required_attrs = &.{ "ordering", "scope" }, }); pub const operation_name = operation_spec.name; pub fn create(ctx: *ir.Context, loc: ir.Location, scope: Scope, ordering: MemoryOrder) !FenceOp { try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); const state = ir.Operation.State.init(operation_name, loc); const op = try builder.create(state); errdefer op.erase(); try setScopeAttr(op, ctx, scope); try setOrderingAttr(op, ctx, ordering); return .{ .op = op }; } pub fn getScope(self: FenceOp) ?Scope { return getScopeAttr(self.op); } pub fn getOrdering(self: FenceOp) ?MemoryOrder { return getOrderingAttr(self.op); } }; pub const MemcpyAsyncOp = struct { op: *ir.Operation, pub const operation_spec = op_specs.leaf(.{ .mnemonic = "memcpy_async", .interfaces = &.{gpuEffects(.launch, &.{0}, &.{1})}, .operands = ir.dialects.shape.between(3, 5), .operand_names = .{ "src", "dst", "num_bytes", "stream", "event" }, .results = 0, .operand_segments = ir.dialects.segments.operands(.{ 1, 1, 1, ir.dialects.shape.atMost(1), ir.dialects.shape.atMost(1), }), }); pub const operation_name = operation_spec.name; pub fn create( ctx: *ir.Context, loc: ir.Location, src: *ir.Value, dst: *ir.Value, num_bytes: *ir.Value, stream: ?*ir.Value, event: ?*ir.Value, ) !MemcpyAsyncOp { try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); var state = ir.Operation.State.init(operation_name, loc); var operands: [5]*ir.Value = undefined; var operand_count: usize = 0; operands[operand_count] = src; operand_count += 1; operands[operand_count] = dst; operand_count += 1; operands[operand_count] = num_bytes; operand_count += 1; if (stream) |stream_val| { operands[operand_count] = stream_val; operand_count += 1; } if (event) |event_val| { operands[operand_count] = event_val; operand_count += 1; } state.addOperands(operands[0..operand_count]); const op = try builder.create(state); errdefer op.erase(); const segment_sizes = [_]usize{ 1, 1, 1, if (stream != null) 1 else 0, if (event != null) 1 else 0, }; try ir.dialects.setOperandSegmentSizes(operation_spec, op, &segment_sizes); return .{ .op = op }; } pub fn getSrc(self: MemcpyAsyncOp) *ir.Value { return ir.dialects.operand(operation_spec, self.op, "src"); } pub fn getDst(self: MemcpyAsyncOp) *ir.Value { return ir.dialects.operand(operation_spec, self.op, "dst"); } pub fn getNumBytes(self: MemcpyAsyncOp) *ir.Value { return ir.dialects.operand(operation_spec, self.op, "num_bytes"); } pub fn getStream(self: MemcpyAsyncOp) ?*ir.Value { return ir.dialects.operandSegmentValue(operation_spec, self.op, "stream"); } pub fn getEvent(self: MemcpyAsyncOp) ?*ir.Value { return ir.dialects.operandSegmentValue(operation_spec, self.op, "event"); } }; pub const TmaCreateDescriptorOp = struct { op: *ir.Operation, pub const operation_spec = op_specs.leaf(.{ .mnemonic = "tma.create_descriptor", .operands = .{ "tensor", "box_shape" }, .results = .{"descriptor"}, }); pub const operation_name = operation_spec.name; pub fn create( ctx: *ir.Context, loc: ir.Location, tensor: *ir.Value, box_shape: *ir.Value, ) !TmaCreateDescriptorOp { try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); var state = ir.Operation.State.init(operation_name, loc); state.addOperands(&.{ tensor, box_shape }); const desc_type = try getTmaDescriptorType(ctx); state.addTypes(&.{desc_type}); const op = try builder.create(state); errdefer op.erase(); return .{ .op = op }; } pub fn getResult(self: *const TmaCreateDescriptorOp) *ir.Value { return self.op.getResult(0).?; } pub fn getTensor(self: TmaCreateDescriptorOp) *ir.Value { return self.op.operands.items[0].value; } pub fn getBoxShape(self: TmaCreateDescriptorOp) *ir.Value { return self.op.operands.items[1].value; } }; pub const TmaLoadOp = struct { op: *ir.Operation, pub const operation_spec = noResultSpec("tma.load", .{ "descriptor", "shared_mem", "barrier", "coords" }); pub const operation_name = operation_spec.name; pub fn create( ctx: *ir.Context, loc: ir.Location, desc: *ir.Value, shmem: *ir.Value, mbarrier: *ir.Value, coords: *ir.Value, ) !TmaLoadOp { try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); var state = ir.Operation.State.init(operation_name, loc); state.addOperands(&.{ desc, shmem, mbarrier, coords }); const op = try builder.create(state); errdefer op.erase(); return .{ .op = op }; } pub fn getDescriptor(self: TmaLoadOp) *ir.Value { return self.op.operands.items[0].value; } pub fn getSharedMem(self: TmaLoadOp) *ir.Value { return self.op.operands.items[1].value; } pub fn getBarrier(self: TmaLoadOp) *ir.Value { return self.op.operands.items[2].value; } pub fn getCoords(self: TmaLoadOp) *ir.Value { return self.op.operands.items[3].value; } }; pub const TmaCommitGroupOp = struct { op: *ir.Operation, pub const operation_spec = noResultSpec("tma.commit_group", 0); pub const operation_name = operation_spec.name; pub fn create(ctx: *ir.Context, loc: ir.Location) !TmaCommitGroupOp { try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); const state = ir.Operation.State.init(operation_name, loc); const op = try builder.create(state); errdefer op.erase(); return .{ .op = op }; } }; pub const TmaWaitGroupOp = struct { op: *ir.Operation, pub const operation_spec = op_specs.leaf(.{ .mnemonic = "tma.wait_group", .interfaces = &.{gpuEffects(.synchronize, &.{}, &.{})}, .operands = 0, .results = 0, .required_attrs = &.{"count"}, }); pub const operation_name = operation_spec.name; pub fn create(ctx: *ir.Context, loc: ir.Location, count: i64) !TmaWaitGroupOp { try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); const state = ir.Operation.State.init(operation_name, loc); const op = try builder.create(state); errdefer op.erase(); try setI64Attr(op, ctx, "count", count); return .{ .op = op }; } pub fn getCount(self: TmaWaitGroupOp) ?i64 { return getI64AttrValue(self.op, "count"); } }; pub const ShflSyncOp = struct { op: *ir.Operation, pub const operation_spec = op_specs.leaf(.{ .mnemonic = "shfl_sync", .interfaces = &.{gpuEffects(.synchronize, &.{}, &.{})}, .operands = .{ "mask", "src", "lane_or_delta" }, .results = .{"result"}, .required_attrs = &.{"mode"}, }); pub const operation_name = operation_spec.name; pub fn create( ctx: *ir.Context, loc: ir.Location, mode: ShuffleMode, mask: *ir.Value, src: *ir.Value, lane_or_delta: *ir.Value, ) !ShflSyncOp { try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); var state = ir.Operation.State.init(operation_name, loc); state.addOperands(&.{ mask, src, lane_or_delta }); state.addTypes(&.{src.type}); const op = try builder.create(state); errdefer op.erase(); const mode_attr = try ctx.getDialectAttr("gpu.shuffle_mode", mode.toString()); try op.setAttr("mode", mode_attr); return .{ .op = op }; } pub fn getResult(self: *const ShflSyncOp) *ir.Value { return self.op.getResult(0).?; } pub fn getMask(self: ShflSyncOp) *ir.Value { return self.op.operands.items[0].value; } pub fn getSrc(self: ShflSyncOp) *ir.Value { return self.op.operands.items[1].value; } pub fn getLaneOrDelta(self: ShflSyncOp) *ir.Value { return self.op.operands.items[2].value; } pub fn getMode(self: ShflSyncOp) ?ShuffleMode { const dialect_attr = self.op.getAttrAs(ir.Attribute.DialectAttr, "mode") orelse return null; return ShuffleMode.fromString(dialect_attr.payload); } }; pub const AllSyncOp = struct { op: *ir.Operation, pub const operation_spec = op_specs.leaf(.{ .mnemonic = "all_sync", .interfaces = &.{gpuEffects(.synchronize, &.{}, &.{})}, .operands = .{ "mask", "predicate" }, .results = .{"result"}, }); pub const operation_name = operation_spec.name; pub fn create(ctx: *ir.Context, loc: ir.Location, mask: *ir.Value, pred: *ir.Value) !AllSyncOp { const arith = choir.dialects.arith; try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); const bool_type = try arith.ArithDialect.getScalarType(ctx, .bool); var state = ir.Operation.State.init(operation_name, loc); state.addOperands(&.{ mask, pred }); state.addTypes(&.{bool_type}); const op = try builder.create(state); errdefer op.erase(); return .{ .op = op }; } pub fn getResult(self: *const AllSyncOp) *ir.Value { return self.op.getResult(0).?; } pub fn getMask(self: AllSyncOp) *ir.Value { return self.op.operands.items[0].value; } pub fn getPredicate(self: AllSyncOp) *ir.Value { return self.op.operands.items[1].value; } }; pub const AnySyncOp = struct { op: *ir.Operation, pub const operation_spec = op_specs.leaf(.{ .mnemonic = "any_sync", .interfaces = &.{gpuEffects(.synchronize, &.{}, &.{})}, .operands = .{ "mask", "predicate" }, .results = .{"result"}, }); pub const operation_name = operation_spec.name; pub fn create(ctx: *ir.Context, loc: ir.Location, mask: *ir.Value, pred: *ir.Value) !AnySyncOp { const arith = choir.dialects.arith; try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); const bool_type = try arith.ArithDialect.getScalarType(ctx, .bool); var state = ir.Operation.State.init(operation_name, loc); state.addOperands(&.{ mask, pred }); state.addTypes(&.{bool_type}); const op = try builder.create(state); errdefer op.erase(); return .{ .op = op }; } pub fn getResult(self: *const AnySyncOp) *ir.Value { return self.op.getResult(0).?; } pub fn getMask(self: AnySyncOp) *ir.Value { return self.op.operands.items[0].value; } pub fn getPredicate(self: AnySyncOp) *ir.Value { return self.op.operands.items[1].value; } }; pub const BallotSyncOp = struct { op: *ir.Operation, pub const operation_spec = op_specs.leaf(.{ .mnemonic = "ballot_sync", .interfaces = &.{gpuEffects(.synchronize, &.{}, &.{})}, .operands = .{ "mask", "predicate" }, .results = .{"result"}, }); pub const operation_name = operation_spec.name; pub fn create(ctx: *ir.Context, loc: ir.Location, mask: *ir.Value, pred: *ir.Value) !BallotSyncOp { const arith = choir.dialects.arith; try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); const i32_type = try arith.ArithDialect.getI32Type(ctx); var state = ir.Operation.State.init(operation_name, loc); state.addOperands(&.{ mask, pred }); state.addTypes(&.{i32_type}); const op = try builder.create(state); errdefer op.erase(); return .{ .op = op }; } pub fn getResult(self: *const BallotSyncOp) *ir.Value { return self.op.getResult(0).?; } pub fn getMask(self: BallotSyncOp) *ir.Value { return self.op.operands.items[0].value; } pub fn getPredicate(self: BallotSyncOp) *ir.Value { return self.op.operands.items[1].value; } }; pub const WarpReduceOp = struct { op: *ir.Operation, pub const operation_spec = op_specs.leaf(.{ .mnemonic = "warp_reduce", .interfaces = &.{gpuEffects(.synchronize, &.{}, &.{})}, .operands = .{ "mask", "value" }, .results = .{"result"}, .required_attrs = &.{"op"}, }); pub const operation_name = operation_spec.name; pub fn create( ctx: *ir.Context, loc: ir.Location, op_kind: WarpOpKind, mask: *ir.Value, value: *ir.Value, ) !WarpReduceOp { try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); var state = ir.Operation.State.init(operation_name, loc); state.addOperands(&.{ mask, value }); state.addTypes(&.{value.type}); const op = try builder.create(state); errdefer op.erase(); try setWarpOpAttr(op, ctx, op_kind); return .{ .op = op }; } pub fn getResult(self: *const WarpReduceOp) *ir.Value { return self.op.getResult(0).?; } pub fn getMask(self: WarpReduceOp) *ir.Value { return self.op.operands.items[0].value; } pub fn getValue(self: WarpReduceOp) *ir.Value { return self.op.operands.items[1].value; } pub fn getOpKind(self: WarpReduceOp) ?WarpOpKind { return getWarpOpAttr(self.op); } }; pub const WarpScanOp = struct { op: *ir.Operation, pub const operation_spec = op_specs.leaf(.{ .mnemonic = "warp_scan", .interfaces = &.{gpuEffects(.synchronize, &.{}, &.{})}, .operands = .{ "mask", "value" }, .results = .{"result"}, .required_attrs = &.{ "inclusive", "op" }, }); pub const operation_name = operation_spec.name; pub fn create( ctx: *ir.Context, loc: ir.Location, op_kind: WarpOpKind, inclusive: bool, mask: *ir.Value, value: *ir.Value, ) !WarpScanOp { try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); var state = ir.Operation.State.init(operation_name, loc); state.addOperands(&.{ mask, value }); state.addTypes(&.{value.type}); const op = try builder.create(state); errdefer op.erase(); try setWarpOpAttr(op, ctx, op_kind); try setBoolAttr(op, ctx, "inclusive", inclusive); return .{ .op = op }; } pub fn getResult(self: *const WarpScanOp) *ir.Value { return self.op.getResult(0).?; } pub fn getMask(self: WarpScanOp) *ir.Value { return self.op.operands.items[0].value; } pub fn getValue(self: WarpScanOp) *ir.Value { return self.op.operands.items[1].value; } pub fn getOpKind(self: WarpScanOp) ?WarpOpKind { return getWarpOpAttr(self.op); } pub fn isInclusive(self: WarpScanOp) bool { return getBoolAttrValue(self.op, "inclusive"); } }; pub const MatchAnyOp = struct { op: *ir.Operation, pub const operation_spec = op_specs.leaf(.{ .mnemonic = "match_any", .interfaces = &.{gpuEffects(.synchronize, &.{}, &.{})}, .operands = .{"value"}, .results = .{"mask"}, }); pub const operation_name = operation_spec.name; pub fn create(ctx: *ir.Context, loc: ir.Location, value: *ir.Value) !MatchAnyOp { const arith = choir.dialects.arith; try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); const i32_type = try arith.ArithDialect.getI32Type(ctx); var state = ir.Operation.State.init(operation_name, loc); state.addOperands(&.{value}); state.addTypes(&.{i32_type}); const op = try builder.create(state); errdefer op.erase(); return .{ .op = op }; } pub fn getResult(self: *const MatchAnyOp) *ir.Value { return self.op.getResult(0).?; } pub fn getValue(self: MatchAnyOp) *ir.Value { return self.op.operands.items[0].value; } }; pub const MatchAllOp = struct { op: *ir.Operation, pub const operation_spec = op_specs.leaf(.{ .mnemonic = "match_all", .interfaces = &.{gpuEffects(.synchronize, &.{}, &.{})}, .operands = .{"value"}, .results = .{ "mask", "all_equal" }, }); pub const operation_name = operation_spec.name; pub fn create(ctx: *ir.Context, loc: ir.Location, value: *ir.Value) !MatchAllOp { const arith = choir.dialects.arith; try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); const i32_type = try arith.ArithDialect.getI32Type(ctx); const bool_type = try arith.ArithDialect.getScalarType(ctx, .bool); var state = ir.Operation.State.init(operation_name, loc); state.addOperands(&.{value}); state.addTypes(&.{ i32_type, bool_type }); const op = try builder.create(state); errdefer op.erase(); return .{ .op = op }; } pub fn getMaskResult(self: *const MatchAllOp) *ir.Value { return self.op.getResult(0).?; } pub fn getAllEqualResult(self: *const MatchAllOp) *ir.Value { return self.op.getResult(1).?; } pub fn getValue(self: MatchAllOp) *ir.Value { return self.op.operands.items[0].value; } }; pub const ActiveMaskOp = struct { op: *ir.Operation, pub const operation_spec = op_specs.leaf(.{ .mnemonic = "active_mask", .interfaces = &.{gpuEffects(.state_observe, &.{}, &.{})}, .operands = 0, .results = .{"mask"}, }); pub const operation_name = operation_spec.name; pub fn create(ctx: *ir.Context, loc: ir.Location) !ActiveMaskOp { const arith = choir.dialects.arith; try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); const i32_type = try arith.ArithDialect.getI32Type(ctx); var state = ir.Operation.State.init(operation_name, loc); state.addTypes(&.{i32_type}); const op = try builder.create(state); errdefer op.erase(); return .{ .op = op }; } pub fn getResult(self: *const ActiveMaskOp) *ir.Value { return self.op.getResult(0).?; } }; pub const SyncWarpOp = struct { op: *ir.Operation, pub const operation_spec = noResultSpec("sync_warp", .{"mask"}); pub const operation_name = operation_spec.name; pub fn create(ctx: *ir.Context, loc: ir.Location, mask: *ir.Value) !SyncWarpOp { try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); var state = ir.Operation.State.init(operation_name, loc); state.addOperands(&.{mask}); const op = try builder.create(state); errdefer op.erase(); return .{ .op = op }; } pub fn getMask(self: SyncWarpOp) *ir.Value { return self.op.operands.items[0].value; } }; pub const mma_sync_a_count = 4; pub const mma_sync_b_count = 2; pub const mma_sync_acc_count = 4; pub const MmaSyncOp = struct { op: *ir.Operation, pub const operation_spec = op_specs.leaf(.{ .mnemonic = "mma_sync", .interfaces = &.{gpuEffects(.synchronize, &.{}, &.{})}, .operands = .{ "a0", "a1", "a2", "a3", "b0", "b1", "c0", "c1", "c2", "c3" }, .results = .{ "d0", "d1", "d2", "d3" }, .required_attrs = &.{"shape"}, }); pub const operation_name = operation_spec.name; pub fn create( ctx: *ir.Context, loc: ir.Location, a: [mma_sync_a_count]*ir.Value, b: [mma_sync_b_count]*ir.Value, c: [mma_sync_acc_count]*ir.Value, shape: MmaShape, ) !MmaSyncOp { try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); var state = ir.Operation.State.init(operation_name, loc); state.addOperands(&.{ a[0], a[1], a[2], a[3], b[0], b[1], c[0], c[1], c[2], c[3] }); state.addTypes(&.{ c[0].type, c[1].type, c[2].type, c[3].type }); const op = try builder.create(state); errdefer op.erase(); try setMmaShapeAttr(op, ctx, shape); return .{ .op = op }; } pub fn getA(self: MmaSyncOp, index: usize) *ir.Value { return self.op.operands.items[index].value; } pub fn getB(self: MmaSyncOp, index: usize) *ir.Value { return self.op.operands.items[mma_sync_a_count + index].value; } pub fn getC(self: MmaSyncOp, index: usize) *ir.Value { return self.op.operands.items[mma_sync_a_count + mma_sync_b_count + index].value; } pub fn getD(self: *const MmaSyncOp, index: usize) *ir.Value { return self.op.getResult(index).?; } pub fn getShape(self: MmaSyncOp) ?MmaShape { return getMmaShapeAttr(self.op); } }; pub const CpAsyncSharedOp = struct { op: *ir.Operation, pub const operation_spec = op_specs.leaf(.{ .mnemonic = "cp_async_shared", .interfaces = &.{gpuEffects(.launch, &.{2}, &.{0})}, .operands = .{ "dst", "dst_index", "src", "src_index" }, .results = 0, .required_attrs = &.{"bytes"}, }); pub const operation_name = operation_spec.name; pub fn create( ctx: *ir.Context, loc: ir.Location, dst: *ir.Value, dst_index: *ir.Value, src: *ir.Value, src_index: *ir.Value, bytes: u32, ) !CpAsyncSharedOp { try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); var state = ir.Operation.State.init(operation_name, loc); state.addOperands(&.{ dst, dst_index, src, src_index }); const op = try builder.create(state); errdefer op.erase(); const bytes_attr = try ctx.getI64Attr(@intCast(bytes)); try op.setAttr("bytes", bytes_attr); return .{ .op = op }; } pub fn getDst(self: CpAsyncSharedOp) *ir.Value { return ir.dialects.operand(operation_spec, self.op, "dst"); } pub fn getDstIndex(self: CpAsyncSharedOp) *ir.Value { return ir.dialects.operand(operation_spec, self.op, "dst_index"); } pub fn getSrc(self: CpAsyncSharedOp) *ir.Value { return ir.dialects.operand(operation_spec, self.op, "src"); } pub fn getSrcIndex(self: CpAsyncSharedOp) *ir.Value { return ir.dialects.operand(operation_spec, self.op, "src_index"); } pub fn getBytes(self: CpAsyncSharedOp) ?u32 { const int_attr = self.op.getAttrAs(ir.Attribute.IntegerAttr, "bytes") orelse return null; const raw = int_attr.getUnsignedValue(); if (raw > std.math.maxInt(u32)) return null; return @intCast(raw); } }; pub const CpAsyncCommitOp = struct { op: *ir.Operation, pub const operation_spec = op_specs.leaf(.{ .mnemonic = "cp_async_commit", .interfaces = &.{gpuEffects(.synchronize, &.{}, &.{})}, .operands = 0, .results = 0, }); pub const operation_name = operation_spec.name; pub fn create(ctx: *ir.Context, loc: ir.Location) !CpAsyncCommitOp { try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); const state = ir.Operation.State.init(operation_name, loc); const op = try builder.create(state); errdefer op.erase(); return .{ .op = op }; } }; pub const CpAsyncWaitOp = struct { op: *ir.Operation, pub const operation_spec = op_specs.leaf(.{ .mnemonic = "cp_async_wait", .interfaces = &.{gpuEffects(.synchronize, &.{}, &.{})}, .operands = 0, .results = 0, .required_attrs = &.{"groups"}, }); pub const operation_name = operation_spec.name; pub fn create(ctx: *ir.Context, loc: ir.Location, groups: u32) !CpAsyncWaitOp { try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); const state = ir.Operation.State.init(operation_name, loc); const op = try builder.create(state); errdefer op.erase(); const groups_attr = try ctx.getI64Attr(@intCast(groups)); try op.setAttr("groups", groups_attr); return .{ .op = op }; } pub fn getGroups(self: CpAsyncWaitOp) ?u32 { const int_attr = self.op.getAttrAs(ir.Attribute.IntegerAttr, "groups") orelse return null; const raw = int_attr.getUnsignedValue(); if (raw > std.math.maxInt(u32)) return null; return @intCast(raw); } }; pub const AtomicLoadOp = struct { op: *ir.Operation, pub const operation_spec = op_specs.leaf(.{ .mnemonic = "atomic_load", .interfaces = &.{gpuEffects(.synchronize, &.{0}, &.{})}, .operands = .{ "memref", "index" }, .results = .{"value"}, .required_attrs = &.{"ordering"}, }); pub const operation_name = operation_spec.name; pub fn create( ctx: *ir.Context, loc: ir.Location, memref: *ir.Value, index: *ir.Value, result_type: ir.Type, ordering: MemoryOrder, ) !AtomicLoadOp { try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); var state = ir.Operation.State.init(operation_name, loc); state.addOperands(&.{ memref, index }); state.addTypes(&.{result_type}); const op = try builder.create(state); errdefer op.erase(); try setOrderingAttr(op, ctx, ordering); return .{ .op = op }; } pub fn getResult(self: *const AtomicLoadOp) *ir.Value { return self.op.getResult(0).?; } pub fn getMemref(self: AtomicLoadOp) *ir.Value { return self.op.operands.items[0].value; } pub fn getIndex(self: AtomicLoadOp) *ir.Value { return self.op.operands.items[1].value; } pub fn getOrdering(self: AtomicLoadOp) ?MemoryOrder { return getOrderingAttr(self.op); } }; pub const AtomicStoreOp = struct { op: *ir.Operation, pub const operation_spec = op_specs.leaf(.{ .mnemonic = "atomic_store", .interfaces = &.{gpuEffects(.synchronize, &.{}, &.{1})}, .operands = .{ "value", "memref", "index" }, .results = 0, .required_attrs = &.{"ordering"}, }); pub const operation_name = operation_spec.name; pub fn create( ctx: *ir.Context, loc: ir.Location, value: *ir.Value, memref: *ir.Value, index: *ir.Value, ordering: MemoryOrder, ) !AtomicStoreOp { try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); var state = ir.Operation.State.init(operation_name, loc); state.addOperands(&.{ value, memref, index }); const op = try builder.create(state); errdefer op.erase(); try setOrderingAttr(op, ctx, ordering); return .{ .op = op }; } pub fn getValue(self: AtomicStoreOp) *ir.Value { return self.op.operands.items[0].value; } pub fn getMemref(self: AtomicStoreOp) *ir.Value { return self.op.operands.items[1].value; } pub fn getIndex(self: AtomicStoreOp) *ir.Value { return self.op.operands.items[2].value; } pub fn getOrdering(self: AtomicStoreOp) ?MemoryOrder { return getOrderingAttr(self.op); } }; pub const AtomicAddOp = struct { op: *ir.Operation, pub const operation_spec = op_specs.leaf(.{ .mnemonic = "atomic_add", .interfaces = &.{gpuEffects(.synchronize, &.{0}, &.{0})}, .operands = .{ "memref", "index", "value" }, .results = .{"old_value"}, .attrs = &.{"scope"}, .required_attrs = &.{"ordering"}, }); pub const operation_name = operation_spec.name; pub fn create( ctx: *ir.Context, loc: ir.Location, memref: *ir.Value, index: *ir.Value, val: *ir.Value, ordering: MemoryOrder, scope: ?Scope, ) !AtomicAddOp { try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); var state = ir.Operation.State.init(operation_name, loc); state.addOperands(&.{ memref, index, val }); state.addTypes(&.{val.type}); const op = try builder.create(state); errdefer op.erase(); try setOrderingAttr(op, ctx, ordering); if (scope) |scope_value| { try setScopeAttr(op, ctx, scope_value); } return .{ .op = op }; } pub fn getResult(self: *const AtomicAddOp) *ir.Value { return self.op.getResult(0).?; } pub fn getMemref(self: AtomicAddOp) *ir.Value { return self.op.operands.items[0].value; } pub fn getIndex(self: AtomicAddOp) *ir.Value { return self.op.operands.items[1].value; } pub fn getVal(self: AtomicAddOp) *ir.Value { return self.op.operands.items[2].value; } pub fn getOrdering(self: AtomicAddOp) ?MemoryOrder { return getOrderingAttr(self.op); } pub fn getScope(self: AtomicAddOp) ?Scope { return getScopeAttr(self.op); } }; pub const AtomicMaxOp = struct { op: *ir.Operation, pub const operation_spec = op_specs.leaf(.{ .mnemonic = "atomic_max", .interfaces = &.{gpuEffects(.synchronize, &.{0}, &.{0})}, .operands = .{ "memref", "index", "value" }, .results = .{"old_value"}, }); pub const operation_name = operation_spec.name; pub fn create( ctx: *ir.Context, loc: ir.Location, memref: *ir.Value, index: *ir.Value, val: *ir.Value, ) !AtomicMaxOp { try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); var state = ir.Operation.State.init(operation_name, loc); state.addOperands(&.{ memref, index, val }); state.addTypes(&.{val.type}); const op = try builder.create(state); errdefer op.erase(); return .{ .op = op }; } pub fn getResult(self: *const AtomicMaxOp) *ir.Value { return self.op.getResult(0).?; } pub fn getMemref(self: AtomicMaxOp) *ir.Value { return self.op.operands.items[0].value; } pub fn getIndex(self: AtomicMaxOp) *ir.Value { return self.op.operands.items[1].value; } pub fn getVal(self: AtomicMaxOp) *ir.Value { return self.op.operands.items[2].value; } }; pub const AtomicCasOp = struct { op: *ir.Operation, pub const operation_spec = op_specs.leaf(.{ .mnemonic = "atomic_cas", .interfaces = &.{gpuEffects(.synchronize, &.{0}, &.{0})}, .operands = .{ "memref", "index", "expected", "desired" }, .results = .{"old_value"}, .attrs = &.{"scope"}, .required_attrs = &.{"ordering"}, }); pub const operation_name = operation_spec.name; pub fn create( ctx: *ir.Context, loc: ir.Location, memref: *ir.Value, index: *ir.Value, expected: *ir.Value, desired: *ir.Value, ordering: MemoryOrder, scope: ?Scope, ) !AtomicCasOp { try loadSpec(ctx); var builder = ir.OperationBuilder.init(ctx); var state = ir.Operation.State.init(operation_name, loc); state.addOperands(&.{ memref, index, expected, desired }); state.addTypes(&.{expected.type}); const op = try builder.create(state); errdefer op.erase(); try setOrderingAttr(op, ctx, ordering); if (scope) |scope_value| { try setScopeAttr(op, ctx, scope_value); } return .{ .op = op }; } pub fn getResult(self: *const AtomicCasOp) *ir.Value { return self.op.getResult(0).?; } pub fn getMemref(self: AtomicCasOp) *ir.Value { return self.op.operands.items[0].value; } pub fn getIndex(self: AtomicCasOp) *ir.Value { return self.op.operands.items[1].value; } pub fn getExpected(self: AtomicCasOp) *ir.Value { return self.op.operands.items[2].value; } pub fn getDesired(self: AtomicCasOp) *ir.Value { return self.op.operands.items[3].value; } pub fn getOrdering(self: AtomicCasOp) ?MemoryOrder { return getOrderingAttr(self.op); } pub fn getScope(self: AtomicCasOp) ?Scope { return getScopeAttr(self.op); } }; fn loadSpec(ctx: *ir.Context) !void { try ir.dialects.loadDialectSpec(ctx, spec); } fn dimIndexSpec(comptime mnemonic: []const u8) ir.dialects.OperationSpec { return op_specs.leaf(.{ .mnemonic = mnemonic, .interfaces = &.{gpuEffects(.state_observe, &.{}, &.{})}, .operands = 0, .results = .{"index"}, .required_attrs = &.{"dim"}, }); } fn indexSpec(comptime mnemonic: []const u8) ir.dialects.OperationSpec { return op_specs.leaf(.{ .mnemonic = mnemonic, .interfaces = &.{gpuEffects(.state_observe, &.{}, &.{})}, .operands = 0, .results = .{"index"}, }); } fn noResultSpec(comptime mnemonic: []const u8, comptime operands: anytype) ir.dialects.OperationSpec { return op_specs.leaf(.{ .mnemonic = mnemonic, .interfaces = &.{gpuEffects(.synchronize, &.{}, &.{})}, .operands = operands, .results = 0, }); } fn getFuncSymbolName(op_ptr: *const anyopaque) ?[]const u8 { const op: *const ir.Operation = @ptrCast(@alignCast(op_ptr)); if (op.getAttr("sym_name")) |attr| { return func.FuncDialect.getSymNameValue(attr); } return null; } fn setFuncSymbolName(op_ptr: *const anyopaque, symbol_name: []const u8) anyerror!void { const op: *ir.Operation = @ptrCast(@alignCast(@constCast(op_ptr))); try op.setAttr("sym_name", try func.FuncDialect.getSymNameAttr(op.getContext(), symbol_name)); } fn isFuncDeclaration(_: *const anyopaque) bool { return false; } pub fn getTmaDescriptorType(ctx: *ir.Context) !ir.Type { try loadSpec(ctx); return ctx.getDialectTypeFromName(type_names.tma_desc); } pub fn getMBarrierType(ctx: *ir.Context) !ir.Type { try loadSpec(ctx); return ctx.getDialectTypeFromName(type_names.mbarrier); } fn setDimensionAttr(op: *ir.Operation, ctx: *ir.Context, dim: Dimension) !void { const dim_attr = try ctx.getDialectAttr("gpu.dim", dim.toString()); try op.setAttr("dim", dim_attr); } fn getDimensionAttr(op: *const ir.Operation) ?Dimension { const dialect_attr = op.getAttrAs(ir.Attribute.DialectAttr, "dim") orelse return null; return Dimension.fromString(dialect_attr.payload); } fn setScopeAttr(op: *ir.Operation, ctx: *ir.Context, scope: Scope) !void { const scope_attr = try ctx.getDialectAttr("gpu.scope", scope.toString()); try op.setAttr("scope", scope_attr); } fn getScopeAttr(op: *const ir.Operation) ?Scope { const dialect_attr = op.getAttrAs(ir.Attribute.DialectAttr, "scope") orelse return null; return Scope.fromString(dialect_attr.payload); } fn setOrderingAttr(op: *ir.Operation, ctx: *ir.Context, ordering: MemoryOrder) !void { const order_attr = try ctx.getDialectAttr("gpu.ordering", ordering.toString()); try op.setAttr("ordering", order_attr); } fn getOrderingAttr(op: *const ir.Operation) ?MemoryOrder { const dialect_attr = op.getAttrAs(ir.Attribute.DialectAttr, "ordering") orelse return null; return MemoryOrder.fromString(dialect_attr.payload); } fn setBoolAttr(op: *ir.Operation, ctx: *ir.Context, attr_name: []const u8, value: bool) !void { const bool_attr = try ctx.getBoolAttr(value); try op.setAttr(attr_name, bool_attr); } fn getBoolAttrValue(op: *const ir.Operation, attr_name: []const u8) bool { const bool_attr = op.getAttrAs(ir.Attribute.BoolAttr, attr_name) orelse return false; return bool_attr.getValue(); } fn setI64Attr(op: *ir.Operation, ctx: *ir.Context, attr_name: []const u8, value: i64) !void { const int_attr = try ctx.getI64Attr(value); try op.setAttr(attr_name, int_attr); } fn getI64AttrValue(op: *const ir.Operation, attr_name: []const u8) ?i64 { const int_attr = op.getAttrAs(ir.Attribute.IntegerAttr, attr_name) orelse return null; return int_attr.getValue(); } fn setWarpOpAttr(op: *ir.Operation, ctx: *ir.Context, op_kind: WarpOpKind) !void { const op_attr = try ctx.getDialectAttr("gpu.warp_op", op_kind.toString()); try op.setAttr("op", op_attr); } fn getWarpOpAttr(op: *const ir.Operation) ?WarpOpKind { const dialect_attr = op.getAttrAs(ir.Attribute.DialectAttr, "op") orelse return null; return WarpOpKind.fromString(dialect_attr.payload); } fn setMmaShapeAttr(op: *ir.Operation, ctx: *ir.Context, shape: MmaShape) !void { var buf: [32]u8 = undefined; const shape_str = try shape.toString(buf[0..]); const shape_attr = try ctx.getDialectAttr("gpu.mma_shape", shape_str); try op.setAttr("shape", shape_attr); } fn getMmaShapeAttr(op: *const ir.Operation) ?MmaShape { const dialect_attr = op.getAttrAs(ir.Attribute.DialectAttr, "shape") orelse return null; return MmaShape.parse(dialect_attr.payload); }};Also reachable as
Complete caller list for dialects.gpu.GpuDialect.BarrierOp.create
7 direct callers.
lib.accy.src.kernel.model.core.builder.Builder.barrier[method] — private source atlib/accy/src/kernel/model/core/builder.zig:1360in nearest public ownerlib.accy.src.kernel.model.core.builderlib.choir.src.backends.gpu.nvptx.conversion.test_nvptx_conversion_lowers_gpu_idx_and_memref_ops[function] — test source atlib/choir/src/backends/gpu/nvptx/conversion.zig:546in nearest public ownertiny.choir.backends.gpu.nvptx.conversionlib.choir.src.backends.gpu.spirv.conversion.test_gpu_to_spirv_conversion_rewrites_gpu_+_arith_ops[function] — test source atlib/choir/src/backends/gpu/spirv/conversion.zig:431in nearest public ownertiny.choir.backends.gpu.spirv.conversionlib.choir.src.backends.gpu.spirv.emitter.codegen.test_spirv_codegen_handles_control_flow,_shared_alloc,_and_warp_ops[function] — test source atlib/choir/src/backends/gpu/spirv/emitter/codegen.zig:1505in nearest public ownertiny.choir.backends.gpu.spirv.emitter.codegenlib.choir.src.dialects.gpu.dialect.checkGpuFactoryAllocationFailures[function] — private source atlib/choir/src/dialects/gpu/dialect.zig:1792in nearest public ownertiny.choir.dialects.gpu.dialectlib.choir.src.dialects.gpu.dialect.test_GpuDialect.BarrierOp_creates_barrier[function] — test source atlib/choir/src/dialects/gpu/dialect.zig:2200in nearest public ownertiny.choir.dialects.gpu.dialectlib.choir.src.dialects.gpu.dialect.test_gpu_effect_declarations_retain_participant_observations_and_collective_ordering[function] — test source atlib/choir/src/dialects/gpu/dialect.zig:2698in nearest public ownertiny.choir.dialects.gpu.dialect
Complete caller list for dialects.gpu.GpuDialect.GlobalIdxOp.create
26 direct callers.
lib.accy.src.kernel.model.core.builder.Builder.globalId[method] — private source atlib/accy/src/kernel/model/core/builder.zig:885in nearest public ownerlib.accy.src.kernel.model.core.builderlib.choir.src.backends.gpu.nvptx.conversion.test_nvptx_conversion_lowers_gpu_idx_and_memref_ops[function] — test source atlib/choir/src/backends/gpu/nvptx/conversion.zig:546in nearest public ownertiny.choir.backends.gpu.nvptx.conversionlib.choir.src.backends.gpu.spirv.emitter.codegen.buildVecAddKernelJob[function] — private source atlib/choir/src/backends/gpu/spirv/emitter/codegen.zig:3293in nearest public ownertiny.choir.backends.gpu.spirv.emitter.codegenlib.choir.src.backends.gpu.spirv.emitter.codegen.emitArithKernelWordsWithControls[function] — private source atlib/choir/src/backends/gpu/spirv/emitter/codegen.zig:1906in nearest public ownertiny.choir.backends.gpu.spirv.emitter.codegenlib.choir.src.backends.gpu.spirv.emitter.codegen.emitMinMaxKernel[function] — private source atlib/choir/src/backends/gpu/spirv/emitter/codegen.zig:2950in nearest public ownertiny.choir.backends.gpu.spirv.emitter.codegenlib.choir.src.backends.gpu.spirv.emitter.codegen.test_spirv_codegen_aliases_same-kind_arith.bitcast_(no_OpBitcast_emission)[function] — test source atlib/choir/src/backends/gpu/spirv/emitter/codegen.zig:2775in nearest public ownertiny.choir.backends.gpu.spirv.emitter.codegenlib.choir.src.backends.gpu.spirv.emitter.codegen.test_spirv_codegen_emits_OpBitcast_for_arith.bitcast_i32_->_f32_(different_kinds,_same_width)[function] — test source atlib/choir/src/backends/gpu/spirv/emitter/codegen.zig:2738in nearest public ownertiny.choir.backends.gpu.spirv.emitter.codegenlib.choir.src.backends.gpu.spirv.emitter.codegen.test_spirv_codegen_emits_OpConvertUToF_for_arith.cast_index_→_f32_(iota_lowering_shape)[function] — test source atlib/choir/src/backends/gpu/spirv/emitter/codegen.zig:2705in nearest public ownertiny.choir.backends.gpu.spirv.emitter.codegenlib.choir.src.backends.gpu.spirv.emitter.codegen.test_spirv_codegen_emits_arith.pow_and_arith.atan2_as_binary_OpExtInst[function] — test source atlib/choir/src/backends/gpu/spirv/emitter/codegen.zig:2417in nearest public ownertiny.choir.backends.gpu.spirv.emitter.codegenlib.choir.src.backends.gpu.spirv.emitter.codegen.test_spirv_codegen_emits_arith_comparison_opcode_families[function] — test source atlib/choir/src/backends/gpu/spirv/emitter/codegen.zig:1634in nearest public ownertiny.choir.backends.gpu.spirv.emitter.codegenlib.choir.src.backends.gpu.spirv.emitter.codegen.test_spirv_codegen_emits_memref_integer_atomics[function] — test source atlib/choir/src/backends/gpu/spirv/emitter/codegen.zig:1286in nearest public ownertiny.choir.backends.gpu.spirv.emitter.codegenlib.choir.src.backends.gpu.spirv.emitter.codegen.test_spirv_codegen_emits_minimal_header_and_entry_point[function] — test source atlib/choir/src/backends/gpu/spirv/emitter/codegen.zig:1192in nearest public ownertiny.choir.backends.gpu.spirv.emitter.codegenlib.choir.src.backends.gpu.spirv.emitter.codegen.test_spirv_codegen_lowers_scalar_arguments_to_one_push_constant_block[function] — test source atlib/choir/src/backends/gpu/spirv/emitter/codegen.zig:2998in nearest public ownertiny.choir.backends.gpu.spirv.emitter.codegenlib.choir.src.backends.gpu.spirv.emitter.codegen.test_spirv_codegen_rejects_arith.and_over_float_(bitwise_needs_arith.bitcast_first)[function] — test source atlib/choir/src/backends/gpu/spirv/emitter/codegen.zig:2619in nearest public ownertiny.choir.backends.gpu.spirv.emitter.codegenlib.choir.src.backends.gpu.spirv.emitter.codegen.test_spirv_codegen_rejects_arith.bitcast_over_arith.bool[function] — test source atlib/choir/src/backends/gpu/spirv/emitter/codegen.zig:2810in nearest public ownertiny.choir.backends.gpu.spirv.emitter.codegenlib.choir.src.backends.gpu.spirv.emitter.codegen.test_spirv_codegen_rejects_arith.exp_on_f64_(GLSL.std.450_requires_16/32-bit)[function] — test source atlib/choir/src/backends/gpu/spirv/emitter/codegen.zig:2123in nearest public ownertiny.choir.backends.gpu.spirv.emitter.codegenlib.choir.src.backends.gpu.spirv.emitter.codegen.test_spirv_codegen_rejects_arith.fma_over_integer_types[function] — test source atlib/choir/src/backends/gpu/spirv/emitter/codegen.zig:2880in nearest public ownertiny.choir.backends.gpu.spirv.emitter.codegenlib.choir.src.backends.gpu.spirv.emitter.codegen.test_spirv_codegen_rejects_arith.pow_on_f64[function] — test source atlib/choir/src/backends/gpu/spirv/emitter/codegen.zig:2463in nearest public ownertiny.choir.backends.gpu.spirv.emitter.codegenlib.choir.src.backends.gpu.spirv.emitter.codegen.test_spirv_codegen_rejects_arith.shl_with_width-mismatched_shift_count_(cross-backend_strict-equality_policy)[function] — test source atlib/choir/src/backends/gpu/spirv/emitter/codegen.zig:2653in nearest public ownertiny.choir.backends.gpu.spirv.emitter.codegenlib.choir.src.backends.gpu.spirv.emitter.codegen.test_spirv_codegen_rejects_arith.shr_over_arith.index_(unsigned_+_arithmetic_shift_mismatch)[function] — test source atlib/choir/src/backends/gpu/spirv/emitter/codegen.zig:2585in nearest public ownertiny.choir.backends.gpu.spirv.emitter.codegenlib.choir.src.backends.gpu.spirv.emitter.codegen.test_spirv_codegen_rejects_arith.sin_on_f64[function] — test source atlib/choir/src/backends/gpu/spirv/emitter/codegen.zig:2386in nearest public ownertiny.choir.backends.gpu.spirv.emitter.codegenlib.choir.src.backends.gpu.spirv.emitter.codegen.test_spirv_codegen_rejects_memref_f32_atomic_add_without_extension_support[function] — test source atlib/choir/src/backends/gpu/spirv/emitter/codegen.zig:1407in nearest public ownertiny.choir.backends.gpu.spirv.emitter.codegenlib.choir.src.backends.gpu.spirv.emitter.codegen.test_spirv_codegen_rejects_width-mismatched_arith.bitcast_(i32_->_f64)[function] — test source atlib/choir/src/backends/gpu/spirv/emitter/codegen.zig:2916in nearest public ownertiny.choir.backends.gpu.spirv.emitter.codegenlib.choir.src.backends.gpu.spirv.emitter.codegen.test_spirv_codegen_stores_bool_memrefs_as_byte_runtime_arrays[function] — test source atlib/choir/src/backends/gpu/spirv/emitter/codegen.zig:1240in nearest public ownertiny.choir.backends.gpu.spirv.emitter.codegenlib.choir.src.dialects.gpu.dialect.checkGpuFactoryAllocationFailures[function] — private source atlib/choir/src/dialects/gpu/dialect.zig:1792in nearest public ownertiny.choir.dialects.gpu.dialectlib.choir.src.dialects.gpu.dialect.test_GpuDialect.GlobalIdxOp_creates_global_index[function] — test source atlib/choir/src/dialects/gpu/dialect.zig:2525in nearest public ownertiny.choir.dialects.gpu.dialect
Complete caller list for dialects.gpu.GpuDialect.ThreadIdxOp.create
7 direct callers.
lib.accy.src.kernel.model.core.builder.Builder.threadId[method] — private source atlib/accy/src/kernel/model/core/builder.zig:892in nearest public ownerlib.accy.src.kernel.model.core.builderlib.choir.src.backends.gpu.spirv.conversion.test_gpu_to_spirv_conversion_rewrites_gpu_+_arith_ops[function] — test source atlib/choir/src/backends/gpu/spirv/conversion.zig:431in nearest public ownertiny.choir.backends.gpu.spirv.conversionlib.choir.src.backends.gpu.spirv.conversion.test_spirv_backend_emits_after_gpu-to-spirv_conversion[function] — test source atlib/choir/src/backends/gpu/spirv/conversion.zig:501in nearest public ownertiny.choir.backends.gpu.spirv.conversionlib.choir.src.backends.gpu.spirv.emitter.codegen.buildReductionKernelJob[function] — private source atlib/choir/src/backends/gpu/spirv/emitter/codegen.zig:3334in nearest public ownertiny.choir.backends.gpu.spirv.emitter.codegenlib.choir.src.backends.gpu.spirv.emitter.codegen.test_spirv_codegen_handles_control_flow,_shared_alloc,_and_warp_ops[function] — test source atlib/choir/src/backends/gpu/spirv/emitter/codegen.zig:1505in nearest public ownertiny.choir.backends.gpu.spirv.emitter.codegenlib.choir.src.dialects.gpu.dialect.checkGpuFactoryAllocationFailures[function] — private source atlib/choir/src/dialects/gpu/dialect.zig:1792in nearest public ownertiny.choir.dialects.gpu.dialectlib.choir.src.dialects.gpu.dialect.test_GpuDialect.ThreadIdxOp_creates_thread_index[function] — test source atlib/choir/src/dialects/gpu/dialect.zig:2166in nearest public ownertiny.choir.dialects.gpu.dialect
Audit
| Definitions | 283 |
|---|---|
| Public names | 566 |
| Members | 37 |
| Version | 26.7.0 |
| Revision | daab053ee433 |