| ... | ... | @@ -8171,24 +8171,105 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 8171 | 8171 | const result = MCValue{ |
| 8172 | 8172 | .eflags = switch (ty.zigTypeTag()) { |
| 8173 | 8173 | else => result: { |
| 8174 | | var flipped = false; |
| 8175 | | const dst_mcv: MCValue = if (lhs_mcv.isRegister() or lhs_mcv.isMemory()) |
| 8176 | | lhs_mcv |
| 8177 | | else if (rhs_mcv.isRegister() or rhs_mcv.isMemory()) dst: { |
| 8178 | | flipped = true; |
| 8179 | | break :dst rhs_mcv; |
| 8180 | | } else .{ .register = try self.copyToTmpRegister(ty, lhs_mcv) }; |
| 8181 | | const dst_lock = switch (dst_mcv) { |
| 8182 | | .register => |reg| self.register_manager.lockReg(reg), |
| 8183 | | else => null, |
| 8174 | const abi_size = @intCast(u16, ty.abiSize(self.target.*)); |
| 8175 | const may_flip: enum { |
| 8176 | may_flip, |
| 8177 | must_flip, |
| 8178 | must_not_flip, |
| 8179 | } = if (abi_size > 8) switch (op) { |
| 8180 | .lt, .gte => .must_not_flip, |
| 8181 | .lte, .gt => .must_flip, |
| 8182 | .eq, .neq => .may_flip, |
| 8183 | } else .may_flip; |
| 8184 | |
| 8185 | const flipped = switch (may_flip) { |
| 8186 | .may_flip => !lhs_mcv.isRegister() and !lhs_mcv.isMemory(), |
| 8187 | .must_flip => true, |
| 8188 | .must_not_flip => false, |
| 8189 | }; |
| 8190 | const unmat_dst_mcv = if (flipped) rhs_mcv else lhs_mcv; |
| 8191 | const dst_mcv = if (unmat_dst_mcv.isRegister() or |
| 8192 | (abi_size <= 8 and unmat_dst_mcv.isMemory())) unmat_dst_mcv else dst: { |
| 8193 | const dst_mcv = try self.allocTempRegOrMem(ty, true); |
| 8194 | try self.genCopy(ty, dst_mcv, unmat_dst_mcv); |
| 8195 | break :dst dst_mcv; |
| 8184 | 8196 | }; |
| 8197 | const dst_lock = |
| 8198 | if (dst_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; |
| 8185 | 8199 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 8200 | |
| 8186 | 8201 | const src_mcv = if (flipped) lhs_mcv else rhs_mcv; |
| 8202 | const src_lock = |
| 8203 | if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; |
| 8204 | defer if (src_lock) |lock| self.register_manager.unlockReg(lock); |
| 8187 | 8205 | |
| 8188 | | try self.genBinOpMir(.{ ._, .cmp }, ty, dst_mcv, src_mcv); |
| 8189 | 8206 | break :result Condition.fromCompareOperator( |
| 8190 | 8207 | if (ty.isAbiInt()) ty.intInfo(self.target.*).signedness else .unsigned, |
| 8191 | | if (flipped) op.reverse() else op, |
| 8208 | result_op: { |
| 8209 | const flipped_op = if (flipped) op.reverse() else op; |
| 8210 | if (abi_size > 8) switch (flipped_op) { |
| 8211 | .lt, .gte => {}, |
| 8212 | .lte, .gt => unreachable, |
| 8213 | .eq, .neq => { |
| 8214 | const dst_addr_mcv: MCValue = switch (dst_mcv) { |
| 8215 | .memory, .indirect, .load_frame => dst_mcv.address(), |
| 8216 | else => .{ .register = try self.copyToTmpRegister( |
| 8217 | Type.usize, |
| 8218 | dst_mcv.address(), |
| 8219 | ) }, |
| 8220 | }; |
| 8221 | const dst_addr_lock = if (dst_addr_mcv.getReg()) |reg| |
| 8222 | self.register_manager.lockReg(reg) |
| 8223 | else |
| 8224 | null; |
| 8225 | defer if (dst_addr_lock) |lock| self.register_manager.unlockReg(lock); |
| 8226 | |
| 8227 | const src_addr_mcv: MCValue = switch (src_mcv) { |
| 8228 | .memory, .indirect, .load_frame => src_mcv.address(), |
| 8229 | else => .{ .register = try self.copyToTmpRegister( |
| 8230 | Type.usize, |
| 8231 | src_mcv.address(), |
| 8232 | ) }, |
| 8233 | }; |
| 8234 | const src_addr_lock = if (src_addr_mcv.getReg()) |reg| |
| 8235 | self.register_manager.lockReg(reg) |
| 8236 | else |
| 8237 | null; |
| 8238 | defer if (src_addr_lock) |lock| self.register_manager.unlockReg(lock); |
| 8239 | |
| 8240 | const regs = try self.register_manager.allocRegs(2, .{ null, null }, gp); |
| 8241 | const acc_reg = regs[0].to64(); |
| 8242 | const locks = self.register_manager.lockRegsAssumeUnused(2, regs); |
| 8243 | defer for (locks) |lock| self.register_manager.unlockReg(lock); |
| 8244 | |
| 8245 | const limbs_len = std.math.divCeil(u16, abi_size, 8) catch unreachable; |
| 8246 | var limb_i: u16 = 0; |
| 8247 | while (limb_i < limbs_len) : (limb_i += 1) { |
| 8248 | const tmp_reg = regs[@min(limb_i, 1)].to64(); |
| 8249 | try self.genSetReg( |
| 8250 | tmp_reg, |
| 8251 | Type.usize, |
| 8252 | dst_addr_mcv.offset(limb_i * 8).deref(), |
| 8253 | ); |
| 8254 | try self.genBinOpMir( |
| 8255 | .{ ._, .xor }, |
| 8256 | Type.usize, |
| 8257 | .{ .register = tmp_reg }, |
| 8258 | src_addr_mcv.offset(limb_i * 8).deref(), |
| 8259 | ); |
| 8260 | if (limb_i > 0) try self.asmRegisterRegister( |
| 8261 | .{ ._, .@"or" }, |
| 8262 | acc_reg, |
| 8263 | tmp_reg, |
| 8264 | ); |
| 8265 | } |
| 8266 | try self.asmRegisterRegister(.{ ._, .@"test" }, acc_reg, acc_reg); |
| 8267 | break :result_op flipped_op; |
| 8268 | }, |
| 8269 | }; |
| 8270 | try self.genBinOpMir(.{ ._, .cmp }, ty, dst_mcv, src_mcv); |
| 8271 | break :result_op flipped_op; |
| 8272 | }, |
| 8192 | 8273 | ); |
| 8193 | 8274 | }, |
| 8194 | 8275 | .Float => result: { |
| ... | ... | @@ -10006,7 +10087,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { |
| 10006 | 10087 | if (src_ty.isAbiInt()) src_ty.intInfo(self.target.*).signedness else .unsigned; |
| 10007 | 10088 | const abi_size = @intCast(u16, dst_ty.abiSize(self.target.*)); |
| 10008 | 10089 | const bit_size = @intCast(u16, dst_ty.bitSize(self.target.*)); |
| 10009 | | const dst_limbs_len = std.math.divCeil(u16, bit_size, 64) catch unreachable; |
| 10090 | const dst_limbs_len = math.divCeil(u16, bit_size, 64) catch unreachable; |
| 10010 | 10091 | if (dst_signedness != src_signedness and abi_size * 8 > bit_size) { |
| 10011 | 10092 | const high_reg = if (dst_mcv.isRegister()) |
| 10012 | 10093 | dst_mcv.getReg().? |
| ... | ... | @@ -10071,7 +10152,7 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void { |
| 10071 | 10152 | if (src_ty.isAbiInt()) src_ty.intInfo(self.target.*).signedness else .unsigned; |
| 10072 | 10153 | const dst_ty = self.air.typeOfIndex(inst); |
| 10073 | 10154 | |
| 10074 | | const src_size = std.math.divCeil(u32, @max(switch (src_signedness) { |
| 10155 | const src_size = math.divCeil(u32, @max(switch (src_signedness) { |
| 10075 | 10156 | .signed => src_bits, |
| 10076 | 10157 | .unsigned => src_bits + 1, |
| 10077 | 10158 | }, 32), 8) catch unreachable; |
| ... | ... | @@ -10124,7 +10205,7 @@ fn airFloatToInt(self: *Self, inst: Air.Inst.Index) !void { |
| 10124 | 10205 | const dst_signedness = |
| 10125 | 10206 | if (dst_ty.isAbiInt()) dst_ty.intInfo(self.target.*).signedness else .unsigned; |
| 10126 | 10207 | |
| 10127 | | const dst_size = std.math.divCeil(u32, @max(switch (dst_signedness) { |
| 10208 | const dst_size = math.divCeil(u32, @max(switch (dst_signedness) { |
| 10128 | 10209 | .signed => dst_bits, |
| 10129 | 10210 | .unsigned => dst_bits + 1, |
| 10130 | 10211 | }, 32), 8) catch unreachable; |