5
5
using System . Numerics ;
6
6
using System . Runtime . CompilerServices ;
7
7
using System . Runtime . InteropServices ;
8
+ using static SixLabors . ImageSharp . SimdUtils ;
8
9
9
10
// The JIT can detect and optimize rotation idioms ROTL (Rotate Left)
10
11
// and ROTR (Rotate Right) emitting efficient CPU instructions:
@@ -18,9 +19,12 @@ namespace SixLabors.ImageSharp;
18
19
internal interface IComponentShuffle
19
20
{
20
21
/// <summary>
21
- /// Gets the shuffle control.
22
+ /// Shuffles then slices 8-bit integers within 128-bit lanes in <paramref name="source"/>
23
+ /// using the control and store the results in <paramref name="dest"/>.
22
24
/// </summary>
23
- byte Control { get ; }
25
+ /// <param name="source">The source span of bytes.</param>
26
+ /// <param name="dest">The destination span of bytes.</param>
27
+ void ShuffleReduce ( ref ReadOnlySpan < byte > source , ref Span < byte > dest ) ;
24
28
25
29
/// <summary>
26
30
/// Shuffle 8-bit integers within 128-bit lanes in <paramref name="source"/>
@@ -42,37 +46,25 @@ internal interface IShuffle4 : IComponentShuffle
42
46
43
47
internal readonly struct DefaultShuffle4 : IShuffle4
44
48
{
45
- private readonly byte p3 ;
46
- private readonly byte p2 ;
47
- private readonly byte p1 ;
48
- private readonly byte p0 ;
49
-
50
- public DefaultShuffle4 ( byte p3 , byte p2 , byte p1 , byte p0 )
49
+ public DefaultShuffle4 ( byte control )
51
50
{
52
- DebugGuard . MustBeBetweenOrEqualTo < byte > ( p3 , 0 , 3 , nameof ( p3 ) ) ;
53
- DebugGuard . MustBeBetweenOrEqualTo < byte > ( p2 , 0 , 3 , nameof ( p2 ) ) ;
54
- DebugGuard . MustBeBetweenOrEqualTo < byte > ( p1 , 0 , 3 , nameof ( p1 ) ) ;
55
- DebugGuard . MustBeBetweenOrEqualTo < byte > ( p0 , 0 , 3 , nameof ( p0 ) ) ;
56
-
57
- this . p3 = p3 ;
58
- this . p2 = p2 ;
59
- this . p1 = p1 ;
60
- this . p0 = p0 ;
61
- this . Control = SimdUtils . Shuffle . MmShuffle ( p3 , p2 , p1 , p0 ) ;
51
+ DebugGuard . MustBeBetweenOrEqualTo < byte > ( control , 0 , 3 , nameof ( control ) ) ;
52
+ this . Control = control ;
62
53
}
63
54
64
55
public byte Control { get ; }
65
56
57
+ [ MethodImpl ( InliningOptions . ShortMethod ) ]
58
+ public void ShuffleReduce ( ref ReadOnlySpan < byte > source , ref Span < byte > dest )
59
+ => HwIntrinsics . Shuffle4Reduce ( ref source , ref dest , this . Control ) ;
60
+
66
61
[ MethodImpl ( InliningOptions . ShortMethod ) ]
67
62
public void RunFallbackShuffle ( ReadOnlySpan < byte > source , Span < byte > dest )
68
63
{
69
64
ref byte sBase = ref MemoryMarshal . GetReference ( source ) ;
70
65
ref byte dBase = ref MemoryMarshal . GetReference ( dest ) ;
71
66
72
- int p3 = this . p3 ;
73
- int p2 = this . p2 ;
74
- int p1 = this . p1 ;
75
- int p0 = this . p0 ;
67
+ Shuffle . InverseMMShuffle ( this . Control , out int p3 , out int p2 , out int p1 , out int p0 ) ;
76
68
77
69
for ( int i = 0 ; i < source . Length ; i += 4 )
78
70
{
@@ -86,11 +78,9 @@ public void RunFallbackShuffle(ReadOnlySpan<byte> source, Span<byte> dest)
86
78
87
79
internal readonly struct WXYZShuffle4 : IShuffle4
88
80
{
89
- public byte Control
90
- {
91
- [ MethodImpl ( InliningOptions . ShortMethod ) ]
92
- get => SimdUtils . Shuffle . MmShuffle ( 2 , 1 , 0 , 3 ) ;
93
- }
81
+ [ MethodImpl ( InliningOptions . ShortMethod ) ]
82
+ public void ShuffleReduce ( ref ReadOnlySpan < byte > source , ref Span < byte > dest )
83
+ => HwIntrinsics . Shuffle4Reduce ( ref source , ref dest , Shuffle . MMShuffle2103 ) ;
94
84
95
85
[ MethodImpl ( InliningOptions . ShortMethod ) ]
96
86
public void RunFallbackShuffle ( ReadOnlySpan < byte > source , Span < byte > dest )
@@ -112,11 +102,9 @@ public void RunFallbackShuffle(ReadOnlySpan<byte> source, Span<byte> dest)
112
102
113
103
internal readonly struct WZYXShuffle4 : IShuffle4
114
104
{
115
- public byte Control
116
- {
117
- [ MethodImpl ( InliningOptions . ShortMethod ) ]
118
- get => SimdUtils . Shuffle . MmShuffle ( 0 , 1 , 2 , 3 ) ;
119
- }
105
+ [ MethodImpl ( InliningOptions . ShortMethod ) ]
106
+ public void ShuffleReduce ( ref ReadOnlySpan < byte > source , ref Span < byte > dest )
107
+ => HwIntrinsics . Shuffle4Reduce ( ref source , ref dest , Shuffle . MMShuffle0123 ) ;
120
108
121
109
[ MethodImpl ( InliningOptions . ShortMethod ) ]
122
110
public void RunFallbackShuffle ( ReadOnlySpan < byte > source , Span < byte > dest )
@@ -138,11 +126,9 @@ public void RunFallbackShuffle(ReadOnlySpan<byte> source, Span<byte> dest)
138
126
139
127
internal readonly struct YZWXShuffle4 : IShuffle4
140
128
{
141
- public byte Control
142
- {
143
- [ MethodImpl ( InliningOptions . ShortMethod ) ]
144
- get => SimdUtils . Shuffle . MmShuffle ( 0 , 3 , 2 , 1 ) ;
145
- }
129
+ [ MethodImpl ( InliningOptions . ShortMethod ) ]
130
+ public void ShuffleReduce ( ref ReadOnlySpan < byte > source , ref Span < byte > dest )
131
+ => HwIntrinsics . Shuffle4Reduce ( ref source , ref dest , Shuffle . MMShuffle0321 ) ;
146
132
147
133
[ MethodImpl ( InliningOptions . ShortMethod ) ]
148
134
public void RunFallbackShuffle ( ReadOnlySpan < byte > source , Span < byte > dest )
@@ -164,11 +150,9 @@ public void RunFallbackShuffle(ReadOnlySpan<byte> source, Span<byte> dest)
164
150
165
151
internal readonly struct ZYXWShuffle4 : IShuffle4
166
152
{
167
- public byte Control
168
- {
169
- [ MethodImpl ( InliningOptions . ShortMethod ) ]
170
- get => SimdUtils . Shuffle . MmShuffle ( 3 , 0 , 1 , 2 ) ;
171
- }
153
+ [ MethodImpl ( InliningOptions . ShortMethod ) ]
154
+ public void ShuffleReduce ( ref ReadOnlySpan < byte > source , ref Span < byte > dest )
155
+ => HwIntrinsics . Shuffle4Reduce ( ref source , ref dest , Shuffle . MMShuffle3012 ) ;
172
156
173
157
[ MethodImpl ( InliningOptions . ShortMethod ) ]
174
158
public void RunFallbackShuffle ( ReadOnlySpan < byte > source , Span < byte > dest )
@@ -197,11 +181,9 @@ public void RunFallbackShuffle(ReadOnlySpan<byte> source, Span<byte> dest)
197
181
198
182
internal readonly struct XWZYShuffle4 : IShuffle4
199
183
{
200
- public byte Control
201
- {
202
- [ MethodImpl ( InliningOptions . ShortMethod ) ]
203
- get => SimdUtils . Shuffle . MmShuffle ( 1 , 2 , 3 , 0 ) ;
204
- }
184
+ [ MethodImpl ( InliningOptions . ShortMethod ) ]
185
+ public void ShuffleReduce ( ref ReadOnlySpan < byte > source , ref Span < byte > dest )
186
+ => HwIntrinsics . Shuffle4Reduce ( ref source , ref dest , Shuffle . MMShuffle1230 ) ;
205
187
206
188
[ MethodImpl ( InliningOptions . ShortMethod ) ]
207
189
public void RunFallbackShuffle ( ReadOnlySpan < byte > source , Span < byte > dest )
0 commit comments