authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-10-12 10:23:52-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-10-13 03:49:06-04:00
logffece163a2a9251e12062b7909dddadeffa34ea1
treee3985607f3a093d53f6bf81b3bfc9d0c11febf91
parent28e60ddf42ac7a4c8a1794ed769ec08e620d7b88

x86_64: fix reduce evaluation order

Closes #37197

3 files changed, 200 insertions(+), 23 deletions(-)

src/codegen/x86_64/CodeGen.zig+150-23
......@@ -156748,10 +156748,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
156748156748 .dst_temps = .{ .{ .mut_rc = .{ .ref = .src0, .rc = .sse } }, .unused },
156749156749 .each = .{ .once = &.{
156750156750 .{ ._, .v_ps, .cvtph2, .dst0x, .src0q, ._, ._ },
156751 .{ ._, .v_ps, .shuf, .tmp0x, .dst0x, .dst0x, .ui(0b11_10) },
156752 .{ ._, .v_ss, .add, .dst0x, .dst0x, .tmp0x, ._ },
156753156751 .{ ._, .v_ps, .shuf, .tmp0x, .dst0x, .dst0x, .ui(0b01) },
156754156752 .{ ._, .v_ss, .add, .dst0x, .dst0x, .tmp0x, ._ },
156753 .{ ._, .v_ps, .shuf, .tmp0x, .dst0x, .dst0x, .ui(0b11_10) },
156754 .{ ._, .v_ss, .add, .dst0x, .dst0x, .tmp0x, ._ },
156755156755 .{ ._, .v_, .cvtps2ph, .dst0q, .dst0x, .rm(.{}), ._ },
156756156756 } },
156757156757 }, .{
......@@ -157043,9 +157043,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
157043157043 },
157044157044 .dst_temps = .{ .{ .mut_rc = .{ .ref = .src0, .rc = .sse } }, .unused },
157045157045 .each = .{ .once = &.{
157046 .{ ._, .v_ps, .movhl, .tmp0x, .src0x, .src0x, ._ },
157046 .{ ._, .v_ps, .shuf, .tmp0x, .src0x, .src0x, .ui(0b01) },
157047157047 .{ ._, .v_ss, .add, .tmp0x, .src0x, .tmp0x, ._ },
157048 .{ ._, .v_ps, .shuf, .dst0x, .src0x, .src0x, .ui(0b01) },
157048 .{ ._, .v_ps, .movhl, .dst0x, .src0x, .src0x, ._ },
157049157049 .{ ._, .v_ss, .add, .dst0x, .tmp0x, .dst0x, ._ },
157050157050 } },
157051157051 }, .{
......@@ -157075,6 +157075,33 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
157075157075 .{ ._, .h_ps, .add, .dst0x, .src0x, ._, ._ },
157076157076 .{ ._, ._ss, .add, .dst0x, .tmp0x, ._, ._ },
157077157077 } },
157078 }, .{
157079 .required_features = .{ .sse3, null, null, null },
157080 .dst_constraints = .{ .{ .float = .dword }, .any },
157081 .src_constraints = .{ .{ .exclusive_scalar_float = .{ .of = .xword, .is = .dword } }, .any, .any },
157082 .patterns = &.{
157083 .{ .src = .{ .to_mut_sse, .none, .none } },
157084 },
157085 .extra_temps = .{
157086 .{ .type = .vector_4_f32, .kind = .{ .rc = .sse } },
157087 .unused,
157088 .unused,
157089 .unused,
157090 .unused,
157091 .unused,
157092 .unused,
157093 .unused,
157094 .unused,
157095 .unused,
157096 .unused,
157097 },
157098 .dst_temps = .{ .{ .ref = .src0 }, .unused },
157099 .each = .{ .once = &.{
157100 .{ ._, ._, .movshdup, .tmp0x, .src0x, ._, ._ },
157101 .{ ._, ._ss, .add, .dst0x, .tmp0x, ._, ._ },
157102 .{ ._, ._ps, .movhl, .tmp0x, .dst0x, ._, ._ },
157103 .{ ._, ._ss, .add, .dst0x, .tmp0x, ._, ._ },
157104 } },
157078157105 }, .{
157079157106 .required_features = .{ .sse, null, null, null },
157080157107 .dst_constraints = .{ .{ .float = .dword }, .any },
......@@ -157097,10 +157124,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
157097157124 },
157098157125 .dst_temps = .{ .{ .ref = .src0 }, .unused },
157099157126 .each = .{ .once = &.{
157100 .{ ._, ._ps, .xor, .tmp0x, .tmp0x, ._, ._ },
157127 .{ ._, ._ps, .mova, .tmp0x, .src0x, ._, ._ },
157128 .{ ._, ._ps, .shuf, .tmp0x, .src0x, .ui(0b01), ._ },
157129 .{ ._, ._ss, .add, .dst0x, .tmp0x, ._, ._ },
157101157130 .{ ._, ._ps, .movhl, .tmp0x, .src0x, ._, ._ },
157102 .{ ._, ._ss, .add, .tmp0x, .src0x, ._, ._ },
157103 .{ ._, ._ps, .shuf, .dst0x, .src0x, .ui(0b01), ._ },
157104157131 .{ ._, ._ss, .add, .dst0x, .tmp0x, ._, ._ },
157105157132 } },
157106157133 }, .{
......@@ -157282,9 +157309,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
157282157309 },
157283157310 .dst_temps = .{ .{ .mut_rc = .{ .ref = .src0, .rc = .sse } }, .unused },
157284157311 .each = .{ .once = &.{
157285 .{ ._, .v_f128, .extract, .tmp0x, .src0y, .ui(1), ._ },
157312 .{ ._, .v_ps, .movhl, .tmp0x, .src0x, .src0x, ._ },
157286157313 .{ ._, .v_sd, .add, .tmp0x, .src0x, .tmp0x, ._ },
157287 .{ ._, .v_ps, .movhl, .dst0x, .src0x, .src0x, ._ },
157314 .{ ._, .v_f128, .extract, .dst0x, .src0y, .ui(1), ._ },
157288157315 .{ ._, .v_sd, .add, .dst0x, .tmp0x, .dst0x, ._ },
157289157316 } },
157290157317 }, .{
......@@ -157346,6 +157373,44 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
157346157373 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
157347157374 } },
157348157375 }, .{
157376 .required_abi = .gnu,
157377 .required_features = .{ .x87, null, null, null },
157378 .dst_constraints = .{ .{ .float = .qword }, .any },
157379 .src_constraints = .{ .{ .multiple_scalar_float = .{ .of = .qword, .is = .qword } }, .any, .any },
157380 .patterns = &.{
157381 .{ .src = .{ .to_mem, .none, .none } },
157382 },
157383 .extra_temps = .{
157384 .{ .type = .u16, .kind = .mem },
157385 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
157386 .{ .type = .f64, .kind = .{ .reg = .st7 } },
157387 .unused,
157388 .unused,
157389 .unused,
157390 .unused,
157391 .unused,
157392 .unused,
157393 .unused,
157394 .unused,
157395 },
157396 .dst_temps = .{ .mem, .unused },
157397 .clobbers = .{ .eflags = true },
157398 .each = .{ .once = &.{
157399 .{ ._, .fn_cw, .st, .tmp0w, ._, ._, ._ },
157400 .{ ._, ._, .movzx, .tmp1d, .memd(.tmp0b, 1), ._, ._ },
157401 .{ ._, ._, .@"and", .memd(.tmp0b, 1), .ui(0b111_1_11_10), ._, ._ },
157402 .{ ._, .f_cw, .ld, .tmp0w, ._, ._, ._ },
157403 .{ ._, ._, .mov, .memd(.tmp0b, 1), .tmp1b, ._, ._ },
157404 .{ ._, ._, .mov, .tmp1p, .sia(8, .src0, .sub_unaligned_size), ._, ._ },
157405 .{ ._, .f_, .ld, .mem(.src0q), ._, ._, ._ },
157406 .{ .@"0:", .f_, .add, .memia(.src0q, .tmp1, .add_unaligned_size), ._, ._, ._ },
157407 .{ ._, ._, .add, .tmp1p, .si(8), ._, ._ },
157408 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
157409 .{ ._, .f_p, .st, .dst0q, ._, ._, ._ },
157410 .{ ._, .f_cw, .ld, .tmp0w, ._, ._, ._ },
157411 } },
157412 }, .{
157413 .required_abi = .msvc,
157349157414 .required_features = .{ .x87, null, null, null },
157350157415 .dst_constraints = .{ .{ .float = .qword }, .any },
157351157416 .src_constraints = .{ .{ .multiple_scalar_float = .{ .of = .qword, .is = .qword } }, .any, .any },
......@@ -160584,10 +160649,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
160584160649 .dst_temps = .{ .{ .mut_rc = .{ .ref = .src0, .rc = .sse } }, .unused },
160585160650 .each = .{ .once = &.{
160586160651 .{ ._, .v_ps, .cvtph2, .dst0x, .src0q, ._, ._ },
160587 .{ ._, .v_ps, .shuf, .tmp0x, .dst0x, .dst0x, .ui(0b11_10) },
160588 .{ ._, .v_ss, .mul, .dst0x, .dst0x, .tmp0x, ._ },
160589160652 .{ ._, .v_ps, .shuf, .tmp0x, .dst0x, .dst0x, .ui(0b01) },
160590160653 .{ ._, .v_ss, .mul, .dst0x, .dst0x, .tmp0x, ._ },
160654 .{ ._, .v_ps, .shuf, .tmp0x, .dst0x, .dst0x, .ui(0b11_10) },
160655 .{ ._, .v_ss, .mul, .dst0x, .dst0x, .tmp0x, ._ },
160591160656 .{ ._, .v_, .cvtps2ph, .dst0q, .dst0x, .rm(.{}), ._ },
160592160657 } },
160593160658 }, .{
......@@ -160798,11 +160863,38 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
160798160863 },
160799160864 .dst_temps = .{ .{ .mut_rc = .{ .ref = .src0, .rc = .sse } }, .unused },
160800160865 .each = .{ .once = &.{
160801 .{ ._, .v_ps, .movhl, .tmp0x, .src0x, .src0x, ._ },
160866 .{ ._, .v_ps, .shuf, .tmp0x, .src0x, .src0x, .ui(0b01) },
160802160867 .{ ._, .v_ss, .mul, .tmp0x, .src0x, .tmp0x, ._ },
160803 .{ ._, .v_ps, .shuf, .dst0x, .src0x, .src0x, .ui(0b01) },
160868 .{ ._, .v_ps, .movhl, .dst0x, .src0x, .src0x, ._ },
160804160869 .{ ._, .v_ss, .mul, .dst0x, .tmp0x, .dst0x, ._ },
160805160870 } },
160871 }, .{
160872 .required_features = .{ .sse3, null, null, null },
160873 .dst_constraints = .{ .{ .float = .dword }, .any },
160874 .src_constraints = .{ .{ .exclusive_scalar_float = .{ .of = .xword, .is = .dword } }, .any, .any },
160875 .patterns = &.{
160876 .{ .src = .{ .to_mut_sse, .none, .none } },
160877 },
160878 .extra_temps = .{
160879 .{ .type = .vector_4_f32, .kind = .{ .rc = .sse } },
160880 .unused,
160881 .unused,
160882 .unused,
160883 .unused,
160884 .unused,
160885 .unused,
160886 .unused,
160887 .unused,
160888 .unused,
160889 .unused,
160890 },
160891 .dst_temps = .{ .{ .ref = .src0 }, .unused },
160892 .each = .{ .once = &.{
160893 .{ ._, ._, .movshdup, .tmp0x, .src0x, ._, ._ },
160894 .{ ._, ._ss, .mul, .dst0x, .tmp0x, ._, ._ },
160895 .{ ._, ._ps, .movhl, .tmp0x, .dst0x, ._, ._ },
160896 .{ ._, ._ss, .mul, .dst0x, .tmp0x, ._, ._ },
160897 } },
160806160898 }, .{
160807160899 .required_features = .{ .sse, null, null, null },
160808160900 .dst_constraints = .{ .{ .float = .dword }, .any },
......@@ -160825,10 +160917,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
160825160917 },
160826160918 .dst_temps = .{ .{ .ref = .src0 }, .unused },
160827160919 .each = .{ .once = &.{
160828 .{ ._, ._ps, .xor, .tmp0x, .tmp0x, ._, ._ },
160920 .{ ._, ._ps, .mova, .tmp0x, .src0x, ._, ._ },
160921 .{ ._, ._ps, .shuf, .tmp0x, .src0x, .ui(0b01), ._ },
160922 .{ ._, ._ss, .mul, .dst0x, .tmp0x, ._, ._ },
160829160923 .{ ._, ._ps, .movhl, .tmp0x, .src0x, ._, ._ },
160830 .{ ._, ._ss, .mul, .tmp0x, .src0x, ._, ._ },
160831 .{ ._, ._ps, .shuf, .dst0x, .src0x, .ui(0b01), ._ },
160832160924 .{ ._, ._ss, .mul, .dst0x, .tmp0x, ._, ._ },
160833160925 } },
160834160926 }, .{
......@@ -160962,9 +161054,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
160962161054 },
160963161055 .dst_temps = .{ .{ .mut_rc = .{ .ref = .src0, .rc = .sse } }, .unused },
160964161056 .each = .{ .once = &.{
160965 .{ ._, .v_f128, .extract, .tmp0x, .src0y, .ui(1), ._ },
161057 .{ ._, .v_ps, .movhl, .tmp0x, .src0x, .src0x, ._ },
160966161058 .{ ._, .v_sd, .mul, .tmp0x, .src0x, .tmp0x, ._ },
160967 .{ ._, .v_ps, .movhl, .dst0x, .src0x, .src0x, ._ },
161059 .{ ._, .v_f128, .extract, .dst0x, .src0y, .ui(1), ._ },
160968161060 .{ ._, .v_sd, .mul, .dst0x, .tmp0x, .dst0x, ._ },
160969161061 } },
160970161062 }, .{
......@@ -161026,6 +161118,44 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
161026161118 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
161027161119 } },
161028161120 }, .{
161121 .required_abi = .gnu,
161122 .required_features = .{ .x87, null, null, null },
161123 .dst_constraints = .{ .{ .float = .qword }, .any },
161124 .src_constraints = .{ .{ .multiple_scalar_float = .{ .of = .qword, .is = .qword } }, .any, .any },
161125 .patterns = &.{
161126 .{ .src = .{ .to_mem, .none, .none } },
161127 },
161128 .extra_temps = .{
161129 .{ .type = .u16, .kind = .mem },
161130 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
161131 .{ .type = .f64, .kind = .{ .reg = .st7 } },
161132 .unused,
161133 .unused,
161134 .unused,
161135 .unused,
161136 .unused,
161137 .unused,
161138 .unused,
161139 .unused,
161140 },
161141 .dst_temps = .{ .mem, .unused },
161142 .clobbers = .{ .eflags = true },
161143 .each = .{ .once = &.{
161144 .{ ._, .fn_cw, .st, .tmp0w, ._, ._, ._ },
161145 .{ ._, ._, .movzx, .tmp1d, .memd(.tmp0b, 1), ._, ._ },
161146 .{ ._, ._, .@"and", .memd(.tmp0b, 1), .ui(0b111_1_11_10), ._, ._ },
161147 .{ ._, .f_cw, .ld, .tmp0w, ._, ._, ._ },
161148 .{ ._, ._, .mov, .memd(.tmp0b, 1), .tmp1b, ._, ._ },
161149 .{ ._, ._, .mov, .tmp1p, .sia(8, .src0, .sub_unaligned_size), ._, ._ },
161150 .{ ._, .f_, .ld, .mem(.src0q), ._, ._, ._ },
161151 .{ .@"0:", .f_, .mul, .memia(.src0q, .tmp1, .add_unaligned_size), ._, ._, ._ },
161152 .{ ._, ._, .add, .tmp1p, .si(8), ._, ._ },
161153 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
161154 .{ ._, .f_p, .st, .dst0q, ._, ._, ._ },
161155 .{ ._, .f_cw, .ld, .tmp0w, ._, ._, ._ },
161156 } },
161157 }, .{
161158 .required_abi = .msvc,
161029161159 .required_features = .{ .x87, null, null, null },
161030161160 .dst_constraints = .{ .{ .float = .qword }, .any },
161031161161 .src_constraints = .{ .{ .multiple_scalar_float = .{ .of = .qword, .is = .qword } }, .any, .any },
......@@ -161050,13 +161180,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
161050161180 .each = .{ .once = &.{
161051161181 .{ ._, ._, .mov, .tmp0p, .sia(8, .src0, .sub_unaligned_size), ._, ._ },
161052161182 .{ ._, .f_, .ld, .mem(.src0q), ._, ._, ._ },
161053 .{ ._, ._mp, .j, .@"1f", ._, ._, ._ },
161054 .{ .pseudo, .f_cstp, .in, ._, ._, ._, ._ },
161055 .{ .@"0:", .f_, .ld, .dst0q, ._, ._, ._ },
161056 .{ .@"1:", .f_, .mul, .memia(.src0q, .tmp0, .add_unaligned_size), ._, ._, ._ },
161183 .{ .@"0:", .f_, .mul, .memia(.src0q, .tmp0, .add_unaligned_size), ._, ._, ._ },
161057161184 .{ ._, ._, .add, .tmp0p, .si(8), ._, ._ },
161058 .{ ._, .f_p, .st, .dst0q, ._, ._, ._ },
161059161185 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
161186 .{ ._, .f_p, .st, .dst0q, ._, ._, ._ },
161060161187 } },
161061161188 }, .{
161062161189 .required_abi = .gnu,
test/behavior/x86_64/math.zig+4
......@@ -22,6 +22,10 @@ pub const Sse = if (builtin.cpu.has(.x86, .avx))
2222else
2323 @Vector(16, u8);
2424
25pub fn fracBits(comptime Float: type) comptime_int {
26 return std.math.floatFractionalBits(Float);
27}
28
2529pub fn Scalar(comptime Type: type) type {
2630 return switch (@typeInfo(Type)) {
2731 else => Type,
test/behavior/x86_64/unary.zig+46
......@@ -5,6 +5,7 @@ const Compare = math.Compare;
55const fmax = math.fmax;
66const fmin = math.fmin;
77const Gpr = math.Gpr;
8const fracBits = math.fracBits;
89const inf = math.inf;
910const Log2IntCeil = math.Log2IntCeil;
1011const math = @import("math.zig");
......@@ -4487,34 +4488,65 @@ fn unary(comptime op: anytype, comptime opts: struct {
44874488 fn testFloatVectorTypes() !void {
44884489 try testArgs(@Vector(1, f16), undefined);
44894490 try testArgs(@Vector(2, f16), undefined);
4491 try testArgs(@Vector(3, f16), undefined);
44904492 try testArgs(@Vector(4, f16), undefined);
4493 try testArgs(@Vector(5, f16), undefined);
4494 try testArgs(@Vector(7, f16), undefined);
44914495 try testArgs(@Vector(8, f16), undefined);
4496 try testArgs(@Vector(9, f16), undefined);
4497 try testArgs(@Vector(15, f16), undefined);
44924498 try testArgs(@Vector(16, f16), undefined);
4499 try testArgs(@Vector(17, f16), undefined);
4500 try testArgs(@Vector(31, f16), undefined);
44934501 try testArgs(@Vector(32, f16), undefined);
4502 try testArgs(@Vector(33, f16), undefined);
4503 try testArgs(@Vector(63, f16), undefined);
44944504 try testArgs(@Vector(64, f16), undefined);
4505 try testArgs(@Vector(65, f16), undefined);
44954506
44964507 try testArgs(@Vector(1, f32), undefined);
44974508 try testArgs(@Vector(2, f32), undefined);
4509 try testArgs(@Vector(3, f32), undefined);
44984510 try testArgs(@Vector(4, f32), undefined);
4511 try testArgs(@Vector(5, f32), undefined);
4512 try testArgs(@Vector(7, f32), undefined);
44994513 try testArgs(@Vector(8, f32), undefined);
4514 try testArgs(@Vector(9, f32), undefined);
4515 try testArgs(@Vector(15, f32), undefined);
45004516 try testArgs(@Vector(16, f32), undefined);
4517 try testArgs(@Vector(17, f32), undefined);
4518 try testArgs(@Vector(31, f32), undefined);
45014519 try testArgs(@Vector(32, f32), undefined);
4520 try testArgs(@Vector(33, f32), undefined);
45024521
45034522 try testArgs(@Vector(1, f64), undefined);
45044523 try testArgs(@Vector(2, f64), undefined);
4524 try testArgs(@Vector(3, f64), undefined);
45054525 try testArgs(@Vector(4, f64), undefined);
4526 try testArgs(@Vector(5, f64), undefined);
4527 try testArgs(@Vector(7, f64), undefined);
45064528 try testArgs(@Vector(8, f64), undefined);
4529 try testArgs(@Vector(9, f64), undefined);
4530 try testArgs(@Vector(15, f64), undefined);
45074531 try testArgs(@Vector(16, f64), undefined);
4532 try testArgs(@Vector(17, f64), undefined);
45084533
45094534 try testArgs(@Vector(1, f80), undefined);
45104535 try testArgs(@Vector(2, f80), undefined);
4536 try testArgs(@Vector(3, f80), undefined);
45114537 try testArgs(@Vector(4, f80), undefined);
4538 try testArgs(@Vector(5, f80), undefined);
4539 try testArgs(@Vector(7, f80), undefined);
45124540 try testArgs(@Vector(8, f80), undefined);
4541 try testArgs(@Vector(9, f80), undefined);
45134542
45144543 try testArgs(@Vector(1, f128), undefined);
45154544 try testArgs(@Vector(2, f128), undefined);
4545 try testArgs(@Vector(3, f128), undefined);
45164546 try testArgs(@Vector(4, f128), undefined);
4547 try testArgs(@Vector(7, f128), undefined);
45174548 try testArgs(@Vector(8, f128), undefined);
4549 try testArgs(@Vector(9, f128), undefined);
45184550 }
45194551 fn testFloatVectors() !void {
45204552 try testArgs(@Vector(1, f16), .{
......@@ -5257,6 +5289,20 @@ test reduceMulOptimized {
52575289 try test_reduce_mul_optimized.testFloatVectors();
52585290}
52595291
5292inline fn reduceAddOrder(comptime Type: type, _: Type) @typeInfo(Type).vector.child {
5293 const vector = @typeInfo(Type).vector;
5294 const full_mant_bits = 1 + fracBits(vector.child);
5295 comptime var rhs: Type = @splat(1);
5296 rhs[0] = @exp2(full_mant_bits);
5297 rhs[@as(usize, vector.len) -| 2] = -rhs[0];
5298 rhs[vector.len - 1] = @exp2(-full_mant_bits);
5299 return @reduce(.Add, runtime(Type, rhs));
5300}
5301test reduceAddOrder {
5302 const test_reduce_add_order = unary(reduceAddOrder, .{});
5303 try test_reduce_add_order.testFloatVectorTypes();
5304}
5305
52605306inline fn splat(comptime Type: type, rhs: Type) Type {
52615307 return @splat(rhs[0]);
52625308}