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

--- Comment #2 from Jeevitha <jeevitha at gcc dot gnu.org> ---
For the following testcase:

#include <altivec.h>

vector signed int without_sel(vector signed int l, vector signed int r) {
    vector signed int mask = {63, 63, 63, 63};
    l = l & ~mask;
    l |= r & mask;
    return l;
}


Current trunk emits:

xxspltiw %vs0,63
xxspltiw %vs32,4294967232
xxlor    %vs33,%vs34,%vs34
xxland   %vs35,%vs35,%vs0
vand     %v2,%v0,%v1
vor      %v2,%v2,%v3
blr


This sequence performs (l & ~mask) | (r & mask), which is a standard bitfield
merge pattern with non-overlapping masks.
Ideally, this should be optimized into a vsel instruction (e.g., vec_sel(l, r,
mask)).

Currently, GCC fails to combine this pattern into altivec_vsel<mode>* because
it treats the two masks (mask and ~mask) independently and does not detect that
they are complementary.

Dump before combine:
 2: r120:V4SI = %2:V4SI
 4: r122:V4SI = %4:V4SI
11: r123:V4SI = const_vector(const_int -64)
12: r118:V4SI = r120:V4SI & r123:V4SI
17: r126:V4SI = const_vector(const_int 63)
18: r125:V4SI = r122:V4SI & r126:V4SI
19: r124:V4SI = r125:V4SI | r118:V4SI

Reply via email to