Skip to content

[RISCV] Implement CodeGen Support for XCValu Extension in CV32E40P #78138

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

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all 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
28 changes: 28 additions & 0 deletions llvm/include/llvm/IR/IntrinsicsRISCVXCV.td
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,18 @@ class ScalarCoreVBitManipGprIntrinsic
: DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty],
[IntrNoMem, IntrSpeculatable]>;

class ScalarCoreVAluGprIntrinsic
: DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty],
[IntrNoMem, IntrSpeculatable]>;

class ScalarCoreVAluGprGprIntrinsic
: DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty],
[IntrNoMem, IntrSpeculatable]>;

class ScalarCoreVAluGprGprGprIntrinsic
: DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
[IntrNoMem, IntrSpeculatable]>;

let TargetPrefix = "riscv" in {
def int_riscv_cv_bitmanip_extract : ScalarCoreVBitManipGprGprIntrinsic;
def int_riscv_cv_bitmanip_extractu : ScalarCoreVBitManipGprGprIntrinsic;
Expand All @@ -34,4 +46,20 @@ let TargetPrefix = "riscv" in {
: DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
[IntrNoMem, IntrWillReturn, IntrSpeculatable,
ImmArg<ArgIndex<1>>, ImmArg<ArgIndex<2>>]>;

def int_riscv_cv_alu_exths : ScalarCoreVAluGprIntrinsic;
def int_riscv_cv_alu_exthz : ScalarCoreVAluGprIntrinsic;
def int_riscv_cv_alu_extbs : ScalarCoreVAluGprIntrinsic;
def int_riscv_cv_alu_extbz : ScalarCoreVAluGprIntrinsic;

def int_riscv_cv_alu_clip : ScalarCoreVAluGprGprIntrinsic;
def int_riscv_cv_alu_clipu : ScalarCoreVAluGprGprIntrinsic;
def int_riscv_cv_alu_addn : ScalarCoreVAluGprGprGprIntrinsic;
def int_riscv_cv_alu_addun : ScalarCoreVAluGprGprGprIntrinsic;
def int_riscv_cv_alu_addrn : ScalarCoreVAluGprGprGprIntrinsic;
def int_riscv_cv_alu_addurn : ScalarCoreVAluGprGprGprIntrinsic;
def int_riscv_cv_alu_subn : ScalarCoreVAluGprGprGprIntrinsic;
def int_riscv_cv_alu_subun : ScalarCoreVAluGprGprGprIntrinsic;
def int_riscv_cv_alu_subrn : ScalarCoreVAluGprGprGprIntrinsic;
def int_riscv_cv_alu_suburn : ScalarCoreVAluGprGprGprIntrinsic;
} // TargetPrefix = "riscv"
16 changes: 14 additions & 2 deletions llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,10 +250,12 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
if (RV64LegalI32 && Subtarget.is64Bit())
setOperationAction(ISD::SELECT_CC, MVT::i32, Expand);

setCondCodeAction(ISD::SETLE, XLenVT, Expand);
if (!Subtarget.hasVendorXCValu())
setCondCodeAction(ISD::SETLE, XLenVT, Expand);
setCondCodeAction(ISD::SETGT, XLenVT, Custom);
setCondCodeAction(ISD::SETGE, XLenVT, Expand);
setCondCodeAction(ISD::SETULE, XLenVT, Expand);
if (!Subtarget.hasVendorXCValu())
setCondCodeAction(ISD::SETULE, XLenVT, Expand);
setCondCodeAction(ISD::SETUGT, XLenVT, Custom);
setCondCodeAction(ISD::SETUGE, XLenVT, Expand);

Expand Down Expand Up @@ -1433,6 +1435,16 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
}
}

if (Subtarget.hasVendorXCValu()) {
setOperationAction(ISD::ABS, XLenVT, Legal);
setOperationAction(ISD::SMIN, XLenVT, Legal);
setOperationAction(ISD::UMIN, XLenVT, Legal);
setOperationAction(ISD::SMAX, XLenVT, Legal);
setOperationAction(ISD::UMAX, XLenVT, Legal);
setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8, Legal);
setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Legal);
}

// Function alignments.
const Align FunctionAlignment(Subtarget.hasStdExtCOrZca() ? 2 : 4);
setMinFunctionAlignment(FunctionAlignment);
Expand Down
162 changes: 157 additions & 5 deletions llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ let DecoderNamespace = "XCValu" in {

} // DecoderNamespace = "XCValu"

let Predicates = [HasVendorXCValu],
let Predicates = [HasVendorXCValu, IsRV32],
hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
// General ALU Operations
def CV_ABS : CVInstAluR<0b0101000, 0b011, "cv.abs">,
Expand Down Expand Up @@ -249,10 +249,10 @@ let Predicates = [HasVendorXCValu],
Sched<[]>;
def CV_SUBURN : CVInstAluRRI<0b11, 0b011, "cv.suburn">,
Sched<[]>;
} // Predicates = [HasVendorXCValu],
} // Predicates = [HasVendorXCValu, IsRV32],
// hasSideEffects = 0, mayLoad = 0, mayStore = 0

let Predicates = [HasVendorXCValu],
let Predicates = [HasVendorXCValu, IsRV32],
hasSideEffects = 0, mayLoad = 0, mayStore = 0,
Constraints = "$rd = $rd_wb" in {
def CV_ADDNR : CVInstAluRRNR<0b1000000, 0b011, "cv.addnr">,
Expand All @@ -272,7 +272,7 @@ let Predicates = [HasVendorXCValu],
def CV_SUBURNR : CVInstAluRRNR<0b1000111, 0b011, "cv.suburnr">,
Sched<[]>;

} // Predicates = [HasVendorXCValu],
} // Predicates = [HasVendorXCValu, IsRV32],
// hasSideEffects = 0, mayLoad = 0, mayStore = 0,
// Constraints = "$rd = $rd_wb"

Expand Down Expand Up @@ -662,6 +662,8 @@ let Predicates = [HasVendorXCVelw, IsRV32], hasSideEffects = 0,
def cv_tuimm2 : TImmLeaf<XLenVT, [{return isUInt<2>(Imm);}]>;
def cv_tuimm5 : TImmLeaf<XLenVT, [{return isUInt<5>(Imm);}]>;
def cv_uimm10 : ImmLeaf<XLenVT, [{return isUInt<10>(Imm);}]>;
def cv_uimm_pow2: Operand<XLenVT>,
ImmLeaf<XLenVT, [{return isPowerOf2_32(Imm + 1);}]>;

def CV_LO5: SDNodeXForm<imm, [{
return CurDAG->getTargetConstant(N->getZExtValue() & 0x1f, SDLoc(N),
Expand All @@ -673,6 +675,50 @@ def CV_HI5: SDNodeXForm<imm, [{
N->getValueType(0));
}]>;

def positive : PatFrags<(ops node:$value),
[(abs node:$value), (and node:$value, 0x7FFFFFFF)]>;
def between : PatFrags<(ops node:$lowerBound, node:$upperBound, node:$value),
[(smin (smax node:$value, node:$lowerBound), node:$upperBound),
(smax (smin node:$value, node:$upperBound), node:$lowerBound)]>;
def betweenu : PatFrags<(ops node:$upperBound, node:$value),
[(smin (smax node:$value, 0), node:$upperBound),
(smax (smin node:$value, node:$upperBound), 0)]>;
def powerOf2 : ImmLeaf<XLenVT, [{ return isPowerOf2_32(Imm); }]>;
def powerOf2Minus1 : ImmLeaf<XLenVT, [{ return isPowerOf2_32(Imm+1); }]>;
def negativePowerOf2 : ImmLeaf<XLenVT, [{ return isPowerOf2_32(-Imm); }]>;
def roundBit : PatFrag<(ops node:$shiftAmount),
(srl (shl 1, node:$shiftAmount), (XLenVT 1))>;
def trailing1sPlus1 : SDNodeXForm<imm, [{
return CurDAG->getTargetConstant(
llvm::countr_one(N->getZExtValue()) + 1,
SDLoc(N), N->getValueType(0));
}]>;

def shiftRound : PatFrag<(ops node:$value, node:$shiftAmount),
(sra (add node:$value, powerOf2), node:$shiftAmount), [{
if (auto powerOf2 = dyn_cast<ConstantSDNode>(N->getOperand(0)->getOperand(1)))
return (powerOf2->getZExtValue() << 1) == (1U << N->getConstantOperandVal(1));
return false;
}]>;

def ushiftRound : PatFrag<(ops node:$value, node:$shiftAmount),
(srl (add node:$value, powerOf2), node:$shiftAmount), [{
if (auto powerOf2 = dyn_cast<ConstantSDNode>(N->getOperand(0)->getOperand(1)))
return (powerOf2->getZExtValue() << 1) == (1U << N->getConstantOperandVal(1));
return false;
}]>;

def clip : PatFrag<(ops node:$upperBound, node:$value),
(between negativePowerOf2, node:$upperBound, node:$value), [{
// Checking lower & upper bound for the clip instruction
if (auto bound1 = dyn_cast<ConstantSDNode>(N->getOperand(0)->getOperand(1))) {
if (auto bound2 = dyn_cast<ConstantSDNode>(N->getOperand(1))) {
return (bound1->getSExtValue() == ~bound2->getSExtValue());
}
}
return false;
}]>;

multiclass PatCoreVBitManip<Intrinsic intr> {
def : PatGprGpr<intr, !cast<RVInst>("CV_" # NAME # "R")>;
def : Pat<(intr GPR:$rs1, cv_uimm10:$imm),
Expand Down Expand Up @@ -705,8 +751,114 @@ let Predicates = [HasVendorXCVbitmanip, IsRV32] in {
def : Pat<(bitreverse (XLenVT GPR:$rs)), (CV_BITREV GPR:$rs, 0, 0)>;
}

class PatCoreVAluGpr <string intr, string asm> :
PatGpr<!cast<Intrinsic>("int_riscv_cv_alu_" # intr),
!cast<RVInst>("CV_" # asm)>;
class PatCoreVAluGprGpr <string intr, string asm> :
PatGprGpr<!cast<Intrinsic>("int_riscv_cv_alu_" # intr),
!cast<RVInst>("CV_" # asm)>;

multiclass PatCoreVAluGprImm <Intrinsic intr> {
def : PatGprGpr<intr, !cast<RVInst>("CV_" # NAME # "R")>;
def : Pat<(intr (XLenVT GPR:$rs1), powerOf2Minus1:$upperBound),
(!cast<RVInst>("CV_" # NAME) GPR:$rs1,
(trailing1sPlus1 imm:$upperBound))>;
}

multiclass PatCoreVAluGprGprImm <Intrinsic intr> {
def : Pat<(intr GPR:$rs1, GPR:$rs2, GPR:$rs3),
(!cast<RVInst>("CV_" # NAME # "R") GPR:$rs1, GPR:$rs2, GPR:$rs3)>;
def : Pat<(intr GPR:$rs1, GPR:$rs2, uimm5:$imm),
(!cast<RVInst>("CV_" # NAME) GPR:$rs1, GPR:$rs2, uimm5:$imm)>;
}

let Predicates = [HasVendorXCValu, IsRV32], AddedComplexity = 1 in {
def : PatGpr<abs, CV_ABS>;
def : PatGprGpr<setle, CV_SLET>;
def : PatGprGpr<setule, CV_SLETU>;
def : PatGprGpr<smin, CV_MIN>;
def : PatGprGpr<umin, CV_MINU>;
def : PatGprGpr<smax, CV_MAX>;
def : PatGprGpr<umax, CV_MAXU>;

def : Pat<(sext_inreg (XLenVT GPR:$rs1), i16), (CV_EXTHS GPR:$rs1)>;
def : Pat<(sext_inreg (XLenVT GPR:$rs1), i8), (CV_EXTBS GPR:$rs1)>;

def : Pat<(and (XLenVT GPR:$rs1), 0xffff), (CV_EXTHZ GPR:$rs1)>;
def : Pat<(and (XLenVT GPR:$rs1), 0xff), (CV_EXTBZ GPR:$rs1)>;

def : Pat<(clip powerOf2Minus1:$upperBound, (XLenVT GPR:$rs1)),
(CV_CLIP GPR:$rs1, (trailing1sPlus1 imm:$upperBound))>;
def : Pat<(between (not (positive GPR:$rs2)), (positive GPR:$rs2), (XLenVT GPR:$rs1)),
(CV_CLIPR GPR:$rs1, GPR:$rs2)>;
def : Pat<(betweenu powerOf2Minus1:$upperBound, (XLenVT GPR:$rs1)),
(CV_CLIPU GPR:$rs1, (trailing1sPlus1 imm:$upperBound))>;
def : Pat<(betweenu (positive GPR:$rs2), (XLenVT GPR:$rs1)),
(CV_CLIPUR GPR:$rs1, GPR:$rs2)>;

def : Pat<(sra (add (XLenVT GPR:$rs1), (XLenVT GPR:$rs2)), uimm5:$imm5),
(CV_ADDN GPR:$rs1, GPR:$rs2, uimm5:$imm5)>;
def : Pat<(srl (add (XLenVT GPR:$rs1), (XLenVT GPR:$rs2)), uimm5:$imm5),
(CV_ADDUN GPR:$rs1, GPR:$rs2, uimm5:$imm5)>;
def : Pat<(shiftRound (add (XLenVT GPR:$rs1), (XLenVT GPR:$rs2)),
uimm5:$imm5),
(CV_ADDRN GPR:$rs1, GPR:$rs2, uimm5:$imm5)>;
def : Pat<(ushiftRound (add (XLenVT GPR:$rs1), (XLenVT GPR:$rs2)),
uimm5:$imm5),
(CV_ADDURN GPR:$rs1, GPR:$rs2, uimm5:$imm5)>;

def : Pat<(sra (sub (XLenVT GPR:$rs1), (XLenVT GPR:$rs2)), uimm5:$imm5),
(CV_SUBN GPR:$rs1, GPR:$rs2, uimm5:$imm5)>;
def : Pat<(srl (sub (XLenVT GPR:$rs1), (XLenVT GPR:$rs2)), uimm5:$imm5),
(CV_SUBUN GPR:$rs1, GPR:$rs2, uimm5:$imm5)>;
def : Pat<(shiftRound (sub (XLenVT GPR:$rs1), (XLenVT GPR:$rs2)),
uimm5:$imm5),
(CV_SUBRN GPR:$rs1, GPR:$rs2, uimm5:$imm5)>;
def : Pat<(ushiftRound (sub (XLenVT GPR:$rs1), (XLenVT GPR:$rs2)),
uimm5:$imm5),
(CV_SUBURN GPR:$rs1, GPR:$rs2, uimm5:$imm5)>;

def : Pat<(sra (add (XLenVT GPR:$rd), (XLenVT GPR:$rs1)), (XLenVT GPR:$rs2)),
(CV_ADDNR GPR:$rd, GPR:$rs1, GPR:$rs2)>;
def : Pat<(srl (add (XLenVT GPR:$rd), (XLenVT GPR:$rs1)), (XLenVT GPR:$rs2)),
(CV_ADDUNR GPR:$rd, GPR:$rs1, GPR:$rs2)>;
def : Pat<(sra (add (add (XLenVT GPR:$rd), (XLenVT GPR:$rs1)),
(roundBit (XLenVT GPR:$rs2))), (XLenVT GPR:$rs2)),
(CV_ADDRNR GPR:$rd, GPR:$rs1, GPR:$rs2)>;
def : Pat<(srl (add (add (XLenVT GPR:$rd), (XLenVT GPR:$rs1)),
(roundBit (XLenVT GPR:$rs2))), (XLenVT GPR:$rs2)),
(CV_ADDURNR GPR:$rd, GPR:$rs1, GPR:$rs2)>;

def : Pat<(sra (sub (XLenVT GPR:$rd), (XLenVT GPR:$rs1)), (XLenVT GPR:$rs2)),
(CV_SUBNR GPR:$rd, GPR:$rs1, GPR:$rs2)>;
def : Pat<(srl (sub (XLenVT GPR:$rd), (XLenVT GPR:$rs1)), (XLenVT GPR:$rs2)),
(CV_SUBUNR GPR:$rd, GPR:$rs1, GPR:$rs2)>;
def : Pat<(sra (add (sub (XLenVT GPR:$rd), (XLenVT GPR:$rs1)),
(roundBit (XLenVT GPR:$rs2))), (XLenVT GPR:$rs2)),
(CV_SUBRNR GPR:$rd, GPR:$rs1, GPR:$rs2)>;
def : Pat<(srl (add (sub (XLenVT GPR:$rd), (XLenVT GPR:$rs1)),
(roundBit (XLenVT GPR:$rs2))), (XLenVT GPR:$rs2)),
(CV_SUBURNR GPR:$rd, GPR:$rs1, GPR:$rs2)>;

def : PatCoreVAluGpr<"exths", "EXTHS">;
def : PatCoreVAluGpr<"exthz", "EXTHZ">;
def : PatCoreVAluGpr<"extbs", "EXTBS">;
def : PatCoreVAluGpr<"extbz", "EXTBZ">;

defm CLIP : PatCoreVAluGprImm<int_riscv_cv_alu_clip>;
defm CLIPU : PatCoreVAluGprImm<int_riscv_cv_alu_clipu>;
defm ADDN : PatCoreVAluGprGprImm<int_riscv_cv_alu_addn>;
defm ADDUN : PatCoreVAluGprGprImm<int_riscv_cv_alu_addun>;
defm ADDRN : PatCoreVAluGprGprImm<int_riscv_cv_alu_addrn>;
defm ADDURN : PatCoreVAluGprGprImm<int_riscv_cv_alu_addurn>;
defm SUBN : PatCoreVAluGprGprImm<int_riscv_cv_alu_subn>;
defm SUBUN : PatCoreVAluGprGprImm<int_riscv_cv_alu_subun>;
defm SUBRN : PatCoreVAluGprGprImm<int_riscv_cv_alu_subrn>;
defm SUBURN : PatCoreVAluGprGprImm<int_riscv_cv_alu_suburn>;
} // Predicates = [HasVendorXCValu, IsRV32]

//===----------------------------------------------------------------------===//
// Patterns for immediate branching operations
// Patterns for immediate branching operations
//===----------------------------------------------------------------------===//

let Predicates = [HasVendorXCVbi, IsRV32], AddedComplexity = 2 in {
Expand Down
Loading
Loading