authorgravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2026-07-08 10:31:16+03:30
committergravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2026-07-10 11:39:54+03:30
log332c73ccd2246af417afaa42597055c9ba6255c1
tree03a89089e04301768ea3ccc111b4d20c654fdb58
parentf02d21c8c888b07ead4034562beb1872faee11d6

spirv: cache composite integer limbs and use 64bit ints when possible


1 files changed, 210 insertions(+), 149 deletions(-)

src/codegen/spirv/CodeGen.zig+210-149
......@@ -37,6 +37,10 @@ prologue: Section = .{},
3737body: Section = .{},
3838args: std.ArrayList(Id) = .empty,
3939next_arg_index: u32 = 0,
40/// Caches the limb extractions for composite integer values so repeated
41/// arithmetic on the same operand doesn't re-emit `OpCompositeExtract` per
42/// limb per use. Slices are owned by `cg.arena`.
43composite_limbs: std.AutoHashMapUnmanaged(Id, []const Id) = .empty,
4044block_stack: std.ArrayList(*Block) = .empty,
4145block_label: Id = .none,
4246/// Whether the current block has been terminated by a terminator
......@@ -49,7 +53,18 @@ tracked_allocas: std.AutoHashMapUnmanaged(Id, ?Id) = .empty,
4953loop_switches: std.AutoHashMapUnmanaged(Air.Inst.Index, LoopSwitch) = .empty,
5054id_scratch: std.ArrayList(Id) = .empty,
5155
52const big_int_bits = @bitSizeOf(u32);
56fn bigIntBits(cg: *const CodeGen) u16 {
57 const target = cg.zcu.getTarget();
58 return if (target.cpu.has(.spirv, .int64)) 64 else 32;
59}
60
61fn limbType(cg: *const CodeGen) Type {
62 return if (cg.bigIntBits() == 64) .u64 else .u32;
63}
64
65fn limbTypeId(cg: *CodeGen) !Id {
66 return cg.resolveType(cg.limbType(), .direct);
67}
5368
5469/// Data can be lowered into in two basic representations: indirect, which is when
5570/// a type is stored in memory, and direct, which is how a type is stored when its
......@@ -163,6 +178,7 @@ pub fn deinit(cg: *CodeGen) void {
163178 cg.block_stack.deinit(gpa);
164179 cg.block_results.deinit(gpa);
165180 cg.args.deinit(gpa);
181 cg.composite_limbs.deinit(gpa);
166182 cg.tracked_allocas.deinit(gpa);
167183 cg.inst_results.deinit(gpa);
168184 cg.loop_switches.deinit(gpa);
......@@ -478,7 +494,7 @@ pub fn backingIntBits(cg: *const CodeGen, bits: u16) struct { u16, bool } {
478494 if (bits <= int.bits and int.enabled) return .{ int.bits, false };
479495 }
480496
481 return .{ std.mem.alignForward(u16, bits, big_int_bits), true };
497 return .{ std.mem.alignForward(u16, bits, cg.bigIntBits()), true };
482498}
483499
484500pub fn intType(cg: *CodeGen, signedness: std.lang.Signedness, bits: u16) !Id {
......@@ -492,14 +508,16 @@ pub fn intType(cg: *CodeGen, signedness: std.lang.Signedness, bits: u16) !Id {
492508 };
493509 const backing_bits, const big_int = cg.backingIntBits(bits);
494510 if (big_int) {
495 const u32_ty = try cg.intType(.unsigned, 32);
511 const limb_bits = cg.bigIntBits();
512 const limb_ty = try cg.intType(.unsigned, limb_bits);
513 const len_ty = try cg.intType(.unsigned, 32);
496514 const len_id = cg.allocId();
497515 try cg.sections.globals.emit(cg.gpa, .OpConstant, .{
498 .id_result_type = u32_ty,
516 .id_result_type = len_ty,
499517 .id_result = len_id,
500 .value = .{ .uint32 = backing_bits / big_int_bits },
518 .value = .{ .uint32 = backing_bits / limb_bits },
501519 });
502 return cg.arrayType(len_id, u32_ty);
520 return cg.arrayType(len_id, limb_ty);
503521 }
504522
505523 const result_id = cg.allocId();
......@@ -1443,7 +1461,7 @@ fn constInt(cg: *CodeGen, ty: Type, value: anytype) !Id {
14431461 .signed => @bitCast(@as(i64, @intCast(value))),
14441462 .unsigned => @as(u64, @intCast(value)),
14451463 };
1446 const n_limbs = backing_bits / big_int_bits;
1464 const n_limbs = backing_bits / cg.bigIntBits();
14471465 const fill: u32 = if (signedness == .signed and value < 0) 0xFFFFFFFF else 0;
14481466 const scratch_top = cg.id_scratch.items.len;
14491467 defer cg.id_scratch.shrinkRetainingCapacity(scratch_top);
......@@ -1616,21 +1634,33 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id {
16161634 const int_info = ty.intInfo(zcu);
16171635 const backing_bits, const is_big_int = cg.backingIntBits(int_info.bits);
16181636 if (is_big_int) {
1619 const n_limbs = backing_bits / big_int_bits;
1637 const limb_bits = cg.bigIntBits();
1638 const n_limbs = backing_bits / limb_bits;
16201639 const big_result_ty_id = try cg.resolveType(ty, .indirect);
16211640 var bigint_space: Value.BigIntSpace = undefined;
16221641 const bigint = val.toBigInt(&bigint_space, zcu);
1623 const limb_values = try gpa.alloc(u32, n_limbs);
1624 defer gpa.free(limb_values);
1625 bigint.writeTwosComplement(std.mem.sliceAsBytes(limb_values), .little);
1626 if (builtin.cpu.arch.endian() == .big) {
1627 for (limb_values) |*limb| limb.* = @byteSwap(limb.*);
1628 }
1642 const limb_bytes = try gpa.alloc(u8, backing_bits / 8);
1643 defer gpa.free(limb_bytes);
1644 bigint.writeTwosComplement(limb_bytes, .little);
16291645 const scratch_top = cg.id_scratch.items.len;
16301646 defer cg.id_scratch.shrinkRetainingCapacity(scratch_top);
16311647 const constituents = try cg.id_scratch.addManyAsSlice(gpa, n_limbs);
1632 for (constituents, 0..) |*c, i| {
1633 c.* = try cg.constInt(.u32, limb_values[i]);
1648 switch (limb_bits) {
1649 32 => {
1650 const limbs_u32: []u32 = @ptrCast(@alignCast(limb_bytes));
1651 for (constituents, limbs_u32) |*c, v| {
1652 const host_v = if (builtin.cpu.arch.endian() == .big) @byteSwap(v) else v;
1653 c.* = try cg.constInt(.u32, host_v);
1654 }
1655 },
1656 64 => {
1657 const limbs_u64: []u64 = @ptrCast(@alignCast(limb_bytes));
1658 for (constituents, limbs_u64) |*c, v| {
1659 const host_v = if (builtin.cpu.arch.endian() == .big) @byteSwap(v) else v;
1660 c.* = try cg.constInt(.u64, host_v);
1661 }
1662 },
1663 else => unreachable,
16341664 }
16351665 break :cache try cg.constructComposite(big_result_ty_id, constituents);
16361666 }
......@@ -2766,20 +2796,28 @@ const CompositeInt = struct {
27662796 info: ArithmeticTypeInfo,
27672797
27682798 fn init(cg: *CodeGen, composite_id: Id, info: ArithmeticTypeInfo) !CompositeInt {
2769 const n_limbs: u16 = info.backing_bits / big_int_bits;
2799 const n_limbs: u16 = info.backing_bits / cg.bigIntBits();
27702800 const gpa = cg.gpa;
2771 const u32_ty_id = try cg.resolveType(.u32, .direct);
2801 if (cg.composite_limbs.get(composite_id)) |cached| {
2802 assert(cached.len == n_limbs);
2803 const limbs = try cg.id_scratch.addManyAsSlice(gpa, n_limbs);
2804 @memcpy(limbs, cached);
2805 return .{ .cg = cg, .limbs = limbs, .n_limbs = n_limbs, .info = info };
2806 }
2807 const limb_ty_id = try cg.limbTypeId();
27722808 const limbs = try cg.id_scratch.addManyAsSlice(gpa, n_limbs);
27732809 for (limbs, 0..) |*limb, i| {
27742810 const result_id = cg.allocId();
27752811 try cg.body.emit(gpa, .OpCompositeExtract, .{
2776 .id_result_type = u32_ty_id,
2812 .id_result_type = limb_ty_id,
27772813 .id_result = result_id,
27782814 .composite = composite_id,
27792815 .indexes = &.{@as(u32, @intCast(i))},
27802816 });
27812817 limb.* = result_id;
27822818 }
2819 const cached = try cg.arena.dupe(Id, limbs);
2820 try cg.composite_limbs.put(gpa, composite_id, cached);
27832821 return .{ .cg = cg, .limbs = limbs, .n_limbs = n_limbs, .info = info };
27842822 }
27852823
......@@ -2793,9 +2831,9 @@ const CompositeInt = struct {
27932831 }
27942832
27952833 fn zero(cg: *CodeGen, info: ArithmeticTypeInfo) !CompositeInt {
2796 const n_limbs: u16 = info.backing_bits / big_int_bits;
2834 const n_limbs: u16 = info.backing_bits / cg.bigIntBits();
27972835 const limbs = try cg.id_scratch.addManyAsSlice(cg.gpa, n_limbs);
2798 const zero_id = try cg.constInt(.u32, @as(u32, 0));
2836 const zero_id = try cg.constInt(cg.limbType(), @as(u64, 0));
27992837 for (limbs) |*limb| limb.* = zero_id;
28002838 return .{ .cg = cg, .limbs = limbs, .n_limbs = n_limbs, .info = info };
28012839 }
......@@ -2808,10 +2846,10 @@ const CompositeInt = struct {
28082846 fn limbBinOp(ci: CompositeInt, opcode: Opcode, lhs: Id, rhs: Id) !Id {
28092847 const cg = ci.cg;
28102848 const gpa = cg.gpa;
2811 const u32_ty_id = try cg.resolveType(.u32, .direct);
2849 const limb_ty_id = try cg.limbTypeId();
28122850 const result_id = cg.allocId();
28132851 try cg.body.emitRaw(gpa, opcode, 4);
2814 cg.body.writeOperand(Id, u32_ty_id);
2852 cg.body.writeOperand(Id, limb_ty_id);
28152853 cg.body.writeOperand(Id, result_id);
28162854 cg.body.writeOperand(Id, lhs);
28172855 cg.body.writeOperand(Id, rhs);
......@@ -2821,10 +2859,10 @@ const CompositeInt = struct {
28212859 fn limbUnOp(ci: CompositeInt, opcode: Opcode, operand: Id) !Id {
28222860 const cg = ci.cg;
28232861 const gpa = cg.gpa;
2824 const u32_ty_id = try cg.resolveType(.u32, .direct);
2862 const limb_ty_id = try cg.limbTypeId();
28252863 const result_id = cg.allocId();
28262864 try cg.body.emitRaw(gpa, opcode, 3);
2827 cg.body.writeOperand(Id, u32_ty_id);
2865 cg.body.writeOperand(Id, limb_ty_id);
28282866 cg.body.writeOperand(Id, result_id);
28292867 cg.body.writeOperand(Id, operand);
28302868 return result_id;
......@@ -2916,16 +2954,17 @@ const CompositeInt = struct {
29162954 var cmp_l = l;
29172955 var cmp_r = r;
29182956 if (use_signed) {
2919 const i32_ty_id = try cg.resolveType(.i32, .direct);
2957 const signed_limb_ty: Type = if (cg.bigIntBits() == 64) .i64 else .i32;
2958 const signed_limb_ty_id = try cg.resolveType(signed_limb_ty, .direct);
29202959 const sl = cg.allocId();
29212960 try cg.body.emit(gpa, .OpBitcast, .{
2922 .id_result_type = i32_ty_id,
2961 .id_result_type = signed_limb_ty_id,
29232962 .id_result = sl,
29242963 .operand = l,
29252964 });
29262965 const sr = cg.allocId();
29272966 try cg.body.emit(gpa, .OpBitcast, .{
2928 .id_result_type = i32_ty_id,
2967 .id_result_type = signed_limb_ty_id,
29292968 .id_result = sr,
29302969 .operand = r,
29312970 });
......@@ -2969,16 +3008,17 @@ const CompositeInt = struct {
29693008 const comp = zcu.comp;
29703009 const io = comp.io;
29713010
2972 const u32_zig = try pt.intType(.unsigned, 32);
2973 const u32_ty_id = try cg.resolveType(.u32, .direct);
3011 const limb_bits = cg.bigIntBits();
3012 const limb_zig = try pt.intType(.unsigned, limb_bits);
3013 const limb_ty_id = try cg.limbTypeId();
29743014 const carry_struct_ty: Type = .fromInterned(try ip.getTupleType(gpa, io, pt.tid, .{
2975 .types = &.{ u32_zig.toIntern(), u32_zig.toIntern() },
3015 .types = &.{ limb_zig.toIntern(), limb_zig.toIntern() },
29763016 .values = &.{ .none, .none },
29773017 }));
29783018 const carry_struct_ty_id = try cg.resolveType(carry_struct_ty, .direct);
29793019
29803020 const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, ci.n_limbs);
2981 var carry_id = try cg.constInt(.u32, @as(u32, 0));
3021 var carry_id = try cg.constInt(cg.limbType(), @as(u64, 0));
29823022
29833023 const opcode: Opcode = if (is_add) .OpIAddCarry else .OpISubBorrow;
29843024
......@@ -2992,14 +3032,14 @@ const CompositeInt = struct {
29923032
29933033 const sum1 = cg.allocId();
29943034 try cg.body.emit(gpa, .OpCompositeExtract, .{
2995 .id_result_type = u32_ty_id,
3035 .id_result_type = limb_ty_id,
29963036 .id_result = sum1,
29973037 .composite = op1,
29983038 .indexes = &.{0},
29993039 });
30003040 const carry1 = cg.allocId();
30013041 try cg.body.emit(gpa, .OpCompositeExtract, .{
3002 .id_result_type = u32_ty_id,
3042 .id_result_type = limb_ty_id,
30033043 .id_result = carry1,
30043044 .composite = op1,
30053045 .indexes = &.{1},
......@@ -3014,14 +3054,14 @@ const CompositeInt = struct {
30143054
30153055 result_limbs[i] = cg.allocId();
30163056 try cg.body.emit(gpa, .OpCompositeExtract, .{
3017 .id_result_type = u32_ty_id,
3057 .id_result_type = limb_ty_id,
30183058 .id_result = result_limbs[i],
30193059 .composite = op2,
30203060 .indexes = &.{0},
30213061 });
30223062 const carry2 = cg.allocId();
30233063 try cg.body.emit(gpa, .OpCompositeExtract, .{
3024 .id_result_type = u32_ty_id,
3064 .id_result_type = limb_ty_id,
30253065 .id_result = carry2,
30263066 .composite = op2,
30273067 .indexes = &.{1},
......@@ -3036,16 +3076,18 @@ const CompositeInt = struct {
30363076 fn shl(ci: CompositeInt, shift_amt_id: Id) !CompositeInt {
30373077 const cg = ci.cg;
30383078 const gpa = cg.gpa;
3039 const u32_ty_id = try cg.resolveType(.u32, .direct);
3079 const limb_bits = cg.bigIntBits();
3080 const limb_ty = cg.limbType();
3081 const limb_ty_id = try cg.limbTypeId();
30403082 const bool_ty_id = try cg.resolveType(.bool, .direct);
3041 const zero_id = try cg.constInt(.u32, @as(u32, 0));
3042 const five_id = try cg.constInt(.u32, @as(u32, 5));
3043 const thirty_one_id = try cg.constInt(.u32, @as(u32, 31));
3044 const thirty_two_id = try cg.constInt(.u32, @as(u32, 32));
3045
3046 const whole = try ci.limbBinOp(.OpShiftRightLogical, shift_amt_id, five_id);
3047 const frac = try ci.limbBinOp(.OpBitwiseAnd, shift_amt_id, thirty_one_id);
3048 const comp_frac = try ci.limbBinOp(.OpISub, thirty_two_id, frac);
3083 const zero_id = try cg.constInt(limb_ty, @as(u64, 0));
3084 const log2_bits_id = try cg.constInt(limb_ty, @as(u64, std.math.log2_int(u16, limb_bits)));
3085 const bits_minus_1_id = try cg.constInt(limb_ty, @as(u64, limb_bits - 1));
3086 const bits_id = try cg.constInt(limb_ty, @as(u64, limb_bits));
3087
3088 const whole = try ci.limbBinOp(.OpShiftRightLogical, shift_amt_id, log2_bits_id);
3089 const frac = try ci.limbBinOp(.OpBitwiseAnd, shift_amt_id, bits_minus_1_id);
3090 const comp_frac = try ci.limbBinOp(.OpISub, bits_id, frac);
30493091 const frac_is_zero = blk: {
30503092 const r = cg.allocId();
30513093 try cg.body.emit(gpa, .OpIEqual, .{
......@@ -3060,12 +3102,12 @@ const CompositeInt = struct {
30603102 const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, ci.n_limbs);
30613103
30623104 for (0..ci.n_limbs) |i| {
3063 const i_id = try cg.constInt(.u32, @as(u32, @intCast(i)));
3105 const i_id = try cg.constInt(limb_ty, @as(u64, @intCast(i)));
30643106 var main_val = zero_id;
30653107 var carry_val = zero_id;
30663108
30673109 for (0..ci.n_limbs) |j| {
3068 const j_id = try cg.constInt(.u32, @as(u32, @intCast(j)));
3110 const j_id = try cg.constInt(limb_ty, @as(u64, @intCast(j)));
30693111 const j_plus_whole = try ci.limbBinOp(.OpIAdd, j_id, whole);
30703112
30713113 const is_main = blk: {
......@@ -3082,7 +3124,7 @@ const CompositeInt = struct {
30823124 main_val = blk: {
30833125 const r = cg.allocId();
30843126 try cg.body.emit(gpa, .OpSelect, .{
3085 .id_result_type = u32_ty_id,
3127 .id_result_type = limb_ty_id,
30863128 .id_result = r,
30873129 .condition = is_main,
30883130 .object_1 = shifted,
......@@ -3091,7 +3133,7 @@ const CompositeInt = struct {
30913133 break :blk r;
30923134 };
30933135
3094 const one_id = try cg.constInt(.u32, @as(u32, 1));
3136 const one_id = try cg.constInt(limb_ty, @as(u64, 1));
30953137 const j_plus_whole_plus_1 = try ci.limbBinOp(.OpIAdd, j_plus_whole, one_id);
30963138 const is_carry = blk: {
30973139 const r = cg.allocId();
......@@ -3107,7 +3149,7 @@ const CompositeInt = struct {
31073149 const guarded_carry = blk: {
31083150 const r = cg.allocId();
31093151 try cg.body.emit(gpa, .OpSelect, .{
3110 .id_result_type = u32_ty_id,
3152 .id_result_type = limb_ty_id,
31113153 .id_result = r,
31123154 .condition = frac_is_zero,
31133155 .object_1 = zero_id,
......@@ -3118,7 +3160,7 @@ const CompositeInt = struct {
31183160 carry_val = blk: {
31193161 const r = cg.allocId();
31203162 try cg.body.emit(gpa, .OpSelect, .{
3121 .id_result_type = u32_ty_id,
3163 .id_result_type = limb_ty_id,
31223164 .id_result = r,
31233165 .condition = is_carry,
31243166 .object_1 = guarded_carry,
......@@ -3137,16 +3179,18 @@ const CompositeInt = struct {
31373179 fn shr(ci: CompositeInt, shift_amt_id: Id, comptime is_arithmetic: bool) !CompositeInt {
31383180 const cg = ci.cg;
31393181 const gpa = cg.gpa;
3140 const u32_ty_id = try cg.resolveType(.u32, .direct);
3182 const limb_bits = cg.bigIntBits();
3183 const limb_ty = cg.limbType();
3184 const limb_ty_id = try cg.limbTypeId();
31413185 const bool_ty_id = try cg.resolveType(.bool, .direct);
3142 const zero_id = try cg.constInt(.u32, @as(u32, 0));
3143 const five_id = try cg.constInt(.u32, @as(u32, 5));
3144 const thirty_one_id = try cg.constInt(.u32, @as(u32, 31));
3145 const thirty_two_id = try cg.constInt(.u32, @as(u32, 32));
3146
3147 const whole = try ci.limbBinOp(.OpShiftRightLogical, shift_amt_id, five_id);
3148 const frac = try ci.limbBinOp(.OpBitwiseAnd, shift_amt_id, thirty_one_id);
3149 const comp_frac = try ci.limbBinOp(.OpISub, thirty_two_id, frac);
3186 const zero_id = try cg.constInt(limb_ty, @as(u64, 0));
3187 const log2_bits_id = try cg.constInt(limb_ty, @as(u64, std.math.log2_int(u16, limb_bits)));
3188 const bits_minus_1_id = try cg.constInt(limb_ty, @as(u64, limb_bits - 1));
3189 const bits_id = try cg.constInt(limb_ty, @as(u64, limb_bits));
3190
3191 const whole = try ci.limbBinOp(.OpShiftRightLogical, shift_amt_id, log2_bits_id);
3192 const frac = try ci.limbBinOp(.OpBitwiseAnd, shift_amt_id, bits_minus_1_id);
3193 const comp_frac = try ci.limbBinOp(.OpISub, bits_id, frac);
31503194 const frac_is_zero = blk: {
31513195 const r = cg.allocId();
31523196 try cg.body.emit(gpa, .OpIEqual, .{
......@@ -3159,24 +3203,25 @@ const CompositeInt = struct {
31593203 };
31603204
31613205 const fill_id = if (is_arithmetic) blk: {
3162 const i32_ty_id = try cg.resolveType(.i32, .direct);
3206 const signed_limb_ty: Type = if (limb_bits == 64) .i64 else .i32;
3207 const signed_limb_ty_id = try cg.resolveType(signed_limb_ty, .direct);
31633208 const msb_signed = cg.allocId();
31643209 try cg.body.emit(gpa, .OpBitcast, .{
3165 .id_result_type = i32_ty_id,
3210 .id_result_type = signed_limb_ty_id,
31663211 .id_result = msb_signed,
31673212 .operand = ci.limbs[ci.n_limbs - 1],
31683213 });
3169 const shift31 = try cg.constInt(.i32, @as(i32, 31));
3214 const shift_amt = try cg.constInt(signed_limb_ty, @as(u64, limb_bits - 1));
31703215 const sign_ext = cg.allocId();
31713216 try cg.body.emit(gpa, .OpShiftRightArithmetic, .{
3172 .id_result_type = i32_ty_id,
3217 .id_result_type = signed_limb_ty_id,
31733218 .id_result = sign_ext,
31743219 .base = msb_signed,
3175 .shift = shift31,
3220 .shift = shift_amt,
31763221 });
31773222 const back = cg.allocId();
31783223 try cg.body.emit(gpa, .OpBitcast, .{
3179 .id_result_type = u32_ty_id,
3224 .id_result_type = limb_ty_id,
31803225 .id_result = back,
31813226 .operand = sign_ext,
31823227 });
......@@ -3189,7 +3234,7 @@ const CompositeInt = struct {
31893234 const shifted_fill = try ci.limbBinOp(.OpShiftLeftLogical, fill_id, comp_frac);
31903235 const guarded = cg.allocId();
31913236 try cg.body.emit(gpa, .OpSelect, .{
3192 .id_result_type = u32_ty_id,
3237 .id_result_type = limb_ty_id,
31933238 .id_result = guarded,
31943239 .condition = frac_is_zero,
31953240 .object_1 = zero_id,
......@@ -3199,12 +3244,12 @@ const CompositeInt = struct {
31993244 } else zero_id;
32003245
32013246 for (0..ci.n_limbs) |i| {
3202 const i_id = try cg.constInt(.u32, @as(u32, @intCast(i)));
3247 const i_id = try cg.constInt(limb_ty, @as(u64, @intCast(i)));
32033248 var main_val = fill_id;
32043249 var carry_val = arith_carry_init;
32053250
32063251 for (0..ci.n_limbs) |j| {
3207 const j_id = try cg.constInt(.u32, @as(u32, @intCast(j)));
3252 const j_id = try cg.constInt(limb_ty, @as(u64, @intCast(j)));
32083253 const i_plus_whole = try ci.limbBinOp(.OpIAdd, i_id, whole);
32093254 const is_main = blk: {
32103255 const r = cg.allocId();
......@@ -3220,7 +3265,7 @@ const CompositeInt = struct {
32203265 main_val = blk: {
32213266 const r = cg.allocId();
32223267 try cg.body.emit(gpa, .OpSelect, .{
3223 .id_result_type = u32_ty_id,
3268 .id_result_type = limb_ty_id,
32243269 .id_result = r,
32253270 .condition = is_main,
32263271 .object_1 = shifted,
......@@ -3229,7 +3274,7 @@ const CompositeInt = struct {
32293274 break :blk r;
32303275 };
32313276
3232 const one_id = try cg.constInt(.u32, @as(u32, 1));
3277 const one_id = try cg.constInt(limb_ty, @as(u64, 1));
32333278 const i_plus_whole_plus_1 = try ci.limbBinOp(.OpIAdd, i_plus_whole, one_id);
32343279 const is_carry = blk: {
32353280 const r = cg.allocId();
......@@ -3245,7 +3290,7 @@ const CompositeInt = struct {
32453290 const guarded_carry = blk: {
32463291 const r = cg.allocId();
32473292 try cg.body.emit(gpa, .OpSelect, .{
3248 .id_result_type = u32_ty_id,
3293 .id_result_type = limb_ty_id,
32493294 .id_result = r,
32503295 .condition = frac_is_zero,
32513296 .object_1 = zero_id,
......@@ -3256,7 +3301,7 @@ const CompositeInt = struct {
32563301 carry_val = blk: {
32573302 const r = cg.allocId();
32583303 try cg.body.emit(gpa, .OpSelect, .{
3259 .id_result_type = u32_ty_id,
3304 .id_result_type = limb_ty_id,
32603305 .id_result = r,
32613306 .condition = is_carry,
32623307 .object_1 = guarded_carry,
......@@ -3284,17 +3329,18 @@ const CompositeInt = struct {
32843329
32853330 const n: usize = ci.n_limbs;
32863331 const total: usize = if (wide) 2 * n else n;
3287 const u32_zig = try pt.intType(.unsigned, 32);
3288 const u32_ty_id = try cg.resolveType(.u32, .direct);
3332 const limb_bits = cg.bigIntBits();
3333 const limb_zig = try pt.intType(.unsigned, limb_bits);
3334 const limb_ty_id = try cg.limbTypeId();
32893335
32903336 const pair_struct_ty: Type = .fromInterned(try ip.getTupleType(gpa, io, pt.tid, .{
3291 .types = &.{ u32_zig.toIntern(), u32_zig.toIntern() },
3337 .types = &.{ limb_zig.toIntern(), limb_zig.toIntern() },
32923338 .values = &.{ .none, .none },
32933339 }));
32943340 const pair_struct_ty_id = try cg.resolveType(pair_struct_ty, .direct);
32953341
32963342 const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, total);
3297 const zero_id = try cg.constInt(.u32, @as(u32, 0));
3343 const zero_id = try cg.constInt(cg.limbType(), @as(u64, 0));
32983344 for (result_limbs) |*r| r.* = zero_id;
32993345
33003346 for (0..n) |i| {
......@@ -3309,7 +3355,7 @@ const CompositeInt = struct {
33093355 .opencl => {
33103356 lo = cg.allocId();
33113357 try cg.body.emit(gpa, .OpIMul, .{
3312 .id_result_type = u32_ty_id,
3358 .id_result_type = limb_ty_id,
33133359 .id_result = lo,
33143360 .operand_1 = ci.limbs[i],
33153361 .operand_2 = other.limbs[j],
......@@ -3318,7 +3364,7 @@ const CompositeInt = struct {
33183364 const set = try cg.importExtendedSet();
33193365 hi = cg.allocId();
33203366 try cg.body.emit(gpa, .OpExtInst, .{
3321 .id_result_type = u32_ty_id,
3367 .id_result_type = limb_ty_id,
33223368 .id_result = hi,
33233369 .set = set,
33243370 .instruction = .{ .inst = @intFromEnum(spec.OpenClOpcode.u_mul_hi) },
......@@ -3336,14 +3382,14 @@ const CompositeInt = struct {
33363382
33373383 lo = cg.allocId();
33383384 try cg.body.emit(gpa, .OpCompositeExtract, .{
3339 .id_result_type = u32_ty_id,
3385 .id_result_type = limb_ty_id,
33403386 .id_result = lo,
33413387 .composite = mul_result,
33423388 .indexes = &.{0},
33433389 });
33443390 hi = cg.allocId();
33453391 try cg.body.emit(gpa, .OpCompositeExtract, .{
3346 .id_result_type = u32_ty_id,
3392 .id_result_type = limb_ty_id,
33473393 .id_result = hi,
33483394 .composite = mul_result,
33493395 .indexes = &.{1},
......@@ -3361,14 +3407,14 @@ const CompositeInt = struct {
33613407
33623408 const sum1 = cg.allocId();
33633409 try cg.body.emit(gpa, .OpCompositeExtract, .{
3364 .id_result_type = u32_ty_id,
3410 .id_result_type = limb_ty_id,
33653411 .id_result = sum1,
33663412 .composite = add1,
33673413 .indexes = &.{0},
33683414 });
33693415 const c1 = cg.allocId();
33703416 try cg.body.emit(gpa, .OpCompositeExtract, .{
3371 .id_result_type = u32_ty_id,
3417 .id_result_type = limb_ty_id,
33723418 .id_result = c1,
33733419 .composite = add1,
33743420 .indexes = &.{1},
......@@ -3384,14 +3430,14 @@ const CompositeInt = struct {
33843430
33853431 result_limbs[k] = cg.allocId();
33863432 try cg.body.emit(gpa, .OpCompositeExtract, .{
3387 .id_result_type = u32_ty_id,
3433 .id_result_type = limb_ty_id,
33883434 .id_result = result_limbs[k],
33893435 .composite = add2,
33903436 .indexes = &.{0},
33913437 });
33923438 const c2 = cg.allocId();
33933439 try cg.body.emit(gpa, .OpCompositeExtract, .{
3394 .id_result_type = u32_ty_id,
3440 .id_result_type = limb_ty_id,
33953441 .id_result = c2,
33963442 .composite = add2,
33973443 .indexes = &.{1},
......@@ -3412,7 +3458,8 @@ const CompositeInt = struct {
34123458 if (ci.info.bits == ci.info.backing_bits) return ci;
34133459 const cg = ci.cg;
34143460 const gpa = cg.gpa;
3415 const top_bits: u16 = ci.info.bits % big_int_bits;
3461 const limb_bits = cg.bigIntBits();
3462 const top_bits: u16 = ci.info.bits % limb_bits;
34163463 assert(top_bits != 0);
34173464
34183465 const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, ci.n_limbs);
......@@ -3421,41 +3468,43 @@ const CompositeInt = struct {
34213468 }
34223469
34233470 const top_limb = ci.limbs[ci.n_limbs - 1];
3471 const limb_ty = cg.limbType();
3472 const limb_signed_ty: Type = if (limb_bits == 64) .i64 else .i32;
34243473 switch (ci.info.signedness) {
34253474 .unsigned => {
3426 const mask_val: u32 = (@as(u32, 1) << @as(u5, @intCast(top_bits))) - 1;
3427 const mask_id = try cg.constInt(.u32, mask_val);
3475 const mask_val: u64 = (@as(u64, 1) << @as(u6, @intCast(top_bits))) - 1;
3476 const mask_id = try cg.constInt(limb_ty, mask_val);
34283477 result_limbs[ci.n_limbs - 1] = try ci.limbBinOp(.OpBitwiseAnd, top_limb, mask_id);
34293478 },
34303479 .signed => {
3431 const u32_ty_id = try cg.resolveType(.u32, .direct);
3432 const i32_ty_id = try cg.resolveType(.i32, .direct);
3433 const shift_amt: u32 = 32 - top_bits;
3434 const shift_id = try cg.constInt(.u32, shift_amt);
3480 const limb_ty_id = try cg.limbTypeId();
3481 const signed_ty_id = try cg.resolveType(limb_signed_ty, .direct);
3482 const shift_amt: u32 = @intCast(limb_bits - top_bits);
3483 const shift_id = try cg.constInt(limb_ty, shift_amt);
34353484
34363485 const as_signed = cg.allocId();
34373486 try cg.body.emit(gpa, .OpBitcast, .{
3438 .id_result_type = i32_ty_id,
3487 .id_result_type = signed_ty_id,
34393488 .id_result = as_signed,
34403489 .operand = top_limb,
34413490 });
34423491 const shifted_left = cg.allocId();
34433492 try cg.body.emit(gpa, .OpShiftLeftLogical, .{
3444 .id_result_type = i32_ty_id,
3493 .id_result_type = signed_ty_id,
34453494 .id_result = shifted_left,
34463495 .base = as_signed,
34473496 .shift = shift_id,
34483497 });
34493498 const shifted_right = cg.allocId();
34503499 try cg.body.emit(gpa, .OpShiftRightArithmetic, .{
3451 .id_result_type = i32_ty_id,
3500 .id_result_type = signed_ty_id,
34523501 .id_result = shifted_right,
34533502 .base = shifted_left,
34543503 .shift = shift_id,
34553504 });
34563505 const back = cg.allocId();
34573506 try cg.body.emit(gpa, .OpBitcast, .{
3458 .id_result_type = u32_ty_id,
3507 .id_result_type = limb_ty_id,
34593508 .id_result = back,
34603509 .operand = shifted_right,
34613510 });
......@@ -4552,13 +4601,14 @@ fn airShift(cg: *CodeGen, inst: Air.Inst.Index, unsigned: Opcode, signed: Opcode
45524601 switch (info.class) {
45534602 .composite_integer => {
45544603 const shift_info = cg.arithmeticTypeInfo(shift.ty);
4604 const limb_ty = cg.limbType();
45554605 const shift_amt_id = switch (shift_info.class) {
45564606 .composite_integer => blk: {
45574607 const shift_id = try shift.materialize(cg);
4558 const u32_ty_id = try cg.resolveType(.u32, .direct);
4608 const limb_ty_id = try cg.limbTypeId();
45594609 const result_id = cg.allocId();
45604610 try cg.body.emit(cg.gpa, .OpCompositeExtract, .{
4561 .id_result_type = u32_ty_id,
4611 .id_result_type = limb_ty_id,
45624612 .id_result = result_id,
45634613 .composite = shift_id,
45644614 .indexes = &.{@as(u32, 0)},
......@@ -4566,7 +4616,7 @@ fn airShift(cg: *CodeGen, inst: Air.Inst.Index, unsigned: Opcode, signed: Opcode
45664616 break :blk result_id;
45674617 },
45684618 else => blk: {
4569 const converted = try cg.buildConvert(.u32, shift);
4619 const converted = try cg.buildConvert(limb_ty, shift);
45704620 break :blk try converted.materialize(cg);
45714621 },
45724622 };
......@@ -4887,12 +4937,12 @@ fn airAbs(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
48874937 const is_neg = try ci.cmp(ci_z, .lt);
48884938 const ci_neg = try ci_z.addSub(ci, false);
48894939 const result_info = cg.arithmeticTypeInfo(result_ty);
4890 const u32_ty_id = try cg.resolveType(.u32, .direct);
4940 const limb_ty_id = try cg.limbTypeId();
48914941 const result_limbs = try cg.id_scratch.addManyAsSlice(cg.gpa, ci.n_limbs);
48924942 for (0..ci.n_limbs) |i| {
48934943 result_limbs[i] = cg.allocId();
48944944 try cg.body.emit(cg.gpa, .OpSelect, .{
4895 .id_result_type = u32_ty_id,
4945 .id_result_type = limb_ty_id,
48964946 .id_result = result_limbs[i],
48974947 .condition = is_neg,
48984948 .object_1 = ci_neg.limbs[i],
......@@ -5066,12 +5116,13 @@ fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
50665116 const high_limbs = wide_limbs[ci_lhs2.n_limbs..];
50675117
50685118 const bool_ty_id = try cg.resolveType(.bool, .direct);
5069 const u32_ty_id = try cg.resolveType(.u32, .direct);
5070 const n: usize = info.backing_bits / big_int_bits;
5119 const limb_ty_id = try cg.limbTypeId();
5120 const limb_ty = cg.limbType();
5121 const n: usize = info.backing_bits / cg.bigIntBits();
50715122
50725123 const ov_bool = switch (info.signedness) {
50735124 .unsigned => blk: {
5074 const zero_id = try cg.constInt(.u32, @as(u32, 0));
5125 const zero_id = try cg.constInt(limb_ty, @as(u64, 0));
50755126 var any_nonzero = cg.allocId();
50765127 try cg.body.emit(gpa, .OpINotEqual, .{
50775128 .id_result_type = bool_ty_id,
......@@ -5104,32 +5155,33 @@ fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
51045155 .signed => blk: {
51055156 const ci_res = try CompositeInt.init(cg, result_val_id, info);
51065157 const top_limb = ci_res.limbs[n - 1];
5107 const i32_ty_id = try cg.resolveType(.i32, .direct);
5158 const signed_limb_ty: Type = if (cg.bigIntBits() == 64) .i64 else .i32;
5159 const signed_limb_ty_id = try cg.resolveType(signed_limb_ty, .direct);
51085160
5109 const top_bits: u16 = if (info.bits % big_int_bits == 0)
5110 big_int_bits
5161 const top_bits: u16 = if (info.bits % cg.bigIntBits() == 0)
5162 cg.bigIntBits()
51115163 else
5112 info.bits % big_int_bits;
5164 info.bits % cg.bigIntBits();
51135165
5114 const shift_amt: u32 = top_bits - 1;
5115 const shift_id = try cg.constInt(.u32, shift_amt);
5166 const shift_amt: u64 = top_bits - 1;
5167 const shift_id = try cg.constInt(limb_ty, shift_amt);
51165168
51175169 const as_signed = cg.allocId();
51185170 try cg.body.emit(gpa, .OpBitcast, .{
5119 .id_result_type = i32_ty_id,
5171 .id_result_type = signed_limb_ty_id,
51205172 .id_result = as_signed,
51215173 .operand = top_limb,
51225174 });
51235175 const sign_ext = cg.allocId();
51245176 try cg.body.emit(gpa, .OpShiftRightArithmetic, .{
5125 .id_result_type = i32_ty_id,
5177 .id_result_type = signed_limb_ty_id,
51265178 .id_result = sign_ext,
51275179 .base = as_signed,
51285180 .shift = shift_id,
51295181 });
51305182 const expected = cg.allocId();
51315183 try cg.body.emit(gpa, .OpBitcast, .{
5132 .id_result_type = u32_ty_id,
5184 .id_result_type = limb_ty_id,
51335185 .id_result = expected,
51345186 .operand = sign_ext,
51355187 });
......@@ -5162,25 +5214,25 @@ fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
51625214 }
51635215
51645216 if (info.bits != info.backing_bits) {
5165 const top_bits_s: u16 = info.bits % big_int_bits;
5166 const s_shift_id = try cg.constInt(.u32, top_bits_s - 1);
5217 const top_bits_s: u16 = info.bits % cg.bigIntBits();
5218 const s_shift_id = try cg.constInt(limb_ty, @as(u64, top_bits_s - 1));
51675219
51685220 const top_as_signed = cg.allocId();
51695221 try cg.body.emit(gpa, .OpBitcast, .{
5170 .id_result_type = i32_ty_id,
5222 .id_result_type = signed_limb_ty_id,
51715223 .id_result = top_as_signed,
51725224 .operand = top_limb,
51735225 });
51745226 const top_sign_ext = cg.allocId();
51755227 try cg.body.emit(gpa, .OpShiftRightArithmetic, .{
5176 .id_result_type = i32_ty_id,
5228 .id_result_type = signed_limb_ty_id,
51775229 .id_result = top_sign_ext,
51785230 .base = top_as_signed,
51795231 .shift = s_shift_id,
51805232 });
51815233 const top_expected = cg.allocId();
51825234 try cg.body.emit(gpa, .OpBitcast, .{
5183 .id_result_type = u32_ty_id,
5235 .id_result_type = limb_ty_id,
51845236 .id_result = top_expected,
51855237 .operand = top_sign_ext,
51865238 });
......@@ -6117,15 +6169,17 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
61176169
61186170 if (src_composite and dst_composite) {
61196171 const src_id = try src.materialize(cg);
6120 const src_n: u16 = src_info.backing_bits / big_int_bits;
6121 const dst_n: u16 = dst_info.backing_bits / big_int_bits;
6172 const limb_bits = cg.bigIntBits();
6173 const limb_ty = cg.limbType();
6174 const limb_ty_id = try cg.limbTypeId();
6175 const src_n: u16 = src_info.backing_bits / limb_bits;
6176 const dst_n: u16 = dst_info.backing_bits / limb_bits;
61226177 const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, dst_n);
61236178 const min_n = @min(src_n, dst_n);
6124 const u32_ty_id = try cg.resolveType(.u32, .direct);
61256179 for (0..min_n) |i| {
61266180 result_limbs[i] = cg.allocId();
61276181 try cg.body.emit(gpa, .OpCompositeExtract, .{
6128 .id_result_type = u32_ty_id,
6182 .id_result_type = limb_ty_id,
61296183 .id_result = result_limbs[i],
61306184 .composite = src_id,
61316185 .indexes = &.{@as(u32, @intCast(i))},
......@@ -6133,30 +6187,31 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
61336187 }
61346188 if (dst_n > src_n) {
61356189 const fill = if (src_info.signedness == .signed) blk: {
6136 const i32_ty_id = try cg.resolveType(.i32, .direct);
6190 const signed_limb_ty: Type = if (limb_bits == 64) .i64 else .i32;
6191 const signed_limb_ty_id = try cg.resolveType(signed_limb_ty, .direct);
61376192 const msb = result_limbs[src_n - 1];
61386193 const msb_signed = cg.allocId();
61396194 try cg.body.emit(gpa, .OpBitcast, .{
6140 .id_result_type = i32_ty_id,
6195 .id_result_type = signed_limb_ty_id,
61416196 .id_result = msb_signed,
61426197 .operand = msb,
61436198 });
6144 const shift31 = try cg.constInt(.i32, @as(i32, 31));
6199 const shift_amt = try cg.constInt(signed_limb_ty, @as(u64, limb_bits - 1));
61456200 const sign_ext = cg.allocId();
61466201 try cg.body.emit(gpa, .OpShiftRightArithmetic, .{
6147 .id_result_type = i32_ty_id,
6202 .id_result_type = signed_limb_ty_id,
61486203 .id_result = sign_ext,
61496204 .base = msb_signed,
6150 .shift = shift31,
6205 .shift = shift_amt,
61516206 });
61526207 const back = cg.allocId();
61536208 try cg.body.emit(gpa, .OpBitcast, .{
6154 .id_result_type = u32_ty_id,
6209 .id_result_type = limb_ty_id,
61556210 .id_result = back,
61566211 .operand = sign_ext,
61576212 });
61586213 break :blk back;
6159 } else try cg.constInt(.u32, @as(u32, 0));
6214 } else try cg.constInt(limb_ty, @as(u64, 0));
61606215 for (min_n..dst_n) |i| {
61616216 result_limbs[i] = fill;
61626217 }
......@@ -6166,16 +6221,18 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
61666221 return try normalized.materialize(dst_ty);
61676222 } else if (src_composite and !dst_composite) {
61686223 const src_id = try src.materialize(cg);
6169 const u32_ty_id = try cg.resolveType(.u32, .direct);
6170 if (dst_info.backing_bits <= 32) {
6224 const limb_bits = cg.bigIntBits();
6225 const limb_ty = cg.limbType();
6226 const limb_ty_id = try cg.limbTypeId();
6227 if (dst_info.backing_bits <= limb_bits) {
61716228 const limb0 = cg.allocId();
61726229 try cg.body.emit(gpa, .OpCompositeExtract, .{
6173 .id_result_type = u32_ty_id,
6230 .id_result_type = limb_ty_id,
61746231 .id_result = limb0,
61756232 .composite = src_id,
61766233 .indexes = &.{@as(u32, 0)},
61776234 });
6178 const tmp: Temporary = .init(.u32, limb0);
6235 const tmp: Temporary = .init(limb_ty, limb0);
61796236 const converted = try cg.buildConvert(dst_ty, tmp);
61806237 const result = if (dst_info.bits < src_info.bits)
61816238 try cg.normalize(converted, dst_info)
......@@ -6183,16 +6240,17 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
61836240 converted;
61846241 return try result.materialize(cg);
61856242 } else {
6243 assert(limb_bits == 32); // dst > 64 while limbs are 64 shouldn't happen — dst fits in one 64-bit limb.
61866244 const limb0 = cg.allocId();
61876245 try cg.body.emit(gpa, .OpCompositeExtract, .{
6188 .id_result_type = u32_ty_id,
6246 .id_result_type = limb_ty_id,
61896247 .id_result = limb0,
61906248 .composite = src_id,
61916249 .indexes = &.{@as(u32, 0)},
61926250 });
61936251 const limb1 = cg.allocId();
61946252 try cg.body.emit(gpa, .OpCompositeExtract, .{
6195 .id_result_type = u32_ty_id,
6253 .id_result_type = limb_ty_id,
61966254 .id_result = limb1,
61976255 .composite = src_id,
61986256 .indexes = &.{@as(u32, 1)},
......@@ -6234,19 +6292,21 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
62346292 return try result.materialize(cg);
62356293 }
62366294 } else {
6237 const dst_n: u16 = dst_info.backing_bits / big_int_bits;
6295 const limb_bits = cg.bigIntBits();
6296 const limb_ty = cg.limbType();
6297 const limb_ty_id = try cg.limbTypeId();
6298 const dst_n: u16 = dst_info.backing_bits / limb_bits;
62386299 const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, dst_n);
6239 const u32_ty_id = try cg.resolveType(.u32, .direct);
62406300
6241 if (src_info.backing_bits <= 32) {
6242 const converted = try cg.buildConvert(.u32, src);
6301 if (src_info.backing_bits <= limb_bits) {
6302 const converted = try cg.buildConvert(limb_ty, src);
62436303 result_limbs[0] = try converted.materialize(cg);
62446304 } else {
62456305 const src_as_u64 = try cg.buildConvert(.u64, src);
62466306 const src_id = try src_as_u64.materialize(cg);
62476307 result_limbs[0] = cg.allocId();
62486308 try cg.body.emit(gpa, .OpUConvert, .{
6249 .id_result_type = u32_ty_id,
6309 .id_result_type = limb_ty_id,
62506310 .id_result = result_limbs[0],
62516311 .unsigned_value = src_id,
62526312 });
......@@ -6261,38 +6321,39 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
62616321 });
62626322 result_limbs[1] = cg.allocId();
62636323 try cg.body.emit(gpa, .OpUConvert, .{
6264 .id_result_type = u32_ty_id,
6324 .id_result_type = limb_ty_id,
62656325 .id_result = result_limbs[1],
62666326 .unsigned_value = hi,
62676327 });
62686328 }
62696329 // Sign/zero-extend remaining limbs.
6270 const fill_start: u16 = if (src_info.backing_bits <= 32) 1 else 2;
6330 const fill_start: u16 = if (src_info.backing_bits <= limb_bits) 1 else 2;
62716331 const fill = if (src_info.signedness == .signed) blk: {
6272 const i32_ty_id = try cg.resolveType(.i32, .direct);
6332 const signed_limb_ty: Type = if (limb_bits == 64) .i64 else .i32;
6333 const signed_limb_ty_id = try cg.resolveType(signed_limb_ty, .direct);
62736334 const msb = result_limbs[fill_start - 1];
62746335 const msb_signed = cg.allocId();
62756336 try cg.body.emit(gpa, .OpBitcast, .{
6276 .id_result_type = i32_ty_id,
6337 .id_result_type = signed_limb_ty_id,
62776338 .id_result = msb_signed,
62786339 .operand = msb,
62796340 });
6280 const shift31 = try cg.constInt(.i32, @as(i32, 31));
6341 const shift_amt = try cg.constInt(signed_limb_ty, @as(u64, limb_bits - 1));
62816342 const sign_ext = cg.allocId();
62826343 try cg.body.emit(gpa, .OpShiftRightArithmetic, .{
6283 .id_result_type = i32_ty_id,
6344 .id_result_type = signed_limb_ty_id,
62846345 .id_result = sign_ext,
62856346 .base = msb_signed,
6286 .shift = shift31,
6347 .shift = shift_amt,
62876348 });
62886349 const back = cg.allocId();
62896350 try cg.body.emit(gpa, .OpBitcast, .{
6290 .id_result_type = u32_ty_id,
6351 .id_result_type = limb_ty_id,
62916352 .id_result = back,
62926353 .operand = sign_ext,
62936354 });
62946355 break :blk back;
6295 } else try cg.constInt(.u32, @as(u32, 0));
6356 } else try cg.constInt(limb_ty, @as(u64, 0));
62966357 for (fill_start..dst_n) |i| {
62976358 result_limbs[i] = fill;
62986359 }