diff options
| author | Sebastiano Tronto <sebastiano@tronto.net> | 2025-04-01 14:01:49 +0200 |
|---|---|---|
| committer | Sebastiano Tronto <sebastiano@tronto.net> | 2025-04-01 14:01:49 +0200 |
| commit | 73a99f18e7940f424287250f780a18d861aef231 (patch) | |
| tree | f3a4d7e36fff294fa910d53819b561245ad8fe1e | |
| parent | b0053277e385bee23336d1fe6b69a12f49f9172f (diff) | |
| download | nissy-core-73a99f18e7940f424287250f780a18d861aef231.tar.gz nissy-core-73a99f18e7940f424287250f780a18d861aef231.zip | |
Some simplification to AVX2 code
Some simplification after discussion with Arhan Chaudhary (inspired by vcube).
Performance looks unchanged, but at least the code is cleaner.
| -rw-r--r-- | src/arch/avx2.h | 88 | ||||
| -rw-r--r-- | src/core/cube.h | 6 |
2 files changed, 32 insertions, 62 deletions
diff --git a/src/arch/avx2.h b/src/arch/avx2.h index 4682e33..ad4ee0d 100644 --- a/src/arch/avx2.h +++ b/src/arch/avx2.h | |||
| @@ -1,10 +1,16 @@ | |||
| 1 | #define CO2_AVX2 _mm256_set_epi64x(0, 0, 0, INT64_C(0x6060606060606060)) | 1 | #define CO2_AVX2 _mm256_set_epi64x(0, 0, 0, INT64_C(0x6060606060606060)) |
| 2 | #define COCW_AVX2 _mm256_set_epi64x(0, 0, 0, INT64_C(0x2020202020202020)) | 2 | #define COCW_AVX2 _mm256_set_epi64x(0, 0, 0, INT64_C(0x2020202020202020)) |
| 3 | #define CP_AVX2 _mm256_set_epi64x(0, 0, 0, INT64_C(0x0707070707070707)) | 3 | #define CP_AVX2 _mm256_set_epi64x(0, 0, 0, INT64_C(0x0707070707070707)) |
| 4 | #define EP_AVX2 \ | 4 | #define EP_AVX2 _mm256_set_epi64x(\ |
| 5 | _mm256_set_epi64x(INT64_C(0x0F0F0F0F), INT64_C(0x0F0F0F0F0F0F0F0F), 0, 0) | 5 | INT64_C(0x0F0F0F0F), INT64_C(0x0F0F0F0F0F0F0F0F), 0, 0) |
| 6 | #define EO_AVX2 \ | 6 | #define EO_AVX2 _mm256_set_epi64x(\ |
| 7 | _mm256_set_epi64x(INT64_C(0x10101010), INT64_C(0x1010101010101010), 0, 0) | 7 | INT64_C(0x10101010), INT64_C(0x1010101010101010), 0, 0) |
| 8 | #define ORIENT_AVX2 _mm256_set_epi64x(INT64_C(0x10101010), \ | ||
| 9 | INT64_C(0x1010101010101010), 0, INT64_C(0x6060606060606060)) | ||
| 10 | #define USED_AVX2 _mm256_set_epi64x(INT64_C(0x00000000FFFFFFFF), \ | ||
| 11 | INT64_C(0xFFFFFFFFFFFFFFFF), 0, INT64_C(0xFFFFFFFFFFFFFFFF)) | ||
| 12 | #define CARRY_AVX2 _mm256_set_epi64x(INT64_C(0x20202020), \ | ||
| 13 | INT64_C(0x2020202020202020), 0, INT64_C(0x6060606060606060)) | ||
| 8 | 14 | ||
| 9 | #define STATIC_CUBE(c_ufr, c_ubl, c_dfl, c_dbr, c_ufl, c_ubr, c_dfr, c_dbl, \ | 15 | #define STATIC_CUBE(c_ufr, c_ubl, c_dfl, c_dbr, c_ufl, c_ubr, c_dfr, c_dbl, \ |
| 10 | e_uf, e_ub, e_db, e_df, e_ur, e_ul, e_dl, e_dr, e_fr, e_fl, e_bl, e_br) \ | 16 | e_uf, e_ub, e_db, e_df, e_ur, e_ul, e_dl, e_dr, e_fr, e_fl, e_bl, e_br) \ |
| @@ -61,76 +67,36 @@ invertco(cube_t c) | |||
| 61 | } | 67 | } |
| 62 | 68 | ||
| 63 | STATIC_INLINE cube_t | 69 | STATIC_INLINE cube_t |
| 64 | compose_epcpeo(cube_t c1, cube_t c2) | ||
| 65 | { | ||
| 66 | cube_t b, s, eo2; | ||
| 67 | |||
| 68 | /* Permute and clean unused bits */ | ||
| 69 | s = _mm256_shuffle_epi8(c1, c2); | ||
| 70 | b = _mm256_set_epi8( | ||
| 71 | ~0, ~0, ~0, ~0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 72 | ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, 0, 0, 0, 0, 0, 0, 0, 0 | ||
| 73 | ); | ||
| 74 | s = _mm256_andnot_si256(b, s); | ||
| 75 | |||
| 76 | /* Change EO */ | ||
| 77 | eo2 = _mm256_and_si256(c2, EO_AVX2); | ||
| 78 | s = _mm256_xor_si256(s, eo2); | ||
| 79 | |||
| 80 | return s; | ||
| 81 | } | ||
| 82 | |||
| 83 | STATIC_INLINE cube_t | ||
| 84 | compose_edges(cube_t c1, cube_t c2) | 70 | compose_edges(cube_t c1, cube_t c2) |
| 85 | { | 71 | { |
| 86 | return compose_epcpeo(c1, c2); | 72 | return compose(c1, c2); |
| 87 | } | 73 | } |
| 88 | 74 | ||
| 89 | STATIC_INLINE cube_t | 75 | STATIC_INLINE cube_t |
| 90 | compose_corners(cube_t c1, cube_t c2) | 76 | compose_corners(cube_t c1, cube_t c2) |
| 91 | { | 77 | { |
| 92 | /* | ||
| 93 | * We do a full compose. Minor optimizations are possible, like | ||
| 94 | * saving one instruction by not doing EO, but it should not | ||
| 95 | * be significant. | ||
| 96 | */ | ||
| 97 | return compose(c1, c2); | 78 | return compose(c1, c2); |
| 98 | } | 79 | } |
| 99 | 80 | ||
| 100 | STATIC_INLINE cube_t | 81 | STATIC_INLINE cube_t |
| 101 | compose(cube_t c1, cube_t c2) | 82 | compose(cube_t c1, cube_t c2) |
| 102 | { | 83 | { |
| 103 | cube_t s, co1, co2, aux, auy1, auy2, auz1, auz2; | 84 | /* |
| 104 | 85 | * Method taken from Andrew Skalski's vcube (thanks to Arhan Chaudhary | |
| 105 | s = compose_epcpeo(c1, c2); | 86 | * for pointing this out) |
| 106 | 87 | */ | |
| 107 | /* Change CO */ | 88 | cube_t ss, so, su; |
| 108 | co1 = _mm256_and_si256(s, CO2_AVX2); | ||
| 109 | co2 = _mm256_and_si256(c2, CO2_AVX2); | ||
| 110 | aux = _mm256_add_epi8(co1, co2); | ||
| 111 | auy1 = _mm256_add_epi8(aux, COCW_AVX2); | ||
| 112 | auy2 = _mm256_srli_epi32(auy1, 2); | ||
| 113 | auz1 = _mm256_add_epi8(aux, auy2); | ||
| 114 | auz2 = _mm256_and_si256(auz1, CO2_AVX2); | ||
| 115 | |||
| 116 | /* Put together */ | ||
| 117 | s = _mm256_andnot_si256(CO2_AVX2, s); | ||
| 118 | s = _mm256_or_si256(s, auz2); | ||
| 119 | |||
| 120 | return s; | ||
| 121 | } | ||
| 122 | 89 | ||
| 123 | STATIC_INLINE cube_t | 90 | /* Permute */ |
| 124 | cleanaftershuffle(cube_t c) | 91 | ss = _mm256_shuffle_epi8(c1, c2); |
| 125 | { | ||
| 126 | __m256i b; | ||
| 127 | 92 | ||
| 128 | b = _mm256_set_epi8( | 93 | /* Orient */ |
| 129 | ~0, ~0, ~0, ~0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 94 | so = _mm256_and_si256(c2, ORIENT_AVX2); |
| 130 | ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, 0, 0, 0, 0, 0, 0, 0, 0 | 95 | ss = _mm256_add_epi8(ss, so); |
| 131 | ); | 96 | su = _mm256_sub_epi8(ss, CARRY_AVX2); |
| 97 | ss = _mm256_min_epu8(ss, su); | ||
| 132 | 98 | ||
| 133 | return _mm256_andnot_si256(b, c); | 99 | return _mm256_and_si256(ss, USED_AVX2); |
| 134 | } | 100 | } |
| 135 | 101 | ||
| 136 | STATIC_INLINE cube_t | 102 | STATIC_INLINE cube_t |
| @@ -163,11 +129,11 @@ inverse(cube_t c) | |||
| 163 | vi = _mm256_shuffle_epi8(vi, vi); | 129 | vi = _mm256_shuffle_epi8(vi, vi); |
| 164 | vi = _mm256_shuffle_epi8(vi, c); | 130 | vi = _mm256_shuffle_epi8(vi, c); |
| 165 | 131 | ||
| 166 | vo = _mm256_and_si256(c, _mm256_or_si256(EO_AVX2, CO2_AVX2)); | 132 | vo = _mm256_and_si256(c, ORIENT_AVX2); |
| 167 | vo = _mm256_shuffle_epi8(vo, vi); | 133 | vo = _mm256_shuffle_epi8(vo, vi); |
| 168 | vp = _mm256_andnot_si256(_mm256_or_si256(EO_AVX2, CO2_AVX2), vi); | 134 | vp = _mm256_andnot_si256(ORIENT_AVX2, vi); |
| 169 | ret = _mm256_or_si256(vp, vo); | 135 | ret = _mm256_or_si256(vp, vo); |
| 170 | ret = cleanaftershuffle(ret); | 136 | ret = _mm256_and_si256(ret, USED_AVX2); |
| 171 | 137 | ||
| 172 | return invertco(ret); | 138 | return invertco(ret); |
| 173 | } | 139 | } |
diff --git a/src/core/cube.h b/src/core/cube.h index 3dd3ccb..ce8a6b8 100644 --- a/src/core/cube.h +++ b/src/core/cube.h | |||
| @@ -109,9 +109,13 @@ issolvable(cube_t cube) | |||
| 109 | return true; | 109 | return true; |
| 110 | 110 | ||
| 111 | issolvable_parity: | 111 | issolvable_parity: |
| 112 | LOG("There is parity\n"); | ||
| 113 | return false; | ||
| 112 | issolvable_eo: | 114 | issolvable_eo: |
| 115 | LOG("EO is not solvable\n"); | ||
| 116 | return false; | ||
| 113 | issolvable_co: | 117 | issolvable_co: |
| 114 | /* We used to do more logging here, hence the 3 different labels */ | 118 | LOG("CO is not solvable\n"); |
| 115 | return false; | 119 | return false; |
| 116 | } | 120 | } |
| 117 | 121 | ||
