Skip to content

Commit

Permalink
[RISCV] Add MIPS extensions
Browse files Browse the repository at this point in the history
Adding two extensions for MIPS p8700 CPU:
  1. cmove (conditional move)
  2. lsp (load/store pair)

The official product page here:
https://mips.com/products/hardware/p8700
  • Loading branch information
djtodoro committed Dec 31, 2024
1 parent 1d51546 commit a2e1fd5
Show file tree
Hide file tree
Showing 27 changed files with 1,473 additions and 127 deletions.
4 changes: 4 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -4963,6 +4963,10 @@ def msave_restore : Flag<["-"], "msave-restore">, Group<m_riscv_Features_Group>,
def mno_save_restore : Flag<["-"], "mno-save-restore">, Group<m_riscv_Features_Group>,
HelpText<"Disable using library calls for save and restore">;
} // let Flags = [TargetSpecific]
def mload_store_pairs : Flag<["-"], "mload-store-pairs">, Group<m_riscv_Features_Group>;
def mno_load_store_pairs : Flag<["-"], "mno-load-store-pairs">, Group<m_riscv_Features_Group>;
def mccmov : Flag<["-"], "mccmov">, Group<m_riscv_Features_Group>;
def mno_ccmov : Flag<["-"], "mno-ccmov">, Group<m_riscv_Features_Group>;
let Flags = [TargetSpecific] in {
def menable_experimental_extensions : Flag<["-"], "menable-experimental-extensions">, Group<m_Group>,
HelpText<"Enable use of experimental RISC-V extensions.">;
Expand Down
15 changes: 15 additions & 0 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2167,6 +2167,21 @@ void Clang::AddRISCVTargetArgs(const ArgList &Args,
CmdArgs.push_back(A->getValue());
}

if (Arg *A = Args.getLastArg(options::OPT_mload_store_pairs,
options::OPT_mno_load_store_pairs)) {
if (A->getOption().matches(options::OPT_mload_store_pairs)) {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-riscv-load-store-pairs=1");
}
}

if (Arg *A = Args.getLastArg(options::OPT_mccmov,
options::OPT_mno_ccmov)) {
if (A->getOption().matches(options::OPT_mno_ccmov)) {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-riscv-ccmov=0");
}
}
// Handle -mrvv-vector-bits=<bits>
if (Arg *A = Args.getLastArg(options::OPT_mrvv_vector_bits_EQ)) {
StringRef Val = A->getValue();
Expand Down
6 changes: 6 additions & 0 deletions llvm/docs/RISCVUsage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,12 @@ The current vendor extensions supported are:
``experimental-Xqcisls``
LLVM implements `version 0.2 of the Qualcomm uC Scaled Load Store extension specification <https://github.com/quic/riscv-unified-db/releases/latest>`__ by Qualcomm. All instructions are prefixed with `qc.` as described in the specification. These instructions are only available for riscv32.

``Xmipscmove``
LLVM implements conditional move for the `p8700 processor <https://mips.com/products/hardware/p8700/>` by MIPS.

``Xmipslsp``
LLVM implements load/store pair instructions for the `p8700 processor <https://mips.com/products/hardware/p8700/>` by MIPS.

Experimental C Intrinsics
=========================

Expand Down
10 changes: 10 additions & 0 deletions llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -876,6 +876,16 @@ struct RISCVOperand final : public MCParsedAsmOperand {
VK == RISCVMCExpr::VK_RISCV_None;
}

bool isUImm7Lsb000() const {
if (!isImm())
return false;
int64_t Imm;
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
return IsConstantImm && isShiftedUInt<4, 3>(Imm) &&
VK == RISCVMCExpr::VK_RISCV_None;
}

bool isUImm8Lsb00() const {
if (!isImm())
return false;
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/RISCV/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ add_llvm_target(RISCVCodeGen
RISCVISelLowering.cpp
RISCVLandingPadSetup.cpp
RISCVMachineFunctionInfo.cpp
RISCVLoadStoreOptimizer.cpp
RISCVMergeBaseOffset.cpp
RISCVOptWInstrs.cpp
RISCVPostRAExpandPseudoInsts.cpp
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ enum OperandType : unsigned {
OPERAND_UIMM6_LSB0,
OPERAND_UIMM7,
OPERAND_UIMM7_LSB00,
OPERAND_UIMM7_LSB000,
OPERAND_UIMM8_LSB00,
OPERAND_UIMM8,
OPERAND_UIMM8_LSB000,
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/RISCV/RISCV.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ void initializeRISCVMoveMergePass(PassRegistry &);

FunctionPass *createRISCVPushPopOptimizationPass();
void initializeRISCVPushPopOptPass(PassRegistry &);
FunctionPass *createRISCVLoadStoreOptPass();
void initializeRISCVLoadStoreOptPass(PassRegistry &);

FunctionPass *createRISCVZacasABIFixPass();
void initializeRISCVZacasABIFixPass(PassRegistry &);
Expand Down
13 changes: 13 additions & 0 deletions llvm/lib/Target/RISCV/RISCVFeatures.td
Original file line number Diff line number Diff line change
Expand Up @@ -1395,6 +1395,19 @@ def NoConditionalMoveFusion : Predicate<"!Subtarget->hasConditionalMoveFusion()
def TuneMIPSP8700
: SubtargetFeature<"mips-p8700", "RISCVProcFamily", "MIPSP8700",
"MIPS p8700 processor">;
def FeatureVendorMIPSCMove : SubtargetFeature<"xmipscmove", "HasVendorMIPSCMove",
"true", "Using CCMov",
[Feature64Bit]>;
def HasVendorMIPSCMove
: Predicate<"Subtarget->useCCMovInsn()">,
AssemblerPredicate<(all_of FeatureVendorMIPSCMove), "'ccmov' instruction">;
def FeatureVendorMIPSLoadStorePairs
: SubtargetFeature<"xmipslsp", "HasMIPSLSP", "true",
"Optimize for hardware load-store bonding">;
def HasVendorMIPSLoadStorePairs
: Predicate<"Subtarget->useLoadStorePairs()">,
AssemblerPredicate<(all_of FeatureVendorMIPSLoadStorePairs),
"load and store pair instructions">;

def TuneSiFive7 : SubtargetFeature<"sifive7", "RISCVProcFamily", "SiFive7",
"SiFive 7-Series processors">;
Expand Down
4 changes: 3 additions & 1 deletion llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,9 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::ABS, MVT::i32, Custom);
}

if (!Subtarget.hasVendorXTHeadCondMov())
if (Subtarget.hasVendorMIPSCMove())
setOperationAction(ISD::SELECT, XLenVT, Legal);
else if (!Subtarget.hasVendorXTHeadCondMov())
setOperationAction(ISD::SELECT, XLenVT, Custom);

static const unsigned FPLegalNodeTypes[] = {
Expand Down
72 changes: 72 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrFormats.td
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,78 @@ class RVInstJ<RISCVOpcode opcode, dag outs, dag ins, string opcodestr,
let Inst{6-0} = opcode.Value;
}

//===----------------------------------------------------------------------===//
// MIPS custom instruction formats
//===----------------------------------------------------------------------===//

// Load double pair format.
class LDPFormat<dag outs, dag ins, string opcodestr, string argstr>
: RVInst<outs, ins, opcodestr, argstr, [], InstFormatI> {
bits<7> imm7;
bits<5> rs1;
bits<5> rd1;
bits<5> rd2;

let Inst{31-27} = rd2;
let Inst{26-23} = imm7{6-3};
let Inst{22-20} = 0b000;
let Inst{19-15} = rs1;
let Inst{14-12} = 0b100;
let Inst{11-7} = rd1;
let Inst{6-0} = 0b0001011;
}

// Load word pair format.
class LWPFormat<dag outs, dag ins, string opcodestr, string argstr>
: RVInst<outs, ins, opcodestr, argstr, [], InstFormatI> {
bits<7> imm7;
bits<5> rs1;
bits<5> rd1;
bits<5> rd2;

let Inst{31-27} = rd2;
let Inst{26-22} = imm7{6-2};
let Inst{21-20} = 0b01;
let Inst{19-15} = rs1;
let Inst{14-12} = 0b100;
let Inst{11-7} = rd1;
let Inst{6-0} = 0b0001011;
}

// Store double pair format.
class SDPFormat<dag outs, dag ins, string opcodestr, string argstr>
: RVInst<outs, ins, opcodestr, argstr, [], InstFormatI> {
bits<7> imm7;
bits<5> rs3;
bits<5> rs2;
bits<5> rs1;

let Inst{31-27} = rs3;
let Inst{26-25} = imm7{6-5};
let Inst{24-20} = rs2;
let Inst{19-15} = rs1;
let Inst{14-12} = 0b101;
let Inst{11-10} = imm7{4-3};
let Inst{9-0} = 0b0000001011;
}

// Store word pair format.
class SWPFormat<dag outs, dag ins, string opcodestr, string argstr>
: RVInst<outs, ins, opcodestr, argstr, [], InstFormatI> {
bits<7> imm7;
bits<5> rs3;
bits<5> rs2;
bits<5> rs1;

let Inst{31-27} = rs3;
let Inst{26-25} = imm7{6-5};
let Inst{24-20} = rs2;
let Inst{19-15} = rs1;
let Inst{14-12} = 0b101;
let Inst{11-9} = imm7{4-2};
let Inst{8-0} = 0b010001011;
}

//===----------------------------------------------------------------------===//
// Instruction classes for .insn directives
//===----------------------------------------------------------------------===//
Expand Down
43 changes: 43 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2488,6 +2488,9 @@ bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI,
case RISCVOp::OPERAND_UIMM7_LSB00:
Ok = isShiftedUInt<5, 2>(Imm);
break;
case RISCVOp::OPERAND_UIMM7_LSB000:
Ok = isShiftedUInt<4, 3>(Imm);
break;
case RISCVOp::OPERAND_UIMM8_LSB00:
Ok = isShiftedUInt<6, 2>(Imm);
break;
Expand Down Expand Up @@ -2734,6 +2737,46 @@ MachineInstr *RISCVInstrInfo::emitLdStWithAddr(MachineInstr &MemI,
.setMIFlags(MemI.getFlags());
}

bool RISCVInstrInfo::isPairableLdStInstOpc(unsigned Opc) {
switch (Opc) {
default:
return false;
case RISCV::SH:
case RISCV::LH:
case RISCV::LHU:
case RISCV::SW:
case RISCV::FSW:
case RISCV::LW:
case RISCV::FLW:
case RISCV::SD:
case RISCV::FSD:
case RISCV::LD:
case RISCV::FLD:
return true;
}
}

bool RISCVInstrInfo::isLdStSafeToPair(const MachineInstr &LdSt,
const TargetRegisterInfo *TRI) {
// If this is a volatile load/store, don't mess with it.
if (LdSt.hasOrderedMemoryRef() || LdSt.getNumExplicitOperands() != 3)
return false;

if (LdSt.getOperand(1).isFI())
return true;

assert(LdSt.getOperand(1).isReg() && "Expected a reg operand.");
// Can't cluster if the instruction modifies the base register
// or it is update form. e.g. ld x5,8(x5)
if (LdSt.modifiesRegister(LdSt.getOperand(1).getReg(), TRI))
return false;

if (!LdSt.getOperand(2).isImm())
return false;

return true;
}

bool RISCVInstrInfo::getMemOperandsWithOffsetWidth(
const MachineInstr &LdSt, SmallVectorImpl<const MachineOperand *> &BaseOps,
int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width,
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,12 @@ class RISCVInstrInfo : public RISCVGenInstrInfo {
std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override;

/// Return true if pairing the given load or store may be paired with another.
static bool isPairableLdStInstOpc(unsigned Opc);

static bool isLdStSafeToPair(const MachineInstr &LdSt,
const TargetRegisterInfo *TRI);

protected:
const RISCVSubtarget &STI;

Expand Down
Loading

0 comments on commit a2e1fd5

Please sign in to comment.