x86_64: rewrite scalar and vector int @rem

This commit is contained in:
Jacob Young 2025-02-13 16:25:41 -05:00
parent 8c48376d64
commit f6bcc9dbcb
4 changed files with 694 additions and 19 deletions

View file

@ -11648,12 +11648,679 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
};
try res[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg);
},
.rem, .rem_optimized => |air_tag| if (use_old) try cg.airMulDivBinOp(inst, .rem) else fallback: {
.rem, .rem_optimized => |air_tag| if (use_old) try cg.airMulDivBinOp(inst, .rem) else {
const bin_op = air_datas[@intFromEnum(inst)].bin_op;
if (cg.floatBits(cg.typeOf(bin_op.lhs).scalarType(zcu)) == null) break :fallback try cg.airMulDivBinOp(inst, .rem);
var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
var res: [1]Temp = undefined;
cg.select(&res, &.{cg.typeOf(bin_op.lhs)}, &ops, comptime &.{ .{
.src_constraints = .{ .{ .signed_int = .byte }, .{ .signed_int = .byte }, .any },
.patterns = &.{
.{ .src = .{ .mem, .mem, .none } },
.{ .src = .{ .to_gpr, .mem, .none } },
.{ .src = .{ .mem, .to_gpr, .none } },
.{ .src = .{ .to_gpr, .to_gpr, .none } },
},
.dst_temps = .{ .{ .reg = .ah }, .unused },
.clobbers = .{ .eflags = true },
.each = .{ .once = &.{
.{ ._, ._, .movsx, .dst0d, .src0b, ._, ._ },
.{ ._, .i_, .div, .src1b, ._, ._, ._ },
} },
}, .{
.src_constraints = .{ .{ .unsigned_int = .byte }, .{ .unsigned_int = .byte }, .any },
.patterns = &.{
.{ .src = .{ .mem, .mem, .none } },
.{ .src = .{ .to_gpr, .mem, .none } },
.{ .src = .{ .mem, .to_gpr, .none } },
.{ .src = .{ .to_gpr, .to_gpr, .none } },
},
.dst_temps = .{ .{ .reg = .ah }, .unused },
.clobbers = .{ .eflags = true },
.each = .{ .once = &.{
.{ ._, ._, .movzx, .dst0d, .src0b, ._, ._ },
.{ ._, ._, .div, .src1b, ._, ._, ._ },
} },
}, .{
.src_constraints = .{ .{ .signed_int = .word }, .{ .signed_int = .word }, .any },
.patterns = &.{
.{ .src = .{ .{ .to_reg = .ax }, .mem, .none } },
.{ .src = .{ .{ .to_reg = .ax }, .to_gpr, .none } },
},
.dst_temps = .{ .{ .reg = .dx }, .unused },
.clobbers = .{ .eflags = true },
.each = .{ .once = &.{
.{ ._, ._, .cwd, ._, ._, ._, ._ },
.{ ._, .i_, .div, .src1w, ._, ._, ._ },
} },
}, .{
.src_constraints = .{ .{ .unsigned_int = .word }, .{ .unsigned_int = .word }, .any },
.patterns = &.{
.{ .src = .{ .{ .to_reg = .ax }, .mem, .none } },
.{ .src = .{ .{ .to_reg = .ax }, .to_gpr, .none } },
},
.dst_temps = .{ .{ .reg = .dx }, .unused },
.clobbers = .{ .eflags = true },
.each = .{ .once = &.{
.{ ._, ._, .xor, .dst0d, .dst0d, ._, ._ },
.{ ._, ._, .div, .src1w, ._, ._, ._ },
} },
}, .{
.src_constraints = .{ .{ .signed_int = .dword }, .{ .signed_int = .dword }, .any },
.patterns = &.{
.{ .src = .{ .{ .to_reg = .eax }, .mem, .none } },
.{ .src = .{ .{ .to_reg = .eax }, .to_gpr, .none } },
},
.dst_temps = .{ .{ .reg = .edx }, .unused },
.clobbers = .{ .eflags = true },
.each = .{ .once = &.{
.{ ._, ._, .cdq, ._, ._, ._, ._ },
.{ ._, .i_, .div, .src1d, ._, ._, ._ },
} },
}, .{
.src_constraints = .{ .{ .unsigned_int = .dword }, .{ .unsigned_int = .dword }, .any },
.patterns = &.{
.{ .src = .{ .{ .to_reg = .eax }, .mem, .none } },
.{ .src = .{ .{ .to_reg = .eax }, .to_gpr, .none } },
},
.dst_temps = .{ .{ .reg = .edx }, .unused },
.clobbers = .{ .eflags = true },
.each = .{ .once = &.{
.{ ._, ._, .xor, .dst0d, .dst0d, ._, ._ },
.{ ._, ._, .div, .src1d, ._, ._, ._ },
} },
}, .{
.required_features = .{ .@"64bit", null, null, null },
.src_constraints = .{ .{ .signed_int = .qword }, .{ .signed_int = .qword }, .any },
.patterns = &.{
.{ .src = .{ .{ .to_reg = .rax }, .mem, .none } },
.{ .src = .{ .{ .to_reg = .rax }, .to_gpr, .none } },
},
.dst_temps = .{ .{ .reg = .rdx }, .unused },
.clobbers = .{ .eflags = true },
.each = .{ .once = &.{
.{ ._, ._, .cqo, ._, ._, ._, ._ },
.{ ._, .i_, .div, .src1q, ._, ._, ._ },
} },
}, .{
.required_features = .{ .@"64bit", null, null, null },
.src_constraints = .{ .{ .unsigned_int = .qword }, .{ .unsigned_int = .qword }, .any },
.patterns = &.{
.{ .src = .{ .{ .to_reg = .rax }, .mem, .none } },
.{ .src = .{ .{ .to_reg = .rax }, .to_gpr, .none } },
},
.dst_temps = .{ .{ .reg = .rdx }, .unused },
.clobbers = .{ .eflags = true },
.each = .{ .once = &.{
.{ ._, ._, .xor, .dst0q, .dst0q, ._, ._ },
.{ ._, ._, .div, .src1q, ._, ._, ._ },
} },
}, .{
.required_features = .{ .@"64bit", null, null, null },
.src_constraints = .{ .{ .signed_int = .xword }, .{ .signed_int = .xword }, .any },
.patterns = &.{
.{ .src = .{
.{ .to_param_gpr_pair = .{ .cc = .ccc, .index = 0 } },
.{ .to_param_gpr_pair = .{ .cc = .ccc, .index = 2 } },
.none,
} },
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__modti3" } } },
.unused,
.unused,
.unused,
.unused,
.unused,
.unused,
.unused,
.unused,
},
.dst_temps = .{ .{ .ret_gpr_pair = .{ .cc = .ccc, .index = 0 } }, .unused },
.clobbers = .{ .eflags = true, .caller_preserved = .ccc },
.each = .{ .once = &.{
.{ ._, ._, .call, .tmp0d, ._, ._, ._ },
} },
}, .{
.required_features = .{ .@"64bit", null, null, null },
.src_constraints = .{ .{ .unsigned_int = .xword }, .{ .unsigned_int = .xword }, .any },
.patterns = &.{
.{ .src = .{
.{ .to_param_gpr_pair = .{ .cc = .ccc, .index = 0 } },
.{ .to_param_gpr_pair = .{ .cc = .ccc, .index = 2 } },
.none,
} },
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__umodti3" } } },
.unused,
.unused,
.unused,
.unused,
.unused,
.unused,
.unused,
.unused,
},
.dst_temps = .{ .{ .ret_gpr_pair = .{ .cc = .ccc, .index = 0 } }, .unused },
.clobbers = .{ .eflags = true, .caller_preserved = .ccc },
.each = .{ .once = &.{
.{ ._, ._, .call, .tmp0d, ._, ._, ._ },
} },
}, .{
.required_features = .{ .@"64bit", null, null, null },
.src_constraints = .{
.{ .remainder_signed_int = .{ .of = .dword, .is = .dword } },
.{ .remainder_signed_int = .{ .of = .dword, .is = .dword } },
.any,
},
.patterns = &.{
.{ .src = .{ .to_mut_mem, .to_mut_mem, .none } },
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .index = 0 } } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .index = 1 } } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .index = 2 } } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .index = 3 } } },
.{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__modei4" } } },
.unused,
.unused,
.unused,
.unused,
},
.dst_temps = .{ .mem, .unused },
.clobbers = .{ .eflags = true, .caller_preserved = .ccc },
.each = .{ .once = &.{
.{ ._, ._, .lea, .tmp0p, .mem(.dst0), ._, ._ },
.{ ._, ._, .lea, .tmp1p, .mem(.src0), ._, ._ },
.{ ._, ._, .lea, .tmp2p, .mem(.src1), ._, ._ },
.{ ._, ._, .mov, .tmp3d, .sa(.src0, .add_8_size), ._, ._ },
.{ ._, ._, .call, .tmp4d, ._, ._, ._ },
} },
}, .{
.required_features = .{ .@"64bit", null, null, null },
.src_constraints = .{
.{ .remainder_unsigned_int = .{ .of = .dword, .is = .dword } },
.{ .remainder_unsigned_int = .{ .of = .dword, .is = .dword } },
.any,
},
.patterns = &.{
.{ .src = .{ .to_mem, .to_mem, .none } },
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .index = 0 } } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .index = 1 } } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .index = 2 } } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .index = 3 } } },
.{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__umodei4" } } },
.unused,
.unused,
.unused,
.unused,
},
.dst_temps = .{ .mem, .unused },
.clobbers = .{ .eflags = true, .caller_preserved = .ccc },
.each = .{ .once = &.{
.{ ._, ._, .lea, .tmp0p, .mem(.dst0), ._, ._ },
.{ ._, ._, .lea, .tmp1p, .mem(.src0), ._, ._ },
.{ ._, ._, .lea, .tmp2p, .mem(.src1), ._, ._ },
.{ ._, ._, .mov, .tmp3d, .sa(.src0, .add_8_size), ._, ._ },
.{ ._, ._, .call, .tmp4d, ._, ._, ._ },
} },
}, .{
.required_features = .{ .slow_incdec, null, null, null },
.src_constraints = .{
.{ .multiple_scalar_signed_int = .{ .of = .byte, .is = .byte } },
.{ .multiple_scalar_signed_int = .{ .of = .byte, .is = .byte } },
.any,
},
.patterns = &.{
.{ .src = .{ .to_mem, .to_mem, .none } },
},
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i8, .kind = .{ .reg = .ah } },
.unused,
.unused,
.unused,
.unused,
.unused,
.unused,
.unused,
},
.dst_temps = .{ .mem, .unused },
.clobbers = .{ .eflags = true },
.each = .{ .once = &.{
.{ ._, ._, .mov, .tmp0p, .sa(.src0, .sub_unaligned_size), ._, ._ },
.{ .@"0:", ._, .movsx, .tmp1d, .memia(.src0b, .tmp0, .add_unaligned_size), ._, ._ },
.{ ._, .i_, .div, .memia(.src1b, .tmp0, .add_unaligned_size), ._, ._, ._ },
.{ ._, ._, .mov, .memia(.dst0b, .tmp0, .add_unaligned_size), .tmp1b, ._, ._ },
.{ ._, ._, .add, .tmp0p, .si(1), ._, ._ },
.{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
} },
}, .{
.src_constraints = .{
.{ .multiple_scalar_signed_int = .{ .of = .byte, .is = .byte } },
.{ .multiple_scalar_signed_int = .{ .of = .byte, .is = .byte } },
.any,
},
.patterns = &.{
.{ .src = .{ .to_mem, .to_mem, .none } },
},
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i8, .kind = .{ .reg = .ah } },
.unused,
.unused,
.unused,
.unused,
.unused,
.unused,
.unused,
},
.dst_temps = .{ .mem, .unused },
.clobbers = .{ .eflags = true },
.each = .{ .once = &.{
.{ ._, ._, .mov, .tmp0p, .sa(.src0, .sub_unaligned_size), ._, ._ },
.{ .@"0:", ._, .movsx, .tmp1d, .memia(.src0b, .tmp0, .add_unaligned_size), ._, ._ },
.{ ._, .i_, .div, .memia(.src1b, .tmp0, .add_unaligned_size), ._, ._, ._ },
.{ ._, ._, .mov, .memia(.dst0b, .tmp0, .add_unaligned_size), .tmp1b, ._, ._ },
.{ ._, ._c, .in, .tmp0p, ._, ._, ._ },
.{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
} },
}, .{
.required_features = .{ .slow_incdec, null, null, null },
.src_constraints = .{
.{ .multiple_scalar_unsigned_int = .{ .of = .byte, .is = .byte } },
.{ .multiple_scalar_unsigned_int = .{ .of = .byte, .is = .byte } },
.any,
},
.patterns = &.{
.{ .src = .{ .to_mem, .to_mem, .none } },
},
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u8, .kind = .{ .reg = .ah } },
.unused,
.unused,
.unused,
.unused,
.unused,
.unused,
.unused,
},
.dst_temps = .{ .mem, .unused },
.clobbers = .{ .eflags = true },
.each = .{ .once = &.{
.{ ._, ._, .mov, .tmp0p, .sa(.src0, .sub_unaligned_size), ._, ._ },
.{ .@"0:", ._, .movzx, .tmp1d, .memia(.src0b, .tmp0, .add_unaligned_size), ._, ._ },
.{ ._, ._, .div, .memia(.src1b, .tmp0, .add_unaligned_size), ._, ._, ._ },
.{ ._, ._, .mov, .memia(.dst0b, .tmp0, .add_unaligned_size), .tmp1b, ._, ._ },
.{ ._, ._, .add, .tmp0p, .si(1), ._, ._ },
.{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
} },
}, .{
.src_constraints = .{
.{ .multiple_scalar_unsigned_int = .{ .of = .byte, .is = .byte } },
.{ .multiple_scalar_unsigned_int = .{ .of = .byte, .is = .byte } },
.any,
},
.patterns = &.{
.{ .src = .{ .to_mem, .to_mem, .none } },
},
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u8, .kind = .{ .reg = .ah } },
.unused,
.unused,
.unused,
.unused,
.unused,
.unused,
.unused,
},
.dst_temps = .{ .mem, .unused },
.clobbers = .{ .eflags = true },
.each = .{ .once = &.{
.{ ._, ._, .mov, .tmp0p, .sa(.src0, .sub_unaligned_size), ._, ._ },
.{ .@"0:", ._, .movzx, .tmp1d, .memia(.src0b, .tmp0, .add_unaligned_size), ._, ._ },
.{ ._, ._, .div, .memia(.src1b, .tmp0, .add_unaligned_size), ._, ._, ._ },
.{ ._, ._, .mov, .memia(.dst0b, .tmp0, .add_unaligned_size), .tmp1b, ._, ._ },
.{ ._, ._c, .in, .tmp0p, ._, ._, ._ },
.{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
} },
}, .{
.src_constraints = .{
.{ .multiple_scalar_signed_int = .{ .of = .word, .is = .word } },
.{ .multiple_scalar_signed_int = .{ .of = .word, .is = .word } },
.any,
},
.patterns = &.{
.{ .src = .{ .to_mem, .to_mem, .none } },
},
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i16, .kind = .{ .reg = .ax } },
.{ .type = .i16, .kind = .{ .reg = .dx } },
.unused,
.unused,
.unused,
.unused,
.unused,
.unused,
},
.dst_temps = .{ .mem, .unused },
.clobbers = .{ .eflags = true },
.each = .{ .once = &.{
.{ ._, ._, .mov, .tmp0p, .sa(.src0, .sub_unaligned_size), ._, ._ },
.{ .@"0:", ._, .movsx, .tmp1d, .memia(.src0w, .tmp0, .add_unaligned_size), ._, ._ },
.{ ._, ._, .cwd, ._, ._, ._, ._ },
.{ ._, .i_, .div, .memia(.src1w, .tmp0, .add_unaligned_size), ._, ._, ._ },
.{ ._, ._, .mov, .memia(.dst0w, .tmp0, .add_unaligned_size), .tmp2w, ._, ._ },
.{ ._, ._, .add, .tmp0p, .si(2), ._, ._ },
.{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
} },
}, .{
.src_constraints = .{
.{ .multiple_scalar_unsigned_int = .{ .of = .word, .is = .word } },
.{ .multiple_scalar_unsigned_int = .{ .of = .word, .is = .word } },
.any,
},
.patterns = &.{
.{ .src = .{ .to_mem, .to_mem, .none } },
},
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u16, .kind = .{ .reg = .ax } },
.{ .type = .u16, .kind = .{ .reg = .dx } },
.unused,
.unused,
.unused,
.unused,
.unused,
.unused,
},
.dst_temps = .{ .mem, .unused },
.clobbers = .{ .eflags = true },
.each = .{ .once = &.{
.{ ._, ._, .mov, .tmp0p, .sa(.src0, .sub_unaligned_size), ._, ._ },
.{ .@"0:", ._, .movzx, .tmp1d, .memia(.src0w, .tmp0, .add_unaligned_size), ._, ._ },
.{ ._, ._, .xor, .tmp2d, .tmp2d, ._, ._ },
.{ ._, ._, .div, .memia(.src1w, .tmp0, .add_unaligned_size), ._, ._, ._ },
.{ ._, ._, .mov, .memia(.dst0w, .tmp0, .add_unaligned_size), .tmp2w, ._, ._ },
.{ ._, ._, .add, .tmp0p, .si(2), ._, ._ },
.{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
} },
}, .{
.src_constraints = .{
.{ .multiple_scalar_signed_int = .{ .of = .dword, .is = .dword } },
.{ .multiple_scalar_signed_int = .{ .of = .dword, .is = .dword } },
.any,
},
.patterns = &.{
.{ .src = .{ .to_mem, .to_mem, .none } },
},
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .i32, .kind = .{ .reg = .edx } },
.unused,
.unused,
.unused,
.unused,
.unused,
.unused,
},
.dst_temps = .{ .mem, .unused },
.clobbers = .{ .eflags = true },
.each = .{ .once = &.{
.{ ._, ._, .mov, .tmp0p, .sa(.src0, .sub_unaligned_size), ._, ._ },
.{ .@"0:", ._, .mov, .tmp1d, .memia(.src0d, .tmp0, .add_unaligned_size), ._, ._ },
.{ ._, ._, .cdq, ._, ._, ._, ._ },
.{ ._, .i_, .div, .memia(.src1d, .tmp0, .add_unaligned_size), ._, ._, ._ },
.{ ._, ._, .mov, .memia(.dst0d, .tmp0, .add_unaligned_size), .tmp2d, ._, ._ },
.{ ._, ._, .add, .tmp0p, .si(4), ._, ._ },
.{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
} },
}, .{
.src_constraints = .{
.{ .multiple_scalar_unsigned_int = .{ .of = .dword, .is = .dword } },
.{ .multiple_scalar_unsigned_int = .{ .of = .dword, .is = .dword } },
.any,
},
.patterns = &.{
.{ .src = .{ .to_mem, .to_mem, .none } },
},
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .eax } },
.{ .type = .u32, .kind = .{ .reg = .edx } },
.unused,
.unused,
.unused,
.unused,
.unused,
.unused,
},
.dst_temps = .{ .mem, .unused },
.clobbers = .{ .eflags = true },
.each = .{ .once = &.{
.{ ._, ._, .mov, .tmp0p, .sa(.src0, .sub_unaligned_size), ._, ._ },
.{ .@"0:", ._, .mov, .tmp1d, .memia(.src0d, .tmp0, .add_unaligned_size), ._, ._ },
.{ ._, ._, .xor, .tmp2d, .tmp2d, ._, ._ },
.{ ._, ._, .div, .memia(.src1d, .tmp0, .add_unaligned_size), ._, ._, ._ },
.{ ._, ._, .mov, .memia(.dst0d, .tmp0, .add_unaligned_size), .tmp2d, ._, ._ },
.{ ._, ._, .add, .tmp0p, .si(4), ._, ._ },
.{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
} },
}, .{
.required_features = .{ .@"64bit", null, null, null },
.src_constraints = .{
.{ .multiple_scalar_signed_int = .{ .of = .qword, .is = .qword } },
.{ .multiple_scalar_signed_int = .{ .of = .qword, .is = .qword } },
.any,
},
.patterns = &.{
.{ .src = .{ .to_mem, .to_mem, .none } },
},
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i64, .kind = .{ .reg = .rax } },
.{ .type = .i64, .kind = .{ .reg = .rdx } },
.unused,
.unused,
.unused,
.unused,
.unused,
.unused,
},
.dst_temps = .{ .mem, .unused },
.clobbers = .{ .eflags = true },
.each = .{ .once = &.{
.{ ._, ._, .mov, .tmp0p, .sa(.src0, .sub_unaligned_size), ._, ._ },
.{ .@"0:", ._, .mov, .tmp1q, .memia(.src0q, .tmp0, .add_unaligned_size), ._, ._ },
.{ ._, ._, .cqo, ._, ._, ._, ._ },
.{ ._, .i_, .div, .memia(.src1q, .tmp0, .add_unaligned_size), ._, ._, ._ },
.{ ._, ._, .mov, .memia(.dst0q, .tmp0, .add_unaligned_size), .tmp2q, ._, ._ },
.{ ._, ._, .add, .tmp0p, .si(8), ._, ._ },
.{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
} },
}, .{
.required_features = .{ .@"64bit", null, null, null },
.src_constraints = .{
.{ .multiple_scalar_unsigned_int = .{ .of = .qword, .is = .qword } },
.{ .multiple_scalar_unsigned_int = .{ .of = .qword, .is = .qword } },
.any,
},
.patterns = &.{
.{ .src = .{ .to_mem, .to_mem, .none } },
},
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
.unused,
.unused,
.unused,
.unused,
.unused,
.unused,
},
.dst_temps = .{ .mem, .unused },
.clobbers = .{ .eflags = true },
.each = .{ .once = &.{
.{ ._, ._, .mov, .tmp0p, .sa(.src0, .sub_unaligned_size), ._, ._ },
.{ .@"0:", ._, .mov, .tmp1q, .memia(.src0q, .tmp0, .add_unaligned_size), ._, ._ },
.{ ._, ._, .xor, .tmp2d, .tmp2d, ._, ._ },
.{ ._, ._, .div, .memia(.src1q, .tmp0, .add_unaligned_size), ._, ._, ._ },
.{ ._, ._, .mov, .memia(.dst0q, .tmp0, .add_unaligned_size), .tmp2q, ._, ._ },
.{ ._, ._, .add, .tmp0p, .si(8), ._, ._ },
.{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
} },
}, .{
.required_features = .{ .@"64bit", null, null, null },
.src_constraints = .{
.{ .multiple_scalar_signed_int = .{ .of = .xword, .is = .xword } },
.{ .multiple_scalar_signed_int = .{ .of = .xword, .is = .xword } },
.any,
},
.patterns = &.{
.{ .src = .{ .to_mem, .to_mem, .none } },
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .param_gpr = .{ .cc = .ccc, .index = 0 } } },
.{ .type = .i64, .kind = .{ .param_gpr = .{ .cc = .ccc, .index = 1 } } },
.{ .type = .u64, .kind = .{ .param_gpr = .{ .cc = .ccc, .index = 2 } } },
.{ .type = .i64, .kind = .{ .param_gpr = .{ .cc = .ccc, .index = 3 } } },
.{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__modti3" } } },
.{ .type = .u64, .kind = .{ .ret_gpr = .{ .cc = .ccc, .index = 0 } } },
.unused,
.unused,
},
.dst_temps = .{ .mem, .unused },
.clobbers = .{ .eflags = true, .caller_preserved = .ccc },
.each = .{ .once = &.{
.{ ._, ._, .mov, .tmp0p, .sa(.src0, .sub_unaligned_size), ._, ._ },
.{ .@"0:", ._, .mov, .tmp1q, .memia(.src0q, .tmp0, .add_unaligned_size), ._, ._ },
.{ ._, ._, .mov, .tmp2q, .memiad(.src0q, .tmp0, .add_unaligned_size, 8), ._, ._ },
.{ ._, ._, .mov, .tmp3q, .memia(.src1q, .tmp0, .add_unaligned_size), ._, ._ },
.{ ._, ._, .mov, .tmp4q, .memiad(.src1q, .tmp0, .add_unaligned_size, 8), ._, ._ },
.{ ._, ._, .call, .tmp5d, ._, ._, ._ },
.{ ._, ._, .mov, .memia(.dst0q, .tmp0, .add_unaligned_size), .tmp6q, ._, ._ },
.{ ._, ._, .mov, .memiad(.dst0q, .tmp0, .add_unaligned_size, 8), .tmp3q, ._, ._ },
.{ ._, ._, .add, .tmp0p, .si(16), ._, ._ },
.{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
} },
}, .{
.required_features = .{ .@"64bit", null, null, null },
.src_constraints = .{
.{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } },
.{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } },
.any,
},
.patterns = &.{
.{ .src = .{ .to_mem, .to_mem, .none } },
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .param_gpr = .{ .cc = .ccc, .index = 0 } } },
.{ .type = .u64, .kind = .{ .param_gpr = .{ .cc = .ccc, .index = 1 } } },
.{ .type = .u64, .kind = .{ .param_gpr = .{ .cc = .ccc, .index = 2 } } },
.{ .type = .u64, .kind = .{ .param_gpr = .{ .cc = .ccc, .index = 3 } } },
.{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__umodti3" } } },
.{ .type = .u64, .kind = .{ .ret_gpr = .{ .cc = .ccc, .index = 0 } } },
.unused,
.unused,
},
.dst_temps = .{ .mem, .unused },
.clobbers = .{ .eflags = true, .caller_preserved = .ccc },
.each = .{ .once = &.{
.{ ._, ._, .mov, .tmp0p, .sa(.src0, .sub_unaligned_size), ._, ._ },
.{ .@"0:", ._, .mov, .tmp1q, .memia(.src0q, .tmp0, .add_unaligned_size), ._, ._ },
.{ ._, ._, .mov, .tmp2q, .memiad(.src0q, .tmp0, .add_unaligned_size, 8), ._, ._ },
.{ ._, ._, .mov, .tmp3q, .memia(.src1q, .tmp0, .add_unaligned_size), ._, ._ },
.{ ._, ._, .mov, .tmp4q, .memiad(.src1q, .tmp0, .add_unaligned_size, 8), ._, ._ },
.{ ._, ._, .call, .tmp5d, ._, ._, ._ },
.{ ._, ._, .mov, .memia(.dst0q, .tmp0, .add_unaligned_size), .tmp6q, ._, ._ },
.{ ._, ._, .mov, .memiad(.dst0q, .tmp0, .add_unaligned_size, 8), .tmp3q, ._, ._ },
.{ ._, ._, .add, .tmp0p, .si(16), ._, ._ },
.{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
} },
}, .{
.required_features = .{ .@"64bit", null, null, null },
.src_constraints = .{
.{ .scalar_remainder_signed_int = .{ .of = .dword, .is = .dword } },
.{ .scalar_remainder_signed_int = .{ .of = .dword, .is = .dword } },
.any,
},
.patterns = &.{
.{ .src = .{ .to_mut_mem, .to_mut_mem, .none } },
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .index = 0 } } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .index = 1 } } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .index = 2 } } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .index = 3 } } },
.{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__modei4" } } },
.unused,
.unused,
.unused,
},
.dst_temps = .{ .mem, .unused },
.clobbers = .{ .eflags = true, .caller_preserved = .ccc },
.each = .{ .once = &.{
.{ ._, ._, .mov, .tmp0p, .sa(.src0, .sub_unaligned_size), ._, ._ },
.{ .@"0:", ._, .lea, .tmp1p, .memia(.dst0, .tmp0, .add_unaligned_size), ._, ._ },
.{ ._, ._, .lea, .tmp2p, .memia(.src0, .tmp0, .add_unaligned_size), ._, ._ },
.{ ._, ._, .lea, .tmp3p, .memia(.src1, .tmp0, .add_unaligned_size), ._, ._ },
.{ ._, ._, .mov, .tmp4d, .sa(.src0, .add_8_elem_size), ._, ._ },
.{ ._, ._, .call, .tmp5d, ._, ._, ._ },
.{ ._, ._, .add, .tmp0p, .sa(.src0, .add_elem_size), ._, ._ },
.{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
} },
}, .{
.required_features = .{ .@"64bit", null, null, null },
.src_constraints = .{
.{ .scalar_remainder_unsigned_int = .{ .of = .dword, .is = .dword } },
.{ .scalar_remainder_unsigned_int = .{ .of = .dword, .is = .dword } },
.any,
},
.patterns = &.{
.{ .src = .{ .to_mut_mem, .to_mut_mem, .none } },
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .index = 0 } } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .index = 1 } } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .index = 2 } } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .index = 3 } } },
.{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__umodei4" } } },
.unused,
.unused,
.unused,
},
.dst_temps = .{ .mem, .unused },
.clobbers = .{ .eflags = true, .caller_preserved = .ccc },
.each = .{ .once = &.{
.{ ._, ._, .mov, .tmp0p, .sa(.src0, .sub_unaligned_size), ._, ._ },
.{ .@"0:", ._, .lea, .tmp1p, .memia(.dst0, .tmp0, .add_unaligned_size), ._, ._ },
.{ ._, ._, .lea, .tmp2p, .memia(.src0, .tmp0, .add_unaligned_size), ._, ._ },
.{ ._, ._, .lea, .tmp3p, .memia(.src1, .tmp0, .add_unaligned_size), ._, ._ },
.{ ._, ._, .mov, .tmp4d, .sa(.src0, .add_8_elem_size), ._, ._ },
.{ ._, ._, .call, .tmp5d, ._, ._, ._ },
.{ ._, ._, .add, .tmp0p, .sa(.src0, .add_elem_size), ._, ._ },
.{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
} },
}, .{
.required_features = .{ .sse, null, null, null },
.src_constraints = .{
.{ .scalar_float = .{ .of = .word, .is = .word } },

View file

@ -527,7 +527,7 @@ fn testIntDivision() !void {
try expect(mod(i64, -14, 12) == 10);
try expect(mod(i16, -2, 12) == 10);
try expect(mod(i16, -118, 12) == 2);
try expect(mod(i8, -2, 12) == 10); // TODO: fails in x86_64
try expect(mod(i8, -2, 12) == 10);
try expect(rem(i64, -118, 12) == -10);
try expect(rem(i32, 10, 12) == 10);

View file

@ -19079,25 +19079,33 @@ test divFloor {
// workaround https://github.com/ziglang/zig/issues/22748
// TODO: @TypeOf(@rem(lhs, rhs))
inline fn rem(comptime Type: type, lhs: Type, rhs: Type) Type {
if (@inComptime()) {
// workaround https://github.com/ziglang/zig/issues/22748
switch (@typeInfo(Type)) {
else => return if (rhs != 0) @rem(lhs, rhs) else nan(Type),
.vector => |info| {
var res: Type = undefined;
inline for (0..info.len) |i| res[i] = if (rhs[i] != 0) @rem(lhs[i], rhs[i]) else nan(Scalar(Type));
return res;
},
}
switch (@typeInfo(Scalar(Type))) {
else => @compileError(@typeName(Type)),
.int => return @rem(lhs, rhs),
.float => {
if (@inComptime()) {
// workaround https://github.com/ziglang/zig/issues/22748
switch (@typeInfo(Type)) {
else => return if (rhs != 0) @rem(lhs, rhs) else nan(Type),
.vector => |info| {
var res: Type = undefined;
inline for (0..info.len) |i| res[i] = if (rhs[i] != 0) @rem(lhs[i], rhs[i]) else nan(Scalar(Type));
return res;
},
}
}
// workaround https://github.com/ziglang/zig/issues/22748
// TODO: return @rem(lhs, rhs);
var rt_rhs = rhs;
_ = &rt_rhs;
return @rem(lhs, rt_rhs);
},
}
// workaround https://github.com/ziglang/zig/issues/22748
// TODO: return @rem(lhs, rhs);
var rt_rhs = rhs;
_ = &rt_rhs;
return @rem(lhs, rt_rhs);
}
test rem {
const test_rem = binary(rem, .{});
try test_rem.testInts();
try test_rem.testIntVectors();
try test_rem.testFloats();
try test_rem.testFloatVectors();
}

View file

@ -19,5 +19,5 @@ fn divExact(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) {
return @divExact(a, b);
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native