@@ -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