@@ -106,6 +106,26 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
106
106
let dest = CPlace :: for_ptr( Pointer :: new( mem_addr) , a. layout( ) ) ;
107
107
dest. write_cvalue( fx, a) ;
108
108
} ;
109
+ "llvm.x86.addcarry.64" , ( v c_in, c a, c b) {
110
+ llvm_add_sub(
111
+ fx,
112
+ BinOp :: Add ,
113
+ ret,
114
+ c_in,
115
+ a,
116
+ b
117
+ ) ;
118
+ } ;
119
+ "llvm.x86.subborrow.64" , ( v b_in, c a, c b) {
120
+ llvm_add_sub(
121
+ fx,
122
+ BinOp :: Sub ,
123
+ ret,
124
+ b_in,
125
+ a,
126
+ b
127
+ ) ;
128
+ } ;
109
129
}
110
130
111
131
if let Some ( ( _, dest) ) = destination {
@@ -121,3 +141,43 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
121
141
// llvm.x86.avx2.pshuf.b
122
142
// llvm.x86.avx2.psrli.w
123
143
// llvm.x86.sse2.psrli.w
144
+
145
+ fn llvm_add_sub < ' tcx > (
146
+ fx : & mut FunctionCx < ' _ , ' _ , ' tcx > ,
147
+ bin_op : BinOp ,
148
+ ret : CPlace < ' tcx > ,
149
+ cb_in : Value ,
150
+ a : CValue < ' tcx > ,
151
+ b : CValue < ' tcx >
152
+ ) {
153
+ assert_eq ! ( a. layout( ) . ty, fx. tcx. types. u64 , "llvm.x86.addcarry.64/llvm.x86.subborrow.64 second operand must be u64" ) ;
154
+ assert_eq ! ( b. layout( ) . ty, fx. tcx. types. u64 , "llvm.x86.addcarry.64/llvm.x86.subborrow.64 third operand must be u64" ) ;
155
+
156
+ // c + carry -> c + first intermediate carry or borrow respectively
157
+ let int0 = crate :: num:: codegen_checked_int_binop (
158
+ fx,
159
+ bin_op,
160
+ a,
161
+ b,
162
+ ) ;
163
+ let c = int0. value_field ( fx, mir:: Field :: new ( 0 ) ) ;
164
+ let cb0 = int0. value_field ( fx, mir:: Field :: new ( 1 ) ) . load_scalar ( fx) ;
165
+
166
+ // c + carry -> c + second intermediate carry or borrow respectively
167
+ let cb_in_as_u64 = fx. bcx . ins ( ) . uextend ( types:: I64 , cb_in) ;
168
+ let cb_in_as_u64 = CValue :: by_val ( cb_in_as_u64, fx. layout_of ( fx. tcx . types . u64 ) ) ;
169
+ let int1 = crate :: num:: codegen_checked_int_binop (
170
+ fx,
171
+ bin_op,
172
+ c,
173
+ cb_in_as_u64,
174
+ ) ;
175
+ let ( c, cb1) = int1. load_scalar_pair ( fx) ;
176
+
177
+ // carry0 | carry1 -> carry or borrow respectively
178
+ let cb_out = fx. bcx . ins ( ) . bor ( cb0, cb1) ;
179
+
180
+ let layout = fx. layout_of ( fx. tcx . mk_tup ( [ fx. tcx . types . u8 , fx. tcx . types . u64 ] . iter ( ) ) ) ;
181
+ let val = CValue :: by_val_pair ( cb_out, c, layout) ;
182
+ ret. write_cvalue ( fx, val) ;
183
+ }
0 commit comments