authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-08-21 17:10:00+02:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-09-09 19:17:17+02:00
logfdb2c80bdc12bfb6be5235de6a5792e0b0619da8
treea7036e93d6d8bbdc5b2916f1b59f7e07a77238b4
parented4be06883427e2d8f97f2dd241d8996994a0c66
signature Commit is signed but in an unrecognized format.

stage2 ARM: extract mul, div, and mod out of binOp


1 files changed, 229 insertions(+), 142 deletions(-)

src/arch/arm/CodeGen.zig+229-142
...@@ -1410,16 +1410,29 @@ fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {...@@ -1410,16 +1410,29 @@ fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
1410 const lhs = try self.resolveInst(bin_op.lhs);1410 const lhs = try self.resolveInst(bin_op.lhs);
1411 const rhs = try self.resolveInst(bin_op.rhs);1411 const rhs = try self.resolveInst(bin_op.rhs);
14121412
1413 switch (tag) {1413 break :result switch (tag) {
1414 .add,1414 .add => try self.addSub(tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst),
1415 .sub,1415 .sub => try self.addSub(tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst),
1416 => break :result try self.addSub(tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst),1416
1417 else => break :result try self.binOp(tag, lhs, rhs, lhs_ty, rhs_ty, BinOpMetadata{1417 .mul => try self.mul(lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst),
1418
1419 .div_float => try self.divFloat(lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst),
1420
1421 .div_trunc => try self.div(tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst),
1422 .div_floor => try self.div(tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst),
1423
1424 .div_exact => try self.divExact(lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst),
1425
1426 .rem => try self.rem(lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst),
1427
1428 .mod => try self.modulo(lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst),
1429
1430 else => try self.binOp(tag, lhs, rhs, lhs_ty, rhs_ty, BinOpMetadata{
1418 .lhs = bin_op.lhs,1431 .lhs = bin_op.lhs,
1419 .rhs = bin_op.rhs,1432 .rhs = bin_op.rhs,
1420 .inst = inst,1433 .inst = inst,
1421 }),1434 }),
1422 }1435 };
1423 };1436 };
1424 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1437 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1425}1438}
...@@ -3228,141 +3241,6 @@ fn binOp(...@@ -3228,141 +3241,6 @@ fn binOp(
3228 metadata: ?BinOpMetadata,3241 metadata: ?BinOpMetadata,
3229) InnerError!MCValue {3242) InnerError!MCValue {
3230 switch (tag) {3243 switch (tag) {
3231 .mul => {
3232 switch (lhs_ty.zigTypeTag()) {
3233 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
3234 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3235 .Int => {
3236 const mod = self.bin_file.options.module.?;
3237 assert(lhs_ty.eql(rhs_ty, mod));
3238 const int_info = lhs_ty.intInfo(self.target.*);
3239 if (int_info.bits <= 32) {
3240 // TODO add optimisations for multiplication
3241 // with immediates, for example a * 2 can be
3242 // lowered to a << 1
3243 return try self.binOpRegister(.mul, lhs, rhs, lhs_ty, rhs_ty, metadata);
3244 } else {
3245 return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
3246 }
3247 },
3248 else => unreachable,
3249 }
3250 },
3251 .div_float => {
3252 switch (lhs_ty.zigTypeTag()) {
3253 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
3254 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3255 else => unreachable,
3256 }
3257 },
3258 .div_trunc, .div_floor => {
3259 switch (lhs_ty.zigTypeTag()) {
3260 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
3261 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3262 .Int => {
3263 const mod = self.bin_file.options.module.?;
3264 assert(lhs_ty.eql(rhs_ty, mod));
3265 const int_info = lhs_ty.intInfo(self.target.*);
3266 if (int_info.bits <= 32) {
3267 switch (int_info.signedness) {
3268 .signed => {
3269 return self.fail("TODO ARM signed integer division", .{});
3270 },
3271 .unsigned => {
3272 switch (rhs) {
3273 .immediate => |imm| {
3274 if (std.math.isPowerOfTwo(imm)) {
3275 const shift = MCValue{ .immediate = std.math.log2_int(u32, imm) };
3276 return try self.binOp(.shr, lhs, shift, lhs_ty, rhs_ty, metadata);
3277 } else {
3278 return self.fail("TODO ARM integer division by constants", .{});
3279 }
3280 },
3281 else => return self.fail("TODO ARM integer division", .{}),
3282 }
3283 },
3284 }
3285 } else {
3286 return self.fail("TODO ARM integer division for integers > u32/i32", .{});
3287 }
3288 },
3289 else => unreachable,
3290 }
3291 },
3292 .div_exact => {
3293 switch (lhs_ty.zigTypeTag()) {
3294 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
3295 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3296 .Int => return self.fail("TODO ARM div_exact", .{}),
3297 else => unreachable,
3298 }
3299 },
3300 .rem => {
3301 switch (lhs_ty.zigTypeTag()) {
3302 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
3303 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3304 .Int => {
3305 const mod = self.bin_file.options.module.?;
3306 assert(lhs_ty.eql(rhs_ty, mod));
3307 const int_info = lhs_ty.intInfo(self.target.*);
3308 if (int_info.bits <= 32) {
3309 switch (int_info.signedness) {
3310 .signed => {
3311 return self.fail("TODO ARM signed integer mod", .{});
3312 },
3313 .unsigned => {
3314 switch (rhs) {
3315 .immediate => |imm| {
3316 if (std.math.isPowerOfTwo(imm)) {
3317 const log2 = std.math.log2_int(u32, imm);
3318
3319 var lhs_reg: Register = undefined;
3320 var dest_reg: Register = undefined;
3321
3322 const lhs_bind = if (metadata) |md|
3323 ReadArg.Bind{ .inst = md.lhs }
3324 else
3325 ReadArg.Bind{ .mcv = lhs };
3326 const read_args = [_]ReadArg{
3327 .{ .ty = lhs_ty, .bind = lhs_bind, .class = gp, .reg = &lhs_reg },
3328 };
3329 const write_args = [_]WriteArg{
3330 .{ .ty = lhs_ty, .bind = .none, .class = gp, .reg = &dest_reg },
3331 };
3332 try self.allocRegs(
3333 &read_args,
3334 &write_args,
3335 if (metadata) |md| .{
3336 .corresponding_inst = md.inst,
3337 .operand_mapping = &.{0},
3338 } else null,
3339 );
3340
3341 try self.truncRegister(lhs_reg, dest_reg, int_info.signedness, log2);
3342 return MCValue{ .register = dest_reg };
3343 } else {
3344 return self.fail("TODO ARM integer mod by constants", .{});
3345 }
3346 },
3347 else => return self.fail("TODO ARM integer mod", .{}),
3348 }
3349 },
3350 }
3351 } else {
3352 return self.fail("TODO ARM integer division for integers > u32/i32", .{});
3353 }
3354 },
3355 else => unreachable,
3356 }
3357 },
3358 .mod => {
3359 switch (lhs_ty.zigTypeTag()) {
3360 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
3361 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3362 .Int => return self.fail("TODO ARM mod", .{}),
3363 else => unreachable,
3364 }
3365 },
3366 .addwrap,3244 .addwrap,
3367 .subwrap,3245 .subwrap,
3368 .mulwrap,3246 .mulwrap,
...@@ -3557,7 +3435,13 @@ fn binOp(...@@ -3557,7 +3435,13 @@ fn binOp(
3557 } else {3435 } else {
3558 // convert the offset into a byte offset by3436 // convert the offset into a byte offset by
3559 // multiplying it with elem_size3437 // multiplying it with elem_size
3560 const offset = try self.binOp(.mul, rhs, .{ .immediate = elem_size }, Type.usize, Type.usize, null);3438 const rhs_bind = if (metadata) |md|
3439 ReadArg.Bind{ .inst = md.rhs }
3440 else
3441 ReadArg.Bind{ .mcv = rhs };
3442 const imm_bind = ReadArg.Bind{ .mcv = .{ .immediate = elem_size } };
3443
3444 const offset = try self.mul(rhs_bind, imm_bind, Type.usize, Type.usize, null);
3561 const addr = try self.binOp(tag, lhs, offset, Type.initTag(.manyptr_u8), Type.usize, null);3445 const addr = try self.binOp(tag, lhs, offset, Type.initTag(.manyptr_u8), Type.usize, null);
3562 return addr;3446 return addr;
3563 }3447 }
...@@ -3626,6 +3510,209 @@ fn addSub(...@@ -3626,6 +3510,209 @@ fn addSub(
3626 }3510 }
3627}3511}
36283512
3513fn mul(
3514 self: *Self,
3515 lhs_bind: ReadArg.Bind,
3516 rhs_bind: ReadArg.Bind,
3517 lhs_ty: Type,
3518 rhs_ty: Type,
3519 maybe_inst: ?Air.Inst.Index,
3520) InnerError!MCValue {
3521 switch (lhs_ty.zigTypeTag()) {
3522 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
3523 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3524 .Int => {
3525 const mod = self.bin_file.options.module.?;
3526 assert(lhs_ty.eql(rhs_ty, mod));
3527 const int_info = lhs_ty.intInfo(self.target.*);
3528 if (int_info.bits <= 32) {
3529 // TODO add optimisations for multiplication
3530 // with immediates, for example a * 2 can be
3531 // lowered to a << 1
3532 return try self.binOpRegisterNew(.mul, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);
3533 } else {
3534 return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
3535 }
3536 },
3537 else => unreachable,
3538 }
3539}
3540
3541fn divFloat(
3542 self: *Self,
3543 lhs_bind: ReadArg.Bind,
3544 rhs_bind: ReadArg.Bind,
3545 lhs_ty: Type,
3546 rhs_ty: Type,
3547 maybe_inst: ?Air.Inst.Index,
3548) InnerError!MCValue {
3549 _ = lhs_bind;
3550 _ = rhs_bind;
3551 _ = lhs_ty;
3552 _ = rhs_ty;
3553 _ = maybe_inst;
3554
3555 switch (lhs_ty.zigTypeTag()) {
3556 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
3557 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3558 else => unreachable,
3559 }
3560}
3561
3562fn div(
3563 self: *Self,
3564 tag: Air.Inst.Tag,
3565 lhs_bind: ReadArg.Bind,
3566 rhs_bind: ReadArg.Bind,
3567 lhs_ty: Type,
3568 rhs_ty: Type,
3569 maybe_inst: ?Air.Inst.Index,
3570) InnerError!MCValue {
3571 _ = tag;
3572
3573 switch (lhs_ty.zigTypeTag()) {
3574 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
3575 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3576 .Int => {
3577 const mod = self.bin_file.options.module.?;
3578 assert(lhs_ty.eql(rhs_ty, mod));
3579 const int_info = lhs_ty.intInfo(self.target.*);
3580 if (int_info.bits <= 32) {
3581 switch (int_info.signedness) {
3582 .signed => {
3583 return self.fail("TODO ARM signed integer division", .{});
3584 },
3585 .unsigned => {
3586 const rhs_immediate = try rhs_bind.resolveToImmediate(self);
3587
3588 if (rhs_immediate) |imm| {
3589 if (std.math.isPowerOfTwo(imm)) {
3590 const shift = std.math.log2_int(u32, imm);
3591 return try self.binOpImmediateNew(.lsr, lhs_bind, shift, lhs_ty, false, maybe_inst);
3592 } else {
3593 return self.fail("TODO ARM integer division by constants", .{});
3594 }
3595 } else {
3596 return self.fail("TODO ARM integer division", .{});
3597 }
3598 },
3599 }
3600 } else {
3601 return self.fail("TODO ARM integer division for integers > u32/i32", .{});
3602 }
3603 },
3604 else => unreachable,
3605 }
3606}
3607
3608fn divExact(
3609 self: *Self,
3610 lhs_bind: ReadArg.Bind,
3611 rhs_bind: ReadArg.Bind,
3612 lhs_ty: Type,
3613 rhs_ty: Type,
3614 maybe_inst: ?Air.Inst.Index,
3615) InnerError!MCValue {
3616 _ = lhs_bind;
3617 _ = rhs_bind;
3618 _ = lhs_ty;
3619 _ = rhs_ty;
3620 _ = maybe_inst;
3621
3622 switch (lhs_ty.zigTypeTag()) {
3623 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
3624 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3625 .Int => return self.fail("TODO ARM div_exact", .{}),
3626 else => unreachable,
3627 }
3628}
3629
3630fn rem(
3631 self: *Self,
3632 lhs_bind: ReadArg.Bind,
3633 rhs_bind: ReadArg.Bind,
3634 lhs_ty: Type,
3635 rhs_ty: Type,
3636 maybe_inst: ?Air.Inst.Index,
3637) InnerError!MCValue {
3638 switch (lhs_ty.zigTypeTag()) {
3639 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
3640 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3641 .Int => {
3642 const mod = self.bin_file.options.module.?;
3643 assert(lhs_ty.eql(rhs_ty, mod));
3644 const int_info = lhs_ty.intInfo(self.target.*);
3645 if (int_info.bits <= 32) {
3646 switch (int_info.signedness) {
3647 .signed => {
3648 return self.fail("TODO ARM signed integer mod", .{});
3649 },
3650 .unsigned => {
3651 const rhs_immediate = try rhs_bind.resolveToImmediate(self);
3652
3653 if (rhs_immediate) |imm| {
3654 if (std.math.isPowerOfTwo(imm)) {
3655 const log2 = std.math.log2_int(u32, imm);
3656
3657 var lhs_reg: Register = undefined;
3658 var dest_reg: Register = undefined;
3659
3660 const read_args = [_]ReadArg{
3661 .{ .ty = lhs_ty, .bind = lhs_bind, .class = gp, .reg = &lhs_reg },
3662 };
3663 const write_args = [_]WriteArg{
3664 .{ .ty = lhs_ty, .bind = .none, .class = gp, .reg = &dest_reg },
3665 };
3666 try self.allocRegs(
3667 &read_args,
3668 &write_args,
3669 if (maybe_inst) |inst| .{
3670 .corresponding_inst = inst,
3671 .operand_mapping = &.{0},
3672 } else null,
3673 );
3674
3675 try self.truncRegister(lhs_reg, dest_reg, int_info.signedness, log2);
3676
3677 return MCValue{ .register = dest_reg };
3678 } else {
3679 return self.fail("TODO ARM integer mod by constants", .{});
3680 }
3681 } else {
3682 return self.fail("TODO ARM integer mod", .{});
3683 }
3684 },
3685 }
3686 } else {
3687 return self.fail("TODO ARM integer division for integers > u32/i32", .{});
3688 }
3689 },
3690 else => unreachable,
3691 }
3692}
3693
3694fn modulo(
3695 self: *Self,
3696 lhs_bind: ReadArg.Bind,
3697 rhs_bind: ReadArg.Bind,
3698 lhs_ty: Type,
3699 rhs_ty: Type,
3700 maybe_inst: ?Air.Inst.Index,
3701) InnerError!MCValue {
3702 _ = lhs_bind;
3703 _ = rhs_bind;
3704 _ = lhs_ty;
3705 _ = rhs_ty;
3706 _ = maybe_inst;
3707
3708 switch (lhs_ty.zigTypeTag()) {
3709 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
3710 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3711 .Int => return self.fail("TODO ARM mod", .{}),
3712 else => unreachable,
3713 }
3714}
3715
3629fn genLdrRegister(self: *Self, dest_reg: Register, addr_reg: Register, ty: Type) !void {3716fn genLdrRegister(self: *Self, dest_reg: Register, addr_reg: Register, ty: Type) !void {
3630 const abi_size = ty.abiSize(self.target.*);3717 const abi_size = ty.abiSize(self.target.*);
36313718