@@ -13,23 +13,20 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
13
13
ret : CPlace < ' tcx > ,
14
14
target : Option < BasicBlock > ,
15
15
) {
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 {
23
17
// 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
+
25
21
let ( lane_count, lane_ty) = a. layout ( ) . ty . simd_size_and_type ( fx. tcx ) ;
26
22
let lane_ty = fx. clif_type ( lane_ty) . unwrap ( ) ;
27
23
assert ! ( lane_count <= 32 ) ;
28
24
29
25
let mut res = fx. bcx . ins ( ) . iconst ( types:: I32 , 0 ) ;
30
26
31
27
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) ;
33
30
34
31
// cast float to int
35
32
let a_lane = match lane_ty {
@@ -49,26 +46,29 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
49
46
50
47
let res = CValue :: by_val ( res, fx. layout_of ( fx. tcx . types . i32 ) ) ;
51
48
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
+ {
56
64
0 => FloatCC :: Equal ,
57
65
1 => FloatCC :: LessThan ,
58
66
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 ,
65
69
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 ,
72
72
kind => unreachable ! ( "kind {:?}" , kind) ,
73
73
} ;
74
74
@@ -79,50 +79,67 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
79
79
} ;
80
80
bool_to_zero_or_max_uint ( fx, res_lane_ty, res_lane)
81
81
} ) ;
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 ) ,
90
98
} ) ;
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 ) ,
99
115
} ) ;
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
+
102
121
// FIXME correctly handle the unalignment
103
122
let dest = CPlace :: for_ptr ( Pointer :: new ( mem_addr) , a. layout ( ) ) ;
104
123
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
+ }
126
143
}
127
144
128
145
let dest = target. expect ( "all llvm intrinsics used by stdlib should return" ) ;
0 commit comments