authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-16 15:00:32+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-16 15:00:32+01:00
log1b7ec44924ede3816438f9de4b4b5bc3b7705711
treeadae1544584882c5e37b96d1ebd8054f852d93e5
parent3383064b27cc8ad7aa997f6504d627af1fa8c960

x64: separate ptr_add and ptr_sub from normal bin ops


1 files changed, 94 insertions(+), 39 deletions(-)

src/arch/x86_64/CodeGen.zig+94-39
...@@ -582,10 +582,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -582,10 +582,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
582582
583 switch (air_tags[inst]) {583 switch (air_tags[inst]) {
584 // zig fmt: off584 // zig fmt: off
585 .add, .ptr_add => try self.airAdd(inst),585 .add => try self.airAdd(inst),
586 .addwrap => try self.airAddWrap(inst),586 .addwrap => try self.airAddWrap(inst),
587 .add_sat => try self.airAddSat(inst),587 .add_sat => try self.airAddSat(inst),
588 .sub, .ptr_sub => try self.airSub(inst),588 .sub => try self.airSub(inst),
589 .subwrap => try self.airSubWrap(inst),589 .subwrap => try self.airSubWrap(inst),
590 .sub_sat => try self.airSubSat(inst),590 .sub_sat => try self.airSubSat(inst),
591 .mul => try self.airMul(inst),591 .mul => try self.airMul(inst),
...@@ -597,6 +597,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -597,6 +597,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
597 .shl_sat => try self.airShlSat(inst),597 .shl_sat => try self.airShlSat(inst),
598 .min => try self.airMin(inst),598 .min => try self.airMin(inst),
599 .max => try self.airMax(inst),599 .max => try self.airMax(inst),
600 .ptr_add => try self.airPtrAdd(inst),
601 .ptr_sub => try self.airPtrSub(inst),
600 .slice => try self.airSlice(inst),602 .slice => try self.airSlice(inst),
601603
602 .sqrt,604 .sqrt,
...@@ -1068,6 +1070,70 @@ fn airMax(self: *Self, inst: Air.Inst.Index) !void {...@@ -1068,6 +1070,70 @@ fn airMax(self: *Self, inst: Air.Inst.Index) !void {
1068 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1070 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1069}1071}
10701072
1073fn airPtrAdd(self: *Self, inst: Air.Inst.Index) !void {
1074 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1075 if (self.liveness.isUnused(inst)) {
1076 return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none });
1077 }
1078
1079 const mcvs = try self.mcvsForBinMathOp(inst, bin_op.lhs, bin_op.rhs);
1080 var dst_mcv = mcvs.dst;
1081 const src_mcv = mcvs.src;
1082
1083 // TODO clean this up
1084 // TODO take into account alignment
1085 const dst_ty = self.air.typeOfIndex(inst);
1086 const elem_size = dst_ty.elemType2().abiSize(self.target.*);
1087 const dst_reg = blk: {
1088 switch (dst_mcv) {
1089 .register => |reg| break :blk reg,
1090 else => {
1091 src_mcv.freezeIfRegister(&self.register_manager);
1092 defer src_mcv.freezeIfRegister(&self.register_manager);
1093 const reg = try self.copyToTmpRegister(dst_ty, dst_mcv);
1094 break :blk reg;
1095 },
1096 }
1097 };
1098 try self.genIMulOpMir(dst_ty, .{ .register = dst_reg }, .{ .immediate = elem_size });
1099 dst_mcv = .{ .register = dst_reg };
1100 try self.genBinMathOpMir(.add, dst_ty, dst_mcv, src_mcv);
1101
1102 return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none });
1103}
1104
1105fn airPtrSub(self: *Self, inst: Air.Inst.Index) !void {
1106 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1107 if (self.liveness.isUnused(inst)) {
1108 return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none });
1109 }
1110
1111 const mcvs = try self.mcvsForBinMathOp(inst, bin_op.lhs, bin_op.rhs);
1112 var dst_mcv = mcvs.dst;
1113 const src_mcv = mcvs.src;
1114
1115 // TODO clean this up
1116 // TODO take into account alignment
1117 const dst_ty = self.air.typeOfIndex(inst);
1118 const elem_size = dst_ty.elemType2().abiSize(self.target.*);
1119 const dst_reg = blk: {
1120 switch (dst_mcv) {
1121 .register => |reg| break :blk reg,
1122 else => {
1123 src_mcv.freezeIfRegister(&self.register_manager);
1124 defer src_mcv.freezeIfRegister(&self.register_manager);
1125 const reg = try self.copyToTmpRegister(dst_ty, dst_mcv);
1126 break :blk reg;
1127 },
1128 }
1129 };
1130 try self.genIMulOpMir(dst_ty, .{ .register = dst_reg }, .{ .immediate = elem_size });
1131 dst_mcv = .{ .register = dst_reg };
1132 try self.genBinMathOpMir(.sub, dst_ty, dst_mcv, src_mcv);
1133
1134 return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none });
1135}
1136
1071fn airSlice(self: *Self, inst: Air.Inst.Index) !void {1137fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
1072 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;1138 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1073 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;1139 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
...@@ -2148,18 +2214,17 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2148,18 +2214,17 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
2148 return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none });2214 return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none });
2149}2215}
21502216
2151/// Perform "binary" operators, excluding comparisons.2217const BinMathOpMCValuePair = struct {
2152/// Currently, the following ops are supported:2218 dst: MCValue,
2153/// ADD, SUB, XOR, OR, AND2219 src: MCValue,
2154fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air.Inst.Ref) !MCValue {2220};
2155 // We'll handle these ops in two steps.2221
2156 // 1) Prepare an output location (register or memory)2222fn mcvsForBinMathOp(
2157 // This location will be the location of the operand that dies (if one exists)2223 self: *Self,
2158 // or just a temporary register (if one doesn't exist)2224 inst: Air.Inst.Index,
2159 // 2) Perform the op with the other argument2225 op_lhs: Air.Inst.Ref,
2160 // 3) Sometimes, the output location is memory but the op doesn't support it.2226 op_rhs: Air.Inst.Ref,
2161 // In this case, copy that location to a register, then perform the op to that register instead.2227) !BinMathOpMCValuePair {
2162 //
2163 // TODO: make this algorithm less bad2228 // TODO: make this algorithm less bad
2164 const lhs = try self.resolveInst(op_lhs);2229 const lhs = try self.resolveInst(op_lhs);
2165 const rhs = try self.resolveInst(op_rhs);2230 const rhs = try self.resolveInst(op_rhs);
...@@ -2218,35 +2283,26 @@ fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs:...@@ -2218,35 +2283,26 @@ fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs:
2218 dst_mcv.freezeIfRegister(&self.register_manager);2283 dst_mcv.freezeIfRegister(&self.register_manager);
2219 defer dst_mcv.unfreezeIfRegister(&self.register_manager);2284 defer dst_mcv.unfreezeIfRegister(&self.register_manager);
22202285
2221 const tmp_reg = try self.copyToTmpRegister(Type.u64, src_mcv);2286 src_mcv = try self.copyToNewRegister(inst, Type.u64, src_mcv);
2222 src_mcv = MCValue{ .register = tmp_reg };
2223 }2287 }
2224 },2288 },
2225 else => {},2289 else => {},
2226 }2290 }
22272291
2228 // Now for step 2, we assing an MIR instruction2292 return BinMathOpMCValuePair{ .dst = dst_mcv, .src = src_mcv };
2229 const air_tags = self.air.instructions.items(.tag);2293}
2230 switch (air_tags[inst]) {2294
2231 .ptr_add => {2295/// Perform "binary" operators, excluding comparisons.
2232 // TODO clean this up2296/// Currently, the following ops are supported:
2233 // TODO take into account alignment2297/// ADD, SUB, XOR, OR, AND
2234 const elem_size = dst_ty.elemType2().abiSize(self.target.*);2298fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air.Inst.Ref) !MCValue {
2235 const dst_reg = blk: {2299 const dst_ty = self.air.typeOfIndex(inst);
2236 switch (dst_mcv) {2300 const mcvs = try self.mcvsForBinMathOp(inst, op_lhs, op_rhs);
2237 .register => |reg| break :blk reg,2301 const dst_mcv = mcvs.dst;
2238 else => {2302 const src_mcv = mcvs.src;
2239 src_mcv.freezeIfRegister(&self.register_manager);2303 log.warn("dst_mcv = {}, src_mcv = {}", .{ dst_mcv, src_mcv });
2240 defer src_mcv.freezeIfRegister(&self.register_manager);2304 const tag = self.air.instructions.items(.tag)[inst];
2241 const reg = try self.copyToTmpRegister(dst_ty, dst_mcv);2305 switch (tag) {
2242 break :blk reg;
2243 },
2244 }
2245 };
2246 try self.genIMulOpMir(dst_ty, .{ .register = dst_reg }, .{ .immediate = elem_size });
2247 dst_mcv = MCValue{ .register = dst_reg };
2248 try self.genBinMathOpMir(.add, dst_ty, dst_mcv, src_mcv);
2249 },
2250 .add, .addwrap => try self.genBinMathOpMir(.add, dst_ty, dst_mcv, src_mcv),2306 .add, .addwrap => try self.genBinMathOpMir(.add, dst_ty, dst_mcv, src_mcv),
2251 .bool_or, .bit_or => try self.genBinMathOpMir(.@"or", dst_ty, dst_mcv, src_mcv),2307 .bool_or, .bit_or => try self.genBinMathOpMir(.@"or", dst_ty, dst_mcv, src_mcv),
2252 .bool_and, .bit_and => try self.genBinMathOpMir(.@"and", dst_ty, dst_mcv, src_mcv),2308 .bool_and, .bit_and => try self.genBinMathOpMir(.@"and", dst_ty, dst_mcv, src_mcv),
...@@ -2255,7 +2311,6 @@ fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs:...@@ -2255,7 +2311,6 @@ fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs:
2255 .mul, .mulwrap => try self.genIMulOpMir(dst_ty, dst_mcv, src_mcv),2311 .mul, .mulwrap => try self.genIMulOpMir(dst_ty, dst_mcv, src_mcv),
2256 else => unreachable,2312 else => unreachable,
2257 }2313 }
2258
2259 return dst_mcv;2314 return dst_mcv;
2260}2315}
22612316