Skip to content

Commit c9c955a

Browse files
committed
[RISCV] Add matching of codegen patterns to RISCV Bit Manipulation Zbt 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 ternary subset (zbt 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/D79875
1 parent d4be333 commit c9c955a

File tree

6 files changed

+929
-0
lines changed

6 files changed

+929
-0
lines changed

llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp

+49
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,55 @@ bool RISCVDAGToDAGISel::SelectRORIW(SDValue N, SDValue &RS1, SDValue &Shamt) {
459459
return false;
460460
}
461461

462+
// Check that it is a FSRIW (i32 Funnel Shift Right Immediate on RV64).
463+
// We first check that it is the right node tree:
464+
//
465+
// (SIGN_EXTEND_INREG (OR (SHL (AsserSext RS1, i32), VC2),
466+
// (SRL (AND (AssertSext RS2, i32), VC3), VC1)))
467+
//
468+
// Then we check that the constant operands respect these constraints:
469+
//
470+
// VC2 == 32 - VC1
471+
// VC3 == maskLeadingOnes<uint32_t>(VC2)
472+
//
473+
// being VC1 the Shamt we need, VC2 the complementary of Shamt over 32
474+
// and VC3 a 32 bit mask of (32 - VC1) leading ones.
475+
476+
bool RISCVDAGToDAGISel::SelectFSRIW(SDValue N, SDValue &RS1, SDValue &RS2,
477+
SDValue &Shamt) {
478+
if (N.getOpcode() == ISD::SIGN_EXTEND_INREG &&
479+
Subtarget->getXLenVT() == MVT::i64 &&
480+
cast<VTSDNode>(N.getOperand(1))->getVT() == MVT::i32) {
481+
if (N.getOperand(0).getOpcode() == ISD::OR) {
482+
SDValue Or = N.getOperand(0);
483+
if (Or.getOperand(0).getOpcode() == ISD::SHL &&
484+
Or.getOperand(1).getOpcode() == ISD::SRL) {
485+
SDValue Shl = Or.getOperand(0);
486+
SDValue Srl = Or.getOperand(1);
487+
if (Srl.getOperand(0).getOpcode() == ISD::AND) {
488+
SDValue And = Srl.getOperand(0);
489+
if (isa<ConstantSDNode>(Srl.getOperand(1)) &&
490+
isa<ConstantSDNode>(Shl.getOperand(1)) &&
491+
isa<ConstantSDNode>(And.getOperand(1))) {
492+
uint32_t VC1 = Srl.getConstantOperandVal(1);
493+
uint32_t VC2 = Shl.getConstantOperandVal(1);
494+
uint32_t VC3 = And.getConstantOperandVal(1);
495+
if (VC2 == (32 - VC1) &&
496+
VC3 == maskLeadingOnes<uint32_t>(VC2)) {
497+
RS1 = Shl.getOperand(0);
498+
RS2 = And.getOperand(0);
499+
Shamt = CurDAG->getTargetConstant(VC1, SDLoc(N),
500+
Srl.getOperand(1).getValueType());
501+
return true;
502+
}
503+
}
504+
}
505+
}
506+
}
507+
}
508+
return false;
509+
}
510+
462511
// Merge an ADDI into the offset of a load/store instruction where possible.
463512
// (load (addi base, off1), off2) -> (load base, off1+off2)
464513
// (store val, (addi base, off1), off2) -> (store val, base, off1+off2)

llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class RISCVDAGToDAGISel : public SelectionDAGISel {
5252
bool SelectSLOIW(SDValue N, SDValue &RS1, SDValue &Shamt);
5353
bool SelectSROIW(SDValue N, SDValue &RS1, SDValue &Shamt);
5454
bool SelectRORIW(SDValue N, SDValue &RS1, SDValue &Shamt);
55+
bool SelectFSRIW(SDValue N, SDValue &RS1, SDValue &RS2, SDValue &Shamt);
5556

5657
// Include the pieces autogenerated from the target description.
5758
#include "RISCVGenDAGISel.inc"

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,11 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
166166
if (Subtarget.hasStdExtZbp())
167167
setOperationAction(ISD::BITREVERSE, XLenVT, Legal);
168168

169+
if (Subtarget.hasStdExtZbt()) {
170+
setOperationAction(ISD::FSHL, XLenVT, Legal);
171+
setOperationAction(ISD::FSHR, XLenVT, Legal);
172+
}
173+
169174
ISD::CondCode FPCCToExtend[] = {
170175
ISD::SETOGT, ISD::SETOGE, ISD::SETONE, ISD::SETUEQ, ISD::SETUGT,
171176
ISD::SETUGE, ISD::SETULT, ISD::SETULE, ISD::SETUNE, ISD::SETGT,

llvm/lib/Target/RISCV/RISCVInstrInfoB.td

+39
Original file line numberDiff line numberDiff line change
@@ -643,6 +643,7 @@ def SLLIUWPat : ComplexPattern<i64, 2, "SelectSLLIUW", [and]>;
643643
def SLOIWPat : ComplexPattern<i64, 2, "SelectSLOIW", [sext_inreg]>;
644644
def SROIWPat : ComplexPattern<i64, 2, "SelectSROIW", [or]>;
645645
def RORIWPat : ComplexPattern<i64, 2, "SelectRORIW", [sext_inreg]>;
646+
def FSRIWPat : ComplexPattern<i64, 3, "SelectFSRIW", [sext_inreg]>;
646647

647648
let Predicates = [HasStdExtZbbOrZbp] in {
648649
def : Pat<(and GPR:$rs1, (not GPR:$rs2)), (ANDN GPR:$rs1, GPR:$rs2)>;
@@ -804,6 +805,19 @@ def : Pat<(bswap GPR:$rs1), (GREVI GPR:$rs1, (i64 56))>;
804805
def : Pat<(bitreverse GPR:$rs1), (GREVI GPR:$rs1, (i64 63))>;
805806
} // Predicates = [HasStdExtZbp, IsRV64]
806807

808+
let Predicates = [HasStdExtZbt] in {
809+
def : Pat<(or (and (xor GPR:$rs2, -1), GPR:$rs3), (and GPR:$rs2, GPR:$rs1)),
810+
(CMIX GPR:$rs1, GPR:$rs2, GPR:$rs3)>;
811+
def : Pat<(riscv_selectcc GPR:$rs2, (XLenVT 0), (XLenVT 17), GPR:$rs3, GPR:$rs1),
812+
(CMOV GPR:$rs1, GPR:$rs2, GPR:$rs3)>;
813+
def : Pat<(fshl GPR:$rs1, GPR:$rs2, GPR:$rs3),
814+
(FSL GPR:$rs1, GPR:$rs2, GPR:$rs3)>;
815+
def : Pat<(fshr GPR:$rs1, GPR:$rs2, GPR:$rs3),
816+
(FSR GPR:$rs1, GPR:$rs2, GPR:$rs3)>;
817+
def : Pat<(fshr GPR:$rs1, GPR:$rs2, uimmlog2xlen:$shamt),
818+
(FSRI GPR:$rs1, GPR:$rs2, uimmlog2xlen:$shamt)>;
819+
} // Predicates = [HasStdExtZbt]
820+
807821
let Predicates = [HasStdExtZbb] in {
808822
def : Pat<(ctlz GPR:$rs1), (CLZ GPR:$rs1)>;
809823
def : Pat<(cttz GPR:$rs1), (CTZ GPR:$rs1)>;
@@ -1004,6 +1018,31 @@ def : Pat<(sra (bswap GPR:$rs1), (i64 32)), (GREVIW GPR:$rs1, (i64 24))>;
10041018
def : Pat<(sra (bitreverse GPR:$rs1), (i64 32)), (GREVIW GPR:$rs1, (i64 31))>;
10051019
} // Predicates = [HasStdExtZbp, IsRV64]
10061020

1021+
let Predicates = [HasStdExtZbt, IsRV64] in {
1022+
def : Pat<(riscv_selectcc (and (assertsexti32 GPR:$rs3), 31),
1023+
(i64 0),
1024+
(i64 17),
1025+
(assertsexti32 GPR:$rs1),
1026+
(or (riscv_sllw (assertsexti32 GPR:$rs1),
1027+
(and (assertsexti32 GPR:$rs3), 31)),
1028+
(riscv_srlw (assertsexti32 GPR:$rs2),
1029+
(sub (i64 32),
1030+
(assertsexti32 GPR:$rs3))))),
1031+
(FSLW GPR:$rs1, GPR:$rs2, GPR:$rs3)>;
1032+
def : Pat<(riscv_selectcc (and (assertsexti32 GPR:$rs3), 31),
1033+
(i64 0),
1034+
(i64 17),
1035+
(assertsexti32 GPR:$rs2),
1036+
(or (riscv_sllw (assertsexti32 GPR:$rs1),
1037+
(sub (i64 32),
1038+
(assertsexti32 GPR:$rs3))),
1039+
(riscv_srlw (assertsexti32 GPR:$rs2),
1040+
(and (assertsexti32 GPR:$rs3), 31)))),
1041+
(FSRW GPR:$rs1, GPR:$rs2, GPR:$rs3)>;
1042+
def : Pat<(FSRIWPat GPR:$rs1, GPR:$rs2, uimmlog2xlen:$shamt),
1043+
(FSRIW GPR:$rs1, GPR:$rs2, uimmlog2xlen:$shamt)>;
1044+
} // Predicates = [HasStdExtZbt, IsRV64]
1045+
10071046
let Predicates = [HasStdExtZbb, IsRV64] in {
10081047
def : Pat<(add (ctlz (and GPR:$rs1, (i64 0xFFFFFFFF))), (i64 -32)),
10091048
(CLZW GPR:$rs1)>;

0 commit comments

Comments
 (0)