3232 }
3333}
3434
35+ macro_rules! unsafe_base_op {
36+ ( $( impl <const LANES : usize > $op: ident for Simd <$scalar: ty, LANES > {
37+ fn $call: ident( self , rhs: Self ) -> Self :: Output {
38+ unsafe { $simd_call: ident }
39+ }
40+ } ) * ) => {
41+ $( impl <const LANES : usize > $op for Simd <$scalar, LANES >
42+ where
43+ $scalar: SimdElement ,
44+ LaneCount <LANES >: SupportedLaneCount ,
45+ {
46+ type Output = Self ;
47+
48+ #[ inline]
49+ #[ must_use = "operator returns a new vector without mutating the inputs" ]
50+ fn $call( self , rhs: Self ) -> Self :: Output {
51+ unsafe { $crate:: intrinsics:: $simd_call( self , rhs) }
52+ }
53+ }
54+ ) *
55+ }
56+ }
57+
3558/// SAFETY: This macro should not be used for anything except Shl or Shr, and passed the appropriate shift intrinsic.
3659/// It handles performing a bitand in addition to calling the shift operator, so that the result
3760/// is well-defined: LLVM can return a poison value if you shl, lshr, or ashr if rhs >= <Int>::BITS
@@ -41,13 +64,13 @@ where
4164///
4265// FIXME: Consider implementing this in cg_llvm instead?
4366// cg_clif defaults to this, and scalar MIR shifts also default to wrapping
44- macro_rules! wrap_bitshift_inner {
45- ( impl <const LANES : usize > $op: ident for Simd <$int: ty, LANES > {
67+ macro_rules! wrap_bitshift {
68+ ( $ ( impl <const LANES : usize > $op: ident for Simd <$int: ty, LANES > {
4669 fn $call: ident( self , rhs: Self ) -> Self :: Output {
4770 unsafe { $simd_call: ident }
4871 }
49- } ) => {
50- impl <const LANES : usize > $op for Simd <$int, LANES >
72+ } ) * ) => {
73+ $ ( impl <const LANES : usize > $op for Simd <$int, LANES >
5174 where
5275 $int: SimdElement ,
5376 LaneCount <LANES >: SupportedLaneCount ,
@@ -61,24 +84,45 @@ macro_rules! wrap_bitshift_inner {
6184 $crate:: intrinsics:: $simd_call( self , rhs. bitand( Simd :: splat( <$int>:: BITS as $int - 1 ) ) )
6285 }
6386 }
64- }
87+ } ) *
6588 } ;
6689}
6790
68- macro_rules! wrap_bitshifts {
69- ( $( impl <const LANES : usize > ShiftOps for Simd <$int: ty, LANES > {
91+ macro_rules! bitops {
92+ ( $( impl <const LANES : usize > BitOps for Simd <$int: ty, LANES > {
93+ fn bitand( self , rhs: Self ) -> Self :: Output ;
94+ fn bitor( self , rhs: Self ) -> Self :: Output ;
95+ fn bitxor( self , rhs: Self ) -> Self :: Output ;
7096 fn shl( self , rhs: Self ) -> Self :: Output ;
7197 fn shr( self , rhs: Self ) -> Self :: Output ;
7298 } ) * ) => {
7399 $(
74- wrap_bitshift_inner! {
100+ unsafe_base_op!{
101+ impl <const LANES : usize > BitAnd for Simd <$int, LANES > {
102+ fn bitand( self , rhs: Self ) -> Self :: Output {
103+ unsafe { simd_and }
104+ }
105+ }
106+
107+ impl <const LANES : usize > BitOr for Simd <$int, LANES > {
108+ fn bitor( self , rhs: Self ) -> Self :: Output {
109+ unsafe { simd_or }
110+ }
111+ }
112+
113+ impl <const LANES : usize > BitXor for Simd <$int, LANES > {
114+ fn bitxor( self , rhs: Self ) -> Self :: Output {
115+ unsafe { simd_xor }
116+ }
117+ }
118+ }
119+ wrap_bitshift! {
75120 impl <const LANES : usize > Shl for Simd <$int, LANES > {
76121 fn shl( self , rhs: Self ) -> Self :: Output {
77122 unsafe { simd_shl }
78123 }
79124 }
80- }
81- wrap_bitshift_inner! {
125+
82126 impl <const LANES : usize > Shr for Simd <$int, LANES > {
83127 fn shr( self , rhs: Self ) -> Self :: Output {
84128 // This automatically monomorphizes to lshr or ashr, depending,
@@ -91,53 +135,86 @@ macro_rules! wrap_bitshifts {
91135 } ;
92136}
93137
94- wrap_bitshifts ! {
95- impl <const LANES : usize > ShiftOps for Simd <i8 , LANES > {
138+ // Integers can always accept bitand, bitor, and bitxor.
139+ // The only question is how to handle shifts >= <Int>::BITS?
140+ // Our current solution uses wrapping logic.
141+ bitops ! {
142+ impl <const LANES : usize > BitOps for Simd <i8 , LANES > {
143+ fn bitand( self , rhs: Self ) -> Self :: Output ;
144+ fn bitor( self , rhs: Self ) -> Self :: Output ;
145+ fn bitxor( self , rhs: Self ) -> Self :: Output ;
96146 fn shl( self , rhs: Self ) -> Self :: Output ;
97147 fn shr( self , rhs: Self ) -> Self :: Output ;
98148 }
99149
100- impl <const LANES : usize > ShiftOps for Simd <i16 , LANES > {
150+ impl <const LANES : usize > BitOps for Simd <i16 , LANES > {
151+ fn bitand( self , rhs: Self ) -> Self :: Output ;
152+ fn bitor( self , rhs: Self ) -> Self :: Output ;
153+ fn bitxor( self , rhs: Self ) -> Self :: Output ;
101154 fn shl( self , rhs: Self ) -> Self :: Output ;
102155 fn shr( self , rhs: Self ) -> Self :: Output ;
103156 }
104157
105- impl <const LANES : usize > ShiftOps for Simd <i32 , LANES > {
158+ impl <const LANES : usize > BitOps for Simd <i32 , LANES > {
159+ fn bitand( self , rhs: Self ) -> Self :: Output ;
160+ fn bitor( self , rhs: Self ) -> Self :: Output ;
161+ fn bitxor( self , rhs: Self ) -> Self :: Output ;
106162 fn shl( self , rhs: Self ) -> Self :: Output ;
107163 fn shr( self , rhs: Self ) -> Self :: Output ;
108164 }
109165
110- impl <const LANES : usize > ShiftOps for Simd <i64 , LANES > {
166+ impl <const LANES : usize > BitOps for Simd <i64 , LANES > {
167+ fn bitand( self , rhs: Self ) -> Self :: Output ;
168+ fn bitor( self , rhs: Self ) -> Self :: Output ;
169+ fn bitxor( self , rhs: Self ) -> Self :: Output ;
111170 fn shl( self , rhs: Self ) -> Self :: Output ;
112171 fn shr( self , rhs: Self ) -> Self :: Output ;
113172 }
114173
115- impl <const LANES : usize > ShiftOps for Simd <isize , LANES > {
174+ impl <const LANES : usize > BitOps for Simd <isize , LANES > {
175+ fn bitand( self , rhs: Self ) -> Self :: Output ;
176+ fn bitor( self , rhs: Self ) -> Self :: Output ;
177+ fn bitxor( self , rhs: Self ) -> Self :: Output ;
116178 fn shl( self , rhs: Self ) -> Self :: Output ;
117179 fn shr( self , rhs: Self ) -> Self :: Output ;
118180 }
119181
120- impl <const LANES : usize > ShiftOps for Simd <u8 , LANES > {
182+ impl <const LANES : usize > BitOps for Simd <u8 , LANES > {
183+ fn bitand( self , rhs: Self ) -> Self :: Output ;
184+ fn bitor( self , rhs: Self ) -> Self :: Output ;
185+ fn bitxor( self , rhs: Self ) -> Self :: Output ;
121186 fn shl( self , rhs: Self ) -> Self :: Output ;
122187 fn shr( self , rhs: Self ) -> Self :: Output ;
123188 }
124189
125- impl <const LANES : usize > ShiftOps for Simd <u16 , LANES > {
190+ impl <const LANES : usize > BitOps for Simd <u16 , LANES > {
191+ fn bitand( self , rhs: Self ) -> Self :: Output ;
192+ fn bitor( self , rhs: Self ) -> Self :: Output ;
193+ fn bitxor( self , rhs: Self ) -> Self :: Output ;
126194 fn shl( self , rhs: Self ) -> Self :: Output ;
127195 fn shr( self , rhs: Self ) -> Self :: Output ;
128196 }
129197
130- impl <const LANES : usize > ShiftOps for Simd <u32 , LANES > {
198+ impl <const LANES : usize > BitOps for Simd <u32 , LANES > {
199+ fn bitand( self , rhs: Self ) -> Self :: Output ;
200+ fn bitor( self , rhs: Self ) -> Self :: Output ;
201+ fn bitxor( self , rhs: Self ) -> Self :: Output ;
131202 fn shl( self , rhs: Self ) -> Self :: Output ;
132203 fn shr( self , rhs: Self ) -> Self :: Output ;
133204 }
134205
135- impl <const LANES : usize > ShiftOps for Simd <u64 , LANES > {
206+ impl <const LANES : usize > BitOps for Simd <u64 , LANES > {
207+ fn bitand( self , rhs: Self ) -> Self :: Output ;
208+ fn bitor( self , rhs: Self ) -> Self :: Output ;
209+ fn bitxor( self , rhs: Self ) -> Self :: Output ;
136210 fn shl( self , rhs: Self ) -> Self :: Output ;
137211 fn shr( self , rhs: Self ) -> Self :: Output ;
138212 }
139213
140- impl <const LANES : usize > ShiftOps for Simd <usize , LANES > {
214+ impl <const LANES : usize > BitOps for Simd <usize , LANES > {
215+ fn bitand( self , rhs: Self ) -> Self :: Output ;
216+ fn bitor( self , rhs: Self ) -> Self :: Output ;
217+ fn bitxor( self , rhs: Self ) -> Self :: Output ;
141218 fn shl( self , rhs: Self ) -> Self :: Output ;
142219 fn shr( self , rhs: Self ) -> Self :: Output ;
143220 }
@@ -186,15 +263,6 @@ macro_rules! impl_op {
186263 { impl Rem for $scalar: ty } => {
187264 impl_op! { @binary $scalar, Rem :: rem, simd_rem }
188265 } ;
189- { impl BitAnd for $scalar: ty } => {
190- impl_op! { @binary $scalar, BitAnd :: bitand, simd_and }
191- } ;
192- { impl BitOr for $scalar: ty } => {
193- impl_op! { @binary $scalar, BitOr :: bitor, simd_or }
194- } ;
195- { impl BitXor for $scalar: ty } => {
196- impl_op! { @binary $scalar, BitXor :: bitxor, simd_xor }
197- } ;
198266
199267 // generic binary op with assignment when output is `Self`
200268 { @binary $scalar: ty, $trait: ident :: $trait_fn: ident, $intrinsic: ident } => {
@@ -236,9 +304,6 @@ macro_rules! impl_unsigned_int_ops {
236304 impl_op! { impl Add for $scalar }
237305 impl_op! { impl Sub for $scalar }
238306 impl_op! { impl Mul for $scalar }
239- impl_op! { impl BitAnd for $scalar }
240- impl_op! { impl BitOr for $scalar }
241- impl_op! { impl BitXor for $scalar }
242307
243308 // Integers panic on divide by 0
244309 impl_ref_ops! {
0 commit comments