authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-02-17 02:40:45-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-02-17 05:36:18-05:00
log82eedf56d703b3ce659519fe52f58a06279cfde0
tree6a5d1e5d4342d9534b25c3e2fa999be4f8678731
parentcec6867d76cdec2bfa3d0e127fdbd4bc66bff8c3

x86_64: rewrite scalar `@byteSwap`


2 files changed, 670 insertions(+), 2 deletions(-)

src/arch/x86_64/CodeGen.zig+651-2
...@@ -2418,7 +2418,7 @@ fn genBodyBlock(self: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2418,7 +2418,7 @@ fn genBodyBlock(self: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2418}2418}
24192419
2420fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {2420fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2421 @setEvalBranchQuota(12_500);2421 @setEvalBranchQuota(12_600);
2422 const pt = cg.pt;2422 const pt = cg.pt;
2423 const zcu = pt.zcu;2423 const zcu = pt.zcu;
2424 const ip = &zcu.intern_pool;2424 const ip = &zcu.intern_pool;
...@@ -2477,7 +2477,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2477,7 +2477,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
24772477
2478 .ctz => try cg.airCtz(inst),2478 .ctz => try cg.airCtz(inst),
2479 .popcount => try cg.airPopCount(inst),2479 .popcount => try cg.airPopCount(inst),
2480 .byte_swap => try cg.airByteSwap(inst),
2481 .bit_reverse => try cg.airBitReverse(inst),2480 .bit_reverse => try cg.airBitReverse(inst),
2482 .splat => try cg.airSplat(inst),2481 .splat => try cg.airSplat(inst),
2483 .select => try cg.airSelect(inst),2482 .select => try cg.airSelect(inst),
...@@ -30086,6 +30085,656 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -30086,6 +30085,656 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
30086 };30085 };
30087 try res[0].finish(inst, &.{ty_op.operand}, &ops, cg);30086 try res[0].finish(inst, &.{ty_op.operand}, &ops, cg);
30088 },30087 },
30088 .byte_swap => |air_tag| if (use_old) try cg.airByteSwap(inst) else fallback: {
30089 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
30090 if (ty_op.ty.toType().isVector(zcu)) break :fallback try cg.airByteSwap(inst);
30091 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});
30092 var res: [1]Temp = undefined;
30093 cg.select(&res, &.{ty_op.ty.toType()}, &ops, comptime &.{ .{
30094 .src_constraints = .{ .{ .exact_int = 8 }, .any, .any },
30095 .patterns = &.{
30096 .{ .src = .{ .mut_mem, .none, .none } },
30097 .{ .src = .{ .to_mut_gpr, .none, .none } },
30098 },
30099 .dst_temps = .{ .{ .ref = .src0 }, .unused },
30100 .each = .{ .once = &.{} },
30101 }, .{
30102 .required_features = .{ .movbe, null, null, null },
30103 .src_constraints = .{ .{ .exact_int = 16 }, .any, .any },
30104 .patterns = &.{
30105 .{ .src = .{ .mem, .none, .none } },
30106 },
30107 .dst_temps = .{ .{ .rc = .general_purpose }, .unused },
30108 .clobbers = .{ .eflags = true },
30109 .each = .{ .once = &.{
30110 .{ ._, ._, .xor, .dst0d, .dst0d, ._, ._ },
30111 .{ ._, ._, .movbe, .dst0w, .src0w, ._, ._ },
30112 } },
30113 }, .{
30114 .src_constraints = .{ .{ .exact_int = 16 }, .any, .any },
30115 .patterns = &.{
30116 .{ .src = .{ .to_mut_gpr, .none, .none } },
30117 },
30118 .dst_temps = .{ .{ .ref = .src0 }, .unused },
30119 .clobbers = .{ .eflags = true },
30120 .each = .{ .once = &.{
30121 .{ ._, ._r, .ro, .dst0w, .ui(8), ._, ._ },
30122 } },
30123 }, .{
30124 .required_features = .{ .movbe, null, null, null },
30125 .src_constraints = .{ .{ .exact_int = 32 }, .any, .any },
30126 .patterns = &.{
30127 .{ .src = .{ .mem, .none, .none } },
30128 },
30129 .dst_temps = .{ .{ .rc = .general_purpose }, .unused },
30130 .each = .{ .once = &.{
30131 .{ ._, ._, .movbe, .dst0d, .src0d, ._, ._ },
30132 } },
30133 }, .{
30134 .src_constraints = .{ .{ .exact_int = 32 }, .any, .any },
30135 .patterns = &.{
30136 .{ .src = .{ .to_mut_gpr, .none, .none } },
30137 },
30138 .dst_temps = .{ .{ .ref = .src0 }, .unused },
30139 .each = .{ .once = &.{
30140 .{ ._, ._, .bswap, .dst0d, ._, ._, ._ },
30141 } },
30142 }, .{
30143 .required_features = .{ .movbe, null, null, null },
30144 .src_constraints = .{ .{ .signed_int = .dword }, .any, .any },
30145 .patterns = &.{
30146 .{ .src = .{ .mem, .none, .none } },
30147 },
30148 .dst_temps = .{ .{ .rc = .general_purpose }, .unused },
30149 .clobbers = .{ .eflags = true },
30150 .each = .{ .once = &.{
30151 .{ ._, ._, .movbe, .dst0d, .src0d, ._, ._ },
30152 .{ ._, ._r, .sa, .dst0d, .uia(32, .src0, .sub_bit_size), ._, ._ },
30153 } },
30154 }, .{
30155 .src_constraints = .{ .{ .signed_int = .dword }, .any, .any },
30156 .patterns = &.{
30157 .{ .src = .{ .to_mut_gpr, .none, .none } },
30158 },
30159 .dst_temps = .{ .{ .ref = .src0 }, .unused },
30160 .clobbers = .{ .eflags = true },
30161 .each = .{ .once = &.{
30162 .{ ._, ._, .bswap, .dst0d, ._, ._, ._ },
30163 .{ ._, ._r, .sa, .dst0d, .uia(32, .src0, .sub_bit_size), ._, ._ },
30164 } },
30165 }, .{
30166 .required_features = .{ .movbe, null, null, null },
30167 .src_constraints = .{ .{ .unsigned_int = .dword }, .any, .any },
30168 .patterns = &.{
30169 .{ .src = .{ .mem, .none, .none } },
30170 },
30171 .dst_temps = .{ .{ .rc = .general_purpose }, .unused },
30172 .clobbers = .{ .eflags = true },
30173 .each = .{ .once = &.{
30174 .{ ._, ._, .movbe, .dst0d, .src0d, ._, ._ },
30175 .{ ._, ._r, .sh, .dst0d, .uia(32, .src0, .sub_bit_size), ._, ._ },
30176 } },
30177 }, .{
30178 .src_constraints = .{ .{ .unsigned_int = .dword }, .any, .any },
30179 .patterns = &.{
30180 .{ .src = .{ .to_mut_gpr, .none, .none } },
30181 },
30182 .dst_temps = .{ .{ .ref = .src0 }, .unused },
30183 .clobbers = .{ .eflags = true },
30184 .each = .{ .once = &.{
30185 .{ ._, ._, .bswap, .dst0d, ._, ._, ._ },
30186 .{ ._, ._r, .sh, .dst0d, .uia(32, .src0, .sub_bit_size), ._, ._ },
30187 } },
30188 }, .{
30189 .required_features = .{ .movbe, null, null, null },
30190 .src_constraints = .{ .{ .exact_int = 64 }, .any, .any },
30191 .patterns = &.{
30192 .{ .src = .{ .mem, .none, .none } },
30193 },
30194 .dst_temps = .{ .{ .rc = .general_purpose }, .unused },
30195 .each = .{ .once = &.{
30196 .{ ._, ._, .movbe, .dst0q, .src0q, ._, ._ },
30197 } },
30198 }, .{
30199 .src_constraints = .{ .{ .exact_int = 64 }, .any, .any },
30200 .patterns = &.{
30201 .{ .src = .{ .to_mut_gpr, .none, .none } },
30202 },
30203 .dst_temps = .{ .{ .ref = .src0 }, .unused },
30204 .each = .{ .once = &.{
30205 .{ ._, ._, .bswap, .dst0q, ._, ._, ._ },
30206 } },
30207 }, .{
30208 .required_features = .{ .movbe, null, null, null },
30209 .src_constraints = .{ .{ .signed_int = .qword }, .any, .any },
30210 .patterns = &.{
30211 .{ .src = .{ .mem, .none, .none } },
30212 },
30213 .dst_temps = .{ .{ .rc = .general_purpose }, .unused },
30214 .clobbers = .{ .eflags = true },
30215 .each = .{ .once = &.{
30216 .{ ._, ._, .movbe, .dst0q, .src0q, ._, ._ },
30217 .{ ._, ._r, .sa, .dst0q, .uia(64, .src0, .sub_bit_size), ._, ._ },
30218 } },
30219 }, .{
30220 .src_constraints = .{ .{ .signed_int = .qword }, .any, .any },
30221 .patterns = &.{
30222 .{ .src = .{ .to_mut_gpr, .none, .none } },
30223 },
30224 .dst_temps = .{ .{ .ref = .src0 }, .unused },
30225 .clobbers = .{ .eflags = true },
30226 .each = .{ .once = &.{
30227 .{ ._, ._, .bswap, .dst0q, ._, ._, ._ },
30228 .{ ._, ._r, .sa, .dst0q, .uia(64, .src0, .sub_bit_size), ._, ._ },
30229 } },
30230 }, .{
30231 .required_features = .{ .movbe, null, null, null },
30232 .src_constraints = .{ .{ .unsigned_int = .qword }, .any, .any },
30233 .patterns = &.{
30234 .{ .src = .{ .mem, .none, .none } },
30235 },
30236 .dst_temps = .{ .{ .rc = .general_purpose }, .unused },
30237 .clobbers = .{ .eflags = true },
30238 .each = .{ .once = &.{
30239 .{ ._, ._, .movbe, .dst0q, .src0q, ._, ._ },
30240 .{ ._, ._r, .sh, .dst0q, .uia(64, .src0, .sub_bit_size), ._, ._ },
30241 } },
30242 }, .{
30243 .src_constraints = .{ .{ .unsigned_int = .qword }, .any, .any },
30244 .patterns = &.{
30245 .{ .src = .{ .to_mut_gpr, .none, .none } },
30246 },
30247 .dst_temps = .{ .{ .ref = .src0 }, .unused },
30248 .clobbers = .{ .eflags = true },
30249 .each = .{ .once = &.{
30250 .{ ._, ._, .bswap, .dst0q, ._, ._, ._ },
30251 .{ ._, ._r, .sh, .dst0q, .uia(64, .src0, .sub_bit_size), ._, ._ },
30252 } },
30253 }, .{
30254 .required_features = .{ .@"64bit", .movbe, null, null },
30255 .src_constraints = .{ .{ .exact_remainder_int = .{ .of = .xword, .is = .xword } }, .any, .any },
30256 .patterns = &.{
30257 .{ .src = .{ .to_mem, .none, .none } },
30258 },
30259 .extra_temps = .{
30260 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
30261 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
30262 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
30263 .unused,
30264 .unused,
30265 .unused,
30266 .unused,
30267 .unused,
30268 .unused,
30269 .unused,
30270 .unused,
30271 },
30272 .dst_temps = .{ .mem, .unused },
30273 .clobbers = .{ .eflags = true },
30274 .each = .{ .once = &.{
30275 .{ ._, ._, .mov, .tmp0d, .sia(-8, .dst0, .add_size), ._, ._ },
30276 .{ ._, ._, .lea, .tmp1p, .mem(.src0), ._, ._ },
30277 .{ .@"0:", ._, .mov, .tmp2q, .lea(.tmp1q), ._, ._ },
30278 .{ ._, ._, .movbe, .memi(.dst0q, .tmp0), .tmp2q, ._, ._ },
30279 .{ ._, ._, .lea, .tmp1p, .lead(.tmp1, 8), ._, ._ },
30280 .{ ._, ._, .sub, .tmp0d, .si(8), ._, ._ },
30281 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
30282 } },
30283 }, .{
30284 .required_features = .{ .@"64bit", null, null, null },
30285 .src_constraints = .{ .{ .exact_remainder_int = .{ .of = .xword, .is = .xword } }, .any, .any },
30286 .patterns = &.{
30287 .{ .src = .{ .to_mem, .none, .none } },
30288 },
30289 .extra_temps = .{
30290 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
30291 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
30292 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
30293 .unused,
30294 .unused,
30295 .unused,
30296 .unused,
30297 .unused,
30298 .unused,
30299 .unused,
30300 .unused,
30301 },
30302 .dst_temps = .{ .mem, .unused },
30303 .clobbers = .{ .eflags = true },
30304 .each = .{ .once = &.{
30305 .{ ._, ._, .mov, .tmp0d, .sia(-8, .dst0, .add_size), ._, ._ },
30306 .{ ._, ._, .lea, .tmp1p, .mem(.src0), ._, ._ },
30307 .{ .@"0:", ._, .mov, .tmp2q, .lea(.tmp1q), ._, ._ },
30308 .{ ._, ._, .bswap, .tmp2q, ._, ._, ._ },
30309 .{ ._, ._, .mov, .memi(.dst0q, .tmp0), .tmp2q, ._, ._ },
30310 .{ ._, ._, .lea, .tmp1p, .lead(.tmp1, 8), ._, ._ },
30311 .{ ._, ._, .sub, .tmp0d, .si(8), ._, ._ },
30312 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
30313 } },
30314 }, .{
30315 .required_features = .{ .@"64bit", .movbe, null, null },
30316 .src_constraints = .{ .{ .exact_remainder_signed_int = .{ .of = .xword, .is = .qword } }, .any, .any },
30317 .patterns = &.{
30318 .{ .src = .{ .to_mem, .none, .none } },
30319 },
30320 .extra_temps = .{
30321 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
30322 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
30323 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
30324 .unused,
30325 .unused,
30326 .unused,
30327 .unused,
30328 .unused,
30329 .unused,
30330 .unused,
30331 .unused,
30332 },
30333 .dst_temps = .{ .mem, .unused },
30334 .clobbers = .{ .eflags = true },
30335 .each = .{ .once = &.{
30336 .{ ._, ._, .mov, .tmp0d, .sia(-16, .dst0, .add_size), ._, ._ },
30337 .{ ._, ._, .lea, .tmp1p, .mem(.src0), ._, ._ },
30338 .{ ._, ._, .movsx, .tmp2q, .mem(.src0b), ._, ._ },
30339 .{ ._, ._r, .sa, .tmp2q, .ui(63), ._, ._ },
30340 .{ ._, ._, .mov, .memad(.dst0q, .add_size, -8), .tmp2q, ._, ._ },
30341 .{ .@"0:", ._, .mov, .tmp2q, .lea(.tmp1q), ._, ._ },
30342 .{ ._, ._, .movbe, .memi(.dst0q, .tmp0), .tmp2q, ._, ._ },
30343 .{ ._, ._, .lea, .tmp1p, .lead(.tmp1, 8), ._, ._ },
30344 .{ ._, ._, .sub, .tmp0d, .si(8), ._, ._ },
30345 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
30346 } },
30347 }, .{
30348 .required_features = .{ .@"64bit", null, null, null },
30349 .src_constraints = .{ .{ .exact_remainder_signed_int = .{ .of = .xword, .is = .qword } }, .any, .any },
30350 .patterns = &.{
30351 .{ .src = .{ .to_mem, .none, .none } },
30352 },
30353 .extra_temps = .{
30354 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
30355 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
30356 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
30357 .unused,
30358 .unused,
30359 .unused,
30360 .unused,
30361 .unused,
30362 .unused,
30363 .unused,
30364 .unused,
30365 },
30366 .dst_temps = .{ .mem, .unused },
30367 .clobbers = .{ .eflags = true },
30368 .each = .{ .once = &.{
30369 .{ ._, ._, .mov, .tmp0d, .sia(-16, .dst0, .add_size), ._, ._ },
30370 .{ ._, ._, .lea, .tmp1p, .mem(.src0), ._, ._ },
30371 .{ ._, ._, .movsx, .tmp2q, .mem(.src0b), ._, ._ },
30372 .{ ._, ._r, .sa, .tmp2q, .ui(63), ._, ._ },
30373 .{ ._, ._, .mov, .memad(.dst0q, .add_size, -8), .tmp2q, ._, ._ },
30374 .{ .@"0:", ._, .mov, .tmp2q, .lea(.tmp1q), ._, ._ },
30375 .{ ._, ._, .bswap, .tmp2q, ._, ._, ._ },
30376 .{ ._, ._, .mov, .memi(.dst0q, .tmp0), .tmp2q, ._, ._ },
30377 .{ ._, ._, .lea, .tmp1p, .lead(.tmp1, 8), ._, ._ },
30378 .{ ._, ._, .sub, .tmp0d, .si(8), ._, ._ },
30379 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
30380 } },
30381 }, .{
30382 .required_features = .{ .@"64bit", .movbe, null, null },
30383 .src_constraints = .{ .{ .exact_remainder_unsigned_int = .{ .of = .xword, .is = .qword } }, .any, .any },
30384 .patterns = &.{
30385 .{ .src = .{ .to_mem, .none, .none } },
30386 },
30387 .extra_temps = .{
30388 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
30389 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
30390 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
30391 .unused,
30392 .unused,
30393 .unused,
30394 .unused,
30395 .unused,
30396 .unused,
30397 .unused,
30398 .unused,
30399 },
30400 .dst_temps = .{ .mem, .unused },
30401 .clobbers = .{ .eflags = true },
30402 .each = .{ .once = &.{
30403 .{ ._, ._, .mov, .tmp0d, .sia(-16, .dst0, .add_size), ._, ._ },
30404 .{ ._, ._, .lea, .tmp1p, .mem(.src0), ._, ._ },
30405 .{ ._, ._, .mov, .memad(.dst0q, .add_size, -8), .si(0), ._, ._ },
30406 .{ .@"0:", ._, .mov, .tmp2q, .lea(.tmp1q), ._, ._ },
30407 .{ ._, ._, .movbe, .memi(.dst0q, .tmp0), .tmp2q, ._, ._ },
30408 .{ ._, ._, .lea, .tmp1p, .lead(.tmp1, 8), ._, ._ },
30409 .{ ._, ._, .sub, .tmp0d, .si(8), ._, ._ },
30410 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
30411 } },
30412 }, .{
30413 .required_features = .{ .@"64bit", null, null, null },
30414 .src_constraints = .{ .{ .exact_remainder_unsigned_int = .{ .of = .xword, .is = .qword } }, .any, .any },
30415 .patterns = &.{
30416 .{ .src = .{ .to_mem, .none, .none } },
30417 },
30418 .extra_temps = .{
30419 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
30420 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
30421 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
30422 .unused,
30423 .unused,
30424 .unused,
30425 .unused,
30426 .unused,
30427 .unused,
30428 .unused,
30429 .unused,
30430 },
30431 .dst_temps = .{ .mem, .unused },
30432 .clobbers = .{ .eflags = true },
30433 .each = .{ .once = &.{
30434 .{ ._, ._, .mov, .tmp0d, .sia(-16, .dst0, .add_size), ._, ._ },
30435 .{ ._, ._, .lea, .tmp1p, .mem(.src0), ._, ._ },
30436 .{ ._, ._, .mov, .memad(.dst0q, .add_size, -8), .si(0), ._, ._ },
30437 .{ .@"0:", ._, .mov, .tmp2q, .lea(.tmp1q), ._, ._ },
30438 .{ ._, ._, .bswap, .tmp2q, ._, ._, ._ },
30439 .{ ._, ._, .mov, .memi(.dst0q, .tmp0), .tmp2q, ._, ._ },
30440 .{ ._, ._, .lea, .tmp1p, .lead(.tmp1, 8), ._, ._ },
30441 .{ ._, ._, .sub, .tmp0d, .si(8), ._, ._ },
30442 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
30443 } },
30444 }, .{
30445 .required_features = .{ .@"64bit", .movbe, null, null },
30446 .src_constraints = .{ .{ .remainder_signed_int = .{ .of = .xword, .is = .qword } }, .any, .any },
30447 .patterns = &.{
30448 .{ .src = .{ .to_mem, .none, .none } },
30449 },
30450 .extra_temps = .{
30451 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
30452 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
30453 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
30454 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
30455 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
30456 .unused,
30457 .unused,
30458 .unused,
30459 .unused,
30460 .unused,
30461 .unused,
30462 },
30463 .dst_temps = .{ .mem, .unused },
30464 .clobbers = .{ .eflags = true },
30465 .each = .{ .once = &.{
30466 .{ ._, ._, .mov, .tmp0d, .sia(-16, .dst0, .add_size), ._, ._ },
30467 .{ ._, ._, .lea, .tmp1p, .mem(.src0), ._, ._ },
30468 .{ ._, ._, .movsx, .tmp2q, .mem(.src0b), ._, ._ },
30469 .{ ._, ._r, .sa, .tmp2q, .ui(63), ._, ._ },
30470 .{ ._, ._, .mov, .memad(.dst0q, .add_size, -8), .tmp2q, ._, ._ },
30471 .{ .@"0:", ._, .movbe, .tmp3q, .lea(.tmp1q), ._, ._ },
30472 .{ ._, ._, .mov, .tmp4q, .tmp3q, ._, ._ },
30473 .{ ._, ._rd, .sh, .tmp3q, .tmp2q, .uia(64, .src0, .sub_bit_size_rem_64), ._ },
30474 .{ ._, ._, .mov, .tmp2q, .tmp4q, ._, ._ },
30475 .{ ._, ._, .mov, .memi(.dst0q, .tmp0), .tmp3q, ._, ._ },
30476 .{ ._, ._, .lea, .tmp1p, .lead(.tmp1, 8), ._, ._ },
30477 .{ ._, ._, .sub, .tmp0d, .si(8), ._, ._ },
30478 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
30479 } },
30480 }, .{
30481 .required_features = .{ .@"64bit", null, null, null },
30482 .src_constraints = .{ .{ .remainder_signed_int = .{ .of = .xword, .is = .qword } }, .any, .any },
30483 .patterns = &.{
30484 .{ .src = .{ .to_mem, .none, .none } },
30485 },
30486 .extra_temps = .{
30487 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
30488 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
30489 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
30490 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
30491 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
30492 .unused,
30493 .unused,
30494 .unused,
30495 .unused,
30496 .unused,
30497 .unused,
30498 },
30499 .dst_temps = .{ .mem, .unused },
30500 .clobbers = .{ .eflags = true },
30501 .each = .{ .once = &.{
30502 .{ ._, ._, .mov, .tmp0d, .sia(-16, .dst0, .add_size), ._, ._ },
30503 .{ ._, ._, .lea, .tmp1p, .mem(.src0), ._, ._ },
30504 .{ ._, ._, .movsx, .tmp2q, .mem(.src0b), ._, ._ },
30505 .{ ._, ._r, .sa, .tmp2q, .ui(63), ._, ._ },
30506 .{ ._, ._, .mov, .memad(.dst0q, .add_size, -8), .tmp2q, ._, ._ },
30507 .{ .@"0:", ._, .mov, .tmp3q, .lea(.tmp1q), ._, ._ },
30508 .{ ._, ._, .bswap, .tmp3q, ._, ._, ._ },
30509 .{ ._, ._, .mov, .tmp4q, .tmp3q, ._, ._ },
30510 .{ ._, ._rd, .sh, .tmp3q, .tmp2q, .uia(64, .src0, .sub_bit_size_rem_64), ._ },
30511 .{ ._, ._, .mov, .tmp2q, .tmp4q, ._, ._ },
30512 .{ ._, ._, .mov, .memi(.dst0q, .tmp0), .tmp3q, ._, ._ },
30513 .{ ._, ._, .lea, .tmp1p, .lead(.tmp1, 8), ._, ._ },
30514 .{ ._, ._, .sub, .tmp0d, .si(8), ._, ._ },
30515 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
30516 } },
30517 }, .{
30518 .required_features = .{ .@"64bit", .movbe, null, null },
30519 .src_constraints = .{ .{ .remainder_unsigned_int = .{ .of = .xword, .is = .qword } }, .any, .any },
30520 .patterns = &.{
30521 .{ .src = .{ .to_mem, .none, .none } },
30522 },
30523 .extra_temps = .{
30524 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
30525 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
30526 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
30527 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
30528 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
30529 .unused,
30530 .unused,
30531 .unused,
30532 .unused,
30533 .unused,
30534 .unused,
30535 },
30536 .dst_temps = .{ .mem, .unused },
30537 .clobbers = .{ .eflags = true },
30538 .each = .{ .once = &.{
30539 .{ ._, ._, .mov, .tmp0d, .sia(-16, .dst0, .add_size), ._, ._ },
30540 .{ ._, ._, .lea, .tmp1p, .mem(.src0), ._, ._ },
30541 .{ ._, ._, .xor, .tmp2d, .tmp2d, ._, ._ },
30542 .{ ._, ._, .mov, .memad(.dst0q, .add_size, -8), .tmp2q, ._, ._ },
30543 .{ .@"0:", ._, .movbe, .tmp3q, .lea(.tmp1q), ._, ._ },
30544 .{ ._, ._, .mov, .tmp4q, .tmp3q, ._, ._ },
30545 .{ ._, ._rd, .sh, .tmp3q, .tmp2q, .uia(64, .src0, .sub_bit_size_rem_64), ._ },
30546 .{ ._, ._, .mov, .tmp2q, .tmp4q, ._, ._ },
30547 .{ ._, ._, .mov, .memi(.dst0q, .tmp0), .tmp3q, ._, ._ },
30548 .{ ._, ._, .lea, .tmp1p, .lead(.tmp1, 8), ._, ._ },
30549 .{ ._, ._, .sub, .tmp0d, .si(8), ._, ._ },
30550 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
30551 } },
30552 }, .{
30553 .required_features = .{ .@"64bit", null, null, null },
30554 .src_constraints = .{ .{ .remainder_unsigned_int = .{ .of = .xword, .is = .qword } }, .any, .any },
30555 .patterns = &.{
30556 .{ .src = .{ .to_mem, .none, .none } },
30557 },
30558 .extra_temps = .{
30559 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
30560 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
30561 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
30562 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
30563 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
30564 .unused,
30565 .unused,
30566 .unused,
30567 .unused,
30568 .unused,
30569 .unused,
30570 },
30571 .dst_temps = .{ .mem, .unused },
30572 .clobbers = .{ .eflags = true },
30573 .each = .{ .once = &.{
30574 .{ ._, ._, .mov, .tmp0d, .sia(-16, .dst0, .add_size), ._, ._ },
30575 .{ ._, ._, .lea, .tmp1p, .mem(.src0), ._, ._ },
30576 .{ ._, ._, .xor, .tmp2d, .tmp2d, ._, ._ },
30577 .{ ._, ._, .mov, .memad(.dst0q, .add_size, -8), .tmp2q, ._, ._ },
30578 .{ .@"0:", ._, .mov, .tmp3q, .lea(.tmp1q), ._, ._ },
30579 .{ ._, ._, .bswap, .tmp3q, ._, ._, ._ },
30580 .{ ._, ._, .mov, .tmp4q, .tmp3q, ._, ._ },
30581 .{ ._, ._rd, .sh, .tmp3q, .tmp2q, .uia(64, .src0, .sub_bit_size_rem_64), ._ },
30582 .{ ._, ._, .mov, .tmp2q, .tmp4q, ._, ._ },
30583 .{ ._, ._, .mov, .memi(.dst0q, .tmp0), .tmp3q, ._, ._ },
30584 .{ ._, ._, .lea, .tmp1p, .lead(.tmp1, 8), ._, ._ },
30585 .{ ._, ._, .sub, .tmp0d, .si(8), ._, ._ },
30586 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
30587 } },
30588 }, .{
30589 .required_features = .{ .@"64bit", .movbe, null, null },
30590 .src_constraints = .{ .{ .remainder_signed_int = .{ .of = .xword, .is = .xword } }, .any, .any },
30591 .patterns = &.{
30592 .{ .src = .{ .to_mem, .none, .none } },
30593 },
30594 .extra_temps = .{
30595 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
30596 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
30597 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
30598 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
30599 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
30600 .unused,
30601 .unused,
30602 .unused,
30603 .unused,
30604 .unused,
30605 .unused,
30606 },
30607 .dst_temps = .{ .mem, .unused },
30608 .clobbers = .{ .eflags = true },
30609 .each = .{ .once = &.{
30610 .{ ._, ._, .mov, .tmp0d, .sia(-8, .dst0, .add_size), ._, ._ },
30611 .{ ._, ._, .lea, .tmp1p, .mem(.src0), ._, ._ },
30612 .{ ._, ._, .movsx, .tmp2q, .mem(.src0b), ._, ._ },
30613 .{ ._, ._r, .sa, .tmp2q, .ui(63), ._, ._ },
30614 .{ .@"0:", ._, .movbe, .tmp3q, .lea(.tmp1q), ._, ._ },
30615 .{ ._, ._, .mov, .tmp4q, .tmp3q, ._, ._ },
30616 .{ ._, ._rd, .sh, .tmp3q, .tmp2q, .uia(64, .src0, .sub_bit_size_rem_64), ._ },
30617 .{ ._, ._, .mov, .tmp2q, .tmp4q, ._, ._ },
30618 .{ ._, ._, .mov, .memi(.dst0q, .tmp0), .tmp3q, ._, ._ },
30619 .{ ._, ._, .lea, .tmp1p, .lead(.tmp1, 8), ._, ._ },
30620 .{ ._, ._, .sub, .tmp0d, .si(8), ._, ._ },
30621 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
30622 } },
30623 }, .{
30624 .required_features = .{ .@"64bit", null, null, null },
30625 .src_constraints = .{ .{ .remainder_signed_int = .{ .of = .xword, .is = .xword } }, .any, .any },
30626 .patterns = &.{
30627 .{ .src = .{ .to_mem, .none, .none } },
30628 },
30629 .extra_temps = .{
30630 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
30631 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
30632 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
30633 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
30634 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
30635 .unused,
30636 .unused,
30637 .unused,
30638 .unused,
30639 .unused,
30640 .unused,
30641 },
30642 .dst_temps = .{ .mem, .unused },
30643 .clobbers = .{ .eflags = true },
30644 .each = .{ .once = &.{
30645 .{ ._, ._, .mov, .tmp0d, .sia(-8, .dst0, .add_size), ._, ._ },
30646 .{ ._, ._, .lea, .tmp1p, .mem(.src0), ._, ._ },
30647 .{ ._, ._, .movsx, .tmp2q, .mem(.src0b), ._, ._ },
30648 .{ ._, ._r, .sa, .tmp2q, .ui(63), ._, ._ },
30649 .{ .@"0:", ._, .mov, .tmp3q, .lea(.tmp1q), ._, ._ },
30650 .{ ._, ._, .bswap, .tmp3q, ._, ._, ._ },
30651 .{ ._, ._, .mov, .tmp4q, .tmp3q, ._, ._ },
30652 .{ ._, ._rd, .sh, .tmp3q, .tmp2q, .uia(64, .src0, .sub_bit_size_rem_64), ._ },
30653 .{ ._, ._, .mov, .tmp2q, .tmp4q, ._, ._ },
30654 .{ ._, ._, .mov, .memi(.dst0q, .tmp0), .tmp3q, ._, ._ },
30655 .{ ._, ._, .lea, .tmp1p, .lead(.tmp1, 8), ._, ._ },
30656 .{ ._, ._, .sub, .tmp0d, .si(8), ._, ._ },
30657 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
30658 } },
30659 }, .{
30660 .required_features = .{ .@"64bit", .movbe, null, null },
30661 .src_constraints = .{ .{ .remainder_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any },
30662 .patterns = &.{
30663 .{ .src = .{ .to_mem, .none, .none } },
30664 },
30665 .extra_temps = .{
30666 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
30667 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
30668 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
30669 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
30670 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
30671 .unused,
30672 .unused,
30673 .unused,
30674 .unused,
30675 .unused,
30676 .unused,
30677 },
30678 .dst_temps = .{ .mem, .unused },
30679 .clobbers = .{ .eflags = true },
30680 .each = .{ .once = &.{
30681 .{ ._, ._, .mov, .tmp0d, .sia(-8, .dst0, .add_size), ._, ._ },
30682 .{ ._, ._, .lea, .tmp1p, .mem(.src0), ._, ._ },
30683 .{ ._, ._, .xor, .tmp2d, .tmp2d, ._, ._ },
30684 .{ .@"0:", ._, .movbe, .tmp3q, .lea(.tmp1q), ._, ._ },
30685 .{ ._, ._, .mov, .tmp4q, .tmp3q, ._, ._ },
30686 .{ ._, ._rd, .sh, .tmp3q, .tmp2q, .uia(64, .src0, .sub_bit_size_rem_64), ._ },
30687 .{ ._, ._, .mov, .tmp2q, .tmp4q, ._, ._ },
30688 .{ ._, ._, .mov, .memi(.dst0q, .tmp0), .tmp3q, ._, ._ },
30689 .{ ._, ._, .lea, .tmp1p, .lead(.tmp1, 8), ._, ._ },
30690 .{ ._, ._, .sub, .tmp0d, .si(8), ._, ._ },
30691 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
30692 } },
30693 }, .{
30694 .required_features = .{ .@"64bit", null, null, null },
30695 .src_constraints = .{ .{ .remainder_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any },
30696 .patterns = &.{
30697 .{ .src = .{ .to_mem, .none, .none } },
30698 },
30699 .extra_temps = .{
30700 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
30701 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
30702 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
30703 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
30704 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
30705 .unused,
30706 .unused,
30707 .unused,
30708 .unused,
30709 .unused,
30710 .unused,
30711 },
30712 .dst_temps = .{ .mem, .unused },
30713 .clobbers = .{ .eflags = true },
30714 .each = .{ .once = &.{
30715 .{ ._, ._, .mov, .tmp0d, .sia(-8, .dst0, .add_size), ._, ._ },
30716 .{ ._, ._, .lea, .tmp1p, .mem(.src0), ._, ._ },
30717 .{ ._, ._, .xor, .tmp2d, .tmp2d, ._, ._ },
30718 .{ .@"0:", ._, .mov, .tmp3q, .lea(.tmp1q), ._, ._ },
30719 .{ ._, ._, .bswap, .tmp3q, ._, ._, ._ },
30720 .{ ._, ._, .mov, .tmp4q, .tmp3q, ._, ._ },
30721 .{ ._, ._rd, .sh, .tmp3q, .tmp2q, .uia(64, .src0, .sub_bit_size_rem_64), ._ },
30722 .{ ._, ._, .mov, .tmp2q, .tmp4q, ._, ._ },
30723 .{ ._, ._, .mov, .memi(.dst0q, .tmp0), .tmp3q, ._, ._ },
30724 .{ ._, ._, .lea, .tmp1p, .lead(.tmp1, 8), ._, ._ },
30725 .{ ._, ._, .sub, .tmp0d, .si(8), ._, ._ },
30726 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
30727 } },
30728 } }) catch |err| switch (err) {
30729 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{
30730 @tagName(air_tag),
30731 ty_op.ty.toType().fmt(pt),
30732 ops[0].tracking(cg),
30733 }),
30734 else => |e| return e,
30735 };
30736 try res[0].finish(inst, &.{ty_op.operand}, &ops, cg);
30737 },
3008930738
30090 .cmp_vector, .cmp_vector_optimized => |air_tag| if (use_old) try cg.airCmpVector(inst) else fallback: {30739 .cmp_vector, .cmp_vector_optimized => |air_tag| if (use_old) try cg.airCmpVector(inst) else fallback: {
30091 const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;30740 const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
test/behavior/x86_64/math.zig+19
...@@ -55,6 +55,17 @@ fn DoubleBits(comptime Type: type) type {...@@ -55,6 +55,17 @@ fn DoubleBits(comptime Type: type) type {
55 .vector => |vector| @Vector(vector.len, ResultScalar),55 .vector => |vector| @Vector(vector.len, ResultScalar),
56 };56 };
57}57}
58fn RoundBitsUp(comptime Type: type, comptime multiple: u16) type {
59 const ResultScalar = switch (@typeInfo(Scalar(Type))) {
60 .int => |int| @Type(.{ .int = .{ .signedness = int.signedness, .bits = std.mem.alignForward(u16, int.bits, multiple) } }),
61 .float => Scalar(Type),
62 else => @compileError(@typeName(Type)),
63 };
64 return switch (@typeInfo(Type)) {
65 else => ResultScalar,
66 .vector => |vector| @Vector(vector.len, ResultScalar),
67 };
68}
58// inline to avoid a runtime `@splat`69// inline to avoid a runtime `@splat`
59inline fn splat(comptime Type: type, scalar: Scalar(Type)) Type {70inline fn splat(comptime Type: type, scalar: Scalar(Type)) Type {
60 return switch (@typeInfo(Type)) {71 return switch (@typeInfo(Type)) {
...@@ -19262,6 +19273,14 @@ test clz {...@@ -19262,6 +19273,14 @@ test clz {
19262 try test_clz.testIntVectors();19273 try test_clz.testIntVectors();
19263}19274}
1926419275
19276inline fn byteSwap(comptime Type: type, rhs: Type) RoundBitsUp(Type, 8) {
19277 return @byteSwap(@as(RoundBitsUp(Type, 8), rhs));
19278}
19279test byteSwap {
19280 const test_byte_swap = unary(byteSwap, .{});
19281 try test_byte_swap.testInts();
19282}
19283
19265inline fn sqrt(comptime Type: type, rhs: Type) @TypeOf(@sqrt(rhs)) {19284inline fn sqrt(comptime Type: type, rhs: Type) @TypeOf(@sqrt(rhs)) {
19266 return @sqrt(rhs);19285 return @sqrt(rhs);
19267}19286}