Commit b63d9745b5

Jacob Young <jacobly0@users.noreply.github.com>
2023-08-06 13:16:39
llvm: convert intrinsics to using `Builder`
1 parent 3ebf8ce
src/codegen/llvm/bindings.zig
@@ -345,9 +345,6 @@ pub const Value = opaque {
     pub const addSretAttr = ZigLLVMAddSretAttr;
     extern fn ZigLLVMAddSretAttr(fn_ref: *Value, type_val: *Type) void;
 
-    pub const setCallSret = ZigLLVMSetCallSret;
-    extern fn ZigLLVMSetCallSret(Call: *Value, return_type: *Type) void;
-
     pub const getParam = LLVMGetParam;
     extern fn LLVMGetParam(Fn: *Value, Index: c_uint) *Value;
 
@@ -488,9 +485,6 @@ pub const Module = opaque {
     pub const getNamedFunction = LLVMGetNamedFunction;
     extern fn LLVMGetNamedFunction(*Module, Name: [*:0]const u8) ?*Value;
 
-    pub const getIntrinsicDeclaration = LLVMGetIntrinsicDeclaration;
-    extern fn LLVMGetIntrinsicDeclaration(Mod: *Module, ID: c_uint, ParamTypes: ?[*]const *Type, ParamCount: usize) *Value;
-
     pub const printToString = LLVMPrintModuleToString;
     extern fn LLVMPrintModuleToString(*Module) [*:0]const u8;
 
@@ -664,18 +658,6 @@ pub const Builder = opaque {
         Name: [*:0]const u8,
     ) *Value;
 
-    pub const buildCallOld = ZigLLVMBuildCall;
-    extern fn ZigLLVMBuildCall(
-        *Builder,
-        *Type,
-        Fn: *Value,
-        Args: [*]const *Value,
-        NumArgs: c_uint,
-        CC: CallConv,
-        attr: CallAttr,
-        Name: [*:0]const u8,
-    ) *Value;
-
     pub const buildRetVoid = LLVMBuildRetVoid;
     extern fn LLVMBuildRetVoid(*Builder) *Value;
 
@@ -712,12 +694,6 @@ pub const Builder = opaque {
     pub const buildNUWAdd = LLVMBuildNUWAdd;
     extern fn LLVMBuildNUWAdd(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
 
-    pub const buildSAddSat = ZigLLVMBuildSAddSat;
-    extern fn ZigLLVMBuildSAddSat(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
-
-    pub const buildUAddSat = ZigLLVMBuildUAddSat;
-    extern fn ZigLLVMBuildUAddSat(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
-
     pub const buildFSub = LLVMBuildFSub;
     extern fn LLVMBuildFSub(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
 
@@ -733,12 +709,6 @@ pub const Builder = opaque {
     pub const buildNUWSub = LLVMBuildNUWSub;
     extern fn LLVMBuildNUWSub(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
 
-    pub const buildSSubSat = ZigLLVMBuildSSubSat;
-    extern fn ZigLLVMBuildSSubSat(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
-
-    pub const buildUSubSat = ZigLLVMBuildUSubSat;
-    extern fn ZigLLVMBuildUSubSat(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
-
     pub const buildFMul = LLVMBuildFMul;
     extern fn LLVMBuildFMul(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
 
@@ -751,12 +721,6 @@ pub const Builder = opaque {
     pub const buildNUWMul = LLVMBuildNUWMul;
     extern fn LLVMBuildNUWMul(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
 
-    pub const buildSMulFixSat = ZigLLVMBuildSMulFixSat;
-    extern fn ZigLLVMBuildSMulFixSat(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
-
-    pub const buildUMulFixSat = ZigLLVMBuildUMulFixSat;
-    extern fn ZigLLVMBuildUMulFixSat(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
-
     pub const buildUDiv = LLVMBuildUDiv;
     extern fn LLVMBuildUDiv(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
 
@@ -799,21 +763,12 @@ pub const Builder = opaque {
     pub const buildNSWShl = ZigLLVMBuildNSWShl;
     extern fn ZigLLVMBuildNSWShl(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
 
-    pub const buildSShlSat = ZigLLVMBuildSShlSat;
-    extern fn ZigLLVMBuildSShlSat(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
-
-    pub const buildUShlSat = ZigLLVMBuildUShlSat;
-    extern fn ZigLLVMBuildUShlSat(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
-
     pub const buildOr = LLVMBuildOr;
     extern fn LLVMBuildOr(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
 
     pub const buildXor = LLVMBuildXor;
     extern fn LLVMBuildXor(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
 
-    pub const buildIntCast2 = LLVMBuildIntCast2;
-    extern fn LLVMBuildIntCast2(*Builder, Val: *Value, DestTy: *Type, IsSigned: Bool, Name: [*:0]const u8) *Value;
-
     pub const buildBitCast = LLVMBuildBitCast;
     extern fn LLVMBuildBitCast(*Builder, Val: *Value, DestTy: *Type, Name: [*:0]const u8) *Value;
 
@@ -1020,81 +975,6 @@ pub const Builder = opaque {
         is_volatile: bool,
     ) *Value;
 
-    pub const buildMaxNum = ZigLLVMBuildMaxNum;
-    extern fn ZigLLVMBuildMaxNum(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value;
-
-    pub const buildMinNum = ZigLLVMBuildMinNum;
-    extern fn ZigLLVMBuildMinNum(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value;
-
-    pub const buildCeil = ZigLLVMBuildCeil;
-    extern fn ZigLLVMBuildCeil(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
-
-    pub const buildCos = ZigLLVMBuildCos;
-    extern fn ZigLLVMBuildCos(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
-
-    pub const buildExp = ZigLLVMBuildExp;
-    extern fn ZigLLVMBuildExp(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
-
-    pub const buildExp2 = ZigLLVMBuildExp2;
-    extern fn ZigLLVMBuildExp2(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
-
-    pub const buildFAbs = ZigLLVMBuildFAbs;
-    extern fn ZigLLVMBuildFAbs(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
-
-    pub const buildFloor = ZigLLVMBuildFloor;
-    extern fn ZigLLVMBuildFloor(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
-
-    pub const buildLog = ZigLLVMBuildLog;
-    extern fn ZigLLVMBuildLog(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
-
-    pub const buildLog10 = ZigLLVMBuildLog10;
-    extern fn ZigLLVMBuildLog10(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
-
-    pub const buildLog2 = ZigLLVMBuildLog2;
-    extern fn ZigLLVMBuildLog2(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
-
-    pub const buildRound = ZigLLVMBuildRound;
-    extern fn ZigLLVMBuildRound(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
-
-    pub const buildSin = ZigLLVMBuildSin;
-    extern fn ZigLLVMBuildSin(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
-
-    pub const buildSqrt = ZigLLVMBuildSqrt;
-    extern fn ZigLLVMBuildSqrt(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
-
-    pub const buildFTrunc = ZigLLVMBuildFTrunc;
-    extern fn ZigLLVMBuildFTrunc(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
-
-    pub const buildBitReverse = ZigLLVMBuildBitReverse;
-    extern fn ZigLLVMBuildBitReverse(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
-
-    pub const buildBSwap = ZigLLVMBuildBSwap;
-    extern fn ZigLLVMBuildBSwap(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
-
-    pub const buildCTPop = ZigLLVMBuildCTPop;
-    extern fn ZigLLVMBuildCTPop(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
-
-    pub const buildCTLZ = ZigLLVMBuildCTLZ;
-    extern fn ZigLLVMBuildCTLZ(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value;
-
-    pub const buildCTTZ = ZigLLVMBuildCTTZ;
-    extern fn ZigLLVMBuildCTTZ(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value;
-
-    pub const buildFMA = ZigLLVMBuildFMA;
-    extern fn ZigLLVMBuildFMA(builder: *Builder, a: *Value, b: *Value, c: *Value, name: [*:0]const u8) *Value;
-
-    pub const buildUMax = ZigLLVMBuildUMax;
-    extern fn ZigLLVMBuildUMax(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value;
-
-    pub const buildUMin = ZigLLVMBuildUMin;
-    extern fn ZigLLVMBuildUMin(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value;
-
-    pub const buildSMax = ZigLLVMBuildSMax;
-    extern fn ZigLLVMBuildSMax(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value;
-
-    pub const buildSMin = ZigLLVMBuildSMin;
-    extern fn ZigLLVMBuildSMin(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value;
-
     pub const buildExactUDiv = LLVMBuildExactUDiv;
     extern fn LLVMBuildExactUDiv(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
 
@@ -1563,9 +1443,6 @@ extern fn ZigLLVMWriteImportLibrary(
     kill_at: bool,
 ) bool;
 
-pub const setCallElemTypeAttr = ZigLLVMSetCallElemTypeAttr;
-extern fn ZigLLVMSetCallElemTypeAttr(Call: *Value, arg_index: usize, return_type: *Type) void;
-
 pub const Linkage = enum(c_uint) {
     External,
     AvailableExternally,
@@ -1784,9 +1661,6 @@ pub const DIGlobalVariable = opaque {
 pub const DIGlobalVariableExpression = opaque {
     pub const getVariable = ZigLLVMGlobalGetVariable;
     extern fn ZigLLVMGlobalGetVariable(global_variable: *DIGlobalVariableExpression) *DIGlobalVariable;
-
-    pub const getExpression = ZigLLVMGlobalGetExpression;
-    extern fn ZigLLVMGlobalGetExpression(global_variable: *DIGlobalVariableExpression) *DIGlobalExpression;
 };
 pub const DIType = opaque {
     pub const toScope = ZigLLVMTypeToScope;
src/codegen/llvm/Builder.zig
@@ -50,10 +50,12 @@ constant_extra: std.ArrayListUnmanaged(u32),
 constant_limbs: std.ArrayListUnmanaged(std.math.big.Limb),
 
 pub const expected_args_len = 16;
+pub const expected_attrs_len = 16;
 pub const expected_fields_len = 32;
 pub const expected_gep_indices_len = 8;
 pub const expected_cases_len = 8;
 pub const expected_incoming_len = 8;
+pub const expected_intrinsic_name_len = 64;
 
 pub const Options = struct {
     allocator: Allocator,
@@ -151,11 +153,14 @@ pub const Type = enum(u32) {
     i80,
     i128,
     ptr,
+    @"ptr addrspace(4)",
 
     none = std.math.maxInt(u32),
     _,
 
     pub const err_int = Type.i16;
+    pub const ptr_amdgpu_constant =
+        @field(Type, std.fmt.comptimePrint("ptr{ }", .{AddrSpace.amdgpu.constant}));
 
     pub const Tag = enum(u4) {
         simple,
@@ -391,7 +396,7 @@ pub const Type = enum(u32) {
             .double, .i64, .x86_mmx => 64,
             .x86_fp80, .i80 => 80,
             .fp128, .ppc_fp128, .i128 => 128,
-            .ptr => @panic("TODO: query data layout"),
+            .ptr, .@"ptr addrspace(4)" => @panic("TODO: query data layout"),
             _ => {
                 const item = builder.type_items.items[@intFromEnum(self)];
                 return switch (item.tag) {
@@ -690,7 +695,7 @@ pub const Type = enum(u32) {
                 }
             },
             .integer => try writer.print("i{d}", .{item.data}),
-            .pointer => try writer.print("ptr{}", .{@as(AddrSpace, @enumFromInt(item.data))}),
+            .pointer => try writer.print("ptr{ }", .{@as(AddrSpace, @enumFromInt(item.data))}),
             .target => {
                 var extra = data.builder.typeExtraDataTrail(Type.Target, item.data);
                 const types = extra.trail.next(extra.data.types_len, Type, data.builder);
@@ -795,6 +800,7 @@ pub const Type = enum(u32) {
             .i80,
             .i128,
             .ptr,
+            .@"ptr addrspace(4)",
             => true,
             .none => unreachable,
             _ => {
@@ -1201,12 +1207,20 @@ pub const Attribute = union(Kind) {
                         try writer.print(",{d}", .{allocsize.num_elems});
                     try writer.writeByte(')');
                 },
-                .memory => |memory| try writer.print(" {s}({s}, argmem: {s}, inaccessiblemem: {s})", .{
-                    @tagName(attribute),
-                    @tagName(memory.other),
-                    @tagName(memory.argmem),
-                    @tagName(memory.inaccessiblemem),
-                }),
+                .memory => |memory| {
+                    try writer.print(" {s}(", .{@tagName(attribute)});
+                    var any = memory.other != .none or
+                        (memory.argmem == .none and memory.inaccessiblemem == .none);
+                    if (any) try writer.writeAll(@tagName(memory.other));
+                    inline for (.{ "argmem", "inaccessiblemem" }) |kind| {
+                        if (@field(memory, kind) != memory.other) {
+                            if (any) try writer.writeAll(", ");
+                            try writer.print("{s}: {s}", .{ kind, @tagName(@field(memory, kind)) });
+                            any = true;
+                        }
+                    }
+                    try writer.writeByte(')');
+                },
                 .uwtable => |uwtable| if (uwtable != .none) {
                     try writer.print(" {s}", .{@tagName(attribute)});
                     if (uwtable != UwTable.default) try writer.print("({s})", .{@tagName(uwtable)});
@@ -1424,12 +1438,16 @@ pub const Attribute = union(Kind) {
     };
 
     pub const Memory = packed struct(u32) {
-        argmem: Effect,
-        inaccessiblemem: Effect,
-        other: Effect,
+        argmem: Effect = .none,
+        inaccessiblemem: Effect = .none,
+        other: Effect = .none,
         _: u26 = 0,
 
         pub const Effect = enum(u2) { none, read, write, readwrite };
+
+        fn all(effect: Effect) Memory {
+            return .{ .argmem = effect, .inaccessiblemem = effect, .other = effect };
+        }
     };
 
     pub const UwTable = enum(u32) {
@@ -2279,6 +2297,820 @@ pub const Variable = struct {
     };
 };
 
+pub const Intrinsic = enum {
+    // Variable Argument Handling
+    va_start,
+    va_end,
+    va_copy,
+
+    // Code Generator
+    returnaddress,
+    addressofreturnaddress,
+    sponentry,
+    frameaddress,
+    prefetch,
+    @"thread.pointer",
+
+    // Standard C/C++ Library
+    abs,
+    smax,
+    smin,
+    umax,
+    umin,
+    memcpy,
+    @"memcpy.inline",
+    memmove,
+    memset,
+    @"memset.inline",
+    sqrt,
+    powi,
+    sin,
+    cos,
+    pow,
+    exp,
+    exp2,
+    ldexp,
+    frexp,
+    log,
+    log10,
+    log2,
+    fma,
+    fabs,
+    minnum,
+    maxnum,
+    minimum,
+    maximum,
+    copysign,
+    floor,
+    ceil,
+    trunc,
+    rint,
+    nearbyint,
+    round,
+    roundeven,
+    lround,
+    llround,
+    lrint,
+    llrint,
+
+    // Bit Manipulation
+    bitreverse,
+    bswap,
+    ctpop,
+    ctlz,
+    cttz,
+    fshl,
+    fshr,
+
+    // Arithmetic with Overflow
+    @"sadd.with.overflow",
+    @"uadd.with.overflow",
+    @"ssub.with.overflow",
+    @"usub.with.overflow",
+    @"smul.with.overflow",
+    @"umul.with.overflow",
+
+    // Saturation Arithmetic
+    @"sadd.sat",
+    @"uadd.sat",
+    @"ssub.sat",
+    @"usub.sat",
+    @"sshl.sat",
+    @"ushl.sat",
+
+    // Fixed Point Arithmetic
+    @"smul.fix",
+    @"umul.fix",
+    @"smul.fix.sat",
+    @"umul.fix.sat",
+    @"sdiv.fix",
+    @"udiv.fix",
+    @"sdiv.fix.sat",
+    @"udiv.fix.sat",
+
+    // Specialised Arithmetic
+    canonicalisze,
+    fmuladd,
+
+    // Vector Reduction
+    @"vector.reduce.add",
+    @"vector.reduce.fadd",
+    @"vector.reduce.mul",
+    @"vector.reduce.fmul",
+    @"vector.reduce.and",
+    @"vector.reduce.or",
+    @"vector.reduce.xor",
+    @"vector.reduce.smax",
+    @"vector.reduce.smin",
+    @"vector.reduce.umax",
+    @"vector.reduce.umin",
+    @"vector.reduce.fmax",
+    @"vector.reduce.fmin",
+    @"vector.reduce.fmaximum",
+    @"vector.reduce.fminimum",
+    @"vector.reduce.insert",
+    @"vector.reduce.extract",
+    @"vector.insert",
+    @"vector.extract",
+
+    // General
+    @"llvm.var.annotation",
+    @"llvm.ptr.annotation",
+    annotation,
+    @"codeview.annotation",
+    trap,
+    debugtrap,
+    ubsantrap,
+    stackprotector,
+    stackguard,
+    objectsize,
+    expect,
+    @"expect.with.probability",
+    assume,
+    @"ssa.copy",
+    @"type.test",
+    @"type.checked.load",
+    @"type.checked.load.relative",
+    @"arithmetic.fence",
+    donothing,
+    @"load.relative",
+    @"llvm.sideeffect",
+    @"is.constant",
+    ptrmask,
+    @"threadlocal.address",
+    vscale,
+
+    // AMDGPU
+    @"amdgcn.workitem.id.x",
+    @"amdgcn.workitem.id.y",
+    @"amdgcn.workitem.id.z",
+    @"amdgcn.workgroup.id.x",
+    @"amdgcn.workgroup.id.y",
+    @"amdgcn.workgroup.id.z",
+    @"amdgcn.dispatch.ptr",
+
+    // WebAssembly
+    @"wasm.memory.size",
+    @"wasm.memory.grow",
+
+    const Signature = struct {
+        params: []const Parameter = &.{},
+        attrs: []const Attribute = &.{},
+
+        const Parameter = struct {
+            kind: Kind,
+            attrs: []const Attribute = &.{},
+
+            const Kind = union(enum) {
+                type: Type,
+                overloaded,
+                overloaded_tuple: u8,
+                matches: u8,
+                matches_tuple: packed struct { param: u4, field: u4 },
+                matches_with_overflow: u8,
+            };
+        };
+    };
+
+    const signatures = std.enums.EnumArray(Intrinsic, Signature).initDefault(.{}, .{
+        .va_start = .{
+            .params = &.{
+                .{ .kind = .{ .type = .void } },
+                .{ .kind = .{ .type = .ptr } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn },
+        },
+        .va_end = .{
+            .params = &.{
+                .{ .kind = .{ .type = .void } },
+                .{ .kind = .{ .type = .ptr } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn },
+        },
+        .va_copy = .{
+            .params = &.{
+                .{ .kind = .{ .type = .void } },
+                .{ .kind = .{ .type = .ptr } },
+                .{ .kind = .{ .type = .ptr } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn },
+        },
+
+        .returnaddress = .{
+            .params = &.{
+                .{ .kind = .{ .type = .ptr } },
+                .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .addressofreturnaddress = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .sponentry = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .frameaddress = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .prefetch = .{
+            .params = &.{
+                .{ .kind = .{ .type = .void } },
+                .{ .kind = .overloaded, .attrs = &.{ .nocapture, .readonly } },
+                .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
+                .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
+                .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.readwrite) } },
+        },
+        .@"thread.pointer" = .{
+            .params = &.{
+                .{ .kind = .{ .type = .ptr } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+
+        .abs = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .smax = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .smin = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .umax = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .umin = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .sqrt = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .powi = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .overloaded },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .sin = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .cos = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .pow = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .exp = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .exp2 = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .ldexp = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .overloaded },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .frexp = .{
+            .params = &.{
+                .{ .kind = .{ .overloaded_tuple = 2 } },
+                .{ .kind = .{ .matches_tuple = .{ .param = 0, .field = 0 } } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .log = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .log10 = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .log2 = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .fma = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .fabs = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .minnum = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .maxnum = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .minimum = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .maximum = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .copysign = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .floor = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .ceil = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .trunc = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .rint = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .nearbyint = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .round = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .roundeven = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .lround = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .overloaded },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .llround = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .overloaded },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .lrint = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .overloaded },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .llrint = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .overloaded },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+
+        .bitreverse = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .bswap = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .ctpop = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .ctlz = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .type = .i1 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .cttz = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .type = .i1 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .fshl = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .fshr = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+
+        .@"sadd.with.overflow" = .{
+            .params = &.{
+                .{ .kind = .{ .matches_with_overflow = 1 } },
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 1 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .@"uadd.with.overflow" = .{
+            .params = &.{
+                .{ .kind = .{ .matches_with_overflow = 1 } },
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 1 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .@"ssub.with.overflow" = .{
+            .params = &.{
+                .{ .kind = .{ .matches_with_overflow = 1 } },
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 1 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .@"usub.with.overflow" = .{
+            .params = &.{
+                .{ .kind = .{ .matches_with_overflow = 1 } },
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 1 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .@"smul.with.overflow" = .{
+            .params = &.{
+                .{ .kind = .{ .matches_with_overflow = 1 } },
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 1 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .@"umul.with.overflow" = .{
+            .params = &.{
+                .{ .kind = .{ .matches_with_overflow = 1 } },
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 1 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+
+        .@"sadd.sat" = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .@"uadd.sat" = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .@"ssub.sat" = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .@"usub.sat" = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .@"sshl.sat" = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .@"ushl.sat" = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+
+        .@"smul.fix" = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .@"umul.fix" = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .@"smul.fix.sat" = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .@"umul.fix.sat" = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .@"sdiv.fix" = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .@"udiv.fix" = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .@"sdiv.fix.sat" = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .@"udiv.fix.sat" = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .matches = 0 } },
+                .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+
+        .trap = .{
+            .params = &.{
+                .{ .kind = .{ .type = .void } },
+            },
+            .attrs = &.{ .cold, .noreturn, .nounwind, .{ .memory = .{ .inaccessiblemem = .write } } },
+        },
+        .debugtrap = .{
+            .params = &.{
+                .{ .kind = .{ .type = .void } },
+            },
+            .attrs = &.{.nounwind},
+        },
+        .ubsantrap = .{
+            .params = &.{
+                .{ .kind = .{ .type = .void } },
+                .{ .kind = .{ .type = .i8 }, .attrs = &.{.immarg} },
+            },
+            .attrs = &.{ .cold, .noreturn, .nounwind },
+        },
+
+        .@"amdgcn.workitem.id.x" = .{
+            .params = &.{
+                .{ .kind = .{ .type = .i32 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .@"amdgcn.workitem.id.y" = .{
+            .params = &.{
+                .{ .kind = .{ .type = .i32 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .@"amdgcn.workitem.id.z" = .{
+            .params = &.{
+                .{ .kind = .{ .type = .i32 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .@"amdgcn.workgroup.id.x" = .{
+            .params = &.{
+                .{ .kind = .{ .type = .i32 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .@"amdgcn.workgroup.id.y" = .{
+            .params = &.{
+                .{ .kind = .{ .type = .i32 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .@"amdgcn.workgroup.id.z" = .{
+            .params = &.{
+                .{ .kind = .{ .type = .i32 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .@"amdgcn.dispatch.ptr" = .{
+            .params = &.{
+                .{
+                    .kind = .{ .type = Type.ptr_amdgpu_constant },
+                    .attrs = &.{.{ .@"align" = Builder.Alignment.fromByteUnits(4) }},
+                },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+
+        .@"wasm.memory.size" = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .type = .i32 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
+        },
+        .@"wasm.memory.grow" = .{
+            .params = &.{
+                .{ .kind = .overloaded },
+                .{ .kind = .{ .type = .i32 } },
+                .{ .kind = .{ .matches = 0 } },
+            },
+            .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn },
+        },
+    });
+};
+
 pub const Function = struct {
     global: Global.Index,
     call_conv: CallConv = CallConv.default,
@@ -2414,39 +3246,6 @@ pub const Function = struct {
             insertelement,
             insertvalue,
             inttoptr,
-            @"llvm.maxnum.",
-            @"llvm.minnum.",
-            @"llvm.ceil.",
-            @"llvm.cos.",
-            @"llvm.exp.",
-            @"llvm.exp2.",
-            @"llvm.fabs.",
-            @"llvm.floor.",
-            @"llvm.log.",
-            @"llvm.log10.",
-            @"llvm.log2.",
-            @"llvm.round.",
-            @"llvm.sin.",
-            @"llvm.sqrt.",
-            @"llvm.trunc.",
-            @"llvm.fma.",
-            @"llvm.bitreverse.",
-            @"llvm.bswap.",
-            @"llvm.ctpop.",
-            @"llvm.ctlz.",
-            @"llvm.cttz.",
-            @"llvm.sadd.sat.",
-            @"llvm.smax.",
-            @"llvm.smin.",
-            @"llvm.smul.fix.sat.",
-            @"llvm.sshl.sat.",
-            @"llvm.ssub.sat.",
-            @"llvm.uadd.sat.",
-            @"llvm.umax.",
-            @"llvm.umin.",
-            @"llvm.umul.fix.sat.",
-            @"llvm.ushl.sat.",
-            @"llvm.usub.sat.",
             load,
             @"load atomic",
             @"load atomic volatile",
@@ -2575,22 +3374,6 @@ pub const Function = struct {
                     .@"frem fast",
                     .fsub,
                     .@"fsub fast",
-                    .@"llvm.maxnum.",
-                    .@"llvm.minnum.",
-                    .@"llvm.ctlz.",
-                    .@"llvm.cttz.",
-                    .@"llvm.sadd.sat.",
-                    .@"llvm.smax.",
-                    .@"llvm.smin.",
-                    .@"llvm.smul.fix.sat.",
-                    .@"llvm.sshl.sat.",
-                    .@"llvm.ssub.sat.",
-                    .@"llvm.uadd.sat.",
-                    .@"llvm.umax.",
-                    .@"llvm.umin.",
-                    .@"llvm.umul.fix.sat.",
-                    .@"llvm.ushl.sat.",
-                    .@"llvm.usub.sat.",
                     .lshr,
                     .@"lshr exact",
                     .mul,
@@ -2710,22 +3493,6 @@ pub const Function = struct {
                         .changeScalarAssumeCapacity(.i1, wip.builder),
                     .fneg,
                     .@"fneg fast",
-                    .@"llvm.ceil.",
-                    .@"llvm.cos.",
-                    .@"llvm.exp.",
-                    .@"llvm.exp2.",
-                    .@"llvm.fabs.",
-                    .@"llvm.floor.",
-                    .@"llvm.log.",
-                    .@"llvm.log10.",
-                    .@"llvm.log2.",
-                    .@"llvm.round.",
-                    .@"llvm.sin.",
-                    .@"llvm.sqrt.",
-                    .@"llvm.trunc.",
-                    .@"llvm.bitreverse.",
-                    .@"llvm.bswap.",
-                    .@"llvm.ctpop.",
                     => @as(Value, @enumFromInt(instruction.data)).typeOfWip(wip),
                     .getelementptr,
                     .@"getelementptr inbounds",
@@ -2762,7 +3529,6 @@ pub const Function = struct {
                     },
                     .unimplemented => @enumFromInt(instruction.data),
                     .va_arg => wip.extraData(VaArg, instruction.data).type,
-                    .@"llvm.fma." => wip.extraData(FusedMultiplyAdd, instruction.data).a.typeOfWip(wip),
                 };
             }
 
@@ -2791,22 +3557,6 @@ pub const Function = struct {
                     .@"frem fast",
                     .fsub,
                     .@"fsub fast",
-                    .@"llvm.maxnum.",
-                    .@"llvm.minnum.",
-                    .@"llvm.ctlz.",
-                    .@"llvm.cttz.",
-                    .@"llvm.sadd.sat.",
-                    .@"llvm.smax.",
-                    .@"llvm.smin.",
-                    .@"llvm.smul.fix.sat.",
-                    .@"llvm.sshl.sat.",
-                    .@"llvm.ssub.sat.",
-                    .@"llvm.uadd.sat.",
-                    .@"llvm.umax.",
-                    .@"llvm.umin.",
-                    .@"llvm.umul.fix.sat.",
-                    .@"llvm.ushl.sat.",
-                    .@"llvm.usub.sat.",
                     .lshr,
                     .@"lshr exact",
                     .mul,
@@ -2927,22 +3677,6 @@ pub const Function = struct {
                         .changeScalarAssumeCapacity(.i1, builder),
                     .fneg,
                     .@"fneg fast",
-                    .@"llvm.ceil.",
-                    .@"llvm.cos.",
-                    .@"llvm.exp.",
-                    .@"llvm.exp2.",
-                    .@"llvm.fabs.",
-                    .@"llvm.floor.",
-                    .@"llvm.log.",
-                    .@"llvm.log10.",
-                    .@"llvm.log2.",
-                    .@"llvm.round.",
-                    .@"llvm.sin.",
-                    .@"llvm.sqrt.",
-                    .@"llvm.trunc.",
-                    .@"llvm.bitreverse.",
-                    .@"llvm.bswap.",
-                    .@"llvm.ctpop.",
                     => @as(Value, @enumFromInt(instruction.data)).typeOf(function_index, builder),
                     .getelementptr,
                     .@"getelementptr inbounds",
@@ -2981,7 +3715,6 @@ pub const Function = struct {
                     },
                     .unimplemented => @enumFromInt(instruction.data),
                     .va_arg => function.extraData(VaArg, instruction.data).type,
-                    .@"llvm.fma." => function.extraData(FusedMultiplyAdd, instruction.data).a.typeOf(function_index, builder),
                 };
             }
 
@@ -3074,12 +3807,6 @@ pub const Function = struct {
             mask: Value,
         };
 
-        pub const FusedMultiplyAdd = struct {
-            a: Value,
-            b: Value,
-            c: Value,
-        };
-
         pub const ExtractValue = struct {
             val: Value,
             indices_len: u32,
@@ -3487,24 +4214,7 @@ pub const WipFunction = struct {
         switch (tag) {
             .fneg,
             .@"fneg fast",
-            .@"llvm.ceil.",
-            .@"llvm.cos.",
-            .@"llvm.exp.",
-            .@"llvm.exp2.",
-            .@"llvm.fabs.",
-            .@"llvm.floor.",
-            .@"llvm.log.",
-            .@"llvm.log10.",
-            .@"llvm.log2.",
-            .@"llvm.round.",
-            .@"llvm.sin.",
-            .@"llvm.sqrt.",
-            .@"llvm.trunc.",
             => assert(val.typeOfWip(self).scalarType(self.builder).isFloatingPoint()),
-            .@"llvm.bitreverse.",
-            .@"llvm.bswap.",
-            .@"llvm.ctpop.",
-            => assert(val.typeOfWip(self).scalarType(self.builder).isInteger(self.builder)),
             else => unreachable,
         }
         try self.ensureUnusedExtraCapacity(1, NoExtra, 0);
@@ -3513,43 +4223,10 @@ pub const WipFunction = struct {
             switch (tag) {
                 .fneg => self.llvm.builder.setFastMath(false),
                 .@"fneg fast" => self.llvm.builder.setFastMath(true),
-                .@"llvm.ceil.",
-                .@"llvm.cos.",
-                .@"llvm.exp.",
-                .@"llvm.exp2.",
-                .@"llvm.fabs.",
-                .@"llvm.floor.",
-                .@"llvm.log.",
-                .@"llvm.log10.",
-                .@"llvm.log2.",
-                .@"llvm.round.",
-                .@"llvm.sin.",
-                .@"llvm.sqrt.",
-                .@"llvm.trunc.",
-                .@"llvm.bitreverse.",
-                .@"llvm.bswap.",
-                .@"llvm.ctpop.",
-                => {},
                 else => unreachable,
             }
             self.llvm.instructions.appendAssumeCapacity(switch (tag) {
                 .fneg, .@"fneg fast" => &llvm.Builder.buildFNeg,
-                .@"llvm.ceil." => &llvm.Builder.buildCeil,
-                .@"llvm.cos." => &llvm.Builder.buildCos,
-                .@"llvm.exp." => &llvm.Builder.buildExp,
-                .@"llvm.exp2." => &llvm.Builder.buildExp2,
-                .@"llvm.fabs." => &llvm.Builder.buildFAbs,
-                .@"llvm.floor." => &llvm.Builder.buildFloor,
-                .@"llvm.log." => &llvm.Builder.buildLog,
-                .@"llvm.log10." => &llvm.Builder.buildLog10,
-                .@"llvm.log2." => &llvm.Builder.buildLog2,
-                .@"llvm.round." => &llvm.Builder.buildRound,
-                .@"llvm.sin." => &llvm.Builder.buildSin,
-                .@"llvm.sqrt." => &llvm.Builder.buildSqrt,
-                .@"llvm.trunc." => &llvm.Builder.buildFTrunc,
-                .@"llvm.bitreverse." => &llvm.Builder.buildBitReverse,
-                .@"llvm.bswap." => &llvm.Builder.buildBSwap,
-                .@"llvm.ctpop." => &llvm.Builder.buildCTPop,
                 else => unreachable,
             }(self.llvm.builder, val.toLlvm(self), instruction.llvmName(self)));
         }
@@ -3593,20 +4270,6 @@ pub const WipFunction = struct {
             .@"frem fast",
             .fsub,
             .@"fsub fast",
-            .@"llvm.maxnum.",
-            .@"llvm.minnum.",
-            .@"llvm.sadd.sat.",
-            .@"llvm.smax.",
-            .@"llvm.smin.",
-            .@"llvm.smul.fix.sat.",
-            .@"llvm.sshl.sat.",
-            .@"llvm.ssub.sat.",
-            .@"llvm.uadd.sat.",
-            .@"llvm.umax.",
-            .@"llvm.umin.",
-            .@"llvm.umul.fix.sat.",
-            .@"llvm.ushl.sat.",
-            .@"llvm.usub.sat.",
             .lshr,
             .@"lshr exact",
             .mul,
@@ -3627,9 +4290,6 @@ pub const WipFunction = struct {
             .urem,
             .xor,
             => assert(lhs.typeOfWip(self) == rhs.typeOfWip(self)),
-            .@"llvm.ctlz.",
-            .@"llvm.cttz.",
-            => assert(lhs.typeOfWip(self).scalarType(self.builder).isInteger(self.builder) and rhs.typeOfWip(self) == .i1),
             else => unreachable,
         }
         try self.ensureUnusedExtraCapacity(1, Instruction.Binary, 0);
@@ -3665,22 +4325,6 @@ pub const WipFunction = struct {
                 .fmul, .@"fmul fast" => &llvm.Builder.buildFMul,
                 .frem, .@"frem fast" => &llvm.Builder.buildFRem,
                 .fsub, .@"fsub fast" => &llvm.Builder.buildFSub,
-                .@"llvm.maxnum." => &llvm.Builder.buildMaxNum,
-                .@"llvm.minnum." => &llvm.Builder.buildMinNum,
-                .@"llvm.ctlz." => &llvm.Builder.buildCTLZ,
-                .@"llvm.cttz." => &llvm.Builder.buildCTTZ,
-                .@"llvm.sadd.sat." => &llvm.Builder.buildSAddSat,
-                .@"llvm.smax." => &llvm.Builder.buildSMax,
-                .@"llvm.smin." => &llvm.Builder.buildSMin,
-                .@"llvm.smul.fix.sat." => &llvm.Builder.buildSMulFixSat,
-                .@"llvm.sshl.sat." => &llvm.Builder.buildSShlSat,
-                .@"llvm.ssub.sat." => &llvm.Builder.buildSSubSat,
-                .@"llvm.uadd.sat." => &llvm.Builder.buildUAddSat,
-                .@"llvm.umax." => &llvm.Builder.buildUMax,
-                .@"llvm.umin." => &llvm.Builder.buildUMin,
-                .@"llvm.umul.fix.sat." => &llvm.Builder.buildUMulFixSat,
-                .@"llvm.ushl.sat." => &llvm.Builder.buildUShlSat,
-                .@"llvm.usub.sat." => &llvm.Builder.buildUSubSat,
                 .lshr => &llvm.Builder.buildLShr,
                 .@"lshr exact" => &llvm.Builder.buildLShrExact,
                 .mul => &llvm.Builder.buildMul,
@@ -4419,7 +5063,7 @@ pub const WipFunction = struct {
         self: *WipFunction,
         function_attributes: FunctionAttributes,
         ty: Type,
-        kind: Constant.Asm.Info,
+        kind: Constant.Assembly.Info,
         assembly: String,
         constraints: String,
         args: []const Value,
@@ -4429,6 +5073,25 @@ pub const WipFunction = struct {
         return self.call(.normal, CallConv.default, function_attributes, ty, callee, args, name);
     }
 
+    pub fn callIntrinsic(
+        self: *WipFunction,
+        id: Intrinsic,
+        overload: []const Type,
+        args: []const Value,
+        name: []const u8,
+    ) Allocator.Error!Value {
+        const intrinsic = try self.builder.getIntrinsic(id, overload);
+        return self.call(
+            .normal,
+            CallConv.default,
+            .none,
+            intrinsic.typeOf(self.builder),
+            intrinsic.toValue(self.builder),
+            args,
+            name,
+        );
+    }
+
     pub fn vaArg(self: *WipFunction, list: Value, ty: Type, name: []const u8) Allocator.Error!Value {
         try self.ensureUnusedExtraCapacity(1, Instruction.VaArg, 0);
         const instruction = try self.addInst(name, .{
@@ -4448,29 +5111,6 @@ pub const WipFunction = struct {
         return instruction.toValue();
     }
 
-    pub fn fusedMultiplyAdd(self: *WipFunction, a: Value, b: Value, c: Value) Allocator.Error!Value {
-        assert(a.typeOfWip(self) == b.typeOfWip(self) and a.typeOfWip(self) == c.typeOfWip(self));
-        try self.ensureUnusedExtraCapacity(1, Instruction.FusedMultiplyAdd, 0);
-        const instruction = try self.addInst("", .{
-            .tag = .@"llvm.fma.",
-            .data = self.addExtraAssumeCapacity(Instruction.FusedMultiplyAdd{
-                .a = a,
-                .b = b,
-                .c = c,
-            }),
-        });
-        if (self.builder.useLibLlvm()) {
-            self.llvm.instructions.appendAssumeCapacity(llvm.Builder.buildFMA(
-                self.llvm.builder,
-                a.toLlvm(self),
-                b.toLlvm(self),
-                c.toLlvm(self),
-                instruction.llvmName(self),
-            ));
-        }
-        return instruction.toValue();
-    }
-
     pub const WipUnimplemented = struct {
         instruction: Instruction.Index,
 
@@ -4697,22 +5337,6 @@ pub const WipFunction = struct {
                     .@"icmp ugt",
                     .@"icmp ule",
                     .@"icmp ult",
-                    .@"llvm.maxnum.",
-                    .@"llvm.minnum.",
-                    .@"llvm.ctlz.",
-                    .@"llvm.cttz.",
-                    .@"llvm.sadd.sat.",
-                    .@"llvm.smax.",
-                    .@"llvm.smin.",
-                    .@"llvm.smul.fix.sat.",
-                    .@"llvm.sshl.sat.",
-                    .@"llvm.ssub.sat.",
-                    .@"llvm.uadd.sat.",
-                    .@"llvm.umax.",
-                    .@"llvm.umin.",
-                    .@"llvm.umul.fix.sat.",
-                    .@"llvm.ushl.sat.",
-                    .@"llvm.usub.sat.",
                     .lshr,
                     .@"lshr exact",
                     .mul,
@@ -4828,22 +5452,6 @@ pub const WipFunction = struct {
                     .fneg,
                     .@"fneg fast",
                     .ret,
-                    .@"llvm.ceil.",
-                    .@"llvm.cos.",
-                    .@"llvm.exp.",
-                    .@"llvm.exp2.",
-                    .@"llvm.fabs.",
-                    .@"llvm.floor.",
-                    .@"llvm.log.",
-                    .@"llvm.log10.",
-                    .@"llvm.log2.",
-                    .@"llvm.round.",
-                    .@"llvm.sin.",
-                    .@"llvm.sqrt.",
-                    .@"llvm.trunc.",
-                    .@"llvm.bitreverse.",
-                    .@"llvm.bswap.",
-                    .@"llvm.ctpop.",
                     => instruction.data = @intFromEnum(instructions.map(@enumFromInt(instruction.data))),
                     .getelementptr,
                     .@"getelementptr inbounds",
@@ -4949,14 +5557,6 @@ pub const WipFunction = struct {
                             .type = extra.type,
                         });
                     },
-                    .@"llvm.fma." => {
-                        const extra = self.extraData(Instruction.FusedMultiplyAdd, instruction.data);
-                        instruction.data = wip_extra.addExtra(Instruction.FusedMultiplyAdd{
-                            .a = instructions.map(extra.a),
-                            .b = instructions.map(extra.b),
-                            .c = instructions.map(extra.c),
-                        });
-                    },
                 }
                 function.instructions.appendAssumeCapacity(instruction);
                 names[@intFromEnum(new_instruction_index)] = wip_name.map(if (self.builder.strip)
@@ -5627,7 +6227,7 @@ pub const Constant = enum(u32) {
         rhs: Constant,
     };
 
-    pub const Asm = extern struct {
+    pub const Assembly = extern struct {
         type: Type,
         assembly: String,
         constraints: String,
@@ -5651,7 +6251,7 @@ pub const Constant = enum(u32) {
     }
 
     pub fn toValue(self: Constant) Value {
-        return @enumFromInt(@intFromEnum(Value.first_constant) + @intFromEnum(self));
+        return @enumFromInt(Value.first_constant + @intFromEnum(self));
     }
 
     pub fn typeOf(self: Constant, builder: *Builder) Type {
@@ -6139,7 +6739,7 @@ pub const Constant = enum(u32) {
                     .@"asm alignstack inteldialect unwind",
                     .@"asm sideeffect alignstack inteldialect unwind",
                     => |tag| {
-                        const extra = data.builder.constantExtraData(Asm, item.data);
+                        const extra = data.builder.constantExtraData(Assembly, item.data);
                         try writer.print("{s} {\"}, {\"}", .{
                             @tagName(tag),
                             extra.assembly.fmt(data.builder),
@@ -6166,18 +6766,20 @@ pub const Constant = enum(u32) {
 
 pub const Value = enum(u32) {
     none = std.math.maxInt(u31),
+    false = first_constant + @intFromEnum(Constant.false),
+    true = first_constant + @intFromEnum(Constant.true),
     _,
 
-    const first_constant: Value = @enumFromInt(1 << 31);
+    const first_constant = 1 << 31;
 
     pub fn unwrap(self: Value) union(enum) {
         instruction: Function.Instruction.Index,
         constant: Constant,
     } {
-        return if (@intFromEnum(self) < @intFromEnum(first_constant))
+        return if (@intFromEnum(self) < first_constant)
             .{ .instruction = @enumFromInt(@intFromEnum(self)) }
         else
-            .{ .constant = @enumFromInt(@intFromEnum(self) - @intFromEnum(first_constant)) };
+            .{ .constant = @enumFromInt(@intFromEnum(self) - first_constant) };
     }
 
     pub fn typeOfWip(self: Value, wip: *const WipFunction) Type {
@@ -6349,8 +6951,11 @@ pub fn init(options: Options) InitError!Builder {
         inline for (.{ 1, 8, 16, 29, 32, 64, 80, 128 }) |bits|
             assert(self.intTypeAssumeCapacity(bits) ==
                 @field(Type, std.fmt.comptimePrint("i{d}", .{bits})));
-        inline for (.{0}) |addr_space|
-            assert(self.ptrTypeAssumeCapacity(@enumFromInt(addr_space)) == .ptr);
+        inline for (.{ 0, 4 }) |addr_space_index| {
+            const addr_space: AddrSpace = @enumFromInt(addr_space_index);
+            assert(self.ptrTypeAssumeCapacity(addr_space) ==
+                @field(Type, std.fmt.comptimePrint("ptr{ }", .{addr_space})));
+        }
     }
 
     {
@@ -6883,17 +7488,136 @@ pub fn getGlobal(self: *const Builder, name: String) ?Global.Index {
     return @enumFromInt(self.globals.getIndex(name) orelse return null);
 }
 
+pub fn addFunction(self: *Builder, ty: Type, name: String) Allocator.Error!Function.Index {
+    assert(!name.isAnon());
+    try self.ensureUnusedTypeCapacity(1, NoExtra, 0);
+    try self.ensureUnusedGlobalCapacity(name);
+    try self.functions.ensureUnusedCapacity(self.gpa, 1);
+    return self.addFunctionAssumeCapacity(ty, name);
+}
+
+pub fn addFunctionAssumeCapacity(self: *Builder, ty: Type, name: String) Function.Index {
+    assert(ty.isFunction(self));
+    if (self.useLibLlvm()) self.llvm.globals.appendAssumeCapacity(
+        self.llvm.module.?.addFunction(name.slice(self).?, ty.toLlvm(self)),
+    );
+    const function_index: Function.Index = @enumFromInt(self.functions.items.len);
+    self.functions.appendAssumeCapacity(.{ .global = self.addGlobalAssumeCapacity(name, .{
+        .type = ty,
+        .kind = .{ .function = function_index },
+    }) });
+    return function_index;
+}
+
+pub fn getIntrinsic(
+    self: *Builder,
+    id: Intrinsic,
+    overload: []const Type,
+) Allocator.Error!Function.Index {
+    const ExpectedContents = extern union {
+        name: [expected_intrinsic_name_len]u8,
+        attrs: extern struct {
+            params: [expected_args_len]Type,
+            fn_attrs: [FunctionAttributes.params_index + expected_args_len]Attributes,
+            attrs: [expected_attrs_len]Attribute.Index,
+            fields: [expected_fields_len]Type,
+        },
+    };
+    var stack align(@max(@alignOf(std.heap.StackFallbackAllocator(0)), @alignOf(ExpectedContents))) =
+        std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);
+    const allocator = stack.get();
+
+    const name = name: {
+        var buffer = std.ArrayList(u8).init(allocator);
+        defer buffer.deinit();
+
+        try buffer.writer().print("llvm.{s}", .{@tagName(id)});
+        for (overload) |ty| try buffer.writer().print(".{m}", .{ty.fmt(self)});
+        break :name try self.string(buffer.items);
+    };
+    if (self.getGlobal(name)) |global| return global.ptrConst(self).kind.function;
+
+    const signature = Intrinsic.signatures.get(id);
+    const param_types = try allocator.alloc(Type, signature.params.len);
+    defer allocator.free(param_types);
+    const function_attributes =
+        try allocator.alloc(Attributes, FunctionAttributes.return_index + signature.params.len);
+    defer allocator.free(function_attributes);
+
+    var attributes: struct {
+        builder: *Builder,
+        list: std.ArrayList(Attribute.Index),
+
+        fn deinit(state: *@This()) void {
+            state.list.deinit();
+            state.* = undefined;
+        }
+
+        fn get(state: *@This(), attributes: []const Attribute) Allocator.Error!Attributes {
+            try state.list.resize(attributes.len);
+            for (state.list.items, attributes) |*item, attribute|
+                item.* = try state.builder.attr(attribute);
+            return state.builder.attrs(state.list.items);
+        }
+    } = .{ .builder = self, .list = std.ArrayList(Attribute.Index).init(allocator) };
+    defer attributes.deinit();
+
+    var overload_index: usize = 0;
+    function_attributes[FunctionAttributes.function_index] = try attributes.get(signature.attrs);
+    for (
+        param_types,
+        function_attributes[FunctionAttributes.return_index..],
+        signature.params,
+    ) |*param_type, *param_attributes, signature_param| {
+        switch (signature_param.kind) {
+            .type => |ty| param_type.* = ty,
+            .overloaded => {
+                param_type.* = overload[overload_index];
+                overload_index += 1;
+            },
+            .overloaded_tuple => |len| {
+                const fields = try allocator.alloc(Type, len);
+                defer allocator.free(fields);
+                for (fields, overload[overload_index..][0..len]) |*field, ty| field.* = ty;
+                param_type.* = try self.structType(.normal, fields);
+                overload_index += len;
+            },
+            .matches, .matches_tuple, .matches_with_overflow => {},
+        }
+        param_attributes.* = try attributes.get(signature_param.attrs);
+    }
+    assert(overload_index == overload.len);
+    for (param_types, signature.params) |*param_type, signature_param| switch (signature_param.kind) {
+        .type, .overloaded, .overloaded_tuple => {},
+        .matches => |param_index| param_type.* = param_types[param_index],
+        .matches_tuple => |tuple| param_type.* =
+            param_types[tuple.param].structFields(self)[tuple.field],
+        .matches_with_overflow => |param_index| {
+            const ty = param_types[param_index];
+            param_type.* = try self.structType(.normal, &.{ ty, try ty.changeScalar(.i1, self) });
+        },
+    };
+
+    const function_index =
+        try self.addFunction(try self.fnType(param_types[0], param_types[1..], .normal), name);
+    function_index.ptr(self).attributes = try self.fnAttrs(function_attributes);
+    return function_index;
+}
+
 pub fn intConst(self: *Builder, ty: Type, value: anytype) Allocator.Error!Constant {
+    const int_value = switch (@typeInfo(@TypeOf(value))) {
+        .Int, .ComptimeInt => value,
+        .Enum => @intFromEnum(value),
+        else => @compileError("intConst expected an integral value, got " ++ @typeName(@TypeOf(value))),
+    };
     var limbs: [
-        switch (@typeInfo(@TypeOf(value))) {
+        switch (@typeInfo(@TypeOf(int_value))) {
             .Int => |info| std.math.big.int.calcTwosCompLimbCount(info.bits),
-            .ComptimeInt => std.math.big.int.calcLimbLen(value),
-            else => @compileError(
-                "intConst expected an integral value, got " ++ @typeName(@TypeOf(value)),
-            ),
+            .ComptimeInt => std.math.big.int.calcLimbLen(int_value),
+            else => unreachable,
         }
     ]std.math.big.Limb = undefined;
-    return self.bigIntConst(ty, std.math.big.int.Mutable.init(&limbs, value).toConst());
+    return self.bigIntConst(ty, std.math.big.int.Mutable.init(&limbs, int_value).toConst());
 }
 
 pub fn intValue(self: *Builder, ty: Type, value: anytype) Allocator.Error!Value {
@@ -7304,18 +8028,18 @@ pub fn binValue(self: *Builder, tag: Constant.Tag, lhs: Constant, rhs: Constant)
 pub fn asmConst(
     self: *Builder,
     ty: Type,
-    info: Constant.Asm.Info,
+    info: Constant.Assembly.Info,
     assembly: String,
     constraints: String,
 ) Allocator.Error!Constant {
-    try self.ensureUnusedConstantCapacity(1, Constant.Asm, 0);
+    try self.ensureUnusedConstantCapacity(1, Constant.Assembly, 0);
     return self.asmConstAssumeCapacity(ty, info, assembly, constraints);
 }
 
 pub fn asmValue(
     self: *Builder,
     ty: Type,
-    info: Constant.Asm.Info,
+    info: Constant.Assembly.Info,
     assembly: String,
     constraints: String,
 ) Allocator.Error!Value {
@@ -7413,7 +8137,7 @@ pub fn printUnbuffered(
             if (variable.global.getReplacement(self) != .none) continue;
             const global = variable.global.ptrConst(self);
             try writer.print(
-                \\{} ={}{}{}{}{}{}{}{} {s} {%}{ }{, }
+                \\{} ={}{}{}{}{}{}{ }{} {s} {%}{ }{, }
                 \\
             , .{
                 variable.global.fmt(self),
@@ -7472,7 +8196,9 @@ pub fn printUnbuffered(
                     function.attributes.param(arg, self).fmt(self),
                 });
                 if (function.instructions.len > 0)
-                    try writer.print(" {}", .{function.arg(@intCast(arg)).fmt(function_index, self)});
+                    try writer.print(" {}", .{function.arg(@intCast(arg)).fmt(function_index, self)})
+                else
+                    try writer.print(" %{d}", .{arg});
             }
             switch (global.type.functionKind(self)) {
                 .normal => {},
@@ -7481,11 +8207,11 @@ pub fn printUnbuffered(
                     try writer.writeAll("...");
                 },
             }
-            try writer.print("){}{}", .{ global.unnamed_addr, global.addr_space });
+            try writer.print("){}{ }", .{ global.unnamed_addr, global.addr_space });
             if (function_attributes != .none) try writer.print(" #{d}", .{
                 (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index,
             });
-            try writer.print("{}", .{function.alignment});
+            try writer.print("{ }", .{function.alignment});
             if (function.instructions.len > 0) {
                 var block_incoming_len: u32 = undefined;
                 try writer.writeAll(" {\n");
@@ -7735,33 +8461,6 @@ pub fn printUnbuffered(
                                 val.fmt(function_index, self),
                             });
                         },
-                        .@"llvm.ceil.",
-                        .@"llvm.cos.",
-                        .@"llvm.exp.",
-                        .@"llvm.exp2.",
-                        .@"llvm.fabs.",
-                        .@"llvm.floor.",
-                        .@"llvm.log.",
-                        .@"llvm.log10.",
-                        .@"llvm.log2.",
-                        .@"llvm.round.",
-                        .@"llvm.sin.",
-                        .@"llvm.sqrt.",
-                        .@"llvm.trunc.",
-                        .@"llvm.bitreverse.",
-                        .@"llvm.bswap.",
-                        .@"llvm.ctpop.",
-                        => |tag| {
-                            const val: Value = @enumFromInt(instruction.data);
-                            const ty = val.typeOf(function_index, self);
-                            try writer.print("  %{} = call {%} @{s}{m}({%})\n", .{
-                                instruction_index.name(&function).fmt(self),
-                                ty.fmt(self),
-                                @tagName(tag),
-                                ty.fmt(self),
-                                val.fmt(function_index, self),
-                            });
-                        },
                         .getelementptr,
                         .@"getelementptr inbounds",
                         => |tag| {
@@ -7809,41 +8508,6 @@ pub fn printUnbuffered(
                             for (indices) |index| try writer.print(", {d}", .{index});
                             try writer.writeByte('\n');
                         },
-                        .@"llvm.maxnum.",
-                        .@"llvm.minnum.",
-                        .@"llvm.ctlz.",
-                        .@"llvm.cttz.",
-                        .@"llvm.sadd.sat.",
-                        .@"llvm.smax.",
-                        .@"llvm.smin.",
-                        .@"llvm.smul.fix.sat.",
-                        .@"llvm.sshl.sat.",
-                        .@"llvm.ssub.sat.",
-                        .@"llvm.uadd.sat.",
-                        .@"llvm.umax.",
-                        .@"llvm.umin.",
-                        .@"llvm.umul.fix.sat.",
-                        .@"llvm.ushl.sat.",
-                        .@"llvm.usub.sat.",
-                        => |tag| {
-                            const extra =
-                                function.extraData(Function.Instruction.Binary, instruction.data);
-                            const ty = instruction_index.typeOf(function_index, self);
-                            try writer.print("  %{} = call {%} @{s}{m}({%}, {%}{s})\n", .{
-                                instruction_index.name(&function).fmt(self),
-                                ty.fmt(self),
-                                @tagName(tag),
-                                ty.fmt(self),
-                                extra.lhs.fmt(function_index, self),
-                                extra.rhs.fmt(function_index, self),
-                                switch (tag) {
-                                    .@"llvm.smul.fix.sat.",
-                                    .@"llvm.umul.fix.sat.",
-                                    => ", i32 0",
-                                    else => "",
-                                },
-                            });
-                        },
                         .load,
                         .@"load atomic",
                         .@"load atomic volatile",
@@ -7984,20 +8648,6 @@ pub fn printUnbuffered(
                                 extra.type.fmt(self),
                             });
                         },
-                        .@"llvm.fma." => |tag| {
-                            const extra =
-                                function.extraData(Function.Instruction.FusedMultiplyAdd, instruction.data);
-                            const ty = instruction_index.typeOf(function_index, self);
-                            try writer.print("  %{} = call {%} @{s}{m}({%}, {%}, {%})\n", .{
-                                instruction_index.name(&function).fmt(self),
-                                ty.fmt(self),
-                                @tagName(tag),
-                                ty.fmt(self),
-                                extra.a.fmt(function_index, self),
-                                extra.b.fmt(function_index, self),
-                                extra.c.fmt(function_index, self),
-                            });
-                        },
                     }
                 }
                 try writer.writeByte('}');
@@ -9623,13 +10273,13 @@ fn binConstAssumeCapacity(
 fn asmConstAssumeCapacity(
     self: *Builder,
     ty: Type,
-    info: Constant.Asm.Info,
+    info: Constant.Assembly.Info,
     assembly: String,
     constraints: String,
 ) Constant {
     assert(ty.functionKind(self) == .normal);
 
-    const Key = struct { tag: Constant.Tag, extra: Constant.Asm };
+    const Key = struct { tag: Constant.Tag, extra: Constant.Assembly };
     const Adapter = struct {
         builder: *const Builder,
         pub fn hash(_: @This(), key: Key) u32 {
@@ -9641,7 +10291,7 @@ fn asmConstAssumeCapacity(
         pub fn eql(ctx: @This(), lhs_key: Key, _: void, rhs_index: usize) bool {
             if (lhs_key.tag != ctx.builder.constant_items.items(.tag)[rhs_index]) return false;
             const rhs_data = ctx.builder.constant_items.items(.data)[rhs_index];
-            const rhs_extra = ctx.builder.constantExtraData(Constant.Asm, rhs_data);
+            const rhs_extra = ctx.builder.constantExtraData(Constant.Assembly, rhs_data);
             return std.meta.eql(lhs_key.extra, rhs_extra);
         }
     };
src/codegen/llvm.zig
@@ -4962,9 +4962,9 @@ pub const FuncGen = struct {
                 .mul_wrap      => try self.airMulWrap(inst),
                 .mul_sat       => try self.airMulSat(inst),
 
-                .add_safe => try self.airSafeArithmetic(inst, "llvm.sadd.with.overflow", "llvm.uadd.with.overflow"),
-                .sub_safe => try self.airSafeArithmetic(inst, "llvm.ssub.with.overflow", "llvm.usub.with.overflow"),
-                .mul_safe => try self.airSafeArithmetic(inst, "llvm.smul.with.overflow", "llvm.umul.with.overflow"),
+                .add_safe => try self.airSafeArithmetic(inst, .@"sadd.with.overflow", .@"uadd.with.overflow"),
+                .sub_safe => try self.airSafeArithmetic(inst, .@"ssub.with.overflow", .@"usub.with.overflow"),
+                .mul_safe => try self.airSafeArithmetic(inst, .@"smul.with.overflow", .@"umul.with.overflow"),
 
                 .div_float => try self.airDivFloat(inst, false),
                 .div_trunc => try self.airDivTrunc(inst, false),
@@ -4989,9 +4989,9 @@ pub const FuncGen = struct {
                 .rem_optimized       => try self.airRem(inst, true),
                 .mod_optimized       => try self.airMod(inst, true),
 
-                .add_with_overflow => try self.airOverflow(inst, "llvm.sadd.with.overflow", "llvm.uadd.with.overflow"),
-                .sub_with_overflow => try self.airOverflow(inst, "llvm.ssub.with.overflow", "llvm.usub.with.overflow"),
-                .mul_with_overflow => try self.airOverflow(inst, "llvm.smul.with.overflow", "llvm.umul.with.overflow"),
+                .add_with_overflow => try self.airOverflow(inst, .@"sadd.with.overflow", .@"uadd.with.overflow"),
+                .sub_with_overflow => try self.airOverflow(inst, .@"ssub.with.overflow", .@"usub.with.overflow"),
+                .mul_with_overflow => try self.airOverflow(inst, .@"smul.with.overflow", .@"umul.with.overflow"),
                 .shl_with_overflow => try self.airShlWithOverflow(inst),
 
                 .bit_and, .bool_and => try self.airAnd(inst),
@@ -5100,11 +5100,11 @@ pub const FuncGen = struct {
                 .memcpy         => try self.airMemcpy(inst),
                 .set_union_tag  => try self.airSetUnionTag(inst),
                 .get_union_tag  => try self.airGetUnionTag(inst),
-                .clz            => try self.airClzCtz(inst, .@"llvm.ctlz."),
-                .ctz            => try self.airClzCtz(inst, .@"llvm.cttz."),
-                .popcount       => try self.airBitOp(inst, .@"llvm.ctpop."),
+                .clz            => try self.airClzCtz(inst, .ctlz),
+                .ctz            => try self.airClzCtz(inst, .cttz),
+                .popcount       => try self.airBitOp(inst, .ctpop),
                 .byte_swap      => try self.airByteSwap(inst),
-                .bit_reverse    => try self.airBitOp(inst, .@"llvm.bitreverse."),
+                .bit_reverse    => try self.airBitOp(inst, .bitreverse),
                 .tag_name       => try self.airTagName(inst),
                 .error_name     => try self.airErrorName(inst),
                 .splat          => try self.airSplat(inst),
@@ -5645,22 +5645,7 @@ pub const FuncGen = struct {
         const result_alignment = Builder.Alignment.fromByteUnits(va_list_ty.abiAlignment(mod));
         const dest_list = try self.buildAlloca(llvm_va_list_ty, result_alignment);
 
-        const llvm_fn_name = "llvm.va_copy";
-        const llvm_fn_ty = try o.builder.fnType(.void, &.{ .ptr, .ptr }, .normal);
-        const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse
-            o.llvm_module.addFunction(llvm_fn_name, llvm_fn_ty.toLlvm(&o.builder));
-
-        const args: [2]*llvm.Value = .{ dest_list.toLlvm(&self.wip), src_list.toLlvm(&self.wip) };
-        _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCallOld(
-            llvm_fn_ty.toLlvm(&o.builder),
-            llvm_fn,
-            &args,
-            args.len,
-            .Fast,
-            .Auto,
-            "",
-        ), &self.wip);
-
+        _ = try self.wip.callIntrinsic(.va_copy, &.{}, &.{ dest_list, src_list }, "");
         return if (isByRef(va_list_ty, mod))
             dest_list
         else
@@ -5668,25 +5653,10 @@ pub const FuncGen = struct {
     }
 
     fn airCVaEnd(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
-        const o = self.dg.object;
         const un_op = self.air.instructions.items(.data)[inst].un_op;
-        const list = try self.resolveInst(un_op);
-
-        const llvm_fn_name = "llvm.va_end";
-        const llvm_fn_ty = try o.builder.fnType(.void, &.{.ptr}, .normal);
-        const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse
-            o.llvm_module.addFunction(llvm_fn_name, llvm_fn_ty.toLlvm(&o.builder));
+        const src_list = try self.resolveInst(un_op);
 
-        const args: [1]*llvm.Value = .{list.toLlvm(&self.wip)};
-        _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCallOld(
-            llvm_fn_ty.toLlvm(&o.builder),
-            llvm_fn,
-            &args,
-            args.len,
-            .Fast,
-            .Auto,
-            "",
-        ), &self.wip);
+        _ = try self.wip.callIntrinsic(.va_end, &.{}, &.{src_list}, "");
         return .none;
     }
 
@@ -5697,28 +5667,13 @@ pub const FuncGen = struct {
         const llvm_va_list_ty = try o.lowerType(va_list_ty);
 
         const result_alignment = Builder.Alignment.fromByteUnits(va_list_ty.abiAlignment(mod));
-        const list = try self.buildAlloca(llvm_va_list_ty, result_alignment);
-
-        const llvm_fn_name = "llvm.va_start";
-        const llvm_fn_ty = try o.builder.fnType(.void, &.{.ptr}, .normal);
-        const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse
-            o.llvm_module.addFunction(llvm_fn_name, llvm_fn_ty.toLlvm(&o.builder));
-
-        const args: [1]*llvm.Value = .{list.toLlvm(&self.wip)};
-        _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCallOld(
-            llvm_fn_ty.toLlvm(&o.builder),
-            llvm_fn,
-            &args,
-            args.len,
-            .Fast,
-            .Auto,
-            "",
-        ), &self.wip);
+        const dest_list = try self.buildAlloca(llvm_va_list_ty, result_alignment);
 
+        _ = try self.wip.callIntrinsic(.va_start, &.{}, &.{dest_list}, "");
         return if (isByRef(va_list_ty, mod))
-            list
+            dest_list
         else
-            try self.wip.load(.normal, llvm_va_list_ty, list, result_alignment, "");
+            try self.wip.load(.normal, llvm_va_list_ty, dest_list, result_alignment, "");
     }
 
     fn airCmp(self: *FuncGen, inst: Air.Inst.Index, op: math.CompareOperator, want_fast_math: bool) !Builder.Value {
@@ -7570,40 +7525,18 @@ pub const FuncGen = struct {
         const o = self.dg.object;
         const pl_op = self.air.instructions.items(.data)[inst].pl_op;
         const index = pl_op.payload;
-        const llvm_fn = try self.getIntrinsic("llvm.wasm.memory.size", &.{.i32});
-        const args: [1]*llvm.Value = .{
-            (try o.builder.intConst(.i32, index)).toLlvm(&o.builder),
-        };
-        return (try self.wip.unimplemented(.i32, "")).finish(self.builder.buildCallOld(
-            (try o.builder.fnType(.i32, &.{.i32}, .normal)).toLlvm(&o.builder),
-            llvm_fn,
-            &args,
-            args.len,
-            .Fast,
-            .Auto,
-            "",
-        ), &self.wip);
+        return self.wip.callIntrinsic(.@"wasm.memory.size", &.{.i32}, &.{
+            try o.builder.intValue(.i32, index),
+        }, "");
     }
 
     fn airWasmMemoryGrow(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
         const o = self.dg.object;
         const pl_op = self.air.instructions.items(.data)[inst].pl_op;
         const index = pl_op.payload;
-        const operand = try self.resolveInst(pl_op.operand);
-        const llvm_fn = try self.getIntrinsic("llvm.wasm.memory.grow", &.{.i32});
-        const args: [2]*llvm.Value = .{
-            (try o.builder.intConst(.i32, index)).toLlvm(&o.builder),
-            operand.toLlvm(&self.wip),
-        };
-        return (try self.wip.unimplemented(.i32, "")).finish(self.builder.buildCallOld(
-            (try o.builder.fnType(.i32, &.{ .i32, .i32 }, .normal)).toLlvm(&o.builder),
-            llvm_fn,
-            &args,
-            args.len,
-            .Fast,
-            .Auto,
-            "",
-        ), &self.wip);
+        return self.wip.callIntrinsic(.@"wasm.memory.grow", &.{.i32}, &.{
+            try o.builder.intValue(.i32, index), try self.resolveInst(pl_op.operand),
+        }, "");
     }
 
     fn airVectorStoreElem(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
@@ -7636,13 +7569,16 @@ pub const FuncGen = struct {
         const bin_op = self.air.instructions.items(.data)[inst].bin_op;
         const lhs = try self.resolveInst(bin_op.lhs);
         const rhs = try self.resolveInst(bin_op.rhs);
-        const scalar_ty = self.typeOfIndex(inst).scalarType(mod);
+        const inst_ty = self.typeOfIndex(inst);
+        const scalar_ty = inst_ty.scalarType(mod);
 
-        if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.fmin, scalar_ty, 2, .{ lhs, rhs });
-        return self.wip.bin(if (scalar_ty.isSignedInt(mod))
-            .@"llvm.smin."
-        else
-            .@"llvm.umin.", lhs, rhs, "");
+        if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.fmin, inst_ty, 2, .{ lhs, rhs });
+        return self.wip.callIntrinsic(
+            if (scalar_ty.isSignedInt(mod)) .smin else .umin,
+            &.{try o.lowerType(inst_ty)},
+            &.{ lhs, rhs },
+            "",
+        );
     }
 
     fn airMax(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
@@ -7651,13 +7587,16 @@ pub const FuncGen = struct {
         const bin_op = self.air.instructions.items(.data)[inst].bin_op;
         const lhs = try self.resolveInst(bin_op.lhs);
         const rhs = try self.resolveInst(bin_op.rhs);
-        const scalar_ty = self.typeOfIndex(inst).scalarType(mod);
+        const inst_ty = self.typeOfIndex(inst);
+        const scalar_ty = inst_ty.scalarType(mod);
 
-        if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.fmax, scalar_ty, 2, .{ lhs, rhs });
-        return self.wip.bin(if (scalar_ty.isSignedInt(mod))
-            .@"llvm.smax."
-        else
-            .@"llvm.umax.", lhs, rhs, "");
+        if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.fmax, inst_ty, 2, .{ lhs, rhs });
+        return self.wip.callIntrinsic(
+            if (scalar_ty.isSignedInt(mod)) .smax else .umax,
+            &.{try o.lowerType(inst_ty)},
+            &.{ lhs, rhs },
+            "",
+        );
     }
 
     fn airSlice(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
@@ -7688,8 +7627,8 @@ pub const FuncGen = struct {
     fn airSafeArithmetic(
         fg: *FuncGen,
         inst: Air.Inst.Index,
-        signed_intrinsic: []const u8,
-        unsigned_intrinsic: []const u8,
+        signed_intrinsic: Builder.Intrinsic,
+        unsigned_intrinsic: Builder.Intrinsic,
     ) !Builder.Value {
         const o = fg.dg.object;
         const mod = o.module;
@@ -7699,36 +7638,19 @@ pub const FuncGen = struct {
         const rhs = try fg.resolveInst(bin_op.rhs);
         const inst_ty = fg.typeOfIndex(inst);
         const scalar_ty = inst_ty.scalarType(mod);
-        const is_scalar = scalar_ty.ip_index == inst_ty.ip_index;
 
-        const intrinsic_name = switch (scalar_ty.isSignedInt(mod)) {
-            true => signed_intrinsic,
-            false => unsigned_intrinsic,
-        };
+        const intrinsic = if (scalar_ty.isSignedInt(mod)) signed_intrinsic else unsigned_intrinsic;
         const llvm_inst_ty = try o.lowerType(inst_ty);
-        const llvm_ret_ty = try o.builder.structType(.normal, &.{
-            llvm_inst_ty,
-            try llvm_inst_ty.changeScalar(.i1, &o.builder),
-        });
-        const llvm_fn_ty = try o.builder.fnType(llvm_ret_ty, &.{ llvm_inst_ty, llvm_inst_ty }, .normal);
-        const llvm_fn = try fg.getIntrinsic(intrinsic_name, &.{llvm_inst_ty});
-        const result_struct = (try fg.wip.unimplemented(llvm_ret_ty, "")).finish(fg.builder.buildCallOld(
-            llvm_fn_ty.toLlvm(&o.builder),
-            llvm_fn,
-            &[_]*llvm.Value{ lhs.toLlvm(&fg.wip), rhs.toLlvm(&fg.wip) },
-            2,
-            .Fast,
-            .Auto,
-            "",
-        ), &fg.wip);
-        const overflow_bit = try fg.wip.extractValue(result_struct, &.{1}, "");
-        const scalar_overflow_bit = switch (is_scalar) {
-            true => overflow_bit,
-            false => (try fg.wip.unimplemented(.i1, "")).finish(
+        const results = try fg.wip.callIntrinsic(intrinsic, &.{llvm_inst_ty}, &.{ lhs, rhs }, "");
+
+        const overflow_bit = try fg.wip.extractValue(results, &.{1}, "");
+        const scalar_overflow_bit = if (llvm_inst_ty.isVector(&o.builder))
+            (try fg.wip.unimplemented(.i1, "")).finish(
                 fg.builder.buildOrReduce(overflow_bit.toLlvm(&fg.wip)),
                 &fg.wip,
-            ),
-        };
+            )
+        else
+            overflow_bit;
 
         const fail_block = try fg.wip.block(1, "OverflowFail");
         const ok_block = try fg.wip.block(1, "OverflowOk");
@@ -7738,7 +7660,7 @@ pub const FuncGen = struct {
         try fg.buildSimplePanic(.integer_overflow);
 
         fg.wip.cursor = .{ .block = ok_block };
-        return fg.wip.extractValue(result_struct, &.{0}, "");
+        return fg.wip.extractValue(results, &.{0}, "");
     }
 
     fn airAddWrap(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
@@ -7759,10 +7681,12 @@ pub const FuncGen = struct {
         const scalar_ty = inst_ty.scalarType(mod);
 
         if (scalar_ty.isAnyFloat()) return self.todo("saturating float add", .{});
-        return self.wip.bin(if (scalar_ty.isSignedInt(mod))
-            .@"llvm.sadd.sat."
-        else
-            .@"llvm.uadd.sat.", lhs, rhs, "");
+        return self.wip.callIntrinsic(
+            if (scalar_ty.isSignedInt(mod)) .@"sadd.sat" else .@"uadd.sat",
+            &.{try o.lowerType(inst_ty)},
+            &.{ lhs, rhs },
+            "",
+        );
     }
 
     fn airSub(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {
@@ -7798,10 +7722,12 @@ pub const FuncGen = struct {
         const scalar_ty = inst_ty.scalarType(mod);
 
         if (scalar_ty.isAnyFloat()) return self.todo("saturating float sub", .{});
-        return self.wip.bin(if (scalar_ty.isSignedInt(mod))
-            .@"llvm.ssub.sat."
-        else
-            .@"llvm.usub.sat.", lhs, rhs, "");
+        return self.wip.callIntrinsic(
+            if (scalar_ty.isSignedInt(mod)) .@"ssub.sat" else .@"usub.sat",
+            &.{try o.lowerType(inst_ty)},
+            &.{ lhs, rhs },
+            "",
+        );
     }
 
     fn airMul(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {
@@ -7837,10 +7763,12 @@ pub const FuncGen = struct {
         const scalar_ty = inst_ty.scalarType(mod);
 
         if (scalar_ty.isAnyFloat()) return self.todo("saturating float mul", .{});
-        return self.wip.bin(if (scalar_ty.isSignedInt(mod))
-            .@"llvm.smul.fix.sat."
-        else
-            .@"llvm.umul.fix.sat.", lhs, rhs, "");
+        return self.wip.callIntrinsic(
+            if (scalar_ty.isSignedInt(mod)) .@"smul.fix.sat" else .@"umul.fix.sat",
+            &.{try o.lowerType(inst_ty)},
+            &.{ lhs, rhs, try o.builder.intValue(.i32, 0) },
+            "",
+        );
     }
 
     fn airDivFloat(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {
@@ -8028,8 +7956,8 @@ pub const FuncGen = struct {
     fn airOverflow(
         self: *FuncGen,
         inst: Air.Inst.Index,
-        signed_intrinsic: []const u8,
-        unsigned_intrinsic: []const u8,
+        signed_intrinsic: Builder.Intrinsic,
+        unsigned_intrinsic: Builder.Intrinsic,
     ) !Builder.Value {
         const o = self.dg.object;
         const mod = o.module;
@@ -8041,48 +7969,29 @@ pub const FuncGen = struct {
 
         const lhs_ty = self.typeOf(extra.lhs);
         const scalar_ty = lhs_ty.scalarType(mod);
-        const dest_ty = self.typeOfIndex(inst);
-
-        const intrinsic_name = if (scalar_ty.isSignedInt(mod)) signed_intrinsic else unsigned_intrinsic;
+        const inst_ty = self.typeOfIndex(inst);
 
-        const llvm_dest_ty = try o.lowerType(dest_ty);
+        const intrinsic = if (scalar_ty.isSignedInt(mod)) signed_intrinsic else unsigned_intrinsic;
+        const llvm_inst_ty = try o.lowerType(inst_ty);
         const llvm_lhs_ty = try o.lowerType(lhs_ty);
+        const results = try self.wip.callIntrinsic(intrinsic, &.{llvm_lhs_ty}, &.{ lhs, rhs }, "");
 
-        const llvm_fn = try self.getIntrinsic(intrinsic_name, &.{llvm_lhs_ty});
-        const llvm_ret_ty = try o.builder.structType(
-            .normal,
-            &.{ llvm_lhs_ty, try llvm_lhs_ty.changeScalar(.i1, &o.builder) },
-        );
-        const llvm_fn_ty = try o.builder.fnType(llvm_ret_ty, &.{ llvm_lhs_ty, llvm_lhs_ty }, .normal);
-        const result_struct = (try self.wip.unimplemented(llvm_ret_ty, "")).finish(
-            self.builder.buildCallOld(
-                llvm_fn_ty.toLlvm(&o.builder),
-                llvm_fn,
-                &[_]*llvm.Value{ lhs.toLlvm(&self.wip), rhs.toLlvm(&self.wip) },
-                2,
-                .Fast,
-                .Auto,
-                "",
-            ),
-            &self.wip,
-        );
-
-        const result = try self.wip.extractValue(result_struct, &.{0}, "");
-        const overflow_bit = try self.wip.extractValue(result_struct, &.{1}, "");
+        const result_val = try self.wip.extractValue(results, &.{0}, "");
+        const overflow_bit = try self.wip.extractValue(results, &.{1}, "");
 
-        const result_index = llvmField(dest_ty, 0, mod).?.index;
-        const overflow_index = llvmField(dest_ty, 1, mod).?.index;
+        const result_index = llvmField(inst_ty, 0, mod).?.index;
+        const overflow_index = llvmField(inst_ty, 1, mod).?.index;
 
-        if (isByRef(dest_ty, mod)) {
-            const result_alignment = Builder.Alignment.fromByteUnits(dest_ty.abiAlignment(mod));
-            const alloca_inst = try self.buildAlloca(llvm_dest_ty, result_alignment);
+        if (isByRef(inst_ty, mod)) {
+            const result_alignment = Builder.Alignment.fromByteUnits(inst_ty.abiAlignment(mod));
+            const alloca_inst = try self.buildAlloca(llvm_inst_ty, result_alignment);
             {
-                const field_ptr = try self.wip.gepStruct(llvm_dest_ty, alloca_inst, result_index, "");
-                _ = try self.wip.store(.normal, result, field_ptr, result_alignment);
+                const field_ptr = try self.wip.gepStruct(llvm_inst_ty, alloca_inst, result_index, "");
+                _ = try self.wip.store(.normal, result_val, field_ptr, result_alignment);
             }
             {
                 const overflow_alignment = comptime Builder.Alignment.fromByteUnits(1);
-                const field_ptr = try self.wip.gepStruct(llvm_dest_ty, alloca_inst, overflow_index, "");
+                const field_ptr = try self.wip.gepStruct(llvm_inst_ty, alloca_inst, overflow_index, "");
                 _ = try self.wip.store(.normal, overflow_bit, field_ptr, overflow_alignment);
             }
 
@@ -8090,9 +7999,9 @@ pub const FuncGen = struct {
         }
 
         var fields: [2]Builder.Value = undefined;
-        fields[result_index] = result;
+        fields[result_index] = result_val;
         fields[overflow_index] = overflow_bit;
-        return self.wip.buildAggregate(llvm_dest_ty, &fields, "");
+        return self.wip.buildAggregate(llvm_inst_ty, &fields, "");
     }
 
     fn buildElementwiseCall(
@@ -8140,22 +8049,7 @@ pub const FuncGen = struct {
             .function => |function| function,
             else => unreachable,
         };
-
-        const fn_type = try o.builder.fnType(return_type, param_types, .normal);
-        const f = o.llvm_module.addFunction(fn_name.slice(&o.builder).?, fn_type.toLlvm(&o.builder));
-
-        var global = Builder.Global{
-            .type = fn_type,
-            .kind = .{ .function = @enumFromInt(o.builder.functions.items.len) },
-        };
-        var function = Builder.Function{
-            .global = @enumFromInt(o.builder.globals.count()),
-        };
-
-        try o.builder.llvm.globals.append(self.gpa, f);
-        _ = try o.builder.addGlobal(fn_name, global);
-        try o.builder.functions.append(self.gpa, function);
-        return global.kind.function;
+        return o.builder.addFunction(try o.builder.fnType(return_type, param_types, .normal), fn_name);
     }
 
     /// Creates a floating point comparison by lowering to the appropriate
@@ -8290,22 +8184,22 @@ pub const FuncGen = struct {
             .mul => return self.wip.bin(.fmul, params[0], params[1], ""),
             .div => return self.wip.bin(.fdiv, params[0], params[1], ""),
             .fmod => return self.wip.bin(.frem, params[0], params[1], ""),
-            .fmax => return self.wip.bin(.@"llvm.maxnum.", params[0], params[1], ""),
-            .fmin => return self.wip.bin(.@"llvm.minnum.", params[0], params[1], ""),
-            .ceil => return self.wip.un(.@"llvm.ceil.", params[0], ""),
-            .cos => return self.wip.un(.@"llvm.cos.", params[0], ""),
-            .exp => return self.wip.un(.@"llvm.exp.", params[0], ""),
-            .exp2 => return self.wip.un(.@"llvm.exp2.", params[0], ""),
-            .fabs => return self.wip.un(.@"llvm.fabs.", params[0], ""),
-            .floor => return self.wip.un(.@"llvm.floor.", params[0], ""),
-            .log => return self.wip.un(.@"llvm.log.", params[0], ""),
-            .log10 => return self.wip.un(.@"llvm.log10.", params[0], ""),
-            .log2 => return self.wip.un(.@"llvm.log2.", params[0], ""),
-            .round => return self.wip.un(.@"llvm.round.", params[0], ""),
-            .sin => return self.wip.un(.@"llvm.sin.", params[0], ""),
-            .sqrt => return self.wip.un(.@"llvm.sqrt.", params[0], ""),
-            .trunc => return self.wip.un(.@"llvm.trunc.", params[0], ""),
-            .fma => return self.wip.fusedMultiplyAdd(params[0], params[1], params[2]),
+            .fmax => return self.wip.callIntrinsic(.maxnum, &.{llvm_ty}, &params, ""),
+            .fmin => return self.wip.callIntrinsic(.minnum, &.{llvm_ty}, &params, ""),
+            .ceil => return self.wip.callIntrinsic(.ceil, &.{llvm_ty}, &params, ""),
+            .cos => return self.wip.callIntrinsic(.cos, &.{llvm_ty}, &params, ""),
+            .exp => return self.wip.callIntrinsic(.exp, &.{llvm_ty}, &params, ""),
+            .exp2 => return self.wip.callIntrinsic(.exp2, &.{llvm_ty}, &params, ""),
+            .fabs => return self.wip.callIntrinsic(.fabs, &.{llvm_ty}, &params, ""),
+            .floor => return self.wip.callIntrinsic(.floor, &.{llvm_ty}, &params, ""),
+            .log => return self.wip.callIntrinsic(.log, &.{llvm_ty}, &params, ""),
+            .log10 => return self.wip.callIntrinsic(.log10, &.{llvm_ty}, &params, ""),
+            .log2 => return self.wip.callIntrinsic(.log2, &.{llvm_ty}, &params, ""),
+            .round => return self.wip.callIntrinsic(.round, &.{llvm_ty}, &params, ""),
+            .sin => return self.wip.callIntrinsic(.sin, &.{llvm_ty}, &params, ""),
+            .sqrt => return self.wip.callIntrinsic(.sqrt, &.{llvm_ty}, &params, ""),
+            .trunc => return self.wip.callIntrinsic(.trunc, &.{llvm_ty}, &params, ""),
+            .fma => return self.wip.callIntrinsic(.fma, &.{llvm_ty}, &params, ""),
             .tan => unreachable,
         };
 
@@ -8499,25 +8393,27 @@ pub const FuncGen = struct {
 
         const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty), "");
 
-        const result = try self.wip.bin(if (lhs_scalar_ty.isSignedInt(mod))
-            .@"llvm.sshl.sat."
-        else
-            .@"llvm.ushl.sat.", lhs, casted_rhs, "");
+        const llvm_lhs_ty = try o.lowerType(lhs_ty);
+        const llvm_lhs_scalar_ty = llvm_lhs_ty.scalarType(&o.builder);
+        const result = try self.wip.callIntrinsic(
+            if (lhs_scalar_ty.isSignedInt(mod)) .@"sshl.sat" else .@"ushl.sat",
+            &.{llvm_lhs_ty},
+            &.{ lhs, casted_rhs },
+            "",
+        );
 
         // LLVM langref says "If b is (statically or dynamically) equal to or
         // larger than the integer bit width of the arguments, the result is a
         // poison value."
         // However Zig semantics says that saturating shift left can never produce
         // undefined; instead it saturates.
-        const lhs_llvm_ty = try o.lowerType(lhs_ty);
-        const lhs_scalar_llvm_ty = lhs_llvm_ty.scalarType(&o.builder);
         const bits = try o.builder.splatValue(
-            lhs_llvm_ty,
-            try o.builder.intConst(lhs_scalar_llvm_ty, lhs_bits),
+            llvm_lhs_ty,
+            try o.builder.intConst(llvm_lhs_scalar_ty, lhs_bits),
         );
         const lhs_max = try o.builder.splatValue(
-            lhs_llvm_ty,
-            try o.builder.intConst(lhs_scalar_llvm_ty, -1),
+            llvm_lhs_ty,
+            try o.builder.intConst(llvm_lhs_scalar_ty, -1),
         );
         const in_range = try self.wip.icmp(.ult, rhs, bits, "");
         return self.wip.select(in_range, result, lhs_max, "");
@@ -8940,90 +8836,38 @@ pub const FuncGen = struct {
 
     fn airTrap(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
         _ = inst;
-        const o = self.dg.object;
-        const llvm_fn = try self.getIntrinsic("llvm.trap", &.{});
-        _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCallOld(
-            (try o.builder.fnType(.void, &.{}, .normal)).toLlvm(&o.builder),
-            llvm_fn,
-            undefined,
-            0,
-            .Cold,
-            .Auto,
-            "",
-        ), &self.wip);
+        _ = try self.wip.callIntrinsic(.trap, &.{}, &.{}, "");
         _ = try self.wip.@"unreachable"();
         return .none;
     }
 
     fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
         _ = inst;
-        const o = self.dg.object;
-        const llvm_fn = try self.getIntrinsic("llvm.debugtrap", &.{});
-        _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCallOld(
-            (try o.builder.fnType(.void, &.{}, .normal)).toLlvm(&o.builder),
-            llvm_fn,
-            undefined,
-            0,
-            .C,
-            .Auto,
-            "",
-        ), &self.wip);
+        _ = try self.wip.callIntrinsic(.debugtrap, &.{}, &.{}, "");
         return .none;
     }
 
     fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
         _ = inst;
         const o = self.dg.object;
-        const mod = o.module;
         const llvm_usize = try o.lowerType(Type.usize);
-        const target = mod.getTarget();
-        if (!target_util.supportsReturnAddress(target)) {
+        if (!target_util.supportsReturnAddress(o.module.getTarget())) {
             // https://github.com/ziglang/zig/issues/11946
             return o.builder.intValue(llvm_usize, 0);
         }
-
-        const llvm_fn = try self.getIntrinsic("llvm.returnaddress", &.{});
-        const params = [_]*llvm.Value{
-            (try o.builder.intConst(.i32, 0)).toLlvm(&o.builder),
-        };
-        const ptr_val = (try self.wip.unimplemented(.ptr, "")).finish(self.builder.buildCallOld(
-            (try o.builder.fnType(.ptr, &.{.i32}, .normal)).toLlvm(&o.builder),
-            llvm_fn,
-            &params,
-            params.len,
-            .Fast,
-            .Auto,
-            "",
-        ), &self.wip);
-        return self.wip.cast(.ptrtoint, ptr_val, llvm_usize, "");
+        const result = try self.wip.callIntrinsic(.returnaddress, &.{}, &.{
+            try o.builder.intValue(.i32, 0),
+        }, "");
+        return self.wip.cast(.ptrtoint, result, llvm_usize, "");
     }
 
     fn airFrameAddress(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
         _ = inst;
         const o = self.dg.object;
-        const llvm_fn_name = "llvm.frameaddress.p0";
-        const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: {
-            const fn_type = try o.builder.fnType(.ptr, &.{.i32}, .normal);
-            break :blk o.llvm_module.addFunction(llvm_fn_name, fn_type.toLlvm(&o.builder));
-        };
-        const llvm_fn_ty = try o.builder.fnType(.ptr, &.{.i32}, .normal);
-
-        const params = [_]*llvm.Value{
-            (try o.builder.intConst(.i32, 0)).toLlvm(&o.builder),
-        };
-        const ptr_val = (try self.wip.unimplemented(llvm_fn_ty.functionReturn(&o.builder), "")).finish(
-            self.builder.buildCallOld(
-                llvm_fn_ty.toLlvm(&o.builder),
-                llvm_fn,
-                &params,
-                params.len,
-                .Fast,
-                .Auto,
-                "",
-            ),
-            &self.wip,
-        );
-        return self.wip.cast(.ptrtoint, ptr_val, try o.lowerType(Type.usize), "");
+        const result = try self.wip.callIntrinsic(.frameaddress, &.{.ptr}, &.{
+            try o.builder.intValue(.i32, 0),
+        }, "");
+        return self.wip.cast(.ptrtoint, result, try o.lowerType(Type.usize), "");
     }
 
     fn airFence(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
@@ -9526,26 +9370,37 @@ pub const FuncGen = struct {
         return self.buildFloatOp(.neg, operand_ty, 1, .{operand});
     }
 
-    fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Function.Instruction.Tag) !Builder.Value {
+    fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) !Builder.Value {
         const o = self.dg.object;
         const ty_op = self.air.instructions.items(.data)[inst].ty_op;
+        const inst_ty = self.typeOfIndex(inst);
+        const operand_ty = self.typeOf(ty_op.operand);
         const operand = try self.resolveInst(ty_op.operand);
 
-        const wrong_size_result = try self.wip.bin(intrinsic, operand, (try o.builder.intConst(.i1, 0)).toValue(), "");
-
-        const result_ty = self.typeOfIndex(inst);
-        return self.wip.conv(.unsigned, wrong_size_result, try o.lowerType(result_ty), "");
+        const result =
+            try self.wip.callIntrinsic(
+            intrinsic,
+            &.{try o.lowerType(operand_ty)},
+            &.{ operand, .false },
+            "",
+        );
+        return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty), "");
     }
 
-    fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Function.Instruction.Tag) !Builder.Value {
+    fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) !Builder.Value {
         const o = self.dg.object;
         const ty_op = self.air.instructions.items(.data)[inst].ty_op;
+        const inst_ty = self.typeOfIndex(inst);
+        const operand_ty = self.typeOf(ty_op.operand);
         const operand = try self.resolveInst(ty_op.operand);
 
-        const wrong_size_result = try self.wip.un(intrinsic, operand, "");
-
-        const result_ty = self.typeOfIndex(inst);
-        return self.wip.conv(.unsigned, wrong_size_result, try o.lowerType(result_ty), "");
+        const result = try self.wip.callIntrinsic(
+            intrinsic,
+            &.{try o.lowerType(operand_ty)},
+            &.{operand},
+            "",
+        );
+        return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty), "");
     }
 
     fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
@@ -9556,6 +9411,7 @@ pub const FuncGen = struct {
         var bits = operand_ty.intInfo(mod).bits;
         assert(bits % 8 == 0);
 
+        const inst_ty = self.typeOfIndex(inst);
         var operand = try self.resolveInst(ty_op.operand);
         var llvm_operand_ty = try o.lowerType(operand_ty);
 
@@ -9576,10 +9432,8 @@ pub const FuncGen = struct {
             bits = bits + 8;
         }
 
-        const wrong_size_result = try self.wip.un(.@"llvm.bswap.", operand, "");
-
-        const result_ty = self.typeOfIndex(inst);
-        return self.wip.conv(.unsigned, wrong_size_result, try o.lowerType(result_ty), "");
+        const result = try self.wip.callIntrinsic(.bswap, &.{llvm_operand_ty}, &.{operand}, "");
+        return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty), "");
     }
 
     fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
@@ -9609,11 +9463,7 @@ pub const FuncGen = struct {
 
         self.wip.cursor = .{ .block = end_block };
         const phi = try self.wip.phi(.i1, "");
-        try phi.finish(
-            &.{ Builder.Constant.true.toValue(), Builder.Constant.false.toValue() },
-            &.{ valid_block, invalid_block },
-            &self.wip,
-        );
+        try phi.finish(&.{ .true, .false }, &.{ valid_block, invalid_block }, &self.wip);
         return phi.toValue();
     }
 
@@ -9646,37 +9496,24 @@ pub const FuncGen = struct {
         errdefer assert(o.named_enum_map.remove(enum_type.decl));
 
         const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod);
-        const llvm_fn_name = try o.builder.fmt("__zig_is_named_enum_value_{}", .{
-            fqn.fmt(&mod.intern_pool),
-        });
+        const function_index = try o.builder.addFunction(
+            try o.builder.fnType(.i1, &.{try o.lowerType(enum_type.tag_ty.toType())}, .normal),
+            try o.builder.fmt("__zig_is_named_enum_value_{}", .{fqn.fmt(&mod.intern_pool)}),
+        );
 
         var attributes: Builder.FunctionAttributes.Wip = .{};
         defer attributes.deinit(&o.builder);
 
-        const fn_type = try o.builder.fnType(.i1, &.{
-            try o.lowerType(enum_type.tag_ty.toType()),
-        }, .normal);
-        const fn_val = o.llvm_module.addFunction(llvm_fn_name.slice(&o.builder).?, fn_type.toLlvm(&o.builder));
-        fn_val.setLinkage(.Internal);
-        fn_val.setFunctionCallConv(.Fast);
-        try o.addCommonFnAttributes(&attributes, fn_val);
+        function_index.toLlvm(&o.builder).setLinkage(.Internal);
+        function_index.toLlvm(&o.builder).setFunctionCallConv(.Fast);
+        try o.addCommonFnAttributes(&attributes, function_index.toLlvm(&o.builder));
 
-        var global = Builder.Global{
-            .linkage = .internal,
-            .type = fn_type,
-            .kind = .{ .function = @enumFromInt(o.builder.functions.items.len) },
-        };
-        var function = Builder.Function{
-            .global = @enumFromInt(o.builder.globals.count()),
-            .call_conv = .fastcc,
-            .attributes = try attributes.finish(&o.builder),
-        };
-        try o.builder.llvm.globals.append(self.gpa, fn_val);
-        _ = try o.builder.addGlobal(llvm_fn_name, global);
-        try o.builder.functions.append(self.gpa, function);
-        gop.value_ptr.* = global.kind.function;
+        function_index.ptrConst(&o.builder).global.ptr(&o.builder).linkage = .internal;
+        function_index.ptr(&o.builder).call_conv = .fastcc;
+        function_index.ptr(&o.builder).attributes = try attributes.finish(&o.builder);
+        gop.value_ptr.* = function_index;
 
-        var wip = try Builder.WipFunction.init(&o.builder, global.kind.function);
+        var wip = try Builder.WipFunction.init(&o.builder, function_index);
         defer wip.deinit();
         wip.cursor = .{ .block = try wip.block(0, "Entry") };
 
@@ -9693,13 +9530,13 @@ pub const FuncGen = struct {
             try wip_switch.addCase(this_tag_int_value, named_block, &wip);
         }
         wip.cursor = .{ .block = named_block };
-        _ = try wip.ret(Builder.Constant.true.toValue());
+        _ = try wip.ret(.true);
 
         wip.cursor = .{ .block = unnamed_block };
-        _ = try wip.ret(Builder.Constant.false.toValue());
+        _ = try wip.ret(.false);
 
         try wip.finish();
-        return global.kind.function;
+        return function_index;
     }
 
     fn airTagName(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
@@ -9730,38 +9567,27 @@ pub const FuncGen = struct {
         if (gop.found_existing) return gop.value_ptr.ptrConst(&o.builder).kind.function;
         errdefer assert(o.decl_map.remove(enum_type.decl));
 
+        const usize_ty = try o.lowerType(Type.usize);
+        const ret_ty = try o.lowerType(Type.slice_const_u8_sentinel_0);
         const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod);
-        const llvm_fn_name = try o.builder.fmt("__zig_tag_name_{}", .{fqn.fmt(&mod.intern_pool)});
+        const function_index = try o.builder.addFunction(
+            try o.builder.fnType(ret_ty, &.{try o.lowerType(enum_type.tag_ty.toType())}, .normal),
+            try o.builder.fmt("__zig_tag_name_{}", .{fqn.fmt(&mod.intern_pool)}),
+        );
 
         var attributes: Builder.FunctionAttributes.Wip = .{};
         defer attributes.deinit(&o.builder);
 
-        const ret_ty = try o.lowerType(Type.slice_const_u8_sentinel_0);
-        const usize_ty = try o.lowerType(Type.usize);
+        function_index.toLlvm(&o.builder).setLinkage(.Internal);
+        function_index.toLlvm(&o.builder).setFunctionCallConv(.Fast);
+        try o.addCommonFnAttributes(&attributes, function_index.toLlvm(&o.builder));
 
-        const fn_type = try o.builder.fnType(ret_ty, &.{
-            try o.lowerType(enum_type.tag_ty.toType()),
-        }, .normal);
-        const fn_val = o.llvm_module.addFunction(llvm_fn_name.slice(&o.builder).?, fn_type.toLlvm(&o.builder));
-        fn_val.setLinkage(.Internal);
-        fn_val.setFunctionCallConv(.Fast);
-        try o.addCommonFnAttributes(&attributes, fn_val);
+        function_index.ptrConst(&o.builder).global.ptr(&o.builder).linkage = .internal;
+        function_index.ptr(&o.builder).call_conv = .fastcc;
+        function_index.ptr(&o.builder).attributes = try attributes.finish(&o.builder);
+        gop.value_ptr.* = function_index.ptrConst(&o.builder).global;
 
-        var global = Builder.Global{
-            .linkage = .internal,
-            .type = fn_type,
-            .kind = .{ .function = @enumFromInt(o.builder.functions.items.len) },
-        };
-        var function = Builder.Function{
-            .global = @enumFromInt(o.builder.globals.count()),
-            .call_conv = .fastcc,
-            .attributes = try attributes.finish(&o.builder),
-        };
-        try o.builder.llvm.globals.append(self.gpa, fn_val);
-        gop.value_ptr.* = try o.builder.addGlobal(llvm_fn_name, global);
-        try o.builder.functions.append(self.gpa, function);
-
-        var wip = try Builder.WipFunction.init(&o.builder, global.kind.function);
+        var wip = try Builder.WipFunction.init(&o.builder, function_index);
         defer wip.deinit();
         wip.cursor = .{ .block = try wip.block(0, "Entry") };
 
@@ -9817,7 +9643,7 @@ pub const FuncGen = struct {
         _ = try wip.@"unreachable"();
 
         try wip.finish();
-        return global.kind.function;
+        return function_index;
     }
 
     fn getCmpLtErrorsLenFunction(self: *FuncGen) !Builder.Function.Index {
@@ -9826,33 +9652,23 @@ pub const FuncGen = struct {
         const name = try o.builder.string(lt_errors_fn_name);
         if (o.builder.getGlobal(name)) |llvm_fn| return llvm_fn.ptrConst(&o.builder).kind.function;
 
-        // Function signature: fn (anyerror) bool
-
-        const fn_type = try o.builder.fnType(.i1, &.{Builder.Type.err_int}, .normal);
-        const llvm_fn = o.llvm_module.addFunction(name.slice(&o.builder).?, fn_type.toLlvm(&o.builder));
+        const function_index = try o.builder.addFunction(
+            try o.builder.fnType(.i1, &.{Builder.Type.err_int}, .normal),
+            name,
+        );
 
         var attributes: Builder.FunctionAttributes.Wip = .{};
         defer attributes.deinit(&o.builder);
 
-        llvm_fn.setLinkage(.Internal);
-        llvm_fn.setFunctionCallConv(.Fast);
-        try o.addCommonFnAttributes(&attributes, llvm_fn);
+        function_index.toLlvm(&o.builder).setLinkage(.Internal);
+        function_index.toLlvm(&o.builder).setFunctionCallConv(.Fast);
+        try o.addCommonFnAttributes(&attributes, function_index.toLlvm(&o.builder));
 
-        var global = Builder.Global{
-            .linkage = .internal,
-            .type = fn_type,
-            .kind = .{ .function = @enumFromInt(o.builder.functions.items.len) },
-        };
-        var function = Builder.Function{
-            .global = @enumFromInt(o.builder.globals.count()),
-            .call_conv = .fastcc,
-            .attributes = try attributes.finish(&o.builder),
-        };
+        function_index.ptrConst(&o.builder).global.ptr(&o.builder).linkage = .internal;
+        function_index.ptr(&o.builder).call_conv = .fastcc;
+        function_index.ptr(&o.builder).attributes = try attributes.finish(&o.builder);
 
-        try o.builder.llvm.globals.append(self.gpa, llvm_fn);
-        _ = try o.builder.addGlobal(name, global);
-        try o.builder.functions.append(self.gpa, function);
-        return global.kind.function;
+        return function_index;
     }
 
     fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
@@ -10416,29 +10232,12 @@ pub const FuncGen = struct {
             .data => {},
         }
 
-        const llvm_fn_name = "llvm.prefetch.p0";
-        // declare void @llvm.prefetch(i8*, i32, i32, i32)
-        const llvm_fn_ty = try o.builder.fnType(.void, &.{ .ptr, .i32, .i32, .i32 }, .normal);
-        const fn_val = o.llvm_module.getNamedFunction(llvm_fn_name) orelse
-            o.llvm_module.addFunction(llvm_fn_name, llvm_fn_ty.toLlvm(&o.builder));
-
-        const ptr = try self.resolveInst(prefetch.ptr);
-
-        const params = [_]*llvm.Value{
-            ptr.toLlvm(&self.wip),
-            (try o.builder.intConst(.i32, @intFromEnum(prefetch.rw))).toLlvm(&o.builder),
-            (try o.builder.intConst(.i32, prefetch.locality)).toLlvm(&o.builder),
-            (try o.builder.intConst(.i32, @intFromEnum(prefetch.cache))).toLlvm(&o.builder),
-        };
-        _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCallOld(
-            llvm_fn_ty.toLlvm(&o.builder),
-            fn_val,
-            &params,
-            params.len,
-            .C,
-            .Auto,
-            "",
-        ), &self.wip);
+        _ = try self.wip.callIntrinsic(.prefetch, &.{.ptr}, &.{
+            try self.resolveInst(prefetch.ptr),
+            try o.builder.intValue(.i32, prefetch.rw),
+            try o.builder.intValue(.i32, prefetch.locality),
+            try o.builder.intValue(.i32, prefetch.cache),
+        }, "");
         return .none;
     }
 
@@ -10451,26 +10250,20 @@ pub const FuncGen = struct {
         return self.wip.cast(.addrspacecast, operand, try o.lowerType(inst_ty), "");
     }
 
-    fn amdgcnWorkIntrinsic(self: *FuncGen, dimension: u32, default: u32, comptime basename: []const u8) !Builder.Value {
+    fn amdgcnWorkIntrinsic(
+        self: *FuncGen,
+        dimension: u32,
+        default: u32,
+        comptime basename: []const u8,
+    ) !Builder.Value {
         const o = self.dg.object;
-        const llvm_fn_name = switch (dimension) {
-            0 => basename ++ ".x",
-            1 => basename ++ ".y",
-            2 => basename ++ ".z",
+        const intrinsic = switch (dimension) {
+            0 => @field(Builder.Intrinsic, basename ++ ".x"),
+            1 => @field(Builder.Intrinsic, basename ++ ".y"),
+            2 => @field(Builder.Intrinsic, basename ++ ".z"),
             else => return o.builder.intValue(.i32, default),
         };
-
-        const args: [0]*llvm.Value = .{};
-        const llvm_fn = try self.getIntrinsic(llvm_fn_name, &.{});
-        return (try self.wip.unimplemented(.i32, "")).finish(self.builder.buildCallOld(
-            (try o.builder.fnType(.i32, &.{}, .normal)).toLlvm(&o.builder),
-            llvm_fn,
-            &args,
-            args.len,
-            .Fast,
-            .Auto,
-            "",
-        ), &self.wip);
+        return self.wip.callIntrinsic(intrinsic, &.{}, &.{}, "");
     }
 
     fn airWorkItemId(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
@@ -10480,7 +10273,7 @@ pub const FuncGen = struct {
 
         const pl_op = self.air.instructions.items(.data)[inst].pl_op;
         const dimension = pl_op.payload;
-        return self.amdgcnWorkIntrinsic(dimension, 0, "llvm.amdgcn.workitem.id");
+        return self.amdgcnWorkIntrinsic(dimension, 0, "amdgcn.workitem.id");
     }
 
     fn airWorkGroupSize(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
@@ -10492,27 +10285,9 @@ pub const FuncGen = struct {
         const dimension = pl_op.payload;
         if (dimension >= 3) return o.builder.intValue(.i32, 1);
 
-        var attributes: Builder.FunctionAttributes.Wip = .{};
-        defer attributes.deinit(&o.builder);
-
         // Fetch the dispatch pointer, which points to this structure:
         // https://github.com/RadeonOpenCompute/ROCR-Runtime/blob/adae6c61e10d371f7cbc3d0e94ae2c070cab18a4/src/inc/hsa.h#L2913
-        const llvm_fn = try self.getIntrinsic("llvm.amdgcn.dispatch.ptr", &.{});
-        const args: [0]*llvm.Value = .{};
-        const llvm_ret_ty = try o.builder.ptrType(Builder.AddrSpace.amdgpu.constant);
-        const dispatch_ptr = (try self.wip.unimplemented(llvm_ret_ty, "")).finish(self.builder.buildCallOld(
-            (try o.builder.fnType(llvm_ret_ty, &.{}, .normal)).toLlvm(&o.builder),
-            llvm_fn,
-            &args,
-            args.len,
-            .Fast,
-            .Auto,
-            "",
-        ), &self.wip);
-        try attributes.addRetAttr(.{
-            .@"align" = comptime Builder.Alignment.fromByteUnits(4),
-        }, &o.builder);
-        o.addAttrInt(dispatch_ptr.toLlvm(&self.wip), 0, "align", 4);
+        const dispatch_ptr = try self.wip.callIntrinsic(.@"amdgcn.dispatch.ptr", &.{}, &.{}, "");
 
         // Load the work_group_* member from the struct as u16.
         // Just treat the dispatch pointer as an array of u16 to keep things simple.
@@ -10530,7 +10305,7 @@ pub const FuncGen = struct {
 
         const pl_op = self.air.instructions.items(.data)[inst].pl_op;
         const dimension = pl_op.payload;
-        return self.amdgcnWorkIntrinsic(dimension, 0, "llvm.amdgcn.workgroup.id");
+        return self.amdgcnWorkIntrinsic(dimension, 0, "amdgcn.workgroup.id");
     }
 
     fn getErrorNameTable(self: *FuncGen) Allocator.Error!Builder.Variable.Index {
@@ -10716,20 +10491,6 @@ pub const FuncGen = struct {
         }
     }
 
-    fn getIntrinsic(
-        fg: *FuncGen,
-        name: []const u8,
-        types: []const Builder.Type,
-    ) Allocator.Error!*llvm.Value {
-        const o = fg.dg.object;
-        const id = llvm.lookupIntrinsicID(name.ptr, name.len);
-        assert(id != 0);
-        const llvm_types = try o.gpa.alloc(*llvm.Type, types.len);
-        defer o.gpa.free(llvm_types);
-        for (llvm_types, types) |*llvm_type, ty| llvm_type.* = ty.toLlvm(&o.builder);
-        return o.llvm_module.getIntrinsicDeclaration(id, llvm_types.ptr, llvm_types.len);
-    }
-
     /// Load a by-ref type by constructing a new alloca and performing a memcpy.
     fn loadByRef(
         fg: *FuncGen,
@@ -10778,7 +10539,7 @@ pub const FuncGen = struct {
 
         assert(info.flags.vector_index != .runtime);
         if (info.flags.vector_index != .none) {
-            const index_u32 = try o.builder.intValue(.i32, @intFromEnum(info.flags.vector_index));
+            const index_u32 = try o.builder.intValue(.i32, info.flags.vector_index);
             const vec_elem_ty = try o.lowerType(elem_ty);
             const vec_ty = try o.builder.vectorType(.normal, info.packed_offset.host_size, vec_elem_ty);
 
@@ -10848,7 +10609,7 @@ pub const FuncGen = struct {
 
         assert(info.flags.vector_index != .runtime);
         if (info.flags.vector_index != .none) {
-            const index_u32 = try o.builder.intValue(.i32, @intFromEnum(info.flags.vector_index));
+            const index_u32 = try o.builder.intValue(.i32, info.flags.vector_index);
             const vec_elem_ty = try o.lowerType(elem_ty);
             const vec_ty = try o.builder.vectorType(.normal, info.packed_offset.host_size, vec_elem_ty);
 
@@ -10982,26 +10743,15 @@ pub const FuncGen = struct {
             else => unreachable,
         };
 
-        const fn_llvm_ty = (try o.builder.fnType(llvm_usize, &(.{llvm_usize} ** 2), .normal)).toLlvm(&o.builder);
-        const array_ptr_as_usize = try fg.wip.cast(.ptrtoint, array_ptr, llvm_usize, "");
-        const args = [_]*llvm.Value{ array_ptr_as_usize.toLlvm(&fg.wip), default_value.toLlvm(&fg.wip) };
-        const asm_fn = llvm.getInlineAsm(
-            fn_llvm_ty,
-            arch_specific.template.ptr,
-            arch_specific.template.len,
-            arch_specific.constraints.ptr,
-            arch_specific.constraints.len,
-            .True, // has side effects
-            .False, // alignstack
-            .ATT,
-            .False, // can throw
-        );
-
-        const call = (try fg.wip.unimplemented(llvm_usize, "")).finish(
-            fg.builder.buildCallOld(fn_llvm_ty, asm_fn, &args, args.len, .C, .Auto, ""),
-            &fg.wip,
+        return try fg.wip.callAsm(
+            .none,
+            try o.builder.fnType(llvm_usize, &.{ llvm_usize, llvm_usize }, .normal),
+            .{ .sideeffect = true },
+            try o.builder.string(arch_specific.template),
+            try o.builder.string(arch_specific.constraints),
+            &.{ try fg.wip.cast(.ptrtoint, array_ptr, llvm_usize, ""), default_value },
+            "",
         );
-        return call;
     }
 
     fn typeOf(fg: *FuncGen, inst: Air.Inst.Ref) Type {
src/zig_llvm.cpp
@@ -78,30 +78,6 @@
 
 using namespace llvm;
 
-void ZigLLVMInitializeLoopStrengthReducePass(LLVMPassRegistryRef R) {
-    initializeLoopStrengthReducePass(*unwrap(R));
-}
-
-void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R) {
-    initializeLowerIntrinsicsPass(*unwrap(R));
-}
-
-char *ZigLLVMGetHostCPUName(void) {
-    return strdup((const char *)sys::getHostCPUName().bytes_begin());
-}
-
-char *ZigLLVMGetNativeFeatures(void) {
-    SubtargetFeatures features;
-
-    StringMap<bool> host_features;
-    if (sys::getHostCPUFeatures(host_features)) {
-        for (auto &F : host_features)
-            features.AddFeature(F.first(), F.second);
-    }
-
-    return strdup((const char *)StringRef(features.getString()).bytes_begin());
-}
-
 #ifndef NDEBUG
 static const bool assertions_on = true;
 #else
@@ -179,14 +155,6 @@ LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, const char *Tri
     return reinterpret_cast<LLVMTargetMachineRef>(TM);
 }
 
-unsigned ZigLLVMDataLayoutGetStackAlignment(LLVMTargetDataRef TD) {
-    return unwrap(TD)->getStackAlignment().value();
-}
-
-unsigned ZigLLVMDataLayoutGetProgramAddressSpace(LLVMTargetDataRef TD) {
-    return unwrap(TD)->getProgramAddressSpace();
-}
-
 namespace {
 // LLVM's time profiler can provide a hierarchy view of the time spent
 // in each component. It generates JSON report in Chrome's "Trace Event"
@@ -410,12 +378,7 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
     return false;
 }
 
-ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref) {
-  return wrap(Type::getTokenTy(*unwrap(context_ref)));
-}
-
-
-ZIG_EXTERN_C void ZigLLVMSetOptBisectLimit(LLVMContextRef context_ref, int limit) {
+void ZigLLVMSetOptBisectLimit(LLVMContextRef context_ref, int limit) {
     static OptBisect opt_bisect;
     opt_bisect.setLimit(limit);
     unwrap(context_ref)->setOptPassGate(opt_bisect);
@@ -426,35 +389,23 @@ LLVMValueRef ZigLLVMAddFunctionInAddressSpace(LLVMModuleRef M, const char *Name,
     return wrap(func);
 }
 
-LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
-        LLVMValueRef *Args, unsigned NumArgs, ZigLLVM_CallingConv CC, ZigLLVM_CallAttr attr,
-        const char *Name)
-{
-    FunctionType *FTy = unwrap<FunctionType>(Ty);
-    CallInst *call_inst = unwrap(B)->CreateCall(FTy, unwrap(Fn),
-        ArrayRef(unwrap(Args), NumArgs), Name);
-    call_inst->setCallingConv(static_cast<CallingConv::ID>(CC));
-    switch (attr) {
-        case ZigLLVM_CallAttrAuto:
-            break;
-        case ZigLLVM_CallAttrNeverTail:
-            call_inst->setTailCallKind(CallInst::TCK_NoTail);
+void ZigLLVMSetTailCallKind(LLVMValueRef Call, enum ZigLLVMTailCallKind TailCallKind) {
+    CallInst::TailCallKind TCK;
+    switch (TailCallKind) {
+        case ZigLLVMTailCallKindNone:
+            TCK = CallInst::TCK_None;
             break;
-        case ZigLLVM_CallAttrNeverInline:
-            call_inst->addFnAttr(Attribute::NoInline);
+        case ZigLLVMTailCallKindTail:
+            TCK = CallInst::TCK_Tail;
             break;
-        case ZigLLVM_CallAttrAlwaysTail:
-            call_inst->setTailCallKind(CallInst::TCK_MustTail);
+        case ZigLLVMTailCallKindMustTail:
+            TCK = CallInst::TCK_MustTail;
             break;
-        case ZigLLVM_CallAttrAlwaysInline:
-            call_inst->addFnAttr(Attribute::AlwaysInline);
+        case ZigLLVMTailCallKindNoTail:
+            TCK = CallInst::TCK_NoTail;
             break;
     }
-    return wrap(call_inst);
-}
-
-ZIG_EXTERN_C void ZigLLVMSetTailCallKind(LLVMValueRef Call, CallInst::TailCallKind TailCallKind) {
-    unwrap<CallInst>(Call)->setTailCallKind(TailCallKind);
+    unwrap<CallInst>(Call)->setTailCallKind(TCK);
 }
 
 void ZigLLVMAddAttributeAtIndex(LLVMValueRef Val, unsigned Idx, LLVMAttributeRef A) {
@@ -481,188 +432,6 @@ LLVMValueRef ZigLLVMBuildMemSet(LLVMBuilderRef B, LLVMValueRef Ptr, LLVMValueRef
     return wrap(call_inst);
 }
 
-LLVMValueRef ZigLLVMBuildCeil(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
-    CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::ceil, unwrap(V), nullptr, name);
-    return wrap(call_inst);
-}
-
-LLVMValueRef ZigLLVMBuildCos(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
-    CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::cos, unwrap(V), nullptr, name);
-    return wrap(call_inst);
-}
-
-LLVMValueRef ZigLLVMBuildExp(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
-    CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::exp, unwrap(V), nullptr, name);
-    return wrap(call_inst);
-}
-
-LLVMValueRef ZigLLVMBuildExp2(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
-    CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::exp2, unwrap(V), nullptr, name);
-    return wrap(call_inst);
-}
-
-LLVMValueRef ZigLLVMBuildFAbs(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
-    CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::fabs, unwrap(V), nullptr, name);
-    return wrap(call_inst);
-}
-
-LLVMValueRef ZigLLVMBuildFloor(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
-    CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::floor, unwrap(V), nullptr, name);
-    return wrap(call_inst);
-}
-
-LLVMValueRef ZigLLVMBuildLog(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
-    CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::log, unwrap(V), nullptr, name);
-    return wrap(call_inst);
-}
-
-LLVMValueRef ZigLLVMBuildLog10(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
-    CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::log10, unwrap(V), nullptr, name);
-    return wrap(call_inst);
-}
-
-LLVMValueRef ZigLLVMBuildLog2(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
-    CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::log2, unwrap(V), nullptr, name);
-    return wrap(call_inst);
-}
-
-LLVMValueRef ZigLLVMBuildRound(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
-    CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::round, unwrap(V), nullptr, name);
-    return wrap(call_inst);
-}
-
-LLVMValueRef ZigLLVMBuildSin(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
-    CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::sin, unwrap(V), nullptr, name);
-    return wrap(call_inst);
-}
-
-LLVMValueRef ZigLLVMBuildSqrt(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
-    CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::sqrt, unwrap(V), nullptr, name);
-    return wrap(call_inst);
-}
-
-LLVMValueRef ZigLLVMBuildFTrunc(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
-    CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::trunc, unwrap(V), nullptr, name);
-    return wrap(call_inst);
-}
-
-LLVMValueRef ZigLLVMBuildBitReverse(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
-    CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::bitreverse, unwrap(V), nullptr, name);
-    return wrap(call_inst);
-}
-
-LLVMValueRef ZigLLVMBuildBSwap(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
-    CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::bswap, unwrap(V), nullptr, name);
-    return wrap(call_inst);
-}
-
-LLVMValueRef ZigLLVMBuildCTPop(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
-    CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::ctpop, unwrap(V), nullptr, name);
-    return wrap(call_inst);
-}
-
-LLVMValueRef ZigLLVMBuildCTLZ(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
-    CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::ctlz, unwrap(LHS), unwrap(RHS), nullptr, name);
-    return wrap(call_inst);
-}
-
-LLVMValueRef ZigLLVMBuildCTTZ(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
-    CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::cttz, unwrap(LHS), unwrap(RHS), nullptr, name);
-    return wrap(call_inst);
-}
-
-LLVMValueRef ZigLLVMBuildFMA(LLVMBuilderRef builder, LLVMValueRef A, LLVMValueRef B, LLVMValueRef C, const char *name) {
-    llvm::Type* types[1] = {
-        unwrap(A)->getType(),
-    };
-    llvm::Value* values[3] = {unwrap(A), unwrap(B), unwrap(C)};
-
-    CallInst *call_inst = unwrap(builder)->CreateIntrinsic(Intrinsic::fma, types, values, nullptr, name);
-    return wrap(call_inst);
-}
-
-LLVMValueRef ZigLLVMBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
-    CallInst *call_inst = unwrap(B)->CreateMaxNum(unwrap(LHS), unwrap(RHS), name);
-    return wrap(call_inst);
-}
-
-LLVMValueRef ZigLLVMBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
-    CallInst *call_inst = unwrap(B)->CreateMinNum(unwrap(LHS), unwrap(RHS), name);
-    return wrap(call_inst);
-}
-
-LLVMValueRef ZigLLVMBuildUMax(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
-    CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::umax, unwrap(LHS), unwrap(RHS), nullptr, name);
-    return wrap(call_inst);
-}
-
-LLVMValueRef ZigLLVMBuildUMin(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
-    CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::umin, unwrap(LHS), unwrap(RHS), nullptr, name);
-    return wrap(call_inst);
-}
-
-LLVMValueRef ZigLLVMBuildSMax(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
-    CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::smax, unwrap(LHS), unwrap(RHS), nullptr, name);
-    return wrap(call_inst);
-}
-
-LLVMValueRef ZigLLVMBuildSMin(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
-    CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::smin, unwrap(LHS), unwrap(RHS), nullptr, name);
-    return wrap(call_inst);
-}
-
-LLVMValueRef ZigLLVMBuildSAddSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
-    CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::sadd_sat, unwrap(LHS), unwrap(RHS), nullptr, name);
-    return wrap(call_inst);
-}
-
-LLVMValueRef ZigLLVMBuildUAddSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
-    CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::uadd_sat, unwrap(LHS), unwrap(RHS), nullptr, name);
-    return wrap(call_inst);
-}
-
-LLVMValueRef ZigLLVMBuildSSubSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
-    CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::ssub_sat, unwrap(LHS), unwrap(RHS), nullptr, name);
-    return wrap(call_inst);
-}
-
-LLVMValueRef ZigLLVMBuildUSubSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
-    CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::usub_sat, unwrap(LHS), unwrap(RHS), nullptr, name);
-    return wrap(call_inst);
-}
-
-LLVMValueRef ZigLLVMBuildSMulFixSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
-    llvm::Type* types[1] = {
-        unwrap(LHS)->getType(),
-    };
-    // pass scale = 0 as third argument
-    llvm::Value* values[3] = {unwrap(LHS), unwrap(RHS), unwrap(B)->getInt32(0)};
-
-    CallInst *call_inst = unwrap(B)->CreateIntrinsic(Intrinsic::smul_fix_sat, types, values, nullptr, name);
-    return wrap(call_inst);
-}
-
-LLVMValueRef ZigLLVMBuildUMulFixSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
-    llvm::Type* types[1] = {
-        unwrap(LHS)->getType(),
-    };
-    // pass scale = 0 as third argument
-    llvm::Value* values[3] = {unwrap(LHS), unwrap(RHS), unwrap(B)->getInt32(0)};
-
-    CallInst *call_inst = unwrap(B)->CreateIntrinsic(Intrinsic::umul_fix_sat, types, values, nullptr, name);
-    return wrap(call_inst);
-}
-
-LLVMValueRef ZigLLVMBuildSShlSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
-    CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::sshl_sat, unwrap(LHS), unwrap(RHS), nullptr, name);
-    return wrap(call_inst);
-}
-
-LLVMValueRef ZigLLVMBuildUShlSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
-    CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::ushl_sat, unwrap(LHS), unwrap(RHS), nullptr, name);
-    return wrap(call_inst);
-}
-
 void ZigLLVMFnSetSubprogram(LLVMValueRef fn, ZigLLVMDISubprogram *subprogram) {
     assert( isa<Function>(unwrap(fn)) );
     Function *unwrapped_function = reinterpret_cast<Function*>(unwrap(fn));
@@ -1206,14 +975,6 @@ void ZigLLVMAddSretAttr(LLVMValueRef fn_ref, LLVMTypeRef type_val) {
     func->addParamAttrs(0, attr_builder);
 }
 
-void ZigLLVMAddFunctionElemTypeAttr(LLVMValueRef fn_ref, size_t arg_index, LLVMTypeRef elem_ty) {
-    Function *func = unwrap<Function>(fn_ref);
-    AttrBuilder attr_builder(func->getContext());
-    Type *llvm_type = unwrap<Type>(elem_ty);
-    attr_builder.addTypeAttr(Attribute::ElementType, llvm_type);
-    func->addParamAttrs(arg_index, attr_builder);
-}
-
 void ZigLLVMAddFunctionAttr(LLVMValueRef fn_ref, const char *attr_name, const char *attr_value) {
     Function *func = unwrap<Function>(fn_ref);
     func->addFnAttr(attr_name, attr_value);
@@ -1223,40 +984,6 @@ void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv) {
     cl::ParseCommandLineOptions(argc, argv);
 }
 
-const char *ZigLLVMGetArchTypeName(ZigLLVM_ArchType arch) {
-    return (const char*)Triple::getArchTypeName((Triple::ArchType)arch).bytes_begin();
-}
-
-const char *ZigLLVMGetVendorTypeName(ZigLLVM_VendorType vendor) {
-    return (const char*)Triple::getVendorTypeName((Triple::VendorType)vendor).bytes_begin();
-}
-
-const char *ZigLLVMGetOSTypeName(ZigLLVM_OSType os) {
-    const char* name = (const char*)Triple::getOSTypeName((Triple::OSType)os).bytes_begin();
-    if (strcmp(name, "macosx") == 0) return "macos";
-    return name;
-}
-
-const char *ZigLLVMGetEnvironmentTypeName(ZigLLVM_EnvironmentType env_type) {
-    return (const char*)Triple::getEnvironmentTypeName((Triple::EnvironmentType)env_type).bytes_begin();
-}
-
-void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type,
-        ZigLLVM_VendorType *vendor_type, ZigLLVM_OSType *os_type, ZigLLVM_EnvironmentType *environ_type,
-        ZigLLVM_ObjectFormatType *oformat)
-{
-    char *native_triple = LLVMGetDefaultTargetTriple();
-    Triple triple(Triple::normalize(native_triple));
-
-    *arch_type = (ZigLLVM_ArchType)triple.getArch();
-    *vendor_type = (ZigLLVM_VendorType)triple.getVendor();
-    *os_type = (ZigLLVM_OSType)triple.getOS();
-    *environ_type = (ZigLLVM_EnvironmentType)triple.getEnvironment();
-    *oformat = (ZigLLVM_ObjectFormatType)triple.getObjectFormat();
-
-    free(native_triple);
-}
-
 void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module, bool produce_dwarf64) {
     unwrap(module)->addModuleFlag(Module::Warning, "Debug Info Version", DEBUG_METADATA_VERSION);
     unwrap(module)->addModuleFlag(Module::Warning, "Dwarf Version", 4);
@@ -1314,50 +1041,6 @@ LLVMValueRef ZigLLVMBuildAllocaInAddressSpace(LLVMBuilderRef builder, LLVMTypeRe
   return wrap(unwrap(builder)->CreateAlloca(unwrap(Ty), AddressSpace, nullptr, Name));
 }
 
-void ZigLLVMSetTailCall(LLVMValueRef Call) {
-    unwrap<CallInst>(Call)->setTailCallKind(CallInst::TCK_MustTail);
-}
-
-void ZigLLVMSetCallSret(LLVMValueRef Call, LLVMTypeRef return_type) {
-    CallInst *call_inst = unwrap<CallInst>(Call);
-    Type *llvm_type = unwrap<Type>(return_type);
-    call_inst->addParamAttr(AttributeList::ReturnIndex,
-            Attribute::getWithStructRetType(call_inst->getContext(), llvm_type));
-}
-
-void ZigLLVMSetCallElemTypeAttr(LLVMValueRef Call, size_t arg_index, LLVMTypeRef return_type) {
-    CallInst *call_inst = unwrap<CallInst>(Call);
-    Type *llvm_type = unwrap<Type>(return_type);
-    call_inst->addParamAttr(arg_index,
-            Attribute::get(call_inst->getContext(), Attribute::ElementType, llvm_type));
-}
-
-void ZigLLVMFunctionSetPrefixData(LLVMValueRef function, LLVMValueRef data) {
-    unwrap<Function>(function)->setPrefixData(unwrap<Constant>(data));
-}
-
-void ZigLLVMFunctionSetCallingConv(LLVMValueRef function, ZigLLVM_CallingConv cc) {
-    unwrap<Function>(function)->setCallingConv(static_cast<CallingConv::ID>(cc));
-}
-
-class MyOStream: public raw_ostream {
-    public:
-        MyOStream(void (*_append_diagnostic)(void *, const char *, size_t), void *_context) :
-            raw_ostream(true), append_diagnostic(_append_diagnostic), context(_context), pos(0) {
-
-        }
-        void write_impl(const char *ptr, size_t len) override {
-            append_diagnostic(context, ptr, len);
-            pos += len;
-        }
-        uint64_t current_pos() const override {
-            return pos;
-        }
-        void (*append_diagnostic)(void *, const char *, size_t);
-        void *context;
-        size_t pos;
-};
-
 bool ZigLLVMWriteImportLibrary(const char *def_path, const ZigLLVM_ArchType arch,
                                const char *output_lib_path, bool kill_at)
 {
@@ -1549,10 +1232,6 @@ ZigLLVMDIGlobalVariable* ZigLLVMGlobalGetVariable(ZigLLVMDIGlobalVariableExpress
 	return reinterpret_cast<ZigLLVMDIGlobalVariable*>(reinterpret_cast<DIGlobalVariableExpression*>(global_variable_expression)->getVariable());
 }
 
-ZigLLVMDIGlobalExpression* ZigLLVMGlobalGetExpression(ZigLLVMDIGlobalVariableExpression *global_variable_expression) {
-	return reinterpret_cast<ZigLLVMDIGlobalExpression*>(reinterpret_cast<DIGlobalVariableExpression*>(global_variable_expression)->getExpression());
-}
-
 void ZigLLVMAttachMetaData(LLVMValueRef Val, ZigLLVMDIGlobalVariableExpression *global_variable_expression) {
 	unwrap<GlobalVariable>(Val)->addDebugInfo(reinterpret_cast<DIGlobalVariableExpression*>(global_variable_expression));
 }
src/zig_llvm.h
@@ -43,13 +43,6 @@ struct ZigLLVMInsertionPoint;
 struct ZigLLVMDINode;
 struct ZigLLVMMDString;
 
-ZIG_EXTERN_C void ZigLLVMInitializeLoopStrengthReducePass(LLVMPassRegistryRef R);
-ZIG_EXTERN_C void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R);
-
-/// Caller must free memory with LLVMDisposeMessage
-ZIG_EXTERN_C char *ZigLLVMGetHostCPUName(void);
-ZIG_EXTERN_C char *ZigLLVMGetNativeFeatures(void);
-
 ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,
         char **error_message, bool is_debug,
         bool is_small, bool time_report, bool tsan, bool lto,
@@ -67,13 +60,20 @@ ZIG_EXTERN_C LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, co
     const char *CPU, const char *Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc,
     LLVMCodeModel CodeModel, bool function_sections, enum ZigLLVMABIType float_abi, const char *abi_name);
 
-ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref);
-
 ZIG_EXTERN_C void ZigLLVMSetOptBisectLimit(LLVMContextRef context_ref, int limit);
 
 ZIG_EXTERN_C LLVMValueRef ZigLLVMAddFunctionInAddressSpace(LLVMModuleRef M, const char *Name,
         LLVMTypeRef FunctionTy, unsigned AddressSpace);
 
+enum ZigLLVMTailCallKind {
+    ZigLLVMTailCallKindNone,
+    ZigLLVMTailCallKindTail,
+    ZigLLVMTailCallKindMustTail,
+    ZigLLVMTailCallKindNoTail,
+};
+
+ZIG_EXTERN_C void ZigLLVMSetTailCallKind(LLVMValueRef Call, enum ZigLLVMTailCallKind TailCallKind);
+
 enum ZigLLVM_CallingConv {
     ZigLLVM_C = 0,
     ZigLLVM_Fast = 8,
@@ -129,10 +129,6 @@ enum ZigLLVM_CallAttr {
     ZigLLVM_CallAttrAlwaysTail,
     ZigLLVM_CallAttrAlwaysInline,
 };
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMTypeRef function_type,
-        LLVMValueRef Fn, LLVMValueRef *Args, unsigned NumArgs, enum ZigLLVM_CallingConv CC,
-        enum ZigLLVM_CallAttr attr, const char *Name);
-
 ZIG_EXTERN_C void ZigLLVMAddAttributeAtIndex(LLVMValueRef Val, unsigned Idx, LLVMAttributeRef A);
 
 ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign,
@@ -141,47 +137,6 @@ ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst,
 ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemSet(LLVMBuilderRef B, LLVMValueRef Ptr, LLVMValueRef Val, LLVMValueRef Size,
         unsigned Align, bool isVolatile);
 
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCeil(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCos(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildExp(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildExp2(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFAbs(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFloor(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildLog(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildLog10(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildLog2(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildRound(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSin(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSqrt(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFTrunc(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
-
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildBitReverse(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildBSwap(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCTPop(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
-
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCTLZ(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCTTZ(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
-
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFMA(LLVMBuilderRef builder, LLVMValueRef A, LLVMValueRef B, LLVMValueRef C, const char* name);
-
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMaxNum(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMinNum(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
-
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildUMax(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildUMin(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSMax(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSMin(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildUAddSat(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSAddSat(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildUSubSat(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSSubSat(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSMulFixSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name);
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildUMulFixSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name);
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildUShlSat(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
-ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSShlSat(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
-ZIG_EXTERN_C LLVMValueRef LLVMBuildVectorSplat(LLVMBuilderRef B, unsigned elem_count, LLVMValueRef V, const char *Name);
-
-
 ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildNSWShl(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS,
         const char *name);
 ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildNUWShl(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS,
@@ -345,22 +300,15 @@ ZIG_EXTERN_C LLVMValueRef ZigLLVMInsertDbgValueIntrinsicAtEnd(struct ZigLLVMDIBu
         struct ZigLLVMDILocation *debug_loc, LLVMBasicBlockRef basic_block_ref);
 
 ZIG_EXTERN_C void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state);
-ZIG_EXTERN_C void ZigLLVMSetTailCall(LLVMValueRef Call);
-ZIG_EXTERN_C void ZigLLVMSetCallSret(LLVMValueRef Call, LLVMTypeRef return_type);
-ZIG_EXTERN_C void ZigLLVMSetCallElemTypeAttr(LLVMValueRef Call, size_t arg_index, LLVMTypeRef return_type);
-ZIG_EXTERN_C void ZigLLVMFunctionSetPrefixData(LLVMValueRef fn, LLVMValueRef data);
-ZIG_EXTERN_C void ZigLLVMFunctionSetCallingConv(LLVMValueRef function, enum ZigLLVM_CallingConv cc);
 
 ZIG_EXTERN_C void ZigLLVMAddFunctionAttr(LLVMValueRef fn, const char *attr_name, const char *attr_value);
 ZIG_EXTERN_C void ZigLLVMAddByValAttr(LLVMValueRef fn_ref, unsigned ArgNo, LLVMTypeRef type_val);
 ZIG_EXTERN_C void ZigLLVMAddSretAttr(LLVMValueRef fn_ref, LLVMTypeRef type_val);
-ZIG_EXTERN_C void ZigLLVMAddFunctionElemTypeAttr(LLVMValueRef fn_ref, size_t arg_index, LLVMTypeRef elem_ty);
 ZIG_EXTERN_C void ZigLLVMAddFunctionAttrCold(LLVMValueRef fn);
 
 ZIG_EXTERN_C void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv);
 
 ZIG_EXTERN_C ZigLLVMDIGlobalVariable* ZigLLVMGlobalGetVariable(ZigLLVMDIGlobalVariableExpression *global_variable_expression);
-ZIG_EXTERN_C ZigLLVMDIGlobalExpression* ZigLLVMGlobalGetExpression(ZigLLVMDIGlobalVariableExpression *global_variable_expression);
 ZIG_EXTERN_C void ZigLLVMAttachMetaData(LLVMValueRef Val, ZigLLVMDIGlobalVariableExpression *global_variable_expression);
 
 
@@ -610,11 +558,6 @@ ZIG_EXTERN_C void ZigLLVMTakeName(LLVMValueRef new_owner, LLVMValueRef victim);
 #define ZigLLVM_DIFlags_LittleEndian (1U << 28)
 #define ZigLLVM_DIFlags_AllCallsDescribed (1U << 29)
 
-ZIG_EXTERN_C const char *ZigLLVMGetArchTypeName(enum ZigLLVM_ArchType arch);
-ZIG_EXTERN_C const char *ZigLLVMGetVendorTypeName(enum ZigLLVM_VendorType vendor);
-ZIG_EXTERN_C const char *ZigLLVMGetOSTypeName(enum ZigLLVM_OSType os);
-ZIG_EXTERN_C const char *ZigLLVMGetEnvironmentTypeName(enum ZigLLVM_EnvironmentType abi);
-
 ZIG_EXTERN_C bool ZigLLDLinkCOFF(int argc, const char **argv, bool can_exit_early, bool disable_output);
 ZIG_EXTERN_C bool ZigLLDLinkELF(int argc, const char **argv, bool can_exit_early, bool disable_output);
 ZIG_EXTERN_C bool ZigLLDLinkWasm(int argc, const char **argv, bool can_exit_early, bool disable_output);
@@ -625,11 +568,4 @@ ZIG_EXTERN_C bool ZigLLVMWriteArchive(const char *archive_name, const char **fil
 ZIG_EXTERN_C bool ZigLLVMWriteImportLibrary(const char *def_path, const enum ZigLLVM_ArchType arch,
                                const char *output_lib_path, bool kill_at);
 
-ZIG_EXTERN_C void ZigLLVMGetNativeTarget(enum ZigLLVM_ArchType *arch_type,
-        enum ZigLLVM_VendorType *vendor_type, enum ZigLLVM_OSType *os_type, enum ZigLLVM_EnvironmentType *environ_type,
-        enum ZigLLVM_ObjectFormatType *oformat);
-
-ZIG_EXTERN_C unsigned ZigLLVMDataLayoutGetStackAlignment(LLVMTargetDataRef TD);
-ZIG_EXTERN_C unsigned ZigLLVMDataLayoutGetProgramAddressSpace(LLVMTargetDataRef TD);
-
 #endif