https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119040

            Bug ID: 119040
           Summary: [PPC/Altivec] Missing bit-level optimization (select)
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: wojciech_mula at poczta dot onet.pl
  Target Milestone: ---

This come from real-world usage. Suppose we have a vector of words, we want to
move around some bit-fields of that words. We isolate the bit-fields with `and`
then shift the bit-fields to the desired positions in the final word. But we
never end up with overlapping bit-fields.

Below is a sample code that merges two 6-bit fields into 12-bit one in 32-bit
elements:

---test.cpp---
#include <stdint.h>
#include <altivec.h>

using vec_u32_t = __vector uint32_t;

vec_u32_t merge_2x6_bits(const vec_u32_t a, const vec_u32_t b) {
    vec_u32_t t0 = vec_and(a, vec_splats(uint32_t(0x003f)));
    vec_u32_t t1 = vec_and(b, vec_splats(uint32_t(0x3f00)));

    vec_u32_t t2 = vec_sr(t1, vec_splats(uint32_t(2)));

    return vec_or(t2, t0);
}
---eof---

GCC 14.2.0 with flags `-O3 -maltivec` produces the following code (I omitted
the constants .LC0 & .LC1):

        lis 10,.LC0@ha
        lis 9,.LC1@ha
        la 10,.LC0@l(10)
        la 9,.LC1@l(9)
        lvx 13,0,10
        vspltisw 0,2
        lvx 1,0,9
        vand 3,3,13
        vsrw 3,3,0
        vand 2,2,1
        vor 2,3,2

Since the bit-fields do not overlap, the last sequence of `vand` and `vor` can
be replace with `vsel`. Instead of `((a & mask1) >> 2) | (b & mask2)` we may
have `select(mask1 >> 2, a >> 2, b & mask2)` [providing the prototype of
`select` is select(condition, true, false)].

Reply via email to