Skip to content

Commit d036381

Browse files
authored
[RISCV] Add changes to have better coverage for qc.insb and qc.insbi (#154135)
Before this patch, the selection for `QC_INSB` and `QC_INSBI` entirely happens in C++, and does not support more than one non-constant input. This patch seeks to rectify this shortcoming, by moving the C++ into a target-specific DAGCombine, and adding `RISCV::QC_INSB`. One advantage is this simplifies the code for handling `QC_INSBI`, as the C++ no longer needs to choose between the two instructions based on the inserted value (this is still done, but via ISel Patterns). Another advantage of the DAGCombine is that this introduction can also shift the inserted value to the `QC_INSB`, which our patterns need (and were previously doing to the constant), and this shift can be CSE'd/optimised with any prior shifts, if they exist. This allows the inserted value to be variable, rather than a constant.
1 parent 655cdf2 commit d036381

File tree

5 files changed

+179
-238
lines changed

5 files changed

+179
-238
lines changed

llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -819,49 +819,6 @@ bool RISCVDAGToDAGISel::trySignedBitfieldInsertInSign(SDNode *Node) {
819819
return false;
820820
}
821821

822-
// (xor X, (and (xor X, C1), C2))
823-
// -> (qc.insbi X, (C1 >> ShAmt), Width, ShAmt)
824-
// where C2 is a shifted mask with width=Width and shift=ShAmt
825-
bool RISCVDAGToDAGISel::tryBitfieldInsertOpFromXor(SDNode *Node) {
826-
827-
if (!Subtarget->hasVendorXqcibm())
828-
return false;
829-
830-
using namespace SDPatternMatch;
831-
832-
SDValue X;
833-
APInt CImm, CMask;
834-
if (!sd_match(
835-
Node,
836-
m_Xor(m_Value(X),
837-
m_OneUse(m_And(m_OneUse(m_Xor(m_Deferred(X), m_ConstInt(CImm))),
838-
m_ConstInt(CMask))))))
839-
return false;
840-
841-
unsigned Width, ShAmt;
842-
if (!CMask.isShiftedMask(ShAmt, Width))
843-
return false;
844-
845-
int64_t Imm = CImm.getSExtValue();
846-
Imm >>= ShAmt;
847-
848-
SDLoc DL(Node);
849-
SDValue ImmNode;
850-
auto Opc = RISCV::QC_INSB;
851-
852-
if (isInt<5>(Imm)) {
853-
Opc = RISCV::QC_INSBI;
854-
ImmNode = CurDAG->getSignedTargetConstant(Imm, DL, MVT::i32);
855-
} else {
856-
ImmNode = selectImm(CurDAG, DL, MVT::i32, Imm, *Subtarget);
857-
}
858-
SDValue Ops[] = {X, ImmNode, CurDAG->getTargetConstant(Width, DL, MVT::i32),
859-
CurDAG->getTargetConstant(ShAmt, DL, MVT::i32)};
860-
ReplaceNode(Node, CurDAG->getMachineNode(Opc, DL, MVT::i32, Ops));
861-
862-
return true;
863-
}
864-
865822
bool RISCVDAGToDAGISel::tryUnsignedBitfieldExtract(SDNode *Node,
866823
const SDLoc &DL, MVT VT,
867824
SDValue X, unsigned Msb,
@@ -1442,9 +1399,6 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
14421399
if (tryShrinkShlLogicImm(Node))
14431400
return;
14441401

1445-
if (tryBitfieldInsertOpFromXor(Node))
1446-
return;
1447-
14481402
break;
14491403
case ISD::AND: {
14501404
auto *N1C = dyn_cast<ConstantSDNode>(Node->getOperand(1));

llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ class RISCVDAGToDAGISel : public SelectionDAGISel {
7575
bool trySignedBitfieldExtract(SDNode *Node);
7676
bool trySignedBitfieldInsertInSign(SDNode *Node);
7777
bool trySignedBitfieldInsertInMask(SDNode *Node);
78-
bool tryBitfieldInsertOpFromXor(SDNode *Node);
7978
bool tryBitfieldInsertOpFromOrAndImm(SDNode *Node);
8079
bool tryUnsignedBitfieldExtract(SDNode *Node, const SDLoc &DL, MVT VT,
8180
SDValue X, unsigned Msb, unsigned Lsb);

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16156,6 +16156,48 @@ static SDValue combineOrOfCZERO(SDNode *N, SDValue N0, SDValue N1,
1615616156
return DAG.getNode(ISD::XOR, DL, VT, NewOr, TrueV.getOperand(1));
1615716157
}
1615816158

16159+
// (xor X, (xor (and X, C2), Y))
16160+
// ->(qc_insb X, (sra Y, ShAmt), Width, ShAmt)
16161+
// where C2 is a shifted mask with width = Width and shift = ShAmt
16162+
// qc_insb might become qc.insb or qc.insbi depending on the operands.
16163+
static SDValue combineXorToBitfieldInsert(SDNode *N, SelectionDAG &DAG,
16164+
const RISCVSubtarget &Subtarget) {
16165+
if (!Subtarget.hasVendorXqcibm())
16166+
return SDValue();
16167+
16168+
using namespace SDPatternMatch;
16169+
16170+
SDValue Base, Inserted;
16171+
APInt CMask;
16172+
if (!sd_match(N, m_Xor(m_Value(Base),
16173+
m_OneUse(m_Xor(m_OneUse(m_And(m_Deferred(Base),
16174+
m_ConstInt(CMask))),
16175+
m_Value(Inserted))))))
16176+
return SDValue();
16177+
16178+
if (N->getValueType(0) != MVT::i32)
16179+
return SDValue();
16180+
16181+
unsigned Width, ShAmt;
16182+
if (!CMask.isShiftedMask(ShAmt, Width))
16183+
return SDValue();
16184+
16185+
// Check if all zero bits in CMask are also zero in Inserted
16186+
if (!DAG.MaskedValueIsZero(Inserted, ~CMask))
16187+
return SDValue();
16188+
16189+
SDLoc DL(N);
16190+
16191+
// `Inserted` needs to be right shifted before it is put into the
16192+
// instruction.
16193+
Inserted = DAG.getNode(ISD::SRA, DL, MVT::i32, Inserted,
16194+
DAG.getShiftAmountConstant(ShAmt, MVT::i32, DL));
16195+
16196+
SDValue Ops[] = {Base, Inserted, DAG.getConstant(Width, DL, MVT::i32),
16197+
DAG.getConstant(ShAmt, DL, MVT::i32)};
16198+
return DAG.getNode(RISCVISD::QC_INSB, DL, MVT::i32, Ops);
16199+
}
16200+
1615916201
static SDValue performORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI,
1616016202
const RISCVSubtarget &Subtarget) {
1616116203
SelectionDAG &DAG = DCI.DAG;
@@ -16228,6 +16270,9 @@ static SDValue performXORCombine(SDNode *N, SelectionDAG &DAG,
1622816270
}
1622916271
}
1623016272

16273+
if (SDValue V = combineXorToBitfieldInsert(N, DAG, Subtarget))
16274+
return V;
16275+
1623116276
if (SDValue V = combineBinOpToReduce(N, DAG, Subtarget))
1623216277
return V;
1623316278
if (SDValue V = combineBinOpOfExtractToReduceTree(N, DAG, Subtarget))

llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ def SDT_SetMultiple : SDTypeProfile<0, 4, [SDTCisSameAs<0, 1>,
2222
def qc_setwmi : RVSDNode<"QC_SETWMI", SDT_SetMultiple,
2323
[SDNPHasChain, SDNPMayStore, SDNPMemOperand]>;
2424

25+
def qc_insb : RVSDNode<"QC_INSB", SDTypeProfile<1, 4, [SDTCisSameAs<0, 1>,
26+
SDTCisSameAs<0, 2>,
27+
SDTCisVT<0, i32>,
28+
SDTCisInt<3>,
29+
SDTCisInt<4>]>,
30+
[]>;
31+
2532
def uimm5nonzero : RISCVOp<XLenVT>,
2633
ImmLeaf<XLenVT, [{return (Imm != 0) && isUInt<5>(Imm);}]> {
2734
let ParserMatchClass = UImmAsmOperand<5, "NonZero">;
@@ -1508,6 +1515,11 @@ def : Pat<(i32 (and GPRNoX0:$rs, 1023)), (QC_EXTU GPRNoX0:$rs, 10, 0)>;
15081515
def : Pat<(i32 (and GPRNoX0:$rs, 2047)), (QC_EXTU GPRNoX0:$rs, 11, 0)>;
15091516

15101517
def : Pat<(i32 (bitreverse GPRNoX0:$rs1)), (QC_BREV32 GPRNoX0:$rs1)>;
1518+
1519+
def : Pat<(qc_insb GPRNoX0:$rd, simm5:$imm5, uimm5_plus1:$width, uimm5:$shamt),
1520+
(QC_INSBI GPRNoX0:$rd, simm5:$imm5, uimm5_plus1:$width, uimm5:$shamt)>;
1521+
def : Pat<(qc_insb GPRNoX0:$rd, GPR:$rs1, uimm5_plus1:$width, uimm5:$shamt),
1522+
(QC_INSB GPRNoX0:$rd, GPR:$rs1, uimm5_plus1:$width, uimm5:$shamt)>;
15111523
} // Predicates = [HasVendorXqcibm, IsRV32]
15121524

15131525
// If Zbb is enabled sext.b/h is preferred since they are compressible

0 commit comments

Comments
 (0)