authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-10 17:25:49+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-10 17:25:49+02:00
logaef3c149e64746dac01f4d48a2835abd4204e625
tree0319b807b882c40bb35b2fc87e4f765bb877c61a
parentef9e3fb2b6cabb711b3421250b033f1696f961ae

x64: refactor genMulDivBinOp helper


1 files changed, 80 insertions(+), 84 deletions(-)

src/arch/x86_64/CodeGen.zig+80-84
......@@ -3131,75 +3131,82 @@ fn genMulDivBinOp(
31313131 switch (tag) {
31323132 .mul,
31333133 .mulwrap,
3134 => {
3135 try self.register_manager.getReg(.rax, maybe_inst);
3136 try self.register_manager.getReg(.rdx, null);
3137
3138 try self.genIntMulDivOpMir(switch (signedness) {
3139 .signed => .imul,
3140 .unsigned => .mul,
3141 }, ty, signedness, lhs, rhs);
3142
3143 return switch (signedness) {
3144 .signed => MCValue{ .register = .rax },
3145 .unsigned => MCValue{ .register = registerAlias(.rax, @intCast(u32, ty.abiSize(self.target.*))) },
3146 };
3147 },
3148 .mod,
31493134 .rem,
3135 .div_trunc,
3136 .div_exact,
31503137 => {
3138 const track_inst_rax: ?Air.Inst.Index = switch (tag) {
3139 .mul, .mulwrap, .div_exact, .div_trunc => maybe_inst,
3140 else => null,
3141 };
31513142 const track_inst_rdx: ?Air.Inst.Index = switch (tag) {
3152 .mod => if (signedness == .unsigned) maybe_inst else null,
31533143 .rem => maybe_inst,
3154 else => unreachable,
3144 else => null,
31553145 };
3146 try self.register_manager.getReg(.rax, track_inst_rax);
3147 try self.register_manager.getReg(.rdx, track_inst_rdx);
3148
3149 const mir_tag: Mir.Inst.Tag = switch (signedness) {
3150 .signed => switch (tag) {
3151 .mul, .mulwrap => Mir.Inst.Tag.imul,
3152 .div_trunc, .div_exact, .rem => Mir.Inst.Tag.idiv,
3153 else => unreachable,
3154 },
3155 .unsigned => switch (tag) {
3156 .mul, .mulwrap => Mir.Inst.Tag.mul,
3157 .div_trunc, .div_exact, .rem => Mir.Inst.Tag.div,
3158 else => unreachable,
3159 },
3160 };
3161
3162 try self.genIntMulDivOpMir(mir_tag, ty, .signed, lhs, rhs);
3163
3164 switch (signedness) {
3165 .signed => switch (tag) {
3166 .mul, .mulwrap, .div_trunc, .div_exact => return MCValue{ .register = .rax },
3167 .rem => return MCValue{ .register = .rdx },
3168 else => unreachable,
3169 },
3170 .unsigned => switch (tag) {
3171 .mul, .mulwrap, .div_trunc, .div_exact => return MCValue{
3172 .register = registerAlias(.rax, @intCast(u32, ty.abiSize(self.target.*))),
3173 },
3174 .rem => return MCValue{
3175 .register = registerAlias(.rdx, @intCast(u32, ty.abiSize(self.target.*))),
3176 },
3177 else => unreachable,
3178 },
3179 }
3180 },
31563181
3182 .mod => {
31573183 try self.register_manager.getReg(.rax, null);
3158 try self.register_manager.getReg(.rdx, track_inst_rdx);
3184 try self.register_manager.getReg(.rdx, if (signedness == .unsigned) maybe_inst else null);
31593185
31603186 switch (signedness) {
31613187 .signed => {
3162 switch (tag) {
3163 .rem => {
3164 try self.genIntMulDivOpMir(.idiv, ty, .signed, lhs, rhs);
3165 return MCValue{ .register = .rdx };
3166 },
3167 .mod => {
3168 const div_floor = try self.genInlineIntDivFloor(ty, lhs, rhs);
3169 try self.genIntMulComplexOpMir(ty, div_floor, rhs);
3170 const div_floor_lock = self.register_manager.lockReg(div_floor.register);
3171 defer if (div_floor_lock) |lock| self.register_manager.unlockReg(lock);
3172
3173 const result: MCValue = if (maybe_inst) |inst|
3174 try self.copyToRegisterWithInstTracking(inst, ty, lhs)
3175 else
3176 MCValue{ .register = try self.copyToTmpRegister(ty, lhs) };
3177 try self.genBinOpMir(.sub, ty, result, div_floor);
3178
3179 return result;
3180 },
3181 else => unreachable,
3182 }
3188 const div_floor = try self.genInlineIntDivFloor(ty, lhs, rhs);
3189 try self.genIntMulComplexOpMir(ty, div_floor, rhs);
3190 const div_floor_lock = self.register_manager.lockReg(div_floor.register);
3191 defer if (div_floor_lock) |lock| self.register_manager.unlockReg(lock);
3192
3193 const result: MCValue = if (maybe_inst) |inst|
3194 try self.copyToRegisterWithInstTracking(inst, ty, lhs)
3195 else
3196 MCValue{ .register = try self.copyToTmpRegister(ty, lhs) };
3197 try self.genBinOpMir(.sub, ty, result, div_floor);
3198
3199 return result;
31833200 },
31843201 .unsigned => {
31853202 try self.genIntMulDivOpMir(.div, ty, .unsigned, lhs, rhs);
3186 return MCValue{ .register = .rdx };
3203 return MCValue{ .register = registerAlias(.rdx, @intCast(u32, ty.abiSize(self.target.*))) };
31873204 },
31883205 }
31893206 },
3190 .div_trunc,
3191 .div_floor,
3192 .div_exact,
3193 => {
3194 const track_inst_rax: ?Air.Inst.Index = blk: {
3195 if (signedness == .unsigned) break :blk maybe_inst;
3196 switch (tag) {
3197 .div_exact, .div_trunc => break :blk maybe_inst,
3198 else => break :blk null,
3199 }
3200 };
32013207
3202 try self.register_manager.getReg(.rax, track_inst_rax);
3208 .div_floor => {
3209 try self.register_manager.getReg(.rax, if (signedness == .unsigned) maybe_inst else null);
32033210 try self.register_manager.getReg(.rdx, null);
32043211
32053212 const lhs_lock: ?RegisterLock = switch (lhs) {
......@@ -3209,24 +3216,21 @@ fn genMulDivBinOp(
32093216 defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock);
32103217
32113218 const actual_rhs: MCValue = blk: {
3212 if (signedness == .signed) {
3213 switch (tag) {
3214 .div_floor => {
3215 const rhs_lock: ?RegisterLock = switch (rhs) {
3216 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
3217 else => null,
3218 };
3219 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);
3219 switch (signedness) {
3220 .signed => {
3221 const rhs_lock: ?RegisterLock = switch (rhs) {
3222 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
3223 else => null,
3224 };
3225 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);
32203226
3221 if (maybe_inst) |inst| {
3222 break :blk try self.copyToRegisterWithInstTracking(inst, ty, rhs);
3223 }
3224 break :blk MCValue{ .register = try self.copyToTmpRegister(ty, rhs) };
3225 },
3226 else => {},
3227 }
3227 if (maybe_inst) |inst| {
3228 break :blk try self.copyToRegisterWithInstTracking(inst, ty, rhs);
3229 }
3230 break :blk MCValue{ .register = try self.copyToTmpRegister(ty, rhs) };
3231 },
3232 .unsigned => break :blk rhs,
32283233 }
3229 break :blk rhs;
32303234 };
32313235 const rhs_lock: ?RegisterLock = switch (actual_rhs) {
32323236 .register => |reg| self.register_manager.lockReg(reg),
......@@ -3235,27 +3239,19 @@ fn genMulDivBinOp(
32353239 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);
32363240
32373241 const result: MCValue = result: {
3238 if (signedness == .unsigned) {
3239 try self.genIntMulDivOpMir(.div, ty, signedness, lhs, actual_rhs);
3240 break :result MCValue{ .register = .rax };
3241 }
3242
3243 switch (tag) {
3244 .div_exact, .div_trunc => {
3245 try self.genIntMulDivOpMir(switch (signedness) {
3246 .signed => .idiv,
3247 .unsigned => .div,
3248 }, ty, signedness, lhs, actual_rhs);
3249 break :result MCValue{ .register = .rax };
3250 },
3251 .div_floor => {
3252 break :result try self.genInlineIntDivFloor(ty, lhs, actual_rhs);
3242 switch (signedness) {
3243 .signed => break :result try self.genInlineIntDivFloor(ty, lhs, actual_rhs),
3244 .unsigned => {
3245 try self.genIntMulDivOpMir(.div, ty, .unsigned, lhs, actual_rhs);
3246 break :result MCValue{
3247 .register = registerAlias(.rax, @intCast(u32, ty.abiSize(self.target.*))),
3248 };
32533249 },
3254 else => unreachable,
32553250 }
32563251 };
32573252 return result;
32583253 },
3254
32593255 else => unreachable,
32603256 }
32613257}