authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-02-16 23:40:08+01:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-02-19 12:06:34+01:00
log985a442f462a0a0728ed96a2a77e5290b6d534af
tree82503887665f529c196b43cd30c4aad764742dc6
parent67e334663399d1dcf6fc8c3fa9a896494f1af652
signature Commit is signed but in an unrecognized format.

stage2 ARM: move mul to binOp lowering mechanism


1 files changed, 35 insertions(+), 135 deletions(-)

src/arch/arm/CodeGen.zig+35-135
......@@ -508,7 +508,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
508508 .sub, .ptr_sub => try self.airBinOp(inst),
509509 .subwrap => try self.airSubWrap(inst),
510510 .sub_sat => try self.airSubSat(inst),
511 .mul => try self.airMul(inst),
511 .mul => try self.airBinOp(inst),
512512 .mulwrap => try self.airMulWrap(inst),
513513 .mul_sat => try self.airMulSat(inst),
514514 .rem => try self.airRem(inst),
......@@ -979,12 +979,6 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void {
979979 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
980980}
981981
982fn airMul(self: *Self, inst: Air.Inst.Index) !void {
983 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
984 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genMul(inst, bin_op.lhs, bin_op.rhs);
985 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
986}
987
988982fn airMulWrap(self: *Self, inst: Air.Inst.Index) !void {
989983 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
990984 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement mulwrap for {}", .{self.target.cpu.arch});
......@@ -1252,7 +1246,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
12521246
12531247 const slice_ty = self.air.typeOf(bin_op.lhs);
12541248 const elem_ty = slice_ty.childType();
1255 const elem_size = elem_ty.abiSize(self.target.*);
1249 const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*));
12561250
12571251 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
12581252 const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf);
......@@ -1307,7 +1301,14 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
13071301 else => {
13081302 const dst_mcv = try self.allocRegOrMem(inst, true);
13091303
1310 const offset_mcv = try self.genMulConstant(bin_op.rhs, @intCast(u32, elem_size));
1304 const offset_mcv = try self.binOp(
1305 .mul,
1306 null,
1307 index_mcv,
1308 .{ .immediate = elem_size },
1309 Type.usize,
1310 Type.usize,
1311 );
13111312 assert(offset_mcv == .register); // result of multiplication should always be register
13121313 self.register_manager.freezeRegs(&.{offset_mcv.register});
13131314
......@@ -1768,6 +1769,7 @@ fn binOpRegister(
17681769 const mir_tag: Mir.Inst.Tag = switch (tag) {
17691770 .add, .ptr_add => .add,
17701771 .sub, .ptr_sub => .sub,
1772 .mul => .mul,
17711773 else => unreachable,
17721774 };
17731775 const mir_data: Mir.Inst.Data = switch (tag) {
......@@ -1780,6 +1782,11 @@ fn binOpRegister(
17801782 .rn = lhs_reg,
17811783 .op = Instruction.Operand.reg(rhs_reg, Instruction.Operand.Shift.none),
17821784 } },
1785 .mul => .{ .rrr = .{
1786 .rd = dest_reg,
1787 .rn = lhs_reg,
1788 .rm = rhs_reg,
1789 } },
17831790 else => unreachable,
17841791 };
17851792
......@@ -1938,6 +1945,25 @@ fn binOp(
19381945 else => unreachable,
19391946 }
19401947 },
1948 .mul => {
1949 switch (lhs_ty.zigTypeTag()) {
1950 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
1951 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
1952 .Int => {
1953 assert(lhs_ty.eql(rhs_ty));
1954 const int_info = lhs_ty.intInfo(self.target.*);
1955 if (int_info.bits <= 32) {
1956 // TODO add optimisations for multiplication
1957 // with immediates, for example a * 2 can be
1958 // lowered to a << 1
1959 return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
1960 } else {
1961 return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
1962 }
1963 },
1964 else => unreachable,
1965 }
1966 },
19411967 .ptr_add,
19421968 .ptr_sub,
19431969 => {
......@@ -2219,132 +2245,6 @@ fn genBinOpCode(
22192245 }
22202246}
22212247
2222fn genMul(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air.Inst.Ref) !MCValue {
2223 const lhs = try self.resolveInst(op_lhs);
2224 const rhs = try self.resolveInst(op_rhs);
2225
2226 const lhs_is_register = lhs == .register;
2227 const rhs_is_register = rhs == .register;
2228 const reuse_lhs = lhs_is_register and self.reuseOperand(inst, op_lhs, 0, lhs);
2229 const reuse_rhs = !reuse_lhs and rhs_is_register and self.reuseOperand(inst, op_rhs, 1, rhs);
2230
2231 if (lhs_is_register) self.register_manager.freezeRegs(&.{lhs.register});
2232 defer if (lhs_is_register) self.register_manager.unfreezeRegs(&.{lhs.register});
2233 if (rhs_is_register) self.register_manager.freezeRegs(&.{rhs.register});
2234 defer if (rhs_is_register) self.register_manager.unfreezeRegs(&.{rhs.register});
2235
2236 // Destination must be a register
2237 // LHS must be a register
2238 // RHS must be a register
2239 var dst_mcv: MCValue = undefined;
2240 var lhs_mcv: MCValue = lhs;
2241 var rhs_mcv: MCValue = rhs;
2242
2243 // Allocate registers for operands and/or destination
2244 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
2245 if (reuse_lhs) {
2246 // Allocate 0 or 1 registers
2247 if (!rhs_is_register) {
2248 rhs_mcv = MCValue{ .register = try self.register_manager.allocReg(Air.refToIndex(op_rhs).?) };
2249 branch.inst_table.putAssumeCapacity(Air.refToIndex(op_rhs).?, rhs_mcv);
2250 }
2251 dst_mcv = lhs;
2252 } else if (reuse_rhs) {
2253 // Allocate 0 or 1 registers
2254 if (!lhs_is_register) {
2255 lhs_mcv = MCValue{ .register = try self.register_manager.allocReg(Air.refToIndex(op_lhs).?) };
2256 branch.inst_table.putAssumeCapacity(Air.refToIndex(op_lhs).?, lhs_mcv);
2257 }
2258 dst_mcv = rhs;
2259 } else {
2260 // Allocate 1 or 2 registers
2261 if (lhs_is_register and rhs_is_register) {
2262 dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst) };
2263 } else if (lhs_is_register) {
2264 // Move RHS to register
2265 dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst) };
2266 rhs_mcv = dst_mcv;
2267 } else if (rhs_is_register) {
2268 // Move LHS to register
2269 dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst) };
2270 lhs_mcv = dst_mcv;
2271 } else {
2272 // Move LHS and RHS to register
2273 const regs = try self.register_manager.allocRegs(2, .{ inst, Air.refToIndex(op_rhs).? });
2274 lhs_mcv = MCValue{ .register = regs[0] };
2275 rhs_mcv = MCValue{ .register = regs[1] };
2276 dst_mcv = lhs_mcv;
2277
2278 branch.inst_table.putAssumeCapacity(Air.refToIndex(op_rhs).?, rhs_mcv);
2279 }
2280 }
2281
2282 // Move the operands to the newly allocated registers
2283 if (!lhs_is_register) {
2284 try self.genSetReg(self.air.typeOf(op_lhs), lhs_mcv.register, lhs);
2285 }
2286 if (!rhs_is_register) {
2287 try self.genSetReg(self.air.typeOf(op_rhs), rhs_mcv.register, rhs);
2288 }
2289
2290 _ = try self.addInst(.{
2291 .tag = .mul,
2292 .data = .{ .rrr = .{
2293 .rd = dst_mcv.register,
2294 .rn = lhs_mcv.register,
2295 .rm = rhs_mcv.register,
2296 } },
2297 });
2298 return dst_mcv;
2299}
2300
2301fn genMulConstant(self: *Self, op: Air.Inst.Ref, imm: u32) !MCValue {
2302 const lhs = try self.resolveInst(op);
2303 const rhs = MCValue{ .immediate = imm };
2304
2305 const lhs_is_register = lhs == .register;
2306
2307 if (lhs_is_register) self.register_manager.freezeRegs(&.{lhs.register});
2308 defer if (lhs_is_register) self.register_manager.unfreezeRegs(&.{lhs.register});
2309
2310 // Destination must be a register
2311 // LHS must be a register
2312 // RHS must be a register
2313 var dst_mcv: MCValue = undefined;
2314 var lhs_mcv: MCValue = lhs;
2315 var rhs_mcv: MCValue = rhs;
2316
2317 // Allocate registers for operands and/or destination
2318 // Allocate 1 or 2 registers
2319 if (lhs_is_register) {
2320 // Move RHS to register
2321 dst_mcv = MCValue{ .register = try self.register_manager.allocReg(null) };
2322 rhs_mcv = dst_mcv;
2323 } else {
2324 // Move LHS and RHS to register
2325 const regs = try self.register_manager.allocRegs(2, .{ null, null });
2326 lhs_mcv = MCValue{ .register = regs[0] };
2327 rhs_mcv = MCValue{ .register = regs[1] };
2328 dst_mcv = lhs_mcv;
2329 }
2330
2331 // Move the operands to the newly allocated registers
2332 if (!lhs_is_register) {
2333 try self.genSetReg(self.air.typeOf(op), lhs_mcv.register, lhs);
2334 }
2335 try self.genSetReg(Type.initTag(.usize), rhs_mcv.register, rhs);
2336
2337 _ = try self.addInst(.{
2338 .tag = .mul,
2339 .data = .{ .rrr = .{
2340 .rd = dst_mcv.register,
2341 .rn = lhs_mcv.register,
2342 .rm = rhs_mcv.register,
2343 } },
2344 });
2345 return dst_mcv;
2346}
2347
23482248fn genLdrRegister(self: *Self, dest_reg: Register, addr_reg: Register, abi_size: u32) !void {
23492249 switch (abi_size) {
23502250 1, 3, 4 => {