authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-02-14 02:20:43-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-02-15 03:45:21-05:00
log4ea18c22f958c05aa5c715fc8823d704699746ec
tree9102df332c917f1e0524800f860bfec4c5db962a
parent9f87aacaafb953c3fbb0eefa437728ef8337656e

x86_64: rewrite array access


3 files changed, 392 insertions(+), 106 deletions(-)

src/arch/x86_64/CodeGen.zig+238-87
......@@ -2418,7 +2418,7 @@ fn genBodyBlock(self: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
24182418}
24192419
24202420fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2421 @setEvalBranchQuota(12_300);
2421 @setEvalBranchQuota(12_400);
24222422 const pt = cg.pt;
24232423 const zcu = pt.zcu;
24242424 const ip = &zcu.intern_pool;
......@@ -2486,8 +2486,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
24862486 .reduce_optimized => try cg.airReduce(inst),
24872487 .aggregate_init => try cg.airAggregateInit(inst),
24882488 .prefetch => try cg.airPrefetch(inst),
2489
2490 .array_elem_val => try cg.airArrayElemVal(inst),
24912489 // zig fmt: on
24922490
24932491 .arg => if (cg.debug_output != .none) {
......@@ -15150,7 +15148,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1515015148 },
1515115149 .dst_temps = .{ .{ .rc = .general_purpose }, .unused },
1515215150 .each = .{ .once = &.{
15153 .{ ._, ._, .lea, .dst0p, .leaa(.src0, .add_src0_elem_size_times_src1), ._, ._ },
15151 .{ ._, ._, .lea, .dst0p, .leaa(.src0, .add_src0_elem_size_mul_src1), ._, ._ },
1515415152 } },
1515515153 }, .{
1515615154 .dst_constraints = .{ .{ .elem_size_is = 1 }, .any },
......@@ -15264,7 +15262,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1526415262 },
1526515263 .dst_temps = .{ .{ .rc = .general_purpose }, .unused },
1526615264 .each = .{ .once = &.{
15267 .{ ._, ._, .lea, .dst0p, .leaa(.src0, .sub_src0_elem_size_times_src1), ._, ._ },
15265 .{ ._, ._, .lea, .dst0p, .leaa(.src0, .sub_src0_elem_size_mul_src1), ._, ._ },
1526815266 } },
1526915267 }, .{
1527015268 .dst_constraints = .{ .{ .elem_size_is = 1 }, .any },
......@@ -52951,6 +52949,200 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
5295152949 try ops[0].toOffset(0, cg);
5295252950 try ops[0].finish(inst, &.{ty_op.operand}, &ops, cg);
5295352951 },
52952 .array_elem_val => if (use_old) try cg.airArrayElemVal(inst) else {
52953 const bin_op = air_datas[@intFromEnum(inst)].bin_op;
52954 const array_ty = cg.typeOf(bin_op.lhs);
52955 const res_ty = array_ty.elemType2(zcu);
52956 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
52957 var res: [1]Temp = undefined;
52958 cg.select(&res, &.{res_ty}, &ops, comptime &.{ .{
52959 .src_constraints = .{ .{ .bool_vec = .dword }, .any, .any },
52960 .patterns = &.{
52961 .{ .src = .{ .to_gpr, .imm32, .none } },
52962 },
52963 .dst_temps = .{ .{ .cc = .c }, .unused },
52964 .clobbers = .{ .eflags = true },
52965 .each = .{ .once = &.{
52966 .{ ._, ._, .bt, .src0d, .ua(.none, .add_src1_rem_32), ._, ._ },
52967 } },
52968 }, .{
52969 .src_constraints = .{ .{ .bool_vec = .dword }, .any, .any },
52970 .patterns = &.{
52971 .{ .src = .{ .to_gpr, .to_gpr, .none } },
52972 },
52973 .dst_temps = .{ .{ .cc = .c }, .unused },
52974 .clobbers = .{ .eflags = true },
52975 .each = .{ .once = &.{
52976 .{ ._, ._, .bt, .src0d, .src1d, ._, ._ },
52977 } },
52978 }, .{
52979 .required_features = .{ .@"64bit", null, null, null },
52980 .src_constraints = .{ .{ .bool_vec = .qword }, .any, .any },
52981 .patterns = &.{
52982 .{ .src = .{ .to_gpr, .imm32, .none } },
52983 },
52984 .dst_temps = .{ .{ .cc = .c }, .unused },
52985 .clobbers = .{ .eflags = true },
52986 .each = .{ .once = &.{
52987 .{ ._, ._, .bt, .src0q, .ua(.none, .add_src1_rem_64), ._, ._ },
52988 } },
52989 }, .{
52990 .required_features = .{ .@"64bit", null, null, null },
52991 .src_constraints = .{ .{ .bool_vec = .qword }, .any, .any },
52992 .patterns = &.{
52993 .{ .src = .{ .to_gpr, .to_gpr, .none } },
52994 },
52995 .dst_temps = .{ .{ .cc = .c }, .unused },
52996 .clobbers = .{ .eflags = true },
52997 .each = .{ .once = &.{
52998 .{ ._, ._, .bt, .src0q, .src1q, ._, ._ },
52999 } },
53000 }, .{
53001 .src_constraints = .{ .any_bool_vec, .any, .any },
53002 .patterns = &.{
53003 .{ .src = .{ .to_mem, .imm32, .none } },
53004 },
53005 .dst_temps = .{ .{ .cc = .c }, .unused },
53006 .clobbers = .{ .eflags = true },
53007 .each = .{ .once = &.{
53008 .{ ._, ._, .bt, .mema(.src0d, .add_src1_div_8_down_4), .ua(.none, .add_src1_rem_32), ._, ._ },
53009 } },
53010 }, .{
53011 .src_constraints = .{ .any_bool_vec, .any, .any },
53012 .patterns = &.{
53013 .{ .src = .{ .to_mem, .to_gpr, .none } },
53014 },
53015 .dst_temps = .{ .{ .cc = .c }, .unused },
53016 .clobbers = .{ .eflags = true },
53017 .each = .{ .once = &.{
53018 .{ ._, ._, .bt, .src0d, .src1d, ._, ._ },
53019 } },
53020 }, .{
53021 .dst_constraints = .{ .{ .int = .byte }, .any },
53022 .patterns = &.{
53023 .{ .src = .{ .to_mem, .simm32, .none } },
53024 },
53025 .dst_temps = .{ .{ .rc = .general_purpose }, .unused },
53026 .each = .{ .once = &.{
53027 .{ ._, ._, .movzx, .dst0d, .mema(.src0b, .add_src0_elem_size_mul_src1), ._, ._ },
53028 } },
53029 }, .{
53030 .dst_constraints = .{ .{ .int = .byte }, .any },
53031 .patterns = &.{
53032 .{ .src = .{ .to_mem, .to_gpr, .none } },
53033 },
53034 .dst_temps = .{ .{ .rc = .general_purpose }, .unused },
53035 .each = .{ .once = &.{
53036 .{ ._, ._, .movzx, .dst0d, .memi(.src0b, .src1), ._, ._ },
53037 } },
53038 }, .{
53039 .dst_constraints = .{ .{ .int = .word }, .any },
53040 .patterns = &.{
53041 .{ .src = .{ .to_mem, .simm32, .none } },
53042 },
53043 .dst_temps = .{ .{ .rc = .general_purpose }, .unused },
53044 .each = .{ .once = &.{
53045 .{ ._, ._, .movzx, .dst0d, .mema(.src0w, .add_src0_elem_size_mul_src1), ._, ._ },
53046 } },
53047 }, .{
53048 .dst_constraints = .{ .{ .int = .word }, .any },
53049 .patterns = &.{
53050 .{ .src = .{ .to_mem, .to_gpr, .none } },
53051 },
53052 .dst_temps = .{ .{ .rc = .general_purpose }, .unused },
53053 .each = .{ .once = &.{
53054 .{ ._, ._, .movzx, .dst0d, .memsi(.src0w, .@"2", .src1), ._, ._ },
53055 } },
53056 }, .{
53057 .dst_constraints = .{ .{ .int = .dword }, .any },
53058 .patterns = &.{
53059 .{ .src = .{ .to_mem, .simm32, .none } },
53060 },
53061 .dst_temps = .{ .{ .rc = .general_purpose }, .unused },
53062 .each = .{ .once = &.{
53063 .{ ._, ._, .mov, .dst0d, .mema(.src0d, .add_src0_elem_size_mul_src1), ._, ._ },
53064 } },
53065 }, .{
53066 .dst_constraints = .{ .{ .int = .dword }, .any },
53067 .patterns = &.{
53068 .{ .src = .{ .to_mem, .to_gpr, .none } },
53069 },
53070 .dst_temps = .{ .{ .rc = .general_purpose }, .unused },
53071 .each = .{ .once = &.{
53072 .{ ._, ._, .mov, .dst0d, .memsi(.src0d, .@"4", .src1), ._, ._ },
53073 } },
53074 }, .{
53075 .dst_constraints = .{ .{ .int = .qword }, .any },
53076 .patterns = &.{
53077 .{ .src = .{ .to_mem, .simm32, .none } },
53078 },
53079 .dst_temps = .{ .{ .rc = .general_purpose }, .unused },
53080 .each = .{ .once = &.{
53081 .{ ._, ._, .mov, .dst0q, .mema(.src0q, .add_src0_elem_size_mul_src1), ._, ._ },
53082 } },
53083 }, .{
53084 .required_features = .{ .@"64bit", null, null, null },
53085 .dst_constraints = .{ .{ .int = .qword }, .any },
53086 .patterns = &.{
53087 .{ .src = .{ .to_mem, .to_gpr, .none } },
53088 },
53089 .dst_temps = .{ .{ .rc = .general_purpose }, .unused },
53090 .each = .{ .once = &.{
53091 .{ ._, ._, .mov, .dst0q, .memsi(.src0q, .@"8", .src1), ._, ._ },
53092 } },
53093 } }) catch |err| switch (err) {
53094 error.SelectFailed => {
53095 const elem_size = res_ty.abiSize(zcu);
53096 const base = try cg.tempAllocReg(.usize, abi.RegisterClass.gp);
53097 while (try ops[0].toBase(false, cg) or
53098 try ops[1].toRegClass(true, .general_purpose, cg))
53099 {}
53100 const base_reg = base.tracking(cg).short.register.to64();
53101 const rhs_reg = ops[1].tracking(cg).short.register.to64();
53102 if (!std.math.isPowerOfTwo(elem_size)) {
53103 try cg.spillEflagsIfOccupied();
53104 try cg.asmRegisterRegisterImmediate(
53105 .{ .i_, .mul },
53106 rhs_reg,
53107 rhs_reg,
53108 .u(elem_size),
53109 );
53110 try cg.asmRegisterMemory(
53111 .{ ._, .lea },
53112 base_reg,
53113 try ops[0].tracking(cg).short.mem(cg, .{ .index = rhs_reg }),
53114 );
53115 } else if (elem_size > 8) {
53116 try cg.spillEflagsIfOccupied();
53117 try cg.asmRegisterImmediate(
53118 .{ ._l, .sh },
53119 rhs_reg,
53120 .u(std.math.log2_int(u64, elem_size)),
53121 );
53122 try cg.asmRegisterMemory(
53123 .{ ._, .lea },
53124 base_reg,
53125 try ops[0].tracking(cg).short.mem(cg, .{ .index = rhs_reg }),
53126 );
53127 } else try cg.asmRegisterMemory(
53128 .{ ._, .lea },
53129 base_reg,
53130 try ops[0].tracking(cg).short.mem(cg, .{
53131 .index = rhs_reg,
53132 .scale = .fromFactor(@intCast(elem_size)),
53133 }),
53134 );
53135 // Hack around Sema insanity: lhs could be an arbitrarily large comptime-known array
53136 // which could easily get spilled by the upcoming `load`, which would infinite recurse
53137 // since spilling an array requires the same operation that triggered the spill.
53138 try ops[0].die(cg);
53139 ops[0] = base;
53140 res[0] = try ops[0].load(res_ty, .{}, cg);
53141 },
53142 else => |e| return e,
53143 };
53144 try res[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg);
53145 },
5295453146 .slice_elem_val, .ptr_elem_val => |air_tag| if (use_old) switch (air_tag) {
5295553147 else => unreachable,
5295653148 .slice_elem_val => try cg.airSliceElemVal(inst),
......@@ -52968,7 +53160,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
5296853160 },
5296953161 .dst_temps = .{ .{ .rc = .general_purpose }, .unused },
5297053162 .each = .{ .once = &.{
52971 .{ ._, ._, .movzx, .dst0d, .leaa(.src0b, .add_src0_elem_size_times_src1), ._, ._ },
53163 .{ ._, ._, .movzx, .dst0d, .leaa(.src0b, .add_src0_elem_size_mul_src1), ._, ._ },
5297253164 } },
5297353165 }, .{
5297453166 .dst_constraints = .{ .{ .int = .byte }, .any },
......@@ -52986,7 +53178,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
5298653178 },
5298753179 .dst_temps = .{ .{ .rc = .general_purpose }, .unused },
5298853180 .each = .{ .once = &.{
52989 .{ ._, ._, .movzx, .dst0d, .leaa(.src0w, .add_src0_elem_size_times_src1), ._, ._ },
53181 .{ ._, ._, .movzx, .dst0d, .leaa(.src0w, .add_src0_elem_size_mul_src1), ._, ._ },
5299053182 } },
5299153183 }, .{
5299253184 .dst_constraints = .{ .{ .int = .word }, .any },
......@@ -53004,7 +53196,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
5300453196 },
5300553197 .dst_temps = .{ .{ .rc = .general_purpose }, .unused },
5300653198 .each = .{ .once = &.{
53007 .{ ._, ._, .mov, .dst0d, .leaa(.src0d, .add_src0_elem_size_times_src1), ._, ._ },
53199 .{ ._, ._, .mov, .dst0d, .leaa(.src0d, .add_src0_elem_size_mul_src1), ._, ._ },
5300853200 } },
5300953201 }, .{
5301053202 .dst_constraints = .{ .{ .int = .dword }, .any },
......@@ -53022,7 +53214,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
5302253214 },
5302353215 .dst_temps = .{ .{ .rc = .general_purpose }, .unused },
5302453216 .each = .{ .once = &.{
53025 .{ ._, ._, .mov, .dst0q, .leaa(.src0q, .add_src0_elem_size_times_src1), ._, ._ },
53217 .{ ._, ._, .mov, .dst0q, .leaa(.src0q, .add_src0_elem_size_mul_src1), ._, ._ },
5302653218 } },
5302753219 }, .{
5302853220 .required_features = .{ .@"64bit", null, null, null },
......@@ -53040,8 +53232,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
5304053232 while (true) for (&ops) |*op| {
5304153233 if (try op.toRegClass(true, .general_purpose, cg)) break;
5304253234 } else break;
53043 const lhs_reg = ops[0].unwrap(cg).temp.tracking(cg).short.register.to64();
53044 const rhs_reg = ops[1].unwrap(cg).temp.tracking(cg).short.register.to64();
53235 const lhs_reg = ops[0].tracking(cg).short.register.to64();
53236 const rhs_reg = ops[1].tracking(cg).short.register.to64();
5304553237 if (!std.math.isPowerOfTwo(elem_size)) {
5304653238 try cg.spillEflagsIfOccupied();
5304753239 try cg.asmRegisterRegisterImmediate(
......@@ -53052,7 +53244,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
5305253244 );
5305353245 try cg.asmRegisterMemory(.{ ._, .lea }, lhs_reg, .{
5305453246 .base = .{ .reg = lhs_reg },
53055 .mod = .{ .rm = .{ .size = .qword, .index = rhs_reg } },
53247 .mod = .{ .rm = .{ .index = rhs_reg } },
5305653248 });
5305753249 } else if (elem_size > 8) {
5305853250 try cg.spillEflagsIfOccupied();
......@@ -53063,12 +53255,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
5306353255 );
5306453256 try cg.asmRegisterMemory(.{ ._, .lea }, lhs_reg, .{
5306553257 .base = .{ .reg = lhs_reg },
53066 .mod = .{ .rm = .{ .size = .qword, .index = rhs_reg } },
53258 .mod = .{ .rm = .{ .index = rhs_reg } },
5306753259 });
5306853260 } else try cg.asmRegisterMemory(.{ ._, .lea }, lhs_reg, .{
5306953261 .base = .{ .reg = lhs_reg },
5307053262 .mod = .{ .rm = .{
53071 .size = .qword,
5307253263 .index = rhs_reg,
5307353264 .scale = .fromFactor(@intCast(elem_size)),
5307453265 } },
......@@ -53095,8 +53286,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
5309553286 while (true) for (&ops) |*op| {
5309653287 if (try op.toRegClass(true, .general_purpose, cg)) break;
5309753288 } else break;
53098 const lhs_reg = ops[0].unwrap(cg).temp.tracking(cg).short.register.to64();
53099 const rhs_reg = ops[1].unwrap(cg).temp.tracking(cg).short.register.to64();
53289 const lhs_reg = ops[0].tracking(cg).short.register.to64();
53290 const rhs_reg = ops[1].tracking(cg).short.register.to64();
5310053291 if (!std.math.isPowerOfTwo(elem_size)) {
5310153292 try cg.spillEflagsIfOccupied();
5310253293 try cg.asmRegisterRegisterImmediate(
......@@ -53107,7 +53298,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
5310753298 );
5310853299 try cg.asmRegisterMemory(.{ ._, .lea }, lhs_reg, .{
5310953300 .base = .{ .reg = lhs_reg },
53110 .mod = .{ .rm = .{ .size = .qword, .index = rhs_reg } },
53301 .mod = .{ .rm = .{ .index = rhs_reg } },
5311153302 });
5311253303 } else if (elem_size > 8) {
5311353304 try cg.spillEflagsIfOccupied();
......@@ -53118,12 +53309,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
5311853309 );
5311953310 try cg.asmRegisterMemory(.{ ._, .lea }, lhs_reg, .{
5312053311 .base = .{ .reg = lhs_reg },
53121 .mod = .{ .rm = .{ .size = .qword, .index = rhs_reg } },
53312 .mod = .{ .rm = .{ .index = rhs_reg } },
5312253313 });
5312353314 } else try cg.asmRegisterMemory(.{ ._, .lea }, lhs_reg, .{
5312453315 .base = .{ .reg = lhs_reg },
5312553316 .mod = .{ .rm = .{
53126 .size = .qword,
5312753317 .index = rhs_reg,
5312853318 .scale = .fromFactor(@intCast(elem_size)),
5312953319 } },
......@@ -75183,7 +75373,7 @@ fn airErrUnionPayloadPtrSet(self: *CodeGen, inst: Air.Inst.Index) !void {
7518375373 registerAlias(dst_reg, dst_abi_size),
7518475374 .{
7518575375 .base = .{ .reg = src_reg },
75186 .mod = .{ .rm = .{ .size = .qword, .disp = pl_off } },
75376 .mod = .{ .rm = .{ .disp = pl_off } },
7518775377 },
7518875378 );
7518975379 break :result .{ .register = dst_reg };
......@@ -75446,7 +75636,7 @@ fn airPtrSliceLenPtr(self: *CodeGen, inst: Air.Inst.Index) !void {
7544675636 registerAlias(dst_reg, dst_abi_size),
7544775637 .{
7544875638 .base = .{ .reg = src_reg },
75449 .mod = .{ .rm = .{ .size = .qword, .disp = 8 } },
75639 .mod = .{ .rm = .{ .disp = 8 } },
7545075640 },
7545175641 );
7545275642
......@@ -75700,7 +75890,7 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void {
7570075890 try self.asmRegisterMemory(
7570175891 .{ ._, .lea },
7570275892 addr_reg,
75703 .{ .base = .{ .frame = frame_index }, .mod = .{ .rm = .{ .size = .qword } } },
75893 .{ .base = .{ .frame = frame_index } },
7570475894 );
7570575895 },
7570675896 .load_frame => |frame_addr| try self.asmRegisterMemory(
......@@ -75708,7 +75898,7 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void {
7570875898 addr_reg,
7570975899 .{
7571075900 .base = .{ .frame = frame_addr.index },
75711 .mod = .{ .rm = .{ .size = .qword, .disp = frame_addr.off } },
75901 .mod = .{ .rm = .{ .disp = frame_addr.off } },
7571275902 },
7571375903 ),
7571475904 .memory,
......@@ -76717,7 +76907,6 @@ fn airBitReverse(self: *CodeGen, inst: Air.Inst.Index) !void {
7671776907 .{
7671876908 .base = .{ .reg = dst.to64() },
7671976909 .mod = .{ .rm = .{
76720 .size = .qword,
7672176910 .index = tmp.to64(),
7672276911 .scale = .@"4",
7672376912 } },
......@@ -76744,7 +76933,6 @@ fn airBitReverse(self: *CodeGen, inst: Air.Inst.Index) !void {
7674476933 .{
7674576934 .base = .{ .reg = tmp.to64() },
7674676935 .mod = .{ .rm = .{
76747 .size = .qword,
7674876936 .index = dst.to64(),
7674976937 .scale = .@"2",
7675076938 } },
......@@ -85591,7 +85779,6 @@ fn genSetReg(
8559185779 dst_reg.to64(),
8559285780 .{
8559385781 .base = .{ .reloc = sym_off.sym_index },
85594 .mod = .{ .rm = .{ .size = .qword } },
8559585782 },
8559685783 );
8559785784 if (sym_off.off != 0) try self.asmRegisterMemory(
......@@ -85599,10 +85786,7 @@ fn genSetReg(
8559985786 dst_reg.to64(),
8560085787 .{
8560185788 .base = .{ .reg = dst_reg.to64() },
85602 .mod = .{ .rm = .{
85603 .size = .qword,
85604 .disp = sym_off.off,
85605 } },
85789 .mod = .{ .rm = .{ .disp = sym_off.off } },
8560685790 },
8560785791 );
8560885792 },
......@@ -85816,18 +86000,12 @@ fn genSetMem(
8581686000 const src_reg = registerAlias(reg_off.reg, abi_size);
8581786001 try self.asmRegisterMemory(.{ ._, .lea }, src_reg, .{
8581886002 .base = .{ .reg = src_reg },
85819 .mod = .{ .rm = .{
85820 .size = .qword,
85821 .disp = reg_off.off,
85822 } },
86003 .mod = .{ .rm = .{ .disp = reg_off.off } },
8582386004 });
8582486005 try self.genSetMem(base, disp, ty, .{ .register = reg_off.reg }, opts);
8582586006 return self.asmRegisterMemory(.{ ._, .lea }, src_reg, .{
8582686007 .base = .{ .reg = src_reg },
85827 .mod = .{ .rm = .{
85828 .size = .qword,
85829 .disp = -reg_off.off,
85830 } },
86008 .mod = .{ .rm = .{ .disp = -reg_off.off } },
8583186009 });
8583286010 },
8583386011 else => |e| return e,
......@@ -87185,10 +87363,7 @@ fn airErrorName(self: *CodeGen, inst: Air.Inst.Index) !void {
8718587363 start_reg.to64(),
8718687364 .{
8718787365 .base = .{ .reg = addr_reg.to64() },
87188 .mod = .{ .rm = .{
87189 .size = .dword,
87190 .index = start_reg.to64(),
87191 } },
87366 .mod = .{ .rm = .{ .index = start_reg.to64() } },
8719287367 },
8719387368 );
8719487369 try self.asmRegisterMemory(
......@@ -87196,10 +87371,7 @@ fn airErrorName(self: *CodeGen, inst: Air.Inst.Index) !void {
8719687371 end_reg.to32(),
8719787372 .{
8719887373 .base = .{ .reg = end_reg.to64() },
87199 .mod = .{ .rm = .{
87200 .size = .byte,
87201 .disp = -1,
87202 } },
87374 .mod = .{ .rm = .{ .disp = -1 } },
8720387375 },
8720487376 );
8720587377
......@@ -89375,17 +89547,11 @@ fn airVaArg(self: *CodeGen, inst: Air.Inst.Index) !void {
8937589547 try self.genSetReg(addr_reg, ptr_anyopaque_ty, reg_save_area, .{});
8937689548 if (!unused) try self.asmRegisterMemory(.{ ._, .lea }, addr_reg, .{
8937789549 .base = .{ .reg = addr_reg },
89378 .mod = .{ .rm = .{
89379 .size = .qword,
89380 .index = offset_reg.to64(),
89381 } },
89550 .mod = .{ .rm = .{ .index = offset_reg.to64() } },
8938289551 });
8938389552 try self.asmRegisterMemory(.{ ._, .lea }, offset_reg, .{
8938489553 .base = .{ .reg = offset_reg.to64() },
89385 .mod = .{ .rm = .{
89386 .size = .qword,
89387 .disp = 8,
89388 } },
89554 .mod = .{ .rm = .{ .disp = 8 } },
8938989555 });
8939089556 try self.genCopy(.c_uint, gp_offset, .{ .register = offset_reg }, .{});
8939189557 const done_reloc = try self.asmJmpReloc(undefined);
......@@ -89394,10 +89560,7 @@ fn airVaArg(self: *CodeGen, inst: Air.Inst.Index) !void {
8939489560 try self.genSetReg(addr_reg, ptr_anyopaque_ty, overflow_arg_area, .{});
8939589561 try self.asmRegisterMemory(.{ ._, .lea }, offset_reg.to64(), .{
8939689562 .base = .{ .reg = addr_reg },
89397 .mod = .{ .rm = .{
89398 .size = .qword,
89399 .disp = @intCast(@max(promote_ty.abiSize(zcu), 8)),
89400 } },
89563 .mod = .{ .rm = .{ .disp = @intCast(@max(promote_ty.abiSize(zcu), 8)) } },
8940189564 });
8940289565 try self.genCopy(
8940389566 ptr_anyopaque_ty,
......@@ -89423,17 +89586,11 @@ fn airVaArg(self: *CodeGen, inst: Air.Inst.Index) !void {
8942389586 try self.genSetReg(addr_reg, ptr_anyopaque_ty, reg_save_area, .{});
8942489587 if (!unused) try self.asmRegisterMemory(.{ ._, .lea }, addr_reg, .{
8942589588 .base = .{ .reg = addr_reg },
89426 .mod = .{ .rm = .{
89427 .size = .qword,
89428 .index = offset_reg.to64(),
89429 } },
89589 .mod = .{ .rm = .{ .index = offset_reg.to64() } },
8943089590 });
8943189591 try self.asmRegisterMemory(.{ ._, .lea }, offset_reg, .{
8943289592 .base = .{ .reg = offset_reg.to64() },
89433 .mod = .{ .rm = .{
89434 .size = .qword,
89435 .disp = 16,
89436 } },
89593 .mod = .{ .rm = .{ .disp = 16 } },
8943789594 });
8943889595 try self.genCopy(.c_uint, fp_offset, .{ .register = offset_reg }, .{});
8943989596 const done_reloc = try self.asmJmpReloc(undefined);
......@@ -89442,10 +89599,7 @@ fn airVaArg(self: *CodeGen, inst: Air.Inst.Index) !void {
8944289599 try self.genSetReg(addr_reg, ptr_anyopaque_ty, overflow_arg_area, .{});
8944389600 try self.asmRegisterMemory(.{ ._, .lea }, offset_reg.to64(), .{
8944489601 .base = .{ .reg = addr_reg },
89445 .mod = .{ .rm = .{
89446 .size = .qword,
89447 .disp = @intCast(@max(promote_ty.abiSize(zcu), 8)),
89448 } },
89602 .mod = .{ .rm = .{ .disp = @intCast(@max(promote_ty.abiSize(zcu), 8)) } },
8944989603 });
8945089604 try self.genCopy(
8945189605 ptr_anyopaque_ty,
......@@ -90505,10 +90659,7 @@ const Temp = struct {
9050590659 new_temp_index.tracking(cg).* = .init(.{ .register = new_reg });
9050690660 try cg.asmRegisterMemory(.{ ._, .lea }, new_reg.to64(), .{
9050790661 .base = .{ .reg = reg.to64() },
90508 .mod = .{ .rm = .{
90509 .size = .qword,
90510 .disp = off,
90511 } },
90662 .mod = .{ .rm = .{ .disp = off } },
9051290663 });
9051390664 },
9051490665 .register_offset => |reg_off| {
......@@ -90517,10 +90668,7 @@ const Temp = struct {
9051790668 new_temp_index.tracking(cg).* = .init(.{ .register = new_reg });
9051890669 try cg.asmRegisterMemory(.{ ._, .lea }, new_reg.to64(), .{
9051990670 .base = .{ .reg = reg_off.reg.to64() },
90520 .mod = .{ .rm = .{
90521 .size = .qword,
90522 .disp = reg_off.off + off,
90523 } },
90671 .mod = .{ .rm = .{ .disp = reg_off.off + off } },
9052490672 });
9052590673 },
9052690674 .lea_symbol => |sym_off| new_temp_index.tracking(cg).* = .init(.{ .lea_symbol = .{
......@@ -90627,10 +90775,7 @@ const Temp = struct {
9062790775 new_temp_index.tracking(cg).* = .init(.{ .register = new_reg });
9062890776 try cg.asmRegisterMemory(.{ ._, .lea }, new_reg.to64(), .{
9062990777 .base = .{ .reg = reg_off.reg.to64() },
90630 .mod = .{ .rm = .{
90631 .size = .qword,
90632 .disp = reg_off.off + @as(u31, limb_index) * 8,
90633 } },
90778 .mod = .{ .rm = .{ .disp = reg_off.off + @as(u31, limb_index) * 8 } },
9063490779 });
9063590780 },
9063690781 .load_symbol => |sym_off| {
......@@ -93462,13 +93607,14 @@ const Select = struct {
9346293607 elem_size,
9346393608 src0_elem_size,
9346493609 dst0_elem_size,
93465 src0_elem_size_times_src1,
93610 src0_elem_size_mul_src1,
93611 src1,
9346693612 log2_src0_elem_size,
9346793613 smin,
9346893614 smax,
9346993615 umax,
9347093616 },
93471 op: enum(u2) { mul, div, rem_8_mul },
93617 op: enum(u2) { mul, div, div_8_down, rem_8_mul },
9347293618 rhs: Memory.Scale,
9347393619
9347493620 const none: Adjust = .{ .sign = .pos, .lhs = .none, .op = .mul, .rhs = .@"1" };
......@@ -93512,8 +93658,11 @@ const Select = struct {
9351293658 const add_8_src0_elem_size: Adjust = .{ .sign = .pos, .lhs = .src0_elem_size, .op = .mul, .rhs = .@"8" };
9351393659 const add_src0_elem_size_div_8: Adjust = .{ .sign = .pos, .lhs = .src0_elem_size, .op = .div, .rhs = .@"8" };
9351493660 const sub_src0_elem_size: Adjust = .{ .sign = .neg, .lhs = .src0_elem_size, .op = .mul, .rhs = .@"1" };
93515 const add_src0_elem_size_times_src1: Adjust = .{ .sign = .pos, .lhs = .src0_elem_size_times_src1, .op = .mul, .rhs = .@"1" };
93516 const sub_src0_elem_size_times_src1: Adjust = .{ .sign = .neg, .lhs = .src0_elem_size_times_src1, .op = .mul, .rhs = .@"1" };
93661 const add_src0_elem_size_mul_src1: Adjust = .{ .sign = .pos, .lhs = .src0_elem_size_mul_src1, .op = .mul, .rhs = .@"1" };
93662 const sub_src0_elem_size_mul_src1: Adjust = .{ .sign = .neg, .lhs = .src0_elem_size_mul_src1, .op = .mul, .rhs = .@"1" };
93663 const add_src1_div_8_down_4: Adjust = .{ .sign = .pos, .lhs = .src1, .op = .div_8_down, .rhs = .@"4" };
93664 const add_src1_rem_32: Adjust = .{ .sign = .pos, .lhs = .src1, .op = .rem_8_mul, .rhs = .@"4" };
93665 const add_src1_rem_64: Adjust = .{ .sign = .pos, .lhs = .src1, .op = .rem_8_mul, .rhs = .@"8" };
9351793666 const add_log2_src0_elem_size: Adjust = .{ .sign = .pos, .lhs = .log2_src0_elem_size, .op = .mul, .rhs = .@"1" };
9351893667 const add_dst0_elem_size: Adjust = .{ .sign = .pos, .lhs = .dst0_elem_size, .op = .mul, .rhs = .@"1" };
9351993668 const add_elem_limbs: Adjust = .{ .sign = .pos, .lhs = .elem_limbs, .op = .mul, .rhs = .@"1" };
......@@ -94086,8 +94235,9 @@ const Select = struct {
9408694235 .elem_size => @intCast(op.base.ref.typeOf(s).elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)),
9408794236 .src0_elem_size => @intCast(Select.Operand.Ref.src0.typeOf(s).elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)),
9408894237 .dst0_elem_size => @intCast(Select.Operand.Ref.dst0.typeOf(s).elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)),
94089 .src0_elem_size_times_src1 => @intCast(Select.Operand.Ref.src0.typeOf(s).elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu) *
94238 .src0_elem_size_mul_src1 => @intCast(Select.Operand.Ref.src0.typeOf(s).elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu) *
9409094239 Select.Operand.Ref.src1.valueOf(s).immediate),
94240 .src1 => @intCast(Select.Operand.Ref.src1.valueOf(s).immediate),
9409194241 .log2_src0_elem_size => @intCast(std.math.log2(Select.Operand.Ref.src0.typeOf(s).elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu))),
9409294242 .smin => @as(SignedImm, std.math.minInt(SignedImm)) >> @truncate(
9409394243 -%op.base.ref.typeOf(s).scalarType(s.cg.pt.zcu).bitSize(s.cg.pt.zcu),
......@@ -94107,6 +94257,7 @@ const Select = struct {
9410794257 break :op_res op_res[0];
9410894258 },
9410994259 .div => @shrExact(lhs, rhs),
94260 .div_8_down => lhs >> 3 & @as(SignedImm, -1) << rhs,
9411094261 .rem_8_mul => lhs & (@as(SignedImm, 1) << @intCast(@as(u3, 3) + rhs)) - 1,
9411194262 };
9411294263 return switch (op.flags.adjust.sign) {
src/arch/x86_64/Lower.zig+12-12
......@@ -431,7 +431,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
431431 _ = lower.reloc(.{ .linker_tlsld = sym_index }, 0);
432432 lower.result_insts[lower.result_insts_len] = try .new(.none, .lea, &.{
433433 .{ .reg = .rdi },
434 .{ .mem = Memory.initRip(mem_op.sib.ptr_size, 0) },
434 .{ .mem = Memory.initRip(.none, 0) },
435435 }, lower.target);
436436 lower.result_insts_len += 1;
437437 _ = lower.reloc(.{
......@@ -443,7 +443,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
443443 lower.result_insts_len += 1;
444444 _ = lower.reloc(.{ .linker_dtpoff = sym_index }, 0);
445445 emit_mnemonic = .lea;
446 break :op .{ .mem = Memory.initSib(mem_op.sib.ptr_size, .{
446 break :op .{ .mem = Memory.initSib(.none, .{
447447 .base = .{ .reg = .rax },
448448 .disp = std.math.minInt(i32),
449449 }) };
......@@ -456,7 +456,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
456456 lower.result_insts_len += 1;
457457 _ = lower.reloc(.{ .linker_reloc = sym_index }, 0);
458458 emit_mnemonic = .lea;
459 break :op .{ .mem = Memory.initSib(mem_op.sib.ptr_size, .{
459 break :op .{ .mem = Memory.initSib(.none, .{
460460 .base = .{ .reg = .rax },
461461 .disp = std.math.minInt(i32),
462462 }) };
......@@ -465,10 +465,10 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
465465
466466 _ = lower.reloc(.{ .linker_reloc = sym_index }, 0);
467467 if (lower.pic) switch (mnemonic) {
468 .lea => {
469 if (elf_sym.flags.is_extern_ptr) emit_mnemonic = .mov;
470 break :op .{ .mem = Memory.initRip(mem_op.sib.ptr_size, 0) };
471 },
468 .lea => if (elf_sym.flags.is_extern_ptr) {
469 emit_mnemonic = .mov;
470 break :op .{ .mem = Memory.initRip(.ptr, 0) };
471 } else break :op .{ .mem = Memory.initRip(.none, 0) },
472472 .mov => {
473473 if (elf_sym.flags.is_extern_ptr) {
474474 const reg = ops[0].reg;
......@@ -505,7 +505,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
505505 _ = lower.reloc(.{ .linker_reloc = sym_index }, 0);
506506 lower.result_insts[lower.result_insts_len] = try .new(.none, .mov, &.{
507507 .{ .reg = .rdi },
508 .{ .mem = Memory.initRip(mem_op.sib.ptr_size, 0) },
508 .{ .mem = Memory.initRip(.ptr, 0) },
509509 }, lower.target);
510510 lower.result_insts_len += 1;
511511 lower.result_insts[lower.result_insts_len] = try .new(.none, .call, &.{
......@@ -518,10 +518,10 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
518518
519519 _ = lower.reloc(.{ .linker_reloc = sym_index }, 0);
520520 break :op switch (mnemonic) {
521 .lea => {
522 if (macho_sym.flags.is_extern_ptr) emit_mnemonic = .mov;
523 break :op .{ .mem = Memory.initRip(mem_op.sib.ptr_size, 0) };
524 },
521 .lea => if (macho_sym.flags.is_extern_ptr) {
522 emit_mnemonic = .mov;
523 break :op .{ .mem = Memory.initRip(.ptr, 0) };
524 } else break :op .{ .mem = Memory.initRip(.none, 0) },
525525 .mov => {
526526 if (macho_sym.flags.is_extern_ptr) {
527527 const reg = ops[0].reg;
test/behavior/x86_64/mem.zig+142-7
......@@ -1,4 +1,4 @@
1fn access(comptime array: anytype) !void {
1fn accessSlice(comptime array: anytype) !void {
22 var slice: []const @typeInfo(@TypeOf(array)).array.child = undefined;
33 slice = &array;
44 inline for (0.., &array) |ct_index, *elem| {
......@@ -20,18 +20,153 @@ fn access(comptime array: anytype) !void {
2020 if (slice[rt_index] != elem.*) return error.Unexpected;
2121 }
2222}
23test access {
24 try access([3]u8{ 0xdb, 0xef, 0xbd });
25 try access([3]u16{ 0x340e, 0x3654, 0x88d7 });
26 try access([3]u32{ 0xd424c2c0, 0x2d6ac466, 0x5a0cfaba });
27 try access([3]u64{
23test accessSlice {
24 try accessSlice([3]u8{ 0xdb, 0xef, 0xbd });
25 try accessSlice([3]u16{ 0x340e, 0x3654, 0x88d7 });
26 try accessSlice([3]u32{ 0xd424c2c0, 0x2d6ac466, 0x5a0cfaba });
27 try accessSlice([3]u64{
2828 0x9327a4f5221666a6,
2929 0x5c34d3ddd84a8b12,
3030 0xbae087f39f649260,
3131 });
32 try access([3]u128{
32 try accessSlice([3]u128{
3333 0x601cf010065444d4d42d5536dd9b95db,
3434 0xa03f592fcaa22d40af23a0c735531e3c,
3535 0x5da44907b31602b95c2d93f0b582ceab,
3636 });
3737}
38
39fn accessVector(comptime init: anytype) !void {
40 const Vector = @TypeOf(init);
41 var vector: Vector = undefined;
42 vector = init;
43 inline for (0..@typeInfo(Vector).vector.len) |ct_index| {
44 var rt_index: usize = undefined;
45 rt_index = ct_index;
46 if (&vector[rt_index] != &vector[ct_index]) return error.Unexpected;
47 if (vector[rt_index] != vector[ct_index]) return error.Unexpected;
48 }
49}
50test accessVector {
51 try accessVector(@Vector(1, bool){
52 false,
53 });
54 try accessVector(@Vector(2, bool){
55 false, true,
56 });
57 try accessVector(@Vector(3, bool){
58 true, true, false,
59 });
60 try accessVector(@Vector(5, bool){
61 true, false, true, false, true,
62 });
63 try accessVector(@Vector(7, bool){
64 true, false, true, true, true, false, true,
65 });
66 try accessVector(@Vector(8, bool){
67 false, true, false, true, false, false, false, true,
68 });
69 try accessVector(@Vector(9, bool){
70 true, true, false, true, false, false, false, false,
71 true,
72 });
73 try accessVector(@Vector(15, bool){
74 false, true, true, true, false, true, false, false,
75 true, true, false, false, true, false, false,
76 });
77 try accessVector(@Vector(16, bool){
78 true, true, false, true, false, false, false, false,
79 false, true, true, false, false, false, true, true,
80 });
81 try accessVector(@Vector(17, bool){
82 true, false, true, true, false, true, false, true,
83 true, true, true, false, false, false, true, true,
84 false,
85 });
86 try accessVector(@Vector(31, bool){
87 true, false, true, true, false, true, true, true,
88 false, true, false, true, false, true, true, true,
89 false, false, true, false, false, false, false, true,
90 true, true, true, false, false, false, false,
91 });
92 try accessVector(@Vector(32, bool){
93 true, true, false, false, false, true, true, true,
94 false, true, true, true, false, true, false, true,
95 false, true, false, true, false, true, true, false,
96 false, false, false, false, false, true, true, true,
97 });
98 try accessVector(@Vector(33, bool){
99 true, false, false, false, false, true, true, true,
100 false, false, true, false, true, true, false, true,
101 true, true, false, true, true, false, false, false,
102 false, true, false, false, false, true, true, false,
103 false,
104 });
105 try accessVector(@Vector(63, bool){
106 false, false, true, true, true, false, true, true,
107 true, false, true, true, true, false, true, false,
108 true, true, false, true, false, true, true, true,
109 false, false, true, false, false, false, false, true,
110 true, true, true, true, false, true, false, true,
111 true, true, false, false, true, false, false, true,
112 false, true, false, false, false, false, true, true,
113 false, true, false, false, true, true, true,
114 });
115 try accessVector(@Vector(64, bool){
116 false, false, true, true, true, false, true, true,
117 true, false, true, true, false, true, true, false,
118 false, false, false, false, true, true, false, true,
119 true, true, true, true, false, false, false, true,
120 true, false, true, true, false, false, true, false,
121 false, true, true, false, true, true, false, false,
122 true, true, false, true, false, true, true, true,
123 false, true, true, false, false, false, false, false,
124 });
125 try accessVector(@Vector(65, bool){
126 false, false, true, true, true, true, true, true,
127 true, false, false, false, false, true, true, false,
128 true, false, true, true, true, false, false, false,
129 true, false, true, true, false, true, true, true,
130 true, true, false, true, true, false, true, false,
131 false, true, false, true, false, false, true, false,
132 true, false, true, true, true, false, true, true,
133 false, false, true, true, true, true, false, false,
134 true,
135 });
136 try accessVector(@Vector(8, u8){
137 0x60, 0xf7, 0xf4, 0xb0, 0x05, 0xd3, 0x06, 0x78,
138 });
139 try accessVector(@Vector(8, u16){
140 0x9c91, 0xfb8b, 0x7f80, 0x8304, 0x6e52, 0xd8ef, 0x37fc, 0x7851,
141 });
142 try accessVector(@Vector(8, u32){
143 0x688b88e2, 0x68e2b7a2, 0x87574680, 0xab4f0769,
144 0x75472bb5, 0xa791f2ae, 0xeb2ed416, 0x5f05ce82,
145 });
146 try accessVector(@Vector(8, u64){
147 0xdefd1ddffaedf818, 0x91c78a29d3d59890,
148 0x842aaf8fd3c7b785, 0x970a07b8f9f4a6b3,
149 0x21b2425d1a428246, 0xea50e41174a7977b,
150 0x08d0f1c4f5978b74, 0x8dc88a7fd85e0e67,
151 });
152 try accessVector(@Vector(8, u128){
153 0x6f2cbde1fb219b1e73d7f774d10f0d94,
154 0x7c1412616cda20436d7106691d8ba4cc,
155 0x4ee940b50e97675b3b35d7872a35b5ad,
156 0x6d994fb8caa1b2fac48acbb68fa2d2f1,
157 0xdee698c7ec8de9b5940903e3fc665b63,
158 0x0751491a509e4a1ce8cfa6d62fe9e74c,
159 0x3d880f0a927ce3bfc2682b72070fcd50,
160 0x82f0eec62881598699eeb93fbb456e95,
161 });
162 try accessVector(@Vector(8, u256){
163 0x6ee4f35fe624d365952f73960791238ac781bfba782abc7866a691063e43ce48,
164 0xb006491f54a9c9292458a5835b7d5f4cfa18136f175eef0a13bb8adf5c3dc061,
165 0xd6e25ca1bc5685fc52609e261b9065bc05a8662e9291660033dd7f6d98e562b3,
166 0x992c5e54e0e6331dac258996be7dae9b2a2eff323a39043ba8d2721420dc5f5c,
167 0x257313f45fb3556d0fc323d5f38c953e9a093fe2278655312b6a5b64aab9d901,
168 0x6c8ad2182b9a3b2b19c2c9b152956b383d0fee2e3fbd5b02ed72227446a7b221,
169 0xd80cafc2252b289793799675e43f97ba4a5448c7b57e1544a464687b435efc7b,
170 0xfcb480f2d70afd53c4689dd3f5db7638c24302f2a6a15f738167db090d91fb28,
171 });
172}