[Bug rtl-optimization/125731] Improve RISC-V sequence for conditional xor with a constant

"cvs-commit at gcc dot gnu.org via Gcc-bugs" <[email protected]>
Newsgroups gmane.comp.gcc.bugs
Message-ID <[email protected]/bugzilla/>
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125731

--- Comment #7 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Jeff Law <[email protected]>:

https://gcc.gnu.org/g:af0cf36fb47a704a02dd2ead5f8db5d140e45351

commit r17-3306-gaf0cf36fb47a704a02dd2ead5f8db5d140e45351
Author: Shreya Munnangi <[email protected]>
Date:   Fri Aug 14 14:53:34 2026 -0600

    [PATCH][RISC-V][PR rtl-optimization/125731] Improving sequences for
conditional xor with a constant

    This is Shreya's work to address pr125731.  I did some testing around this
to
    verify riscv64-elf and riscv32-elf are happy.  Testing on the K1/K3/c920
will
    fire up tonight, but not expecting significant issues there.

    --

    In PR125731,

    We are generating inefficient sequences for conditional xor with a
    constant. Given this testcase,

    long fun_not1 (int a, long b)
    {
        if (!(a & 1))
            b ^= 8;
        return b;
    }

    We are generating:

    fun_not1:
            andi    a5,a0,1
            mv      a0,a1
            bne     a5,zero,.L3
            xori    a0,a1,8
    .L3:
            ret

    However, this can be simplified into a branchless sequence.  One such
sequence:

           andi    a5,a0,1
           li      a4,8
           czero.nez       a5,a4,a5
           xor     a0,a1,a5
           ret

    Another form:

            andi    a0,a0,1
            seqz    t0,a0
            slli    t1,t0,3
            xor     a0,a1,t1
            ret
    -- I've edited Shreya's explanation a bit --

    The if-converter's get_base_reg currently returns NULL if presented with a
    constant and that inhibits if conversion through the noce_try_cond_arith
which
    can generate more efficient sequences than generalized conditional moves. 
So
    the first thing we need to do is support constants in get_base_reg.

    The return value from get_base_reg is used to generate a new pseudo
register,
    so if get_base_reg starts returning constants, then we're going to run into
    problems generating the new pseudo because constants are VOIDmode.

    I changed the name to get_base_reg_or_constant to reflect that we are also
    handling constants, not just returning the base registers of a reg or
subreg.
    The point where the caller uses the return value to get a mode for the new
    pseudo has been changed to get the mode from the other operand of the
binary
    operation.

    Those changes are sufficient to if-convert this example as well as enabling
    more efficient code generation for other cases where we have a conditional
    operation where one operand is a constant.

    Although the newly generated sequence is the same number of insns, it will
be
    much faster if the conditional branch is not easily predictable.

            PR rtl-optimization/125731
    gcc/
            * ifcvt.cc (get_base_reg_or_const): Renamed from get_base_reg.
            Handle CONST_INTs too.
            (noce_try_cond_arith): Use get_base_reg_or_const.  Handle case
where
            get_base_reg_or_const returns a CONST_INT.

    gcc/testsuite
            * gcc.target/riscv/pr125731.c: New test.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.