@@ -13,23 +13,20 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
1313 ret : CPlace < ' tcx > ,
1414 target : Option < BasicBlock > ,
1515) {
16- intrinsic_match ! {
17- fx, intrinsic, args,
18- _ => {
19- fx. tcx. sess. warn( & format!( "unsupported llvm intrinsic {}; replacing with trap" , intrinsic) ) ;
20- crate :: trap:: trap_unimplemented( fx, intrinsic) ;
21- } ;
22-
16+ match intrinsic {
2317 // Used by `_mm_movemask_epi8` and `_mm256_movemask_epi8`
24- "llvm.x86.sse2.pmovmskb.128" | "llvm.x86.avx2.pmovmskb" | "llvm.x86.sse2.movmsk.pd" , ( c a) {
18+ "llvm.x86.sse2.pmovmskb.128" | "llvm.x86.avx2.pmovmskb" | "llvm.x86.sse2.movmsk.pd" => {
19+ intrinsic_args ! ( fx, args => ( a) ; intrinsic) ;
20+
2521 let ( lane_count, lane_ty) = a. layout ( ) . ty . simd_size_and_type ( fx. tcx ) ;
2622 let lane_ty = fx. clif_type ( lane_ty) . unwrap ( ) ;
2723 assert ! ( lane_count <= 32 ) ;
2824
2925 let mut res = fx. bcx . ins ( ) . iconst ( types:: I32 , 0 ) ;
3026
3127 for lane in ( 0 ..lane_count) . rev ( ) {
32- let a_lane = a. value_field( fx, mir:: Field :: new( lane. try_into( ) . unwrap( ) ) ) . load_scalar( fx) ;
28+ let a_lane =
29+ a. value_field ( fx, mir:: Field :: new ( lane. try_into ( ) . unwrap ( ) ) ) . load_scalar ( fx) ;
3330
3431 // cast float to int
3532 let a_lane = match lane_ty {
@@ -49,26 +46,29 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
4946
5047 let res = CValue :: by_val ( res, fx. layout_of ( fx. tcx . types . i32 ) ) ;
5148 ret. write_cvalue ( fx, res) ;
52- } ;
53- "llvm.x86.sse2.cmp.ps" | "llvm.x86.sse2.cmp.pd" , ( c x, c y, o kind) {
54- let kind = crate :: constant:: mir_operand_get_const_val( fx, kind) . expect( "llvm.x86.sse2.cmp.* kind not const" ) ;
55- let flt_cc = match kind. try_to_bits( Size :: from_bytes( 1 ) ) . unwrap_or_else( || panic!( "kind not scalar: {:?}" , kind) ) {
49+ }
50+ "llvm.x86.sse2.cmp.ps" | "llvm.x86.sse2.cmp.pd" => {
51+ let ( x, y, kind) = match args {
52+ [ x, y, kind] => ( x, y, kind) ,
53+ _ => bug ! ( "wrong number of args for intrinsic {intrinsic}" ) ,
54+ } ;
55+ let x = codegen_operand ( fx, x) ;
56+ let y = codegen_operand ( fx, y) ;
57+ let kind = crate :: constant:: mir_operand_get_const_val ( fx, kind)
58+ . expect ( "llvm.x86.sse2.cmp.* kind not const" ) ;
59+
60+ let flt_cc = match kind
61+ . try_to_bits ( Size :: from_bytes ( 1 ) )
62+ . unwrap_or_else ( || panic ! ( "kind not scalar: {:?}" , kind) )
63+ {
5664 0 => FloatCC :: Equal ,
5765 1 => FloatCC :: LessThan ,
5866 2 => FloatCC :: LessThanOrEqual ,
59- 7 => {
60- unimplemented!( "Compares corresponding elements in `a` and `b` to see if neither is `NaN`." ) ;
61- }
62- 3 => {
63- unimplemented!( "Compares corresponding elements in `a` and `b` to see if either is `NaN`." ) ;
64- }
67+ 7 => FloatCC :: Ordered ,
68+ 3 => FloatCC :: Unordered ,
6569 4 => FloatCC :: NotEqual ,
66- 5 => {
67- unimplemented!( "not less than" ) ;
68- }
69- 6 => {
70- unimplemented!( "not less than or equal" ) ;
71- }
70+ 5 => FloatCC :: UnorderedOrGreaterThanOrEqual ,
71+ 6 => FloatCC :: UnorderedOrGreaterThan ,
7272 kind => unreachable ! ( "kind {:?}" , kind) ,
7373 } ;
7474
@@ -79,50 +79,67 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
7979 } ;
8080 bool_to_zero_or_max_uint ( fx, res_lane_ty, res_lane)
8181 } ) ;
82- } ;
83- "llvm.x86.sse2.psrli.d" , ( c a, o imm8) {
84- let imm8 = crate :: constant:: mir_operand_get_const_val( fx, imm8) . expect( "llvm.x86.sse2.psrli.d imm8 not const" ) ;
85- simd_for_each_lane( fx, a, ret, & |fx, _lane_ty, _res_lane_ty, lane| {
86- match imm8. try_to_bits( Size :: from_bytes( 4 ) ) . unwrap_or_else( || panic!( "imm8 not scalar: {:?}" , imm8) ) {
87- imm8 if imm8 < 32 => fx. bcx. ins( ) . ushr_imm( lane, i64 :: from( imm8 as u8 ) ) ,
88- _ => fx. bcx. ins( ) . iconst( types:: I32 , 0 ) ,
89- }
82+ }
83+ "llvm.x86.sse2.psrli.d" => {
84+ let ( a, imm8) = match args {
85+ [ a, imm8] => ( a, imm8) ,
86+ _ => bug ! ( "wrong number of args for intrinsic {intrinsic}" ) ,
87+ } ;
88+ let a = codegen_operand ( fx, a) ;
89+ let imm8 = crate :: constant:: mir_operand_get_const_val ( fx, imm8)
90+ . expect ( "llvm.x86.sse2.psrli.d imm8 not const" ) ;
91+
92+ simd_for_each_lane ( fx, a, ret, & |fx, _lane_ty, _res_lane_ty, lane| match imm8
93+ . try_to_bits ( Size :: from_bytes ( 4 ) )
94+ . unwrap_or_else ( || panic ! ( "imm8 not scalar: {:?}" , imm8) )
95+ {
96+ imm8 if imm8 < 32 => fx. bcx . ins ( ) . ushr_imm ( lane, i64:: from ( imm8 as u8 ) ) ,
97+ _ => fx. bcx . ins ( ) . iconst ( types:: I32 , 0 ) ,
9098 } ) ;
91- } ;
92- "llvm.x86.sse2.pslli.d" , ( c a, o imm8) {
93- let imm8 = crate :: constant:: mir_operand_get_const_val( fx, imm8) . expect( "llvm.x86.sse2.psrli.d imm8 not const" ) ;
94- simd_for_each_lane( fx, a, ret, & |fx, _lane_ty, _res_lane_ty, lane| {
95- match imm8. try_to_bits( Size :: from_bytes( 4 ) ) . unwrap_or_else( || panic!( "imm8 not scalar: {:?}" , imm8) ) {
96- imm8 if imm8 < 32 => fx. bcx. ins( ) . ishl_imm( lane, i64 :: from( imm8 as u8 ) ) ,
97- _ => fx. bcx. ins( ) . iconst( types:: I32 , 0 ) ,
98- }
99+ }
100+ "llvm.x86.sse2.pslli.d" => {
101+ let ( a, imm8) = match args {
102+ [ a, imm8] => ( a, imm8) ,
103+ _ => bug ! ( "wrong number of args for intrinsic {intrinsic}" ) ,
104+ } ;
105+ let a = codegen_operand ( fx, a) ;
106+ let imm8 = crate :: constant:: mir_operand_get_const_val ( fx, imm8)
107+ . expect ( "llvm.x86.sse2.psrli.d imm8 not const" ) ;
108+
109+ simd_for_each_lane ( fx, a, ret, & |fx, _lane_ty, _res_lane_ty, lane| match imm8
110+ . try_to_bits ( Size :: from_bytes ( 4 ) )
111+ . unwrap_or_else ( || panic ! ( "imm8 not scalar: {:?}" , imm8) )
112+ {
113+ imm8 if imm8 < 32 => fx. bcx . ins ( ) . ishl_imm ( lane, i64:: from ( imm8 as u8 ) ) ,
114+ _ => fx. bcx . ins ( ) . iconst ( types:: I32 , 0 ) ,
99115 } ) ;
100- } ;
101- "llvm.x86.sse2.storeu.dq" , ( v mem_addr, c a) {
116+ }
117+ "llvm.x86.sse2.storeu.dq" => {
118+ intrinsic_args ! ( fx, args => ( mem_addr, a) ; intrinsic) ;
119+ let mem_addr = mem_addr. load_scalar ( fx) ;
120+
102121 // FIXME correctly handle the unalignment
103122 let dest = CPlace :: for_ptr ( Pointer :: new ( mem_addr) , a. layout ( ) ) ;
104123 dest. write_cvalue ( fx, a) ;
105- } ;
106- "llvm.x86.addcarry.64" , ( v c_in, c a, c b) {
107- llvm_add_sub(
108- fx,
109- BinOp :: Add ,
110- ret,
111- c_in,
112- a,
113- b
114- ) ;
115- } ;
116- "llvm.x86.subborrow.64" , ( v b_in, c a, c b) {
117- llvm_add_sub(
118- fx,
119- BinOp :: Sub ,
120- ret,
121- b_in,
122- a,
123- b
124- ) ;
125- } ;
124+ }
125+ "llvm.x86.addcarry.64" => {
126+ intrinsic_args ! ( fx, args => ( c_in, a, b) ; intrinsic) ;
127+ let c_in = c_in. load_scalar ( fx) ;
128+
129+ llvm_add_sub ( fx, BinOp :: Add , ret, c_in, a, b) ;
130+ }
131+ "llvm.x86.subborrow.64" => {
132+ intrinsic_args ! ( fx, args => ( b_in, a, b) ; intrinsic) ;
133+ let b_in = b_in. load_scalar ( fx) ;
134+
135+ llvm_add_sub ( fx, BinOp :: Sub , ret, b_in, a, b) ;
136+ }
137+ _ => {
138+ fx. tcx
139+ . sess
140+ . warn ( & format ! ( "unsupported llvm intrinsic {}; replacing with trap" , intrinsic) ) ;
141+ crate :: trap:: trap_unimplemented ( fx, intrinsic) ;
142+ }
126143 }
127144
128145 let dest = target. expect ( "all llvm intrinsics used by stdlib should return" ) ;
0 commit comments