Commit e2e69803dc

joachimschmidt557 <joachim.schmidt557@outlook.com>
2022-03-27 15:06:37
stage2 ARM: change binOp lowering mechanism to use Mir tags
The Air -> Mir correspondence is not 1:1, so this better represents what Mir insruction we actually want to generate.
1 parent 8b5d5f4
Changed files (1)
src
arch
src/arch/arm/CodeGen.zig
@@ -1196,7 +1196,7 @@ fn minMax(
                 // register.
                 assert(lhs_reg != rhs_reg); // see note above
 
-                _ = try self.binOpRegister(.cmp_eq, null, .{ .register = lhs_reg }, .{ .register = rhs_reg }, lhs_ty, rhs_ty);
+                _ = try self.binOpRegister(.cmp, null, .{ .register = lhs_reg }, .{ .register = rhs_reg }, lhs_ty, rhs_ty);
 
                 const cond_choose_lhs: Condition = switch (tag) {
                     .max => switch (int_info.signedness) {
@@ -2067,7 +2067,7 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
 /// Asserts that generating an instruction of that form is possible.
 fn binOpRegister(
     self: *Self,
-    tag: Air.Inst.Tag,
+    mir_tag: Mir.Inst.Tag,
     maybe_inst: ?Air.Inst.Index,
     lhs: MCValue,
     rhs: MCValue,
@@ -2112,8 +2112,8 @@ fn binOpRegister(
     };
     defer self.register_manager.unfreezeRegs(&.{rhs_reg});
 
-    const dest_reg = switch (tag) {
-        .cmp_eq => .r0, // cmp has no destination regardless
+    const dest_reg = switch (mir_tag) {
+        .cmp => .r0, // cmp has no destination regardless
         else => if (maybe_inst) |inst| blk: {
             const bin_op = self.air.instructions.items(.data)[inst].bin_op;
 
@@ -2130,41 +2130,21 @@ fn binOpRegister(
     if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs);
     if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs);
 
-    const mir_tag: Mir.Inst.Tag = switch (tag) {
-        .add => .add,
-        .sub => .sub,
-        .cmp_eq => .cmp,
-        .mul => .mul,
-        .bit_and,
-        .bool_and,
-        => .@"and",
-        .bit_or,
-        .bool_or,
-        => .orr,
-        .shl_exact => .lsl,
-        .shr_exact => switch (lhs_ty.intInfo(self.target.*).signedness) {
-            .signed => Mir.Inst.Tag.asr,
-            .unsigned => Mir.Inst.Tag.lsr,
-        },
-        .xor => .eor,
-        else => unreachable,
-    };
-    const mir_data: Mir.Inst.Data = switch (tag) {
+    const mir_data: Mir.Inst.Data = switch (mir_tag) {
         .add,
         .sub,
-        .cmp_eq,
-        .bit_and,
-        .bool_and,
-        .bit_or,
-        .bool_or,
-        .xor,
+        .cmp,
+        .@"and",
+        .orr,
+        .eor,
         => .{ .rr_op = .{
             .rd = dest_reg,
             .rn = lhs_reg,
             .op = Instruction.Operand.reg(rhs_reg, Instruction.Operand.Shift.none),
         } },
-        .shl_exact,
-        .shr_exact,
+        .lsl,
+        .asr,
+        .lsr,
         => .{ .rr_shift = .{
             .rd = dest_reg,
             .rm = lhs_reg,
@@ -2200,7 +2180,7 @@ fn binOpRegister(
 /// Asserts that generating an instruction of that form is possible.
 fn binOpImmediate(
     self: *Self,
-    tag: Air.Inst.Tag,
+    mir_tag: Mir.Inst.Tag,
     maybe_inst: ?Air.Inst.Index,
     lhs: MCValue,
     rhs: MCValue,
@@ -2230,8 +2210,8 @@ fn binOpImmediate(
     };
     defer self.register_manager.unfreezeRegs(&.{lhs_reg});
 
-    const dest_reg = switch (tag) {
-        .cmp_eq => .r0, // cmp has no destination reg
+    const dest_reg = switch (mir_tag) {
+        .cmp => .r0, // cmp has no destination reg
         else => if (maybe_inst) |inst| blk: {
             const bin_op = self.air.instructions.items(.data)[inst].bin_op;
 
@@ -2250,40 +2230,21 @@ fn binOpImmediate(
 
     if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs);
 
-    const mir_tag: Mir.Inst.Tag = switch (tag) {
-        .add => .add,
-        .sub => .sub,
-        .cmp_eq => .cmp,
-        .bit_and,
-        .bool_and,
-        => .@"and",
-        .bit_or,
-        .bool_or,
-        => .orr,
-        .shl_exact => .lsl,
-        .shr_exact => switch (lhs_ty.intInfo(self.target.*).signedness) {
-            .signed => Mir.Inst.Tag.asr,
-            .unsigned => Mir.Inst.Tag.lsr,
-        },
-        .xor => .eor,
-        else => unreachable,
-    };
-    const mir_data: Mir.Inst.Data = switch (tag) {
+    const mir_data: Mir.Inst.Data = switch (mir_tag) {
         .add,
         .sub,
-        .cmp_eq,
-        .bit_and,
-        .bool_and,
-        .bit_or,
-        .bool_or,
-        .xor,
+        .cmp,
+        .@"and",
+        .orr,
+        .eor,
         => .{ .rr_op = .{
             .rd = dest_reg,
             .rn = lhs_reg,
             .op = Instruction.Operand.fromU32(rhs.immediate).?,
         } },
-        .shl_exact,
-        .shr_exact,
+        .lsl,
+        .asr,
+        .lsr,
         => .{ .rr_shift = .{
             .rd = dest_reg,
             .rm = lhs_reg,
@@ -2352,13 +2313,20 @@ fn binOp(
                             else => unreachable,
                         };
 
+                        const mir_tag: Mir.Inst.Tag = switch (tag) {
+                            .add => .add,
+                            .sub => .sub,
+                            .cmp_eq => .cmp,
+                            else => unreachable,
+                        };
+
                         if (rhs_immediate_ok) {
-                            return try self.binOpImmediate(tag, maybe_inst, lhs, rhs, lhs_ty, false);
+                            return try self.binOpImmediate(mir_tag, maybe_inst, lhs, rhs, lhs_ty, false);
                         } else if (lhs_immediate_ok) {
                             // swap lhs and rhs
-                            return try self.binOpImmediate(tag, maybe_inst, rhs, lhs, rhs_ty, true);
+                            return try self.binOpImmediate(mir_tag, maybe_inst, rhs, lhs, rhs_ty, true);
                         } else {
-                            return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
+                            return try self.binOpRegister(mir_tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
                         }
                     } else {
                         return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
@@ -2378,7 +2346,7 @@ fn binOp(
                         // TODO add optimisations for multiplication
                         // with immediates, for example a * 2 can be
                         // lowered to a << 1
-                        return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
+                        return try self.binOpRegister(.mul, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
                     } else {
                         return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
                     }
@@ -2432,13 +2400,20 @@ fn binOp(
                         const lhs_immediate_ok = lhs == .immediate and Instruction.Operand.fromU32(lhs.immediate) != null;
                         const rhs_immediate_ok = rhs == .immediate and Instruction.Operand.fromU32(rhs.immediate) != null;
 
+                        const mir_tag: Mir.Inst.Tag = switch (tag) {
+                            .bit_and => .@"and",
+                            .bit_or => .orr,
+                            .xor => .eor,
+                            else => unreachable,
+                        };
+
                         if (rhs_immediate_ok) {
-                            return try self.binOpImmediate(tag, maybe_inst, lhs, rhs, lhs_ty, false);
+                            return try self.binOpImmediate(mir_tag, maybe_inst, lhs, rhs, lhs_ty, false);
                         } else if (lhs_immediate_ok) {
                             // swap lhs and rhs
-                            return try self.binOpImmediate(tag, maybe_inst, rhs, lhs, rhs_ty, true);
+                            return try self.binOpImmediate(mir_tag, maybe_inst, rhs, lhs, rhs_ty, true);
                         } else {
-                            return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
+                            return try self.binOpRegister(mir_tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
                         }
                     } else {
                         return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
@@ -2457,10 +2432,19 @@ fn binOp(
                     if (int_info.bits <= 32) {
                         const rhs_immediate_ok = rhs == .immediate;
 
+                        const mir_tag: Mir.Inst.Tag = switch (tag) {
+                            .shl_exact => .lsl,
+                            .shr_exact => switch (lhs_ty.intInfo(self.target.*).signedness) {
+                                .signed => Mir.Inst.Tag.asr,
+                                .unsigned => Mir.Inst.Tag.lsr,
+                            },
+                            else => unreachable,
+                        };
+
                         if (rhs_immediate_ok) {
-                            return try self.binOpImmediate(tag, maybe_inst, lhs, rhs, lhs_ty, false);
+                            return try self.binOpImmediate(mir_tag, maybe_inst, lhs, rhs, lhs_ty, false);
                         } else {
-                            return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
+                            return try self.binOpRegister(mir_tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
                         }
                     } else {
                         return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
@@ -2512,13 +2496,19 @@ fn binOp(
                     const lhs_immediate_ok = lhs == .immediate;
                     const rhs_immediate_ok = rhs == .immediate;
 
+                    const mir_tag: Mir.Inst.Tag = switch (tag) {
+                        .bool_and => .@"and",
+                        .bool_or => .orr,
+                        else => unreachable,
+                    };
+
                     if (rhs_immediate_ok) {
-                        return try self.binOpImmediate(tag, maybe_inst, lhs, rhs, lhs_ty, false);
+                        return try self.binOpImmediate(mir_tag, maybe_inst, lhs, rhs, lhs_ty, false);
                     } else if (lhs_immediate_ok) {
                         // swap lhs and rhs
-                        return try self.binOpImmediate(tag, maybe_inst, rhs, lhs, rhs_ty, true);
+                        return try self.binOpImmediate(mir_tag, maybe_inst, rhs, lhs, rhs_ty, true);
                     } else {
-                        return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
+                        return try self.binOpRegister(mir_tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
                     }
                 },
                 else => unreachable,
@@ -2537,7 +2527,7 @@ fn binOp(
                     const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*));
 
                     if (elem_size == 1) {
-                        const base_tag: Air.Inst.Tag = switch (tag) {
+                        const base_tag: Mir.Inst.Tag = switch (tag) {
                             .ptr_add => .add,
                             .ptr_sub => .sub,
                             else => unreachable,