Skip to content

Commit

Permalink
[RISCV] Codegen support for XCVmem extension
Browse files Browse the repository at this point in the history
All post-Increment load/store, register-register load/store

spec:
https://github.com/openhwgroup/cv32e40p/blob/master/docs/source/instruction_set_extensions.rst
  • Loading branch information
ChunyuLiao committed Jan 5, 2024
1 parent 80889ae commit 26f3a72
Show file tree
Hide file tree
Showing 6 changed files with 446 additions and 2 deletions.
2 changes: 1 addition & 1 deletion llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1210,7 +1210,7 @@ struct RISCVOperand final : public MCParsedAsmOperand {
}

void addRegRegOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
assert(N == 2 && "Invalid number of operands!");
Inst.addOperand(MCOperand::createReg(RegReg.Reg1));
Inst.addOperand(MCOperand::createReg(RegReg.Reg2));
}
Expand Down
74 changes: 74 additions & 0 deletions llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1417,6 +1417,67 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
case ISD::LOAD: {
if (tryIndexedLoad(Node))
return;

if (Subtarget->hasVendorXCVmem()) {
// We match post-incrementing load here
LoadSDNode *Load = cast<LoadSDNode>(Node);
if (Load->getAddressingMode() != ISD::POST_INC)
break;

SDValue Chain = Node->getOperand(0);
SDValue Base = Node->getOperand(1);
SDValue Offset = Node->getOperand(2);

bool Simm12 = false;
bool SignExtend = Load->getExtensionType() == ISD::SEXTLOAD;

if (auto ConstantOffset = dyn_cast<ConstantSDNode>(Offset)) {
int ConstantVal = ConstantOffset->getSExtValue();
Simm12 = isInt<12>(ConstantVal);
if (Simm12)
Offset = CurDAG->getTargetConstant(ConstantVal, SDLoc(Offset),
Offset.getValueType());
}

unsigned Opcode = 0;
switch (Load->getMemoryVT().getSimpleVT().SimpleTy) {
case MVT::i8:
if (Simm12 && SignExtend)
Opcode = RISCV::CV_LB_ri_inc;
else if (Simm12 && !SignExtend)
Opcode = RISCV::CV_LBU_ri_inc;
else if (!Simm12 && SignExtend)
Opcode = RISCV::CV_LB_rr_inc;
else
Opcode = RISCV::CV_LBU_rr_inc;
break;
case MVT::i16:
if (Simm12 && SignExtend)
Opcode = RISCV::CV_LH_ri_inc;
else if (Simm12 && !SignExtend)
Opcode = RISCV::CV_LHU_ri_inc;
else if (!Simm12 && SignExtend)
Opcode = RISCV::CV_LH_rr_inc;
else
Opcode = RISCV::CV_LHU_rr_inc;
break;
case MVT::i32:
if (Simm12)
Opcode = RISCV::CV_LW_ri_inc;
else
Opcode = RISCV::CV_LW_rr_inc;
break;
default:
break;
}
if (!Opcode)
break;

ReplaceNode(Node, CurDAG->getMachineNode(Opcode, DL, XLenVT, XLenVT,
Chain.getSimpleValueType(), Base,
Offset, Chain));
return;
}
break;
}
case ISD::INTRINSIC_WO_CHAIN: {
Expand Down Expand Up @@ -2544,6 +2605,19 @@ bool RISCVDAGToDAGISel::SelectAddrRegImmLsb00000(SDValue Addr, SDValue &Base,
return true;
}

bool RISCVDAGToDAGISel::SelectAddrRegReg(SDValue Addr, SDValue &Base,
SDValue &Offset) {
if (Addr.getOpcode() != ISD::ADD)
return false;

if (isa<ConstantSDNode>(Addr.getOperand(1)))
return false;

Base = Addr.getOperand(1);
Offset = Addr.getOperand(0);
return true;
}

bool RISCVDAGToDAGISel::selectShiftMask(SDValue N, unsigned ShiftWidth,
SDValue &ShAmt) {
ShAmt = N;
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ class RISCVDAGToDAGISel : public SelectionDAGISel {
return false;
}

bool SelectAddrRegReg(SDValue Addr, SDValue &Base, SDValue &Offset);

bool tryShrinkShlLogicImm(SDNode *Node);
bool trySignedBitfieldExtract(SDNode *Node);
bool tryIndexedLoad(SDNode *Node);
Expand Down
30 changes: 30 additions & 0 deletions llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1366,6 +1366,16 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
}
}

