authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-07-13 10:54:27+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-07-13 10:54:27+02:00
log1fee9eac8bb5d2e3e78c098b9cebe2cda332e7cf
tree57d1e137b86ec57887527ee02dff812bf68616e0
parent4a28c1d5c3627510cef97b88ee6b3988f65ac0dd
parentf89ace4d04f8567ae92dce74ffb0e0d416077492
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #12095 from joachimschmidt557/stage2-arm

stage2 ARM: add integer div+mod with constant power-of-twos

1 files changed, 127 insertions(+), 22 deletions(-)

src/arch/arm/CodeGen.zig+127-22
......@@ -567,6 +567,12 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
567567 .xor => try self.airBinOp(inst, .xor),
568568 .shr => try self.airBinOp(inst, .shr),
569569 .shr_exact => try self.airBinOp(inst, .shr_exact),
570 .div_float => try self.airBinOp(inst, .div_float),
571 .div_trunc => try self.airBinOp(inst, .div_trunc),
572 .div_floor => try self.airBinOp(inst, .div_floor),
573 .div_exact => try self.airBinOp(inst, .div_exact),
574 .rem => try self.airBinOp(inst, .rem),
575 .mod => try self.airBinOp(inst, .mod),
570576
571577 .ptr_add => try self.airPtrArithmetic(inst, .ptr_add),
572578 .ptr_sub => try self.airPtrArithmetic(inst, .ptr_sub),
......@@ -577,8 +583,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
577583 .add_sat => try self.airAddSat(inst),
578584 .sub_sat => try self.airSubSat(inst),
579585 .mul_sat => try self.airMulSat(inst),
580 .rem => try self.airRem(inst),
581 .mod => try self.airMod(inst),
582586 .shl_sat => try self.airShlSat(inst),
583587 .slice => try self.airSlice(inst),
584588
......@@ -604,8 +608,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
604608 .mul_with_overflow => try self.airMulWithOverflow(inst),
605609 .shl_with_overflow => try self.airShlWithOverflow(inst),
606610
607 .div_float, .div_trunc, .div_floor, .div_exact => try self.airDiv(inst),
608
609611 .cmp_lt => try self.airCmp(inst, .lt),
610612 .cmp_lte => try self.airCmp(inst, .lte),
611613 .cmp_eq => try self.airCmp(inst, .eq),
......@@ -1729,24 +1731,6 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
17291731 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
17301732}
17311733
1732fn airDiv(self: *Self, inst: Air.Inst.Index) !void {
1733 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1734 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement div for {}", .{self.target.cpu.arch});
1735 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1736}
1737
1738fn airRem(self: *Self, inst: Air.Inst.Index) !void {
1739 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1740 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement rem for {}", .{self.target.cpu.arch});
1741 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1742}
1743
1744fn airMod(self: *Self, inst: Air.Inst.Index) !void {
1745 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1746 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement mod for {}", .{self.target.cpu.arch});
1747 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1748}
1749
17501734fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {
17511735 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
17521736 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement shl_sat for {}", .{self.target.cpu.arch});
......@@ -2878,6 +2862,127 @@ fn binOp(
28782862 else => unreachable,
28792863 }
28802864 },
2865 .div_float => {
2866 switch (lhs_ty.zigTypeTag()) {
2867 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
2868 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
2869 else => unreachable,
2870 }
2871 },
2872 .div_trunc, .div_floor => {
2873 switch (lhs_ty.zigTypeTag()) {
2874 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
2875 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
2876 .Int => {
2877 const mod = self.bin_file.options.module.?;
2878 assert(lhs_ty.eql(rhs_ty, mod));
2879 const int_info = lhs_ty.intInfo(self.target.*);
2880 if (int_info.bits <= 32) {
2881 switch (int_info.signedness) {
2882 .signed => {
2883 return self.fail("TODO ARM signed integer division", .{});
2884 },
2885 .unsigned => {
2886 switch (rhs) {
2887 .immediate => |imm| {
2888 if (std.math.isPowerOfTwo(imm)) {
2889 const shift = MCValue{ .immediate = std.math.log2_int(u32, imm) };
2890 return try self.binOp(.shr, lhs, shift, lhs_ty, rhs_ty, metadata);
2891 } else {
2892 return self.fail("TODO ARM integer division by constants", .{});
2893 }
2894 },
2895 else => return self.fail("TODO ARM integer division", .{}),
2896 }
2897 },
2898 }
2899 } else {
2900 return self.fail("TODO ARM integer division for integers > u32/i32", .{});
2901 }
2902 },
2903 else => unreachable,
2904 }
2905 },
2906 .div_exact => {
2907 switch (lhs_ty.zigTypeTag()) {
2908 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
2909 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
2910 .Int => return self.fail("TODO ARM div_exact", .{}),
2911 else => unreachable,
2912 }
2913 },
2914 .rem => {
2915 switch (lhs_ty.zigTypeTag()) {
2916 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
2917 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
2918 .Int => {
2919 const mod = self.bin_file.options.module.?;
2920 assert(lhs_ty.eql(rhs_ty, mod));
2921 const int_info = lhs_ty.intInfo(self.target.*);
2922 if (int_info.bits <= 32) {
2923 switch (int_info.signedness) {
2924 .signed => {
2925 return self.fail("TODO ARM signed integer mod", .{});
2926 },
2927 .unsigned => {
2928 switch (rhs) {
2929 .immediate => |imm| {
2930 if (std.math.isPowerOfTwo(imm)) {
2931 const log2 = std.math.log2_int(u32, imm);
2932
2933 const lhs_is_register = lhs == .register;
2934
2935 const lhs_lock: ?RegisterLock = if (lhs_is_register)
2936 self.register_manager.lockReg(lhs.register)
2937 else
2938 null;
2939 defer if (lhs_lock) |reg| self.register_manager.unlockReg(reg);
2940
2941 const lhs_reg = if (lhs_is_register) lhs.register else blk: {
2942 const track_inst: ?Air.Inst.Index = if (metadata) |md| inst: {
2943 break :inst Air.refToIndex(md.lhs).?;
2944 } else null;
2945
2946 break :blk try self.prepareNewRegForMoving(track_inst, gp, lhs);
2947 };
2948 const new_lhs_lock = self.register_manager.lockReg(lhs_reg);
2949 defer if (new_lhs_lock) |reg| self.register_manager.unlockReg(reg);
2950
2951 const dest_reg = if (metadata) |md| blk: {
2952 if (lhs_is_register and self.reuseOperand(md.inst, md.lhs, 0, lhs)) {
2953 break :blk lhs_reg;
2954 } else {
2955 break :blk try self.register_manager.allocReg(md.inst, gp);
2956 }
2957 } else try self.register_manager.allocReg(null, gp);
2958
2959 if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs);
2960
2961 try self.truncRegister(lhs_reg, dest_reg, int_info.signedness, log2);
2962 return MCValue{ .register = dest_reg };
2963 } else {
2964 return self.fail("TODO ARM integer mod by constants", .{});
2965 }
2966 },
2967 else => return self.fail("TODO ARM integer mod", .{}),
2968 }
2969 },
2970 }
2971 } else {
2972 return self.fail("TODO ARM integer division for integers > u32/i32", .{});
2973 }
2974 },
2975 else => unreachable,
2976 }
2977 },
2978 .mod => {
2979 switch (lhs_ty.zigTypeTag()) {
2980 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
2981 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
2982 .Int => return self.fail("TODO ARM mod", .{}),
2983 else => unreachable,
2984 }
2985 },
28812986 .addwrap,
28822987 .subwrap,
28832988 .mulwrap,