Skip to content

[RISCV] Add ISel patterns for Qualcomm uC Xqcicli extension #148121

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 15, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions llvm/lib/Target/RISCV/RISCVFeatures.td
Original file line number Diff line number Diff line change
Expand Up @@ -1488,6 +1488,9 @@ def HasVendorXqcics
AssemblerPredicate<(all_of FeatureVendorXqcics),
"'Xqcics' (Qualcomm uC Conditional Select Extension)">;

def HasVendorXqcicsOrXqcicm
: Predicate<"Subtarget->hasVendorXqcics() || Subtarget->hasVendorXqcicm()">;

def FeatureVendorXqcicsr
: RISCVExperimentalExtension<0, 4, "Qualcomm uC CSR Extension">;
def HasVendorXqcicsr
Expand Down
46 changes: 46 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
Original file line number Diff line number Diff line change
Expand Up @@ -1336,6 +1336,22 @@ class QCISELECTIICCPat<CondCode Cond, QCISELECTIICC Inst>
: Pat<(select (XLenVT (setcc (XLenVT GPRNoX0:$rd), (XLenVT GPRNoX0:$rs1), Cond)), simm5:$simm1, simm5:$simm2),
(Inst GPRNoX0:$rd, GPRNoX0:$rs1, simm5:$simm1, simm5:$simm2)>;

class QCILICCPat<CondCode Cond, QCILICC Inst>
: Pat<(select (XLenVT (setcc (XLenVT GPRNoX0:$rs1), (XLenVT GPRNoX0:$rs2), Cond)), simm5:$simm, (XLenVT GPRNoX0:$rd)),
(Inst GPRNoX0:$rd, GPRNoX0:$rs1, GPRNoX0:$rs2, simm5:$simm)>;

class QCILICCPatInv<CondCode Cond, QCILICC Inst>
: Pat<(select (XLenVT (setcc (XLenVT GPRNoX0:$rs1), (XLenVT GPRNoX0:$rs2), Cond)), (XLenVT GPRNoX0:$rd), simm5:$simm),
(Inst GPRNoX0:$rd, GPRNoX0:$rs1, GPRNoX0:$rs2, simm5:$simm)>;

class QCILICCIPat<CondCode Cond, QCILICC Inst, DAGOperand InTyImm>
: Pat<(select (XLenVT (setcc (XLenVT GPRNoX0:$rs1), InTyImm:$imm, Cond)), simm5:$simm, (XLenVT GPRNoX0:$rd)),
(Inst GPRNoX0:$rd, GPRNoX0:$rs1, InTyImm:$imm, simm5:$simm)>;

class QCILICCIPatInv<CondCode Cond, QCILICC Inst, DAGOperand InTyImm>
: Pat<(select (XLenVT (setcc (XLenVT GPRNoX0:$rs1), InTyImm:$imm, Cond)), (XLenVT GPRNoX0:$rd), simm5:$simm),
(Inst GPRNoX0:$rd, GPRNoX0:$rs1, InTyImm:$imm, simm5:$simm)>;

// Match `riscv_brcc` and lower to the appropriate XQCIBI branch instruction.
class BcciPat<CondCode Cond, QCIBranchInst_rii Inst, DAGOperand InTyImm>
: Pat<(riscv_brcc (XLenVT GPRNoX0:$rs1), InTyImm:$rs2, Cond, bb:$imm12),
Expand Down Expand Up @@ -1485,6 +1501,36 @@ def : QCIMVCCIPat <SETLT, QC_MVLTI, simm5>;
def : QCIMVCCIPat <SETULT, QC_MVLTUI, uimm5>;
}

let Predicates = [HasVendorXqcicli, HasVendorXqcicsOrXqcicm, IsRV32] in {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's complex and a comment would be helpful, so maybe I'll sketch one out.

These patterns are written using select, which is normally not legal on RISC-V. We cannot mark select as legal when we only have xqcicli, because we cannot isel a select of a condition and two arbitrary xlen values (in registers) when we only have xqcicli (there is no instruction in the extension that can do so).

But we only care about codegen for configs where we have both xqcics/xqcicm and xqcicli - we can sort-of see xqcicli as an optimisation of the other two. If we have either of the other two, then we have marked select as legal and we can lower a select with a condition and two xlen values (in registers).

These patterns would only be used if we have one of the other two extensions, so make that clear with their predicates.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious why you want select to be legal for any of the Xqc instructions. It looks like select_cc (either the RISCVISD version or the ISD version) is a better match for the ISA.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I advised towards this way because I felt our best aim was to try to keep to standard nodes (which is why i avoided riscvisd::select_cc), and to try to keep to what was mostly already happening in RISC-V (which is why i avoided isd::select_cc), but evidently that instinct isn't quite right.

I would like to proceed with this approach for this patch, and later we can refactor to riscvisd::select_cc, I think.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to proceed with this approach for this patch, and later we can refactor to riscvisd::select_cc, I think.

I'm fine with that.

def : QCILICCPat <SETEQ, QC_LIEQ>;
def : QCILICCPat <SETNE, QC_LINE>;
def : QCILICCPat <SETLT, QC_LILT>;
def : QCILICCPat <SETGE, QC_LIGE>;
def : QCILICCPat <SETULT, QC_LILTU>;
def : QCILICCPat <SETUGE, QC_LIGEU>;

def : QCILICCIPat <SETEQ, QC_LIEQI, simm5>;
def : QCILICCIPat <SETNE, QC_LINEI, simm5>;
def : QCILICCIPat <SETLT, QC_LILTI, simm5>;
def : QCILICCIPat <SETGE, QC_LIGEI, simm5>;
def : QCILICCIPat <SETULT, QC_LILTUI, uimm5>;
def : QCILICCIPat <SETUGE, QC_LIGEUI, uimm5>;

def : QCILICCPatInv <SETNE, QC_LIEQ>;
def : QCILICCPatInv <SETEQ, QC_LINE>;
def : QCILICCPatInv <SETGE, QC_LILT>;
def : QCILICCPatInv <SETLT, QC_LIGE>;
def : QCILICCPatInv <SETUGE, QC_LILTU>;
def : QCILICCPatInv <SETULT, QC_LIGEU>;

def : QCILICCIPatInv <SETNE, QC_LIEQI, simm5>;
def : QCILICCIPatInv <SETEQ, QC_LINEI, simm5>;
def : QCILICCIPatInv <SETGE, QC_LILTI, simm5>;
def : QCILICCIPatInv <SETLT, QC_LIGEI, simm5>;
def : QCILICCIPatInv <SETUGE, QC_LILTUI, uimm5>;
def : QCILICCIPatInv <SETULT, QC_LIGEUI, uimm5>;
}

let Predicates = [HasVendorXqcics, IsRV32] in {
def : Pat<(select (XLenVT GPRNoX0:$rd), (XLenVT GPRNoX0:$rs2),(XLenVT GPRNoX0:$rs3)),
(QC_SELECTNEI GPRNoX0:$rd, (XLenVT 0), GPRNoX0:$rs2, GPRNoX0:$rs3)>;
Expand Down
Loading
Loading