Skip to content

Commit 1fee9ea

Browse files
Merge pull request #12095 from joachimschmidt557/stage2-arm
stage2 ARM: add integer div+mod with constant power-of-twos
2 parents 4a28c1d + f89ace4 commit 1fee9ea

File tree

1 file changed

+127
-22
lines changed

1 file changed

+127
-22
lines changed

src/arch/arm/CodeGen.zig

Lines changed: 127 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -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

1732-
fn 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-
1738-
fn 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-
1744-
fn 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-
17501734
fn 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,

0 commit comments

Comments
 (0)