This is an archive of the discontinued LLVM Phabricator instance.

[RISCV] Optimize (br_cc (and X, 0x80000000), 0, seteq, dest) on RV64
AbandonedPublic

Authored by craig.topper on Jul 19 2022, 9:44 AM.

Details

Summary

The 0x80000000 would normally require constant materialization, but
we can replace it with a sext.w to copy bit 31 to bit 63 and use a
sign compare with 0 to test the bit.

We can do something similar for setne and for select_cc which will
eventually becomes a branch. The setne case for select_cc becomes
an srliw instead through other means and I'm not sure it's worth
changing.

I chose sext.w because it's one instruction, srliw would need a
srl+and to be emitted. And a sext.w might be foldable into an earlier
instruction.

We don't want to do this for setcc that won't become a branch because
we don't have a sgez instruction. For those an srliw and an xori is
going to be better. That's probably best done from an isel pattern so
we don't expand and+setcc to srl+and+xor in the DAG.

Diff Detail

Event Timeline

craig.topper created this revision.Jul 19 2022, 9:44 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 19 2022, 9:44 AM
craig.topper requested review of this revision.Jul 19 2022, 9:44 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 19 2022, 9:44 AM

Can't we do something more general here using shifts?

For one bit masks, can't we shift the desired bit to one end and then test? For a left shift, this would be moving the desired bit to test into bit 64 (sign bit) and using the signed comparison as in this patch. For a right shift, this would be moving the desired bit into bit 0, and testing against zero. We do have a snez I believe.

Can't we do something more general here using shifts?

For one bit masks, can't we shift the desired bit to one end and then test? For a left shift, this would be moving the desired bit to test into bit 64 (sign bit) and using the signed comparison as in this patch. For a right shift, this would be moving the desired bit into bit 0, and testing against zero. We do have a snez I believe.

Right shift doesn’t work without clearing the bits that are above the tested bit. But left shift would work.

reames added a comment.EditedJul 20 2022, 10:25 AM

Can't we do something more general here using shifts?

For one bit masks, can't we shift the desired bit to one end and then test? For a left shift, this would be moving the desired bit to test into bit 64 (sign bit) and using the signed comparison as in this patch. For a right shift, this would be moving the desired bit into bit 0, and testing against zero. We do have a snez I believe.

Right shift doesn’t work without clearing the bits that are above the tested bit. But left shift would work.

You're right, you'd need an AND 0x1 after the right shift to isolate the bit. Might still be worth doing over materializing the large mask constant - that's at least an LUI + SHL + AND, so SRLI + AND both with immediate operands seems to be slightly better.

But yes, the ability to do the left shift and signed compare is strictly better, so we should do that one. :)

For multiple bit masks, maybe the right shift variant is worth exploring providing the shifted bit mask fits in the immediate encoding. So any mask with set bits separated by less than 12 bits. I don't see a multi-bit mask variant of the left shift one off the top of my head.

craig.topper abandoned this revision.Jul 20 2022, 2:03 PM

I'm going to abandon this in favor of a more general single bit AND patch using SLLI implemented in a different place with different tests.