Commit 7b833b2fba

joachimschmidt557 <joachim.schmidt557@outlook.com>
2022-02-17 21:12:43
stage2 ARM: move {bool,bit}_{or,and} to binOp lowering mechanism
1 parent 985a442
Changed files (1)
src
arch
src/arch/arm/CodeGen.zig
@@ -548,11 +548,11 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
             .cmp_gt  => try self.airCmp(inst, .gt),
             .cmp_neq => try self.airCmp(inst, .neq),
 
-            .bool_and        => try self.airBoolOp(inst),
-            .bool_or         => try self.airBoolOp(inst),
-            .bit_and         => try self.airBitAnd(inst),
-            .bit_or          => try self.airBitOr(inst),
-            .xor             => try self.airXor(inst),
+            .bool_and        => try self.airBinOp(inst),
+            .bool_or         => try self.airBinOp(inst),
+            .bit_and         => try self.airBinOp(inst),
+            .bit_or          => try self.airBinOp(inst),
+            .xor             => try self.airBinOp(inst),
             .shr, .shr_exact => try self.airShr(inst),
 
             .alloc           => try self.airAlloc(inst),
@@ -1029,24 +1029,6 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void {
     return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
 }
 
-fn airBitAnd(self: *Self, inst: Air.Inst.Index) !void {
-    const bin_op = self.air.instructions.items(.data)[inst].bin_op;
-    const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .bit_and);
-    return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
-}
-
-fn airBitOr(self: *Self, inst: Air.Inst.Index) !void {
-    const bin_op = self.air.instructions.items(.data)[inst].bin_op;
-    const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .bit_or);
-    return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
-}
-
-fn airXor(self: *Self, inst: Air.Inst.Index) !void {
-    const bin_op = self.air.instructions.items(.data)[inst].bin_op;
-    const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .xor);
-    return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
-}
-
 fn airShl(self: *Self, inst: Air.Inst.Index) !void {
     const bin_op = self.air.instructions.items(.data)[inst].bin_op;
     const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .shl);
@@ -1770,11 +1752,23 @@ fn binOpRegister(
         .add, .ptr_add => .add,
         .sub, .ptr_sub => .sub,
         .mul => .mul,
+        .bit_and,
+        .bool_and,
+        => .@"and",
+        .bit_or,
+        .bool_or,
+        => .orr,
+        .xor => .eor,
         else => unreachable,
     };
     const mir_data: Mir.Inst.Data = switch (tag) {
         .add,
         .sub,
+        .bit_and,
+        .bool_and,
+        .bit_or,
+        .bool_or,
+        .xor,
         .ptr_add,
         .ptr_sub,
         => .{ .rr_op = .{
@@ -1862,11 +1856,23 @@ fn binOpImmediate(
     const mir_tag: Mir.Inst.Tag = switch (tag) {
         .add => .add,
         .sub => .sub,
+        .bit_and,
+        .bool_and,
+        => .@"and",
+        .bit_or,
+        .bool_or,
+        => .orr,
+        .xor => .eor,
         else => unreachable,
     };
     const mir_data: Mir.Inst.Data = switch (tag) {
         .add,
         .sub,
+        .bit_and,
+        .bool_and,
+        .bit_or,
+        .bool_or,
+        .xor,
         => .{ .rr_op = .{
             .rd = dest_reg,
             .rn = lhs_reg,
@@ -1964,6 +1970,54 @@ fn binOp(
                 else => unreachable,
             }
         },
+        .bit_and,
+        .bit_or,
+        .xor,
+        => {
+            switch (lhs_ty.zigTypeTag()) {
+                .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
+                .Int => {
+                    assert(lhs_ty.eql(rhs_ty));
+                    const int_info = lhs_ty.intInfo(self.target.*);
+                    if (int_info.bits <= 32) {
+                        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;
+
+                        if (rhs_immediate_ok) {
+                            return try self.binOpImmediate(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);
+                        } else {
+                            return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
+                        }
+                    } else {
+                        return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
+                    }
+                },
+                else => unreachable,
+            }
+        },
+        .bool_and,
+        .bool_or,
+        => {
+            switch (lhs_ty.zigTypeTag()) {
+                .Bool => {
+                    const lhs_immediate_ok = lhs == .immediate;
+                    const rhs_immediate_ok = rhs == .immediate;
+
+                    if (rhs_immediate_ok) {
+                        return try self.binOpImmediate(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);
+                    } else {
+                        return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
+                    }
+                },
+                else => unreachable,
+            }
+        },
         .ptr_add,
         .ptr_sub,
         => {
@@ -2183,17 +2237,9 @@ fn genBinOpCode(
     };
 
     switch (op) {
-        .bool_and,
-        .bit_and,
-        .bool_or,
-        .bit_or,
-        .not,
-        .xor,
-        => {
+        .not => {
             const tag: Mir.Inst.Tag = switch (op) {
-                .bool_and, .bit_and => .@"and",
-                .bool_or, .bit_or => .orr,
-                .not, .xor => .eor,
+                .not => .eor,
                 else => unreachable,
             };
 
@@ -3154,17 +3200,6 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void {
     return self.finishAir(inst, .dead, .{ branch.operand, .none, .none });
 }
 
-fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void {
-    const bin_op = self.air.instructions.items(.data)[inst].bin_op;
-    const air_tags = self.air.instructions.items(.tag);
-    const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (air_tags[inst]) {
-        .bool_and => try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .bool_and),
-        .bool_or => try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .bool_or),
-        else => unreachable, // Not a boolean operation
-    };
-    return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
-}
-
 fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
     const block_data = self.blocks.getPtr(block).?;