@@ -40,13 +40,33 @@ pub(crate) fn bin_op_to_intcc(bin_op: BinOp, signed: bool) -> Option<IntCC> {
40
40
})
41
41
}
42
42
43
+ fn codegen_three_way_compare<'tcx>(
44
+ fx: &mut FunctionCx<'_, '_, 'tcx>,
45
+ signed: bool,
46
+ lhs: Value,
47
+ rhs: Value,
48
+ ) -> CValue<'tcx> {
49
+ // This emits `(lhs > rhs) - (lhs < rhs)`, which is cranelift's preferred form per
50
+ // <https://github.com/bytecodealliance/wasmtime/blob/8052bb9e3b792503b225f2a5b2ba3bc023bff462/cranelift/codegen/src/prelude_opt.isle#L41-L47>
51
+ let gt_cc = crate::num::bin_op_to_intcc(BinOp::Gt, signed).unwrap();
52
+ let lt_cc = crate::num::bin_op_to_intcc(BinOp::Lt, signed).unwrap();
53
+ let gt = fx.bcx.ins().icmp(gt_cc, lhs, rhs);
54
+ let lt = fx.bcx.ins().icmp(lt_cc, lhs, rhs);
55
+ let val = fx.bcx.ins().isub(gt, lt);
56
+ CValue::by_val(val, fx.layout_of(fx.tcx.ty_ordering_enum(Some(fx.mir.span))))
57
+ }
58
+
43
59
fn codegen_compare_bin_op<'tcx>(
44
60
fx: &mut FunctionCx<'_, '_, 'tcx>,
45
61
bin_op: BinOp,
46
62
signed: bool,
47
63
lhs: Value,
48
64
rhs: Value,
49
65
) -> CValue<'tcx> {
66
+ if bin_op == BinOp::Cmp {
67
+ return codegen_three_way_compare(fx, signed, lhs, rhs);
68
+ }
69
+
50
70
let intcc = crate::num::bin_op_to_intcc(bin_op, signed).unwrap();
51
71
let val = fx.bcx.ins().icmp(intcc, lhs, rhs);
52
72
CValue::by_val(val, fx.layout_of(fx.tcx.types.bool))
@@ -59,7 +79,7 @@ pub(crate) fn codegen_binop<'tcx>(
59
79
in_rhs: CValue<'tcx>,
60
80
) -> CValue<'tcx> {
61
81
match bin_op {
62
- BinOp::Eq | BinOp::Lt | BinOp::Le | BinOp::Ne | BinOp::Ge | BinOp::Gt => {
82
+ BinOp::Eq | BinOp::Lt | BinOp::Le | BinOp::Ne | BinOp::Ge | BinOp::Gt | BinOp::Cmp => {
63
83
match in_lhs.layout().ty.kind() {
64
84
ty::Bool | ty::Uint(_) | ty::Int(_) | ty::Char => {
65
85
let signed = type_sign(in_lhs.layout().ty);
@@ -160,7 +180,7 @@ pub(crate) fn codegen_int_binop<'tcx>(
160
180
}
161
181
BinOp::Offset => unreachable!("Offset is not an integer operation"),
162
182
// Compare binops handles by `codegen_binop`.
163
- BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge => {
183
+ BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge | BinOp::Cmp => {
164
184
unreachable!("{:?}({:?}, {:?})", bin_op, in_lhs.layout().ty, in_rhs.layout().ty);
165
185
}
166
186
};
0 commit comments