Skip to content

Commit 31b52b4

Browse files
committed
[RISCV] Add matching of codegen patterns to RISCV Bit Manipulation Zbp asm instructions
This patch provides optimization of bit manipulation operations by enabling the +experimental-b target feature. It adds matching of single block patterns of instructions to specific bit-manip instructions from the permutation subset (zbp subextension) of the experimental B extension of RISC-V. It adds also the correspondent codegen tests. This patch is based on Claire Wolf's proposal for the bit manipulation extension of RISCV: https://github.com/riscv/riscv-bitmanip/blob/master/bitmanip-0.92.pdf Differential Revision: https://reviews.llvm.org/D79871
1 parent e2692f0 commit 31b52b4

File tree

4 files changed

+2784
-1
lines changed

4 files changed

+2784
-1
lines changed

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -151,14 +151,19 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
151151

152152
setOperationAction(ISD::ROTL, XLenVT, Expand);
153153
setOperationAction(ISD::ROTR, XLenVT, Expand);
154-
setOperationAction(ISD::BSWAP, XLenVT, Expand);
154+
155+
if (!Subtarget.hasStdExtZbp())
156+
setOperationAction(ISD::BSWAP, XLenVT, Expand);
155157

156158
if (!Subtarget.hasStdExtZbb()) {
157159
setOperationAction(ISD::CTTZ, XLenVT, Expand);
158160
setOperationAction(ISD::CTLZ, XLenVT, Expand);
159161
setOperationAction(ISD::CTPOP, XLenVT, Expand);
160162
}
161163

164+
if (Subtarget.hasStdExtZbp())
165+
setOperationAction(ISD::BITREVERSE, XLenVT, Legal);
166+
162167
ISD::CondCode FPCCToExtend[] = {
163168
ISD::SETOGT, ISD::SETOGE, ISD::SETONE, ISD::SETUEQ, ISD::SETUGT,
164169
ISD::SETUGE, ISD::SETULT, ISD::SETULE, ISD::SETUNE, ISD::SETGT,

llvm/lib/Target/RISCV/RISCVInstrInfoB.td

+190
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,97 @@ def : Pat<(SLOIPat GPR:$rs1, uimmlog2xlen:$shamt),
651651
(SLOI GPR:$rs1, uimmlog2xlen:$shamt)>;
652652
def : Pat<(SROIPat GPR:$rs1, uimmlog2xlen:$shamt),
653653
(SROI GPR:$rs1, uimmlog2xlen:$shamt)>;
654+
} // Predicates = [HasStdExtZbb]
655+
656+
let Predicates = [HasStdExtZbp, IsRV32] in {
657+
def : Pat<(or (or (and (srl GPR:$rs1, (i32 1)), (i32 0x55555555)), GPR:$rs1),
658+
(and (shl GPR:$rs1, (i32 1)), (i32 0xAAAAAAAA))),
659+
(GORCI GPR:$rs1, (i32 1))>;
660+
def : Pat<(or (or (and (srl GPR:$rs1, (i32 2)), (i32 0x33333333)), GPR:$rs1),
661+
(and (shl GPR:$rs1, (i32 2)), (i32 0xCCCCCCCC))),
662+
(GORCI GPR:$rs1, (i32 2))>;
663+
def : Pat<(or (or (and (srl GPR:$rs1, (i32 4)), (i32 0x0F0F0F0F)), GPR:$rs1),
664+
(and (shl GPR:$rs1, (i32 4)), (i32 0xF0F0F0F0))),
665+
(GORCI GPR:$rs1, (i32 4))>;
666+
def : Pat<(or (or (and (srl GPR:$rs1, (i32 8)), (i32 0x00FF00FF)), GPR:$rs1),
667+
(and (shl GPR:$rs1, (i32 8)), (i32 0xFF00FF00))),
668+
(GORCI GPR:$rs1, (i32 8))>;
669+
def : Pat<(or (or (srl GPR:$rs1, (i32 16)), GPR:$rs1),
670+
(shl GPR:$rs1, (i32 16))),
671+
(GORCI GPR:$rs1, (i32 16))>;
672+
} // Predicates = [HasStdExtZbp, IsRV32]
673+
674+
let Predicates = [HasStdExtZbp, IsRV64] in {
675+
def : Pat<(or (or (and (srl GPR:$rs1, (i64 1)), (i64 0x5555555555555555)),
676+
GPR:$rs1),
677+
(and (shl GPR:$rs1, (i64 1)), (i64 0xAAAAAAAAAAAAAAAA))),
678+
(GORCI GPR:$rs1, (i64 1))>;
679+
def : Pat<(or (or (and (srl GPR:$rs1, (i64 2)), (i64 0x3333333333333333)),
680+
GPR:$rs1),
681+
(and (shl GPR:$rs1, (i64 2)), (i64 0xCCCCCCCCCCCCCCCC))),
682+
(GORCI GPR:$rs1, (i64 2))>;
683+
def : Pat<(or (or (and (srl GPR:$rs1, (i64 4)), (i64 0x0F0F0F0F0F0F0F0F)),
684+
GPR:$rs1),
685+
(and (shl GPR:$rs1, (i64 4)), (i64 0xF0F0F0F0F0F0F0F0))),
686+
(GORCI GPR:$rs1, (i64 4))>;
687+
def : Pat<(or (or (and (srl GPR:$rs1, (i64 8)), (i64 0x00FF00FF00FF00FF)),
688+
GPR:$rs1),
689+
(and (shl GPR:$rs1, (i64 8)), (i64 0xFF00FF00FF00FF00))),
690+
(GORCI GPR:$rs1, (i64 8))>;
691+
def : Pat<(or (or (and (srl GPR:$rs1, (i64 16)), (i64 0x0000FFFF0000FFFF)),
692+
GPR:$rs1),
693+
(and (shl GPR:$rs1, (i64 16)), (i64 0xFFFF0000FFFF0000))),
694+
(GORCI GPR:$rs1, (i64 16))>;
695+
def : Pat<(or (or (srl GPR:$rs1, (i64 32)), GPR:$rs1),
696+
(shl GPR:$rs1, (i64 32))),
697+
(GORCI GPR:$rs1, (i64 32))>;
698+
} // Predicates = [HasStdExtZbp, IsRV64]
699+
700+
let Predicates = [HasStdExtZbp, IsRV32] in {
701+
def : Pat<(or (and (shl GPR:$rs1, (i32 1)), (i32 0xAAAAAAAA)),
702+
(and (srl GPR:$rs1, (i32 1)), (i32 0x55555555))),
703+
(GREVI GPR:$rs1, (i32 1))>;
704+
def : Pat<(or (and (shl GPR:$rs1, (i32 2)), (i32 0xCCCCCCCC)),
705+
(and (srl GPR:$rs1, (i32 2)), (i32 0x33333333))),
706+
(GREVI GPR:$rs1, (i32 2))>;
707+
def : Pat<(or (and (shl GPR:$rs1, (i32 4)), (i32 0xF0F0F0F0)),
708+
(and (srl GPR:$rs1, (i32 4)), (i32 0x0F0F0F0F))),
709+
(GREVI GPR:$rs1, (i32 4))>;
710+
def : Pat<(or (and (shl GPR:$rs1, (i32 8)), (i32 0xFF00FF00)),
711+
(and (srl GPR:$rs1, (i32 8)), (i32 0x00FF00FF))),
712+
(GREVI GPR:$rs1, (i32 8))>;
713+
def : Pat<(rotr (bswap GPR:$rs1), (i32 16)), (GREVI GPR:$rs1, (i32 8))>;
714+
def : Pat<(or (shl GPR:$rs1, (i32 16)), (srl GPR:$rs1, (i32 16))),
715+
(GREVI GPR:$rs1, (i32 16))>;
716+
def : Pat<(rotl GPR:$rs1, (i32 16)), (GREVI GPR:$rs1, (i32 16))>;
717+
def : Pat<(bswap GPR:$rs1), (GREVI GPR:$rs1, (i32 24))>;
718+
def : Pat<(bitreverse GPR:$rs1), (GREVI GPR:$rs1, (i32 31))>;
719+
} // Predicates = [HasStdExtZbp, IsRV32]
720+
721+
let Predicates = [HasStdExtZbp, IsRV64] in {
722+
def : Pat<(or (and (shl GPR:$rs1, (i64 1)), (i64 0xAAAAAAAAAAAAAAAA)),
723+
(and (srl GPR:$rs1, (i64 1)), (i64 0x5555555555555555))),
724+
(GREVI GPR:$rs1, (i64 1))>;
725+
def : Pat<(or (and (shl GPR:$rs1, (i64 2)), (i64 0xCCCCCCCCCCCCCCCC)),
726+
(and (srl GPR:$rs1, (i64 2)), (i64 0x3333333333333333))),
727+
(GREVI GPR:$rs1, (i64 2))>;
728+
def : Pat<(or (and (shl GPR:$rs1, (i64 4)), (i64 0xF0F0F0F0F0F0F0F0)),
729+
(and (srl GPR:$rs1, (i64 4)), (i64 0x0F0F0F0F0F0F0F0F))),
730+
(GREVI GPR:$rs1, (i64 4))>;
731+
def : Pat<(or (and (shl GPR:$rs1, (i64 8)), (i64 0xFF00FF00FF00FF00)),
732+
(and (srl GPR:$rs1, (i64 8)), (i64 0x00FF00FF00FF00FF))),
733+
(GREVI GPR:$rs1, (i64 8))>;
734+
def : Pat<(or (and (shl GPR:$rs1, (i64 16)), (i64 0xFFFF0000FFFF0000)),
735+
(and (srl GPR:$rs1, (i64 16)), (i64 0x0000FFFF0000FFFF))),
736+
(GREVI GPR:$rs1, (i64 16))>;
737+
def : Pat<(or (shl GPR:$rs1, (i64 32)), (srl GPR:$rs1, (i64 32))),
738+
(GREVI GPR:$rs1, (i64 32))>;
739+
def : Pat<(rotl GPR:$rs1, (i64 32)), (GREVI GPR:$rs1, (i64 32))>;
740+
def : Pat<(bswap GPR:$rs1), (GREVI GPR:$rs1, (i64 56))>;
741+
def : Pat<(bitreverse GPR:$rs1), (GREVI GPR:$rs1, (i64 63))>;
742+
} // Predicates = [HasStdExtZbp, IsRV64]
743+
744+
let Predicates = [HasStdExtZbb] in {
654745
def : Pat<(ctlz GPR:$rs1), (CLZ GPR:$rs1)>;
655746
def : Pat<(cttz GPR:$rs1), (CTZ GPR:$rs1)>;
656747
def : Pat<(ctpop GPR:$rs1), (PCNT GPR:$rs1)>;
@@ -681,6 +772,48 @@ def : Pat<(riscv_selectcc GPR:$rs2, GPR:$rs1, (XLenVT 12), GPR:$rs1, GPR:$rs2),
681772
(MAXU GPR:$rs1, GPR:$rs2)>;
682773
} // Predicates = [HasStdExtZbb]
683774

775+
let Predicates = [HasStdExtZbp, IsRV32] in {
776+
def : Pat<(or (or (and (shl GPR:$rs1, (i32 8)), (i32 0x00FF0000)),
777+
(and GPR:$rs1, (i32 0xFF0000FF))),
778+
(and (srl GPR:$rs1, (i32 8)), (i32 0x0000FF00))),
779+
(SHFLI GPR:$rs1, (i32 8))>;
780+
def : Pat<(or (or (and (shl GPR:$rs1, (i32 4)), (i32 0x0F000F00)),
781+
(and GPR:$rs1, (i32 0xF00FF00F))),
782+
(and (srl GPR:$rs1, (i32 4)), (i32 0x00F000F0))),
783+
(SHFLI GPR:$rs1, (i32 4))>;
784+
def : Pat<(or (or (and (shl GPR:$rs1, (i32 2)), (i32 0x30303030)),
785+
(and GPR:$rs1, (i32 0xC3C3C3C3))),
786+
(and (srl GPR:$rs1, (i32 2)), (i32 0x0C0C0C0C))),
787+
(SHFLI GPR:$rs1, (i32 2))>;
788+
def : Pat<(or (or (and (shl GPR:$rs1, (i32 1)), (i32 0x44444444)),
789+
(and GPR:$rs1, (i32 0x99999999))),
790+
(and (srl GPR:$rs1, (i32 1)), (i32 0x22222222))),
791+
(SHFLI GPR:$rs1, (i32 1))>;
792+
} // Predicates = [HasStdExtZbp, IsRV32]
793+
794+
let Predicates = [HasStdExtZbp, IsRV64] in {
795+
def : Pat<(or (or (and (shl GPR:$rs1, (i64 16)), (i64 0x0000FFFF00000000)),
796+
(and GPR:$rs1, (i64 0xFFFF00000000FFFF))),
797+
(and (srl GPR:$rs1, (i64 16)), (i64 0x00000000FFFF0000))),
798+
(SHFLI GPR:$rs1, (i64 16))>;
799+
def : Pat<(or (or (and (shl GPR:$rs1, (i64 8)), (i64 0x00FF000000FF0000)),
800+
(and GPR:$rs1, (i64 0xFF0000FFFF0000FF))),
801+
(and (srl GPR:$rs1, (i64 8)), (i64 0x0000FF000000FF00))),
802+
(SHFLI GPR:$rs1, (i64 8))>;
803+
def : Pat<(or (or (and (shl GPR:$rs1, (i64 4)), (i64 0x0F000F000F000F00)),
804+
(and GPR:$rs1, (i64 0xF00FF00FF00FF00F))),
805+
(and (srl GPR:$rs1, (i64 4)), (i64 0x00F000F000F000F0))),
806+
(SHFLI GPR:$rs1, (i64 4))>;
807+
def : Pat<(or (or (and (shl GPR:$rs1, (i64 2)), (i64 0x3030303030303030)),
808+
(and GPR:$rs1, (i64 0xC3C3C3C3C3C3C3C3))),
809+
(and (srl GPR:$rs1, (i64 2)), (i64 0x0C0C0C0C0C0C0C0C))),
810+
(SHFLI GPR:$rs1, (i64 2))>;
811+
def : Pat<(or (or (and (shl GPR:$rs1, (i64 1)), (i64 0x4444444444444444)),
812+
(and GPR:$rs1, (i64 0x9999999999999999))),
813+
(and (srl GPR:$rs1, (i64 1)), (i64 0x2222222222222222))),
814+
(SHFLI GPR:$rs1, (i64 1))>;
815+
} // Predicates = [HasStdExtZbp, IsRV64]
816+
684817
let Predicates = [HasStdExtZbb, IsRV64] in {
685818
def : Pat<(and (add GPR:$rs, simm12:$simm12), (i64 0xFFFFFFFF)),
686819
(ADDIWU GPR:$rs, simm12:$simm12)>;
@@ -702,6 +835,63 @@ def : Pat<(SLOIWPat GPR:$rs1, uimmlog2xlen:$shamt),
702835
(SLOIW GPR:$rs1, uimmlog2xlen:$shamt)>;
703836
def : Pat<(SROIWPat GPR:$rs1, uimmlog2xlen:$shamt),
704837
(SROIW GPR:$rs1, uimmlog2xlen:$shamt)>;
838+
} // Predicates = [HasStdExtZbb, IsRV64]
839+
840+
let Predicates = [HasStdExtZbp, IsRV64] in {
841+
def : Pat<(sext_inreg (or (or (and (srl GPR:$rs1, (i64 1)), (i64 0x55555555)),
842+
GPR:$rs1),
843+
(and (shl GPR:$rs1, (i64 1)), (i64 0xAAAAAAAA))),
844+
i32),
845+
(GORCIW GPR:$rs1, (i64 1))>;
846+
def : Pat<(sext_inreg (or (or (and (srl GPR:$rs1, (i64 2)), (i64 0x33333333)),
847+
GPR:$rs1),
848+
(and (shl GPR:$rs1, (i64 2)), (i64 0xCCCCCCCC))),
849+
i32),
850+
(GORCIW GPR:$rs1, (i64 2))>;
851+
def : Pat<(sext_inreg (or (or (and (srl GPR:$rs1, (i64 4)), (i64 0x0F0F0F0F)),
852+
GPR:$rs1),
853+
(and (shl GPR:$rs1, (i64 4)), (i64 0xF0F0F0F0))),
854+
i32),
855+
(GORCIW GPR:$rs1, (i64 4))>;
856+
def : Pat<(sext_inreg (or (or (and (srl GPR:$rs1, (i64 8)), (i64 0x00FF00FF)),
857+
GPR:$rs1),
858+
(and (shl GPR:$rs1, (i64 8)), (i64 0xFF00FF00))),
859+
i32),
860+
(GORCIW GPR:$rs1, (i64 8))>;
861+
def : Pat<(sext_inreg (or (or (and (srl GPR:$rs1, (i64 16)), (i64 0x0000FFFF)),
862+
GPR:$rs1),
863+
(and (shl GPR:$rs1, (i64 16)), (i64 0xFFFF0000))),
864+
i32),
865+
(GORCIW GPR:$rs1, (i64 16))>;
866+
def : Pat<(sext_inreg (or (or (srl (and GPR:$rs1, (i64 0xFFFF0000)), (i64 16)),
867+
GPR:$rs1),
868+
(shl GPR:$rs1, (i64 16))), i32),
869+
(GORCIW GPR:$rs1, (i64 16))>;
870+
871+
def : Pat<(sext_inreg (or (and (shl GPR:$rs1, (i64 1)), (i64 0xAAAAAAAA)),
872+
(and (srl GPR:$rs1, (i64 1)), (i64 0x55555555))),
873+
i32),
874+
(GREVIW GPR:$rs1, (i64 1))>;
875+
def : Pat<(sext_inreg (or (and (shl GPR:$rs1, (i64 2)), (i64 0xCCCCCCCC)),
876+
(and (srl GPR:$rs1, (i64 2)), (i64 0x33333333))),
877+
i32),
878+
(GREVIW GPR:$rs1, (i64 2))>;
879+
def : Pat<(sext_inreg (or (and (shl GPR:$rs1, (i64 4)), (i64 0xF0F0F0F0)),
880+
(and (srl GPR:$rs1, (i64 4)), (i64 0x0F0F0F0F))),
881+
i32),
882+
(GREVIW GPR:$rs1, (i64 4))>;
883+
def : Pat<(sext_inreg (or (and (shl GPR:$rs1, (i64 8)), (i64 0xFF00FF00)),
884+
(and (srl GPR:$rs1, (i64 8)), (i64 0x00FF00FF))),
885+
i32),
886+
(GREVIW GPR:$rs1, (i64 8))>;
887+
def : Pat<(sext_inreg (or (shl GPR:$rs1, (i64 16)),
888+
(srl (and GPR:$rs1, 0xFFFF0000), (i64 16))), i32),
889+
(GREVIW GPR:$rs1, (i64 16))>;
890+
def : Pat<(sra (bswap GPR:$rs1), (i64 32)), (GREVIW GPR:$rs1, (i64 24))>;
891+
def : Pat<(sra (bitreverse GPR:$rs1), (i64 32)), (GREVIW GPR:$rs1, (i64 31))>;
892+
} // Predicates = [HasStdExtZbp, IsRV64]
893+
894+
let Predicates = [HasStdExtZbb, IsRV64] in {
705895
def : Pat<(add (ctlz (and GPR:$rs1, (i64 0xFFFFFFFF))), (i64 -32)),
706896
(CLZW GPR:$rs1)>;
707897
// We don't pattern-match CTZW here as it has the same pattern and result as

0 commit comments

Comments
 (0)