| ... | ... | @@ -3131,75 +3131,82 @@ fn genMulDivBinOp( |
| 3131 | 3131 | switch (tag) { |
| 3132 | 3132 | .mul, |
| 3133 | 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 | 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 | 3142 | const track_inst_rdx: ?Air.Inst.Index = switch (tag) { |
| 3152 | | .mod => if (signedness == .unsigned) maybe_inst else null, |
| 3153 | 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 | }, |
| 3156 | 3181 | |
| 3182 | .mod => { |
| 3157 | 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); |
| 3159 | 3185 | |
| 3160 | 3186 | switch (signedness) { |
| 3161 | 3187 | .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; |
| 3183 | 3200 | }, |
| 3184 | 3201 | .unsigned => { |
| 3185 | 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 | | }; |
| 3201 | 3207 | |
| 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 | 3210 | try self.register_manager.getReg(.rdx, null); |
| 3204 | 3211 | |
| 3205 | 3212 | const lhs_lock: ?RegisterLock = switch (lhs) { |
| ... | ... | @@ -3209,24 +3216,21 @@ fn genMulDivBinOp( |
| 3209 | 3216 | defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock); |
| 3210 | 3217 | |
| 3211 | 3218 | 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); |
| 3220 | 3226 | |
| 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, |
| 3228 | 3233 | } |
| 3229 | | break :blk rhs; |
| 3230 | 3234 | }; |
| 3231 | 3235 | const rhs_lock: ?RegisterLock = switch (actual_rhs) { |
| 3232 | 3236 | .register => |reg| self.register_manager.lockReg(reg), |
| ... | ... | @@ -3235,27 +3239,19 @@ fn genMulDivBinOp( |
| 3235 | 3239 | defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock); |
| 3236 | 3240 | |
| 3237 | 3241 | 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 | }; |
| 3253 | 3249 | }, |
| 3254 | | else => unreachable, |
| 3255 | 3250 | } |
| 3256 | 3251 | }; |
| 3257 | 3252 | return result; |
| 3258 | 3253 | }, |
| 3254 | |
| 3259 | 3255 | else => unreachable, |
| 3260 | 3256 | } |
| 3261 | 3257 | } |