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

Jeffrey A. Law <law at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           See Also|                            |https://gcc.gnu.org/bugzill
                   |                            |a/show_bug.cgi?id=123884

--- Comment #17 from Jeffrey A. Law <law at gcc dot gnu.org> ---
So revisiting based on the epiphany I had for pr123884.

That epiphany was that given something like

(ior/xor (sign_extend (ashift (const_int 1) (reg X)))
     (reg Y))

The problem is preserving the sematics of the IOR/XOR where that first operand
is ultimately 0x80000000.  It's not *generally* just a bitmanip+sext.w.  But it
is in some important cases (consider when the second operand is
0xfeedface00000000 vs 0xffffffff80000000 and we change bit 31)


If (reg Y) has 33 or more sign bit copies (as will often be the case when
dealing with 32 bit objects), then the ior/xor followed by an sext.w works
perfectly and can be modeled as a straight forward define_split.  Similarly for
the AND case where we've got an additional NOT operand.

That's much cleaner and unlikely to regress relative to the ext-dce+target
changes idea in c#15.

While it does introduce new sext instructions, it only does so when we
originally had 3/4 insns and we can collapse down to 2.  And since it's a
define_split, we still have the opportunity to eliminate the extension in
combine or REE (but not ext-dce).

For the given testcase the proof of concept patch generates:

        bclr    a0,a0,a1
        sext.w  a0,a0
        ret

Which is optimal for rv64gcb with the lp64 ABI.

So I think we've got a viable path forward.

Reply via email to