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(...@@ -3131,75 +3131,82 @@ fn genMulDivBinOp(
3131 switch (tag) {3131 switch (tag) {
3132 .mul,3132 .mul,
3133 .mulwrap,3133 .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,
3149 .rem,3134 .rem,
3135 .div_trunc,
3136 .div_exact,
3150 => {3137 => {
3138 const track_inst_rax: ?Air.Inst.Index = switch (tag) {
3139 .mul, .mulwrap, .div_exact, .div_trunc => maybe_inst,
3140 else => null,
3141 };
3151 const track_inst_rdx: ?Air.Inst.Index = switch (tag) {3142 const track_inst_rdx: ?Air.Inst.Index = switch (tag) {
3152 .mod => if (signedness == .unsigned) maybe_inst else null,
3153 .rem => maybe_inst,3143 .rem => maybe_inst,
3154 else => unreachable,3144 else => null,
3155 };3145 };
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 => {
3157 try self.register_manager.getReg(.rax, null);3183 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
3160 switch (signedness) {3186 switch (signedness) {
3161 .signed => {3187 .signed => {
3162 switch (tag) {3188 const div_floor = try self.genInlineIntDivFloor(ty, lhs, rhs);
3163 .rem => {3189 try self.genIntMulComplexOpMir(ty, div_floor, rhs);
3164 try self.genIntMulDivOpMir(.idiv, ty, .signed, lhs, rhs);3190 const div_floor_lock = self.register_manager.lockReg(div_floor.register);
3165 return MCValue{ .register = .rdx };3191 defer if (div_floor_lock) |lock| self.register_manager.unlockReg(lock);
3166 },3192
3167 .mod => {3193 const result: MCValue = if (maybe_inst) |inst|
3168 const div_floor = try self.genInlineIntDivFloor(ty, lhs, rhs);3194 try self.copyToRegisterWithInstTracking(inst, ty, lhs)
3169 try self.genIntMulComplexOpMir(ty, div_floor, rhs);3195 else
3170 const div_floor_lock = self.register_manager.lockReg(div_floor.register);3196 MCValue{ .register = try self.copyToTmpRegister(ty, lhs) };
3171 defer if (div_floor_lock) |lock| self.register_manager.unlockReg(lock);3197 try self.genBinOpMir(.sub, ty, result, div_floor);
31723198
3173 const result: MCValue = if (maybe_inst) |inst|3199 return result;
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 }
3183 },3200 },
3184 .unsigned => {3201 .unsigned => {
3185 try self.genIntMulDivOpMir(.div, ty, .unsigned, lhs, rhs);3202 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.*))) };
3187 },3204 },
3188 }3205 }
3189 },3206 },
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);
3203 try self.register_manager.getReg(.rdx, null);3210 try self.register_manager.getReg(.rdx, null);
32043211
3205 const lhs_lock: ?RegisterLock = switch (lhs) {3212 const lhs_lock: ?RegisterLock = switch (lhs) {
...@@ -3209,24 +3216,21 @@ fn genMulDivBinOp(...@@ -3209,24 +3216,21 @@ fn genMulDivBinOp(
3209 defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock);3216 defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock);
32103217
3211 const actual_rhs: MCValue = blk: {3218 const actual_rhs: MCValue = blk: {
3212 if (signedness == .signed) {3219 switch (signedness) {
3213 switch (tag) {3220 .signed => {
3214 .div_floor => {3221 const rhs_lock: ?RegisterLock = switch (rhs) {
3215 const rhs_lock: ?RegisterLock = switch (rhs) {3222 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
3216 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),3223 else => null,
3217 else => null,3224 };
3218 };3225 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);
3219 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);
32203226
3221 if (maybe_inst) |inst| {3227 if (maybe_inst) |inst| {
3222 break :blk try self.copyToRegisterWithInstTracking(inst, ty, rhs);3228 break :blk try self.copyToRegisterWithInstTracking(inst, ty, rhs);
3223 }3229 }
3224 break :blk MCValue{ .register = try self.copyToTmpRegister(ty, rhs) };3230 break :blk MCValue{ .register = try self.copyToTmpRegister(ty, rhs) };
3225 },3231 },
3226 else => {},3232 .unsigned => break :blk rhs,
3227 }
3228 }3233 }
3229 break :blk rhs;
3230 };3234 };
3231 const rhs_lock: ?RegisterLock = switch (actual_rhs) {3235 const rhs_lock: ?RegisterLock = switch (actual_rhs) {
3232 .register => |reg| self.register_manager.lockReg(reg),3236 .register => |reg| self.register_manager.lockReg(reg),
...@@ -3235,27 +3239,19 @@ fn genMulDivBinOp(...@@ -3235,27 +3239,19 @@ fn genMulDivBinOp(
3235 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);3239 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);
32363240
3237 const result: MCValue = result: {3241 const result: MCValue = result: {
3238 if (signedness == .unsigned) {3242 switch (signedness) {
3239 try self.genIntMulDivOpMir(.div, ty, signedness, lhs, actual_rhs);3243 .signed => break :result try self.genInlineIntDivFloor(ty, lhs, actual_rhs),
3240 break :result MCValue{ .register = .rax };3244 .unsigned => {
3241 }3245 try self.genIntMulDivOpMir(.div, ty, .unsigned, lhs, actual_rhs);
32423246 break :result MCValue{
3243 switch (tag) {3247 .register = registerAlias(.rax, @intCast(u32, ty.abiSize(self.target.*))),
3244 .div_exact, .div_trunc => {3248 };
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);
3253 },3249 },
3254 else => unreachable,
3255 }3250 }
3256 };3251 };
3257 return result;3252 return result;
3258 },3253 },
3254
3259 else => unreachable,3255 else => unreachable,
3260 }3256 }
3261}3257}