@@ -8,135 +8,37 @@ use rustc_middle::ty::subst::SubstsRef;
88pub ( crate ) fn codegen_llvm_intrinsic_call < ' tcx > (
99 fx : & mut FunctionCx < ' _ , ' _ , ' tcx > ,
1010 intrinsic : & str ,
11- _substs : SubstsRef < ' tcx > ,
11+ substs : SubstsRef < ' tcx > ,
1212 args : & [ mir:: Operand < ' tcx > ] ,
1313 ret : CPlace < ' tcx > ,
1414 target : Option < BasicBlock > ,
1515) {
16- match intrinsic {
17- "llvm.x86.sse2.pause" | "llvm.aarch64.isb" => {
18- // Spin loop hint
19- }
16+ if intrinsic. starts_with ( "llvm.aarch64" ) {
17+ return llvm_aarch64:: codegen_aarch64_llvm_intrinsic_call (
18+ fx, intrinsic, substs, args, ret, target,
19+ ) ;
20+ }
21+ if intrinsic. starts_with ( "llvm.x86" ) {
22+ return llvm_x86:: codegen_x86_llvm_intrinsic_call ( fx, intrinsic, substs, args, ret, target) ;
23+ }
2024
21- // Used by `_mm_movemask_epi8` and `_mm256_movemask_epi8`
22- "llvm.x86.sse2.pmovmskb.128" | "llvm.x86.avx2.pmovmskb" | " llvm.x86.sse2.movmsk.pd" => {
25+ match intrinsic {
26+ _ if intrinsic . starts_with ( " llvm.ctlz.v" ) => {
2327 intrinsic_args ! ( fx, args => ( a) ; intrinsic) ;
2428
25- let ( lane_count, lane_ty) = a. layout ( ) . ty . simd_size_and_type ( fx. tcx ) ;
26- let lane_ty = fx. clif_type ( lane_ty) . unwrap ( ) ;
27- assert ! ( lane_count <= 32 ) ;
28-
29- let mut res = fx. bcx . ins ( ) . iconst ( types:: I32 , 0 ) ;
30-
31- for lane in ( 0 ..lane_count) . rev ( ) {
32- let a_lane = a. value_lane ( fx, lane) . load_scalar ( fx) ;
33-
34- // cast float to int
35- let a_lane = match lane_ty {
36- types:: F32 => fx. bcx . ins ( ) . bitcast ( types:: I32 , a_lane) ,
37- types:: F64 => fx. bcx . ins ( ) . bitcast ( types:: I64 , a_lane) ,
38- _ => a_lane,
39- } ;
40-
41- // extract sign bit of an int
42- let a_lane_sign = fx. bcx . ins ( ) . ushr_imm ( a_lane, i64:: from ( lane_ty. bits ( ) - 1 ) ) ;
43-
44- // shift sign bit into result
45- let a_lane_sign = clif_intcast ( fx, a_lane_sign, types:: I32 , false ) ;
46- res = fx. bcx . ins ( ) . ishl_imm ( res, 1 ) ;
47- res = fx. bcx . ins ( ) . bor ( res, a_lane_sign) ;
48- }
49-
50- let res = CValue :: by_val ( res, fx. layout_of ( fx. tcx . types . i32 ) ) ;
51- ret. write_cvalue ( fx, res) ;
52- }
53- "llvm.x86.sse2.cmp.ps" | "llvm.x86.sse2.cmp.pd" => {
54- let ( x, y, kind) = match args {
55- [ x, y, kind] => ( x, y, kind) ,
56- _ => bug ! ( "wrong number of args for intrinsic {intrinsic}" ) ,
57- } ;
58- let x = codegen_operand ( fx, x) ;
59- let y = codegen_operand ( fx, y) ;
60- let kind = crate :: constant:: mir_operand_get_const_val ( fx, kind)
61- . expect ( "llvm.x86.sse2.cmp.* kind not const" ) ;
62-
63- let flt_cc = match kind
64- . try_to_bits ( Size :: from_bytes ( 1 ) )
65- . unwrap_or_else ( || panic ! ( "kind not scalar: {:?}" , kind) )
66- {
67- 0 => FloatCC :: Equal ,
68- 1 => FloatCC :: LessThan ,
69- 2 => FloatCC :: LessThanOrEqual ,
70- 7 => FloatCC :: Ordered ,
71- 3 => FloatCC :: Unordered ,
72- 4 => FloatCC :: NotEqual ,
73- 5 => FloatCC :: UnorderedOrGreaterThanOrEqual ,
74- 6 => FloatCC :: UnorderedOrGreaterThan ,
75- kind => unreachable ! ( "kind {:?}" , kind) ,
76- } ;
77-
78- simd_pair_for_each_lane ( fx, x, y, ret, & |fx, lane_ty, res_lane_ty, x_lane, y_lane| {
79- let res_lane = match lane_ty. kind ( ) {
80- ty:: Float ( _) => fx. bcx . ins ( ) . fcmp ( flt_cc, x_lane, y_lane) ,
81- _ => unreachable ! ( "{:?}" , lane_ty) ,
82- } ;
83- bool_to_zero_or_max_uint ( fx, res_lane_ty, res_lane)
29+ simd_for_each_lane ( fx, a, ret, & |fx, _lane_ty, _res_lane_ty, lane| {
30+ fx. bcx . ins ( ) . clz ( lane)
8431 } ) ;
8532 }
86- "llvm.x86.sse2.psrli.d" => {
87- let ( a, imm8) = match args {
88- [ a, imm8] => ( a, imm8) ,
89- _ => bug ! ( "wrong number of args for intrinsic {intrinsic}" ) ,
90- } ;
91- let a = codegen_operand ( fx, a) ;
92- let imm8 = crate :: constant:: mir_operand_get_const_val ( fx, imm8)
93- . expect ( "llvm.x86.sse2.psrli.d imm8 not const" ) ;
9433
95- simd_for_each_lane ( fx, a, ret, & |fx, _lane_ty, _res_lane_ty, lane| match imm8
96- . try_to_bits ( Size :: from_bytes ( 4 ) )
97- . unwrap_or_else ( || panic ! ( "imm8 not scalar: {:?}" , imm8) )
98- {
99- imm8 if imm8 < 32 => fx. bcx . ins ( ) . ushr_imm ( lane, i64:: from ( imm8 as u8 ) ) ,
100- _ => fx. bcx . ins ( ) . iconst ( types:: I32 , 0 ) ,
101- } ) ;
102- }
103- "llvm.x86.sse2.pslli.d" => {
104- let ( a, imm8) = match args {
105- [ a, imm8] => ( a, imm8) ,
106- _ => bug ! ( "wrong number of args for intrinsic {intrinsic}" ) ,
107- } ;
108- let a = codegen_operand ( fx, a) ;
109- let imm8 = crate :: constant:: mir_operand_get_const_val ( fx, imm8)
110- . expect ( "llvm.x86.sse2.psrli.d imm8 not const" ) ;
34+ _ if intrinsic. starts_with ( "llvm.ctpop.v" ) => {
35+ intrinsic_args ! ( fx, args => ( a) ; intrinsic) ;
11136
112- simd_for_each_lane ( fx, a, ret, & |fx, _lane_ty, _res_lane_ty, lane| match imm8
113- . try_to_bits ( Size :: from_bytes ( 4 ) )
114- . unwrap_or_else ( || panic ! ( "imm8 not scalar: {:?}" , imm8) )
115- {
116- imm8 if imm8 < 32 => fx. bcx . ins ( ) . ishl_imm ( lane, i64:: from ( imm8 as u8 ) ) ,
117- _ => fx. bcx . ins ( ) . iconst ( types:: I32 , 0 ) ,
37+ simd_for_each_lane ( fx, a, ret, & |fx, _lane_ty, _res_lane_ty, lane| {
38+ fx. bcx . ins ( ) . popcnt ( lane)
11839 } ) ;
11940 }
120- "llvm.x86.sse2.storeu.dq" => {
121- intrinsic_args ! ( fx, args => ( mem_addr, a) ; intrinsic) ;
122- let mem_addr = mem_addr. load_scalar ( fx) ;
123-
124- // FIXME correctly handle the unalignment
125- let dest = CPlace :: for_ptr ( Pointer :: new ( mem_addr) , a. layout ( ) ) ;
126- dest. write_cvalue ( fx, a) ;
127- }
128- "llvm.x86.addcarry.64" => {
129- intrinsic_args ! ( fx, args => ( c_in, a, b) ; intrinsic) ;
130- let c_in = c_in. load_scalar ( fx) ;
131-
132- llvm_add_sub ( fx, BinOp :: Add , ret, c_in, a, b) ;
133- }
134- "llvm.x86.subborrow.64" => {
135- intrinsic_args ! ( fx, args => ( b_in, a, b) ; intrinsic) ;
136- let b_in = b_in. load_scalar ( fx) ;
13741
138- llvm_add_sub ( fx, BinOp :: Sub , ret, b_in, a, b) ;
139- }
14042 _ => {
14143 fx. tcx
14244 . sess
@@ -150,47 +52,3 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
15052 let ret_block = fx. get_block ( dest) ;
15153 fx. bcx . ins ( ) . jump ( ret_block, & [ ] ) ;
15254}
153-
154- // llvm.x86.avx2.vperm2i128
155- // llvm.x86.ssse3.pshuf.b.128
156- // llvm.x86.avx2.pshuf.b
157- // llvm.x86.avx2.psrli.w
158- // llvm.x86.sse2.psrli.w
159-
160- fn llvm_add_sub < ' tcx > (
161- fx : & mut FunctionCx < ' _ , ' _ , ' tcx > ,
162- bin_op : BinOp ,
163- ret : CPlace < ' tcx > ,
164- cb_in : Value ,
165- a : CValue < ' tcx > ,
166- b : CValue < ' tcx > ,
167- ) {
168- assert_eq ! (
169- a. layout( ) . ty,
170- fx. tcx. types. u64 ,
171- "llvm.x86.addcarry.64/llvm.x86.subborrow.64 second operand must be u64"
172- ) ;
173- assert_eq ! (
174- b. layout( ) . ty,
175- fx. tcx. types. u64 ,
176- "llvm.x86.addcarry.64/llvm.x86.subborrow.64 third operand must be u64"
177- ) ;
178-
179- // c + carry -> c + first intermediate carry or borrow respectively
180- let int0 = crate :: num:: codegen_checked_int_binop ( fx, bin_op, a, b) ;
181- let c = int0. value_field ( fx, mir:: Field :: new ( 0 ) ) ;
182- let cb0 = int0. value_field ( fx, mir:: Field :: new ( 1 ) ) . load_scalar ( fx) ;
183-
184- // c + carry -> c + second intermediate carry or borrow respectively
185- let cb_in_as_u64 = fx. bcx . ins ( ) . uextend ( types:: I64 , cb_in) ;
186- let cb_in_as_u64 = CValue :: by_val ( cb_in_as_u64, fx. layout_of ( fx. tcx . types . u64 ) ) ;
187- let int1 = crate :: num:: codegen_checked_int_binop ( fx, bin_op, c, cb_in_as_u64) ;
188- let ( c, cb1) = int1. load_scalar_pair ( fx) ;
189-
190- // carry0 | carry1 -> carry or borrow respectively
191- let cb_out = fx. bcx . ins ( ) . bor ( cb0, cb1) ;
192-
193- let layout = fx. layout_of ( fx. tcx . mk_tup ( [ fx. tcx . types . u8 , fx. tcx . types . u64 ] . iter ( ) ) ) ;
194- let val = CValue :: by_val_pair ( cb_out, c, layout) ;
195- ret. write_cvalue ( fx, val) ;
196- }
0 commit comments