authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-06-07 11:08:45+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-06-07 23:34:42-04:00
log61844b6bd405b4cca3ab673284609aa6a651d506
treef596f02022a846d6d0a689b076b7bb6895e3c89d
parent70dc910086582b028d404d5de5049ceae0a95161

stage2 AArch64: introduce MCValue.condition_flags

Follows 9747303d16dfca61316a292d1e05ac901191e3a3 for AArch64

1 files changed, 41 insertions(+), 100 deletions(-)

src/arch/aarch64/CodeGen.zig+41-100
...@@ -35,6 +35,7 @@ const RegisterManager = abi.RegisterManager;...@@ -35,6 +35,7 @@ const RegisterManager = abi.RegisterManager;
35const RegisterLock = RegisterManager.RegisterLock;35const RegisterLock = RegisterManager.RegisterLock;
36const Register = bits.Register;36const Register = bits.Register;
37const Instruction = bits.Instruction;37const Instruction = bits.Instruction;
38const Condition = bits.Instruction.Condition;
38const callee_preserved_regs = abi.callee_preserved_regs;39const callee_preserved_regs = abi.callee_preserved_regs;
39const c_abi_int_param_regs = abi.c_abi_int_param_regs;40const c_abi_int_param_regs = abi.c_abi_int_param_regs;
40const c_abi_int_return_regs = abi.c_abi_int_return_regs;41const c_abi_int_return_regs = abi.c_abi_int_return_regs;
...@@ -90,7 +91,7 @@ register_manager: RegisterManager = .{},...@@ -90,7 +91,7 @@ register_manager: RegisterManager = .{},
90/// Maps offset to what is stored there.91/// Maps offset to what is stored there.
91stack: std.AutoHashMapUnmanaged(u32, StackAllocation) = .{},92stack: std.AutoHashMapUnmanaged(u32, StackAllocation) = .{},
92/// Tracks the current instruction allocated to the compare flags93/// Tracks the current instruction allocated to the compare flags
93compare_flags_inst: ?Air.Inst.Index = null,94condition_flags_inst: ?Air.Inst.Index = null,
9495
95/// Offset from the stack base, representing the end of the stack frame.96/// Offset from the stack base, representing the end of the stack frame.
96max_end_stack: u32 = 0,97max_end_stack: u32 = 0,
...@@ -161,12 +162,10 @@ const MCValue = union(enum) {...@@ -161,12 +162,10 @@ const MCValue = union(enum) {
161 /// The value is a pointer to one of the stack variables (payload162 /// The value is a pointer to one of the stack variables (payload
162 /// is stack offset).163 /// is stack offset).
163 ptr_stack_offset: u32,164 ptr_stack_offset: u32,
164 /// The value is in the compare flags assuming an unsigned165 /// The value resides in the N, Z, C, V flags. The value is 1 (if
165 /// operation, with this operator applied on top of it.166 /// the type is u1) or true (if the type in bool) iff the
166 compare_flags_unsigned: math.CompareOperator,167 /// specified condition is true.
167 /// The value is in the compare flags assuming a signed operation,168 condition_flags: Condition,
168 /// with this operator applied on top of it.
169 compare_flags_signed: math.CompareOperator,
170169
171 fn isMemory(mcv: MCValue) bool {170 fn isMemory(mcv: MCValue) bool {
172 return switch (mcv) {171 return switch (mcv) {
...@@ -190,8 +189,7 @@ const MCValue = union(enum) {...@@ -190,8 +189,7 @@ const MCValue = union(enum) {
190189
191 .immediate,190 .immediate,
192 .memory,191 .memory,
193 .compare_flags_unsigned,192 .condition_flags,
194 .compare_flags_signed,
195 .ptr_stack_offset,193 .ptr_stack_offset,
196 .undef,194 .undef,
197 => false,195 => false,
...@@ -758,10 +756,10 @@ fn processDeath(self: *Self, inst: Air.Inst.Index) void {...@@ -758,10 +756,10 @@ fn processDeath(self: *Self, inst: Air.Inst.Index) void {
758 },756 },
759 .register_with_overflow => |rwo| {757 .register_with_overflow => |rwo| {
760 self.register_manager.freeReg(rwo.reg);758 self.register_manager.freeReg(rwo.reg);
761 self.compare_flags_inst = null;759 self.condition_flags_inst = null;
762 },760 },
763 .compare_flags_signed, .compare_flags_unsigned => {761 .condition_flags => {
764 self.compare_flags_inst = null;762 self.condition_flags_inst = null;
765 },763 },
766 else => {}, // TODO process stack allocation death764 else => {}, // TODO process stack allocation death
767 }765 }
...@@ -911,12 +909,10 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void...@@ -911,12 +909,10 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void
911/// Save the current instruction stored in the compare flags if909/// Save the current instruction stored in the compare flags if
912/// occupied910/// occupied
913fn spillCompareFlagsIfOccupied(self: *Self) !void {911fn spillCompareFlagsIfOccupied(self: *Self) !void {
914 if (self.compare_flags_inst) |inst_to_save| {912 if (self.condition_flags_inst) |inst_to_save| {
915 const mcv = self.getResolvedInstValue(inst_to_save);913 const mcv = self.getResolvedInstValue(inst_to_save);
916 const new_mcv = switch (mcv) {914 const new_mcv = switch (mcv) {
917 .compare_flags_signed,915 .condition_flags => try self.allocRegOrMem(inst_to_save, true),
918 .compare_flags_unsigned,
919 => try self.allocRegOrMem(inst_to_save, true),
920 .register_with_overflow => try self.allocRegOrMem(inst_to_save, false),916 .register_with_overflow => try self.allocRegOrMem(inst_to_save, false),
921 else => unreachable, // mcv doesn't occupy the compare flags917 else => unreachable, // mcv doesn't occupy the compare flags
922 };918 };
...@@ -927,7 +923,7 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void {...@@ -927,7 +923,7 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void {
927 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];923 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
928 try branch.inst_table.put(self.gpa, inst_to_save, new_mcv);924 try branch.inst_table.put(self.gpa, inst_to_save, new_mcv);
929925
930 self.compare_flags_inst = null;926 self.condition_flags_inst = null;
931927
932 // TODO consolidate with register manager and spillInstruction928 // TODO consolidate with register manager and spillInstruction
933 // this call should really belong in the register manager!929 // this call should really belong in the register manager!
...@@ -1109,32 +1105,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {...@@ -1109,32 +1105,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
1109 switch (operand) {1105 switch (operand) {
1110 .dead => unreachable,1106 .dead => unreachable,
1111 .unreach => unreachable,1107 .unreach => unreachable,
1112 .compare_flags_unsigned => |op| {1108 .condition_flags => |cond| break :result MCValue{ .condition_flags = cond.negate() },
1113 const r = MCValue{
1114 .compare_flags_unsigned = switch (op) {
1115 .gte => .lt,
1116 .gt => .lte,
1117 .neq => .eq,
1118 .lt => .gte,
1119 .lte => .gt,
1120 .eq => .neq,
1121 },
1122 };
1123 break :result r;
1124 },
1125 .compare_flags_signed => |op| {
1126 const r = MCValue{
1127 .compare_flags_signed = switch (op) {
1128 .gte => .lt,
1129 .gt => .lte,
1130 .neq => .eq,
1131 .lt => .gte,
1132 .lte => .gt,
1133 .eq => .neq,
1134 },
1135 };
1136 break :result r;
1137 },
1138 else => {1109 else => {
1139 switch (operand_ty.zigTypeTag()) {1110 switch (operand_ty.zigTypeTag()) {
1140 .Bool => {1111 .Bool => {
...@@ -1851,7 +1822,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1851,7 +1822,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
1851 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);1822 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);
18521823
1853 try self.spillCompareFlagsIfOccupied();1824 try self.spillCompareFlagsIfOccupied();
1854 self.compare_flags_inst = null;1825 self.condition_flags_inst = null;
18551826
1856 const base_tag: Air.Inst.Tag = switch (tag) {1827 const base_tag: Air.Inst.Tag = switch (tag) {
1857 .add_with_overflow => .add,1828 .add_with_overflow => .add,
...@@ -1875,7 +1846,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1875,7 +1846,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
1875 _ = try self.binOp(.cmp_eq, dest, .{ .register = truncated_reg }, Type.usize, Type.usize, null);1846 _ = try self.binOp(.cmp_eq, dest, .{ .register = truncated_reg }, Type.usize, Type.usize, null);
18761847
1877 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });1848 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });
1878 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .compare_flags_unsigned = .neq });1849 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .condition_flags = .ne });
18791850
1880 break :result MCValue{ .stack_offset = stack_offset };1851 break :result MCValue{ .stack_offset = stack_offset };
1881 },1852 },
...@@ -1907,7 +1878,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1907,7 +1878,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
1907 };1878 };
19081879
1909 try self.spillCompareFlagsIfOccupied();1880 try self.spillCompareFlagsIfOccupied();
1910 self.compare_flags_inst = inst;1881 self.condition_flags_inst = inst;
19111882
1912 const dest = blk: {1883 const dest = blk: {
1913 if (rhs_immediate_ok) {1884 if (rhs_immediate_ok) {
...@@ -1966,7 +1937,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1966,7 +1937,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1966 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);1937 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);
19671938
1968 try self.spillCompareFlagsIfOccupied();1939 try self.spillCompareFlagsIfOccupied();
1969 self.compare_flags_inst = null;1940 self.condition_flags_inst = null;
19701941
1971 const base_tag: Mir.Inst.Tag = switch (int_info.signedness) {1942 const base_tag: Mir.Inst.Tag = switch (int_info.signedness) {
1972 .signed => .smull,1943 .signed => .smull,
...@@ -2015,16 +1986,14 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2015,16 +1986,14 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2015 }1986 }
20161987
2017 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });1988 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });
2018 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{1989 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .condition_flags = .ne });
2019 .compare_flags_unsigned = .neq,
2020 });
20211990
2022 break :result MCValue{ .stack_offset = stack_offset };1991 break :result MCValue{ .stack_offset = stack_offset };
2023 } else if (int_info.bits <= 64) {1992 } else if (int_info.bits <= 64) {
2024 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);1993 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);
20251994
2026 try self.spillCompareFlagsIfOccupied();1995 try self.spillCompareFlagsIfOccupied();
2027 self.compare_flags_inst = null;1996 self.condition_flags_inst = null;
20281997
2029 // TODO this should really be put in a helper similar to `binOpRegister`1998 // TODO this should really be put in a helper similar to `binOpRegister`
2030 const lhs_is_register = lhs == .register;1999 const lhs_is_register = lhs == .register;
...@@ -2194,9 +2163,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2194,9 +2163,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2194 try self.truncRegister(dest_reg, truncated_reg, int_info.signedness, int_info.bits);2163 try self.truncRegister(dest_reg, truncated_reg, int_info.signedness, int_info.bits);
21952164
2196 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });2165 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });
2197 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{2166 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .condition_flags = .ne });
2198 .compare_flags_unsigned = .neq,
2199 });
22002167
2201 break :result MCValue{ .stack_offset = stack_offset };2168 break :result MCValue{ .stack_offset = stack_offset };
2202 } else return self.fail("TODO implement mul_with_overflow for integers > u64/i64", .{});2169 } else return self.fail("TODO implement mul_with_overflow for integers > u64/i64", .{});
...@@ -2236,7 +2203,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2236,7 +2203,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2236 defer if (lhs_lock) |reg| self.register_manager.unlockReg(reg);2203 defer if (lhs_lock) |reg| self.register_manager.unlockReg(reg);
22372204
2238 try self.spillCompareFlagsIfOccupied();2205 try self.spillCompareFlagsIfOccupied();
2239 self.compare_flags_inst = null;2206 self.condition_flags_inst = null;
22402207
2241 // lsl dest, lhs, rhs2208 // lsl dest, lhs, rhs
2242 const dest = try self.binOp(.shl, lhs, rhs, lhs_ty, rhs_ty, null);2209 const dest = try self.binOp(.shl, lhs, rhs, lhs_ty, rhs_ty, null);
...@@ -2251,9 +2218,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2251,9 +2218,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2251 _ = try self.binOp(.cmp_eq, lhs, reconstructed, lhs_ty, lhs_ty, null);2218 _ = try self.binOp(.cmp_eq, lhs, reconstructed, lhs_ty, lhs_ty, null);
22522219
2253 try self.genSetStack(lhs_ty, stack_offset, dest);2220 try self.genSetStack(lhs_ty, stack_offset, dest);
2254 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{2221 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .condition_flags = .ne });
2255 .compare_flags_unsigned = .neq,
2256 });
22572222
2258 break :result MCValue{ .stack_offset = stack_offset };2223 break :result MCValue{ .stack_offset = stack_offset };
2259 } else {2224 } else {
...@@ -2681,8 +2646,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -2681,8 +2646,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
2681 .undef => unreachable,2646 .undef => unreachable,
2682 .unreach => unreachable,2647 .unreach => unreachable,
2683 .dead => unreachable,2648 .dead => unreachable,
2684 .compare_flags_unsigned,2649 .condition_flags,
2685 .compare_flags_signed,
2686 .register_with_overflow,2650 .register_with_overflow,
2687 => unreachable, // cannot hold an address2651 => unreachable, // cannot hold an address
2688 .immediate => |imm| try self.setRegOrMem(elem_ty, dst_mcv, .{ .memory = imm }),2652 .immediate => |imm| try self.setRegOrMem(elem_ty, dst_mcv, .{ .memory = imm }),
...@@ -2694,7 +2658,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -2694,7 +2658,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
2694 switch (dst_mcv) {2658 switch (dst_mcv) {
2695 .dead => unreachable,2659 .dead => unreachable,
2696 .undef => unreachable,2660 .undef => unreachable,
2697 .compare_flags_signed, .compare_flags_unsigned => unreachable,2661 .condition_flags => unreachable,
2698 .register => |dst_reg| {2662 .register => |dst_reg| {
2699 try self.genLdrRegister(dst_reg, addr_reg, elem_ty);2663 try self.genLdrRegister(dst_reg, addr_reg, elem_ty);
2700 },2664 },
...@@ -2903,8 +2867,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -2903,8 +2867,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
2903 .undef => unreachable,2867 .undef => unreachable,
2904 .unreach => unreachable,2868 .unreach => unreachable,
2905 .dead => unreachable,2869 .dead => unreachable,
2906 .compare_flags_unsigned,2870 .condition_flags,
2907 .compare_flags_signed,
2908 .register_with_overflow,2871 .register_with_overflow,
2909 => unreachable, // cannot hold an address2872 => unreachable, // cannot hold an address
2910 .immediate => |imm| {2873 .immediate => |imm| {
...@@ -3370,11 +3333,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -3370,11 +3333,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
3370 });3333 });
33713334
3372 try self.spillCompareFlagsIfOccupied();3335 try self.spillCompareFlagsIfOccupied();
3373 self.compare_flags_inst = inst;3336 self.condition_flags_inst = inst;
33743337
3375 break :result switch (int_info.signedness) {3338 break :result switch (int_info.signedness) {
3376 .signed => MCValue{ .compare_flags_signed = op },3339 .signed => MCValue{ .condition_flags = Condition.fromCompareOperatorSigned(op) },
3377 .unsigned => MCValue{ .compare_flags_unsigned = op },3340 .unsigned => MCValue{ .condition_flags = Condition.fromCompareOperatorUnsigned(op) },
3378 };3341 };
3379 } else {3342 } else {
3380 return self.fail("TODO AArch64 cmp for ints > 64 bits", .{});3343 return self.fail("TODO AArch64 cmp for ints > 64 bits", .{});
...@@ -3434,26 +3397,13 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {...@@ -3434,26 +3397,13 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
34343397
3435fn condBr(self: *Self, condition: MCValue) !Mir.Inst.Index {3398fn condBr(self: *Self, condition: MCValue) !Mir.Inst.Index {
3436 switch (condition) {3399 switch (condition) {
3437 .compare_flags_signed,3400 .condition_flags => |cond| return try self.addInst(.{
3438 .compare_flags_unsigned,
3439 => return try self.addInst(.{
3440 .tag = .b_cond,3401 .tag = .b_cond,
3441 .data = .{3402 .data = .{
3442 .inst_cond = .{3403 .inst_cond = .{
3443 .inst = undefined, // populated later through performReloc3404 .inst = undefined, // populated later through performReloc
3444 .cond = switch (condition) {3405 // Here we map to the opposite condition because the jump is to the false branch.
3445 .compare_flags_signed => |cmp_op| blk: {3406 .cond = cond.negate(),
3446 // Here we map to the opposite condition because the jump is to the false branch.
3447 const condition_code = Instruction.Condition.fromCompareOperatorSigned(cmp_op);
3448 break :blk condition_code.negate();
3449 },
3450 .compare_flags_unsigned => |cmp_op| blk: {
3451 // Here we map to the opposite condition because the jump is to the false branch.
3452 const condition_code = Instruction.Condition.fromCompareOperatorUnsigned(cmp_op);
3453 break :blk condition_code.negate();
3454 },
3455 else => unreachable,
3456 },
3457 },3407 },
3458 },3408 },
3459 }),3409 }),
...@@ -3503,7 +3453,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -3503,7 +3453,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
3503 var parent_stack = try self.stack.clone(self.gpa);3453 var parent_stack = try self.stack.clone(self.gpa);
3504 defer parent_stack.deinit(self.gpa);3454 defer parent_stack.deinit(self.gpa);
3505 const parent_registers = self.register_manager.registers;3455 const parent_registers = self.register_manager.registers;
3506 const parent_compare_flags_inst = self.compare_flags_inst;3456 const parent_condition_flags_inst = self.condition_flags_inst;
35073457
3508 try self.branch_stack.append(.{});3458 try self.branch_stack.append(.{});
3509 errdefer {3459 errdefer {
...@@ -3522,7 +3472,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -3522,7 +3472,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
3522 defer saved_then_branch.deinit(self.gpa);3472 defer saved_then_branch.deinit(self.gpa);
35233473
3524 self.register_manager.registers = parent_registers;3474 self.register_manager.registers = parent_registers;
3525 self.compare_flags_inst = parent_compare_flags_inst;3475 self.condition_flags_inst = parent_condition_flags_inst;
35263476
3527 self.stack.deinit(self.gpa);3477 self.stack.deinit(self.gpa);
3528 self.stack = parent_stack;3478 self.stack = parent_stack;
...@@ -3672,15 +3622,15 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {...@@ -3672,15 +3622,15 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
3672 else => return self.fail("TODO implement isErr for {}", .{operand}),3622 else => return self.fail("TODO implement isErr for {}", .{operand}),
3673 }3623 }
36743624
3675 return MCValue{ .compare_flags_unsigned = .gt };3625 return MCValue{ .condition_flags = .hi };
3676}3626}
36773627
3678fn isNonErr(self: *Self, ty: Type, operand: MCValue) !MCValue {3628fn isNonErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
3679 const is_err_result = try self.isErr(ty, operand);3629 const is_err_result = try self.isErr(ty, operand);
3680 switch (is_err_result) {3630 switch (is_err_result) {
3681 .compare_flags_unsigned => |op| {3631 .condition_flags => |cond| {
3682 assert(op == .gt);3632 assert(cond == .hi);
3683 return MCValue{ .compare_flags_unsigned = .lte };3633 return MCValue{ .condition_flags = cond.negate() };
3684 },3634 },
3685 .immediate => |imm| {3635 .immediate => |imm| {
3686 assert(imm == 0);3636 assert(imm == 0);
...@@ -3889,7 +3839,7 @@ fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {...@@ -3889,7 +3839,7 @@ fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
3889 block_data.mcv = switch (operand_mcv) {3839 block_data.mcv = switch (operand_mcv) {
3890 .none, .dead, .unreach => unreachable,3840 .none, .dead, .unreach => unreachable,
3891 .register, .stack_offset, .memory => operand_mcv,3841 .register, .stack_offset, .memory => operand_mcv,
3892 .immediate => blk: {3842 .immediate, .condition_flags => blk: {
3893 const new_mcv = try self.allocRegOrMem(block, true);3843 const new_mcv = try self.allocRegOrMem(block, true);
3894 try self.setRegOrMem(self.air.typeOfIndex(block), new_mcv, operand_mcv);3844 try self.setRegOrMem(self.air.typeOfIndex(block), new_mcv, operand_mcv);
3895 break :blk new_mcv;3845 break :blk new_mcv;
...@@ -4072,8 +4022,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -4072,8 +4022,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
4072 else => return self.fail("TODO implement memset", .{}),4022 else => return self.fail("TODO implement memset", .{}),
4073 }4023 }
4074 },4024 },
4075 .compare_flags_unsigned,4025 .condition_flags,
4076 .compare_flags_signed,
4077 .immediate,4026 .immediate,
4078 .ptr_stack_offset,4027 .ptr_stack_offset,
4079 => {4028 => {
...@@ -4235,15 +4184,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -4235,15 +4184,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
4235 } },4184 } },
4236 });4185 });
4237 },4186 },
4238 .compare_flags_unsigned,4187 .condition_flags => |condition| {
4239 .compare_flags_signed,
4240 => |op| {
4241 const condition = switch (mcv) {
4242 .compare_flags_unsigned => Instruction.Condition.fromCompareOperatorUnsigned(op),
4243 .compare_flags_signed => Instruction.Condition.fromCompareOperatorSigned(op),
4244 else => unreachable,
4245 };
4246
4247 _ = try self.addInst(.{4188 _ = try self.addInst(.{
4248 .tag = .cset,4189 .tag = .cset,
4249 .data = .{ .r_cond = .{4190 .data = .{ .r_cond = .{