https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122769
--- Comment #4 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
(In reply to Vineet Gupta from comment #3)
> (In reply to Andrew Pinski from comment #2)
> > .
> >
> > slti a0,a0,0
> > czero.eqz a0,a3,a0
> > xor a0,a0,a1
> >
> > Which I can get via:
> > ```
> > uint64_t f1(uint64_t val, uint64_t val2, int bits, uint64_t n) {
> > uint64_t t = -(((int64_t)val) < 0);
> > val2 ^= (t & n);
> > return val2;
> > }
> > ```
> > Which does the right thing there ...
>
> That's because it already expands to a czero
>
> (insn 11 10 12 2 (set (reg:SI 144 [ _9 ])
> (if_then_else:SI (ne:DI (reg:DI 145)
> (const_int 0 [0]))
> (reg:SI 146)
> (const_int 0 [0]))) "test4.c":6:14 40364 {*czero.eqz.sidi}
> (nil))
>
> OTOH, llvm seems to be transforming
>
> if (val & (1ULL << 63))
> val2 ^= n;
>
> to something like (note that @n has actually moved where its been used)
>
> uint64_t tmp = (val >> 63) & n;
> val2 ^= tmp;
>
>
> I need some guidance as to where to tackle this ?
In ifcvt.cc is the best place to start. The next place is figuring out how to
hook up some target specific match patterns to phiopt for the late one (you
can/should use fold_before_rtl_expansion_p () function to say it is late).