if (Subtarget.hasVendorXCVmem()) {
setIndexedLoadAction(ISD::POST_INC, MVT::i8, Legal);
setIndexedLoadAction(ISD::POST_INC, MVT::i16, Legal);
setIndexedLoadAction(ISD::POST_INC, MVT::i32, Legal);

setIndexedStoreAction(ISD::POST_INC, MVT::i8, Legal);
setIndexedStoreAction(ISD::POST_INC, MVT::i16, Legal);
setIndexedStoreAction(ISD::POST_INC, MVT::i32, Legal);
}

// Function alignments.
const Align FunctionAlignment(Subtarget.hasStdExtCOrZca() ? 2 : 4);
setMinFunctionAlignment(FunctionAlignment);
Expand Down Expand Up @@ -19324,6 +19334,26 @@ bool RISCVTargetLowering::getPostIndexedAddressParts(SDNode *N, SDNode *Op,
SDValue &Offset,
ISD::MemIndexedMode &AM,
SelectionDAG &DAG) const {
if (Subtarget.hasVendorXCVmem()) {
if (Op->getOpcode() != ISD::ADD)
return false;

if (LSBaseSDNode *LS = dyn_cast<LSBaseSDNode>(N))
Base = LS->getBasePtr();
else
return false;

if (Base == Op->getOperand(0))
Offset = Op->getOperand(1);
else if (Base == Op->getOperand(1))
Offset = Op->getOperand(0);
else
return false;

AM = ISD::POST_INC;
return true;
}

EVT VT;
SDValue Ptr;
if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) {
Expand Down
45 changes: 44 additions & 1 deletion llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td
Original file line number Diff line number Diff line change
Expand Up @@ -512,11 +512,13 @@ def CVrrAsmOperand : AsmOperandClass {
let DiagnosticType = "InvalidRegReg";
}

def CVrr : Operand<OtherVT> {
def CVrr : Operand<i32>,
ComplexPattern<i32, 2, "SelectAddrRegReg",[]> {
let ParserMatchClass = CVrrAsmOperand;
let EncoderMethod = "getRegReg";
let DecoderMethod = "decodeRegReg";
let PrintMethod = "printRegReg";
let MIOperandInfo = (ops GPR:$base, GPR:$offset);
}

class CVLoad_ri_inc<bits<3> funct3, string opcodestr>
Expand Down Expand Up @@ -659,6 +661,47 @@ let Predicates = [HasVendorXCVelw, IsRV32], hasSideEffects = 0,
def CV_ELW : CVLoad_ri<0b011, "cv.elw">;
}

//===----------------------------------------------------------------------===//
// Patterns for load & store operations
//===----------------------------------------------------------------------===//
class CVLdrrPat<PatFrag LoadOp, RVInst Inst>
: Pat<(XLenVT (LoadOp CVrr:$regreg)),
(Inst CVrr:$regreg)>;

class CVStriPat<PatFrag StoreOp, RVInst Inst>
: Pat<(StoreOp (XLenVT GPR:$rs2), GPR:$rs1, simm12:$imm12),
(Inst GPR:$rs2, GPR:$rs1, simm12:$imm12)>;

class CVStrriPat<PatFrag StoreOp, RVInst Inst>
: Pat<(StoreOp (XLenVT GPR:$rs2), GPR:$rs1, GPR:$rs3),
(Inst GPR:$rs2, GPR:$rs1, GPR:$rs3)>;

class CVStrrPat<PatFrag StoreOp, RVInst Inst>
: Pat<(StoreOp (XLenVT GPR:$rs2), CVrr:$regreg),
(Inst GPR:$rs2, CVrr:$regreg)>;

let Predicates = [HasVendorXCVmem, IsRV32], AddedComplexity = 1 in {
def : CVLdrrPat<sextloadi8, CV_LB_rr>;
def : CVLdrrPat<zextloadi8, CV_LBU_rr>;
def : CVLdrrPat<extloadi8, CV_LBU_rr>;
def : CVLdrrPat<sextloadi16, CV_LH_rr>;
def : CVLdrrPat<zextloadi16, CV_LHU_rr>;
def : CVLdrrPat<extloadi16, CV_LHU_rr>;
def : CVLdrrPat<load, CV_LW_rr>;

def : CVStriPat<post_truncsti8, CV_SB_ri_inc>;
def : CVStriPat<post_truncsti16, CV_SH_ri_inc>;
def : CVStriPat<post_store, CV_SW_ri_inc>;

def : CVStrriPat<post_truncsti8, CV_SB_rr_inc>;
def : CVStrriPat<post_truncsti16, CV_SH_ri_inc>;
def : CVStrriPat<post_store, CV_SW_rr_inc>;

def : CVStrrPat<truncstorei8, CV_SB_rr>;
def : CVStrrPat<truncstorei16, CV_SH_rr>;
def : CVStrrPat<store, CV_SW_rr>;
}

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);}]>;
Expand Down
Loading

0 comments on commit 26f3a72

Please sign in to comment.