Skip to content

Commit

Permalink
Add support for emitting load/store pair instructions
Browse files Browse the repository at this point in the history
In order to support this, immediate operands with LSBs
that are equal to zero are moved from the C extension InstrInfo.
  • Loading branch information
jdmitrovic-syrmia committed May 24, 2024
1 parent 5084072 commit ae9e3dd
Show file tree
Hide file tree
Showing 6 changed files with 239 additions and 137 deletions.
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 @@ -814,6 +814,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/MCTargetDesc/RISCVBaseInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@ enum OperandType : unsigned {
OPERAND_UIMM6,
OPERAND_UIMM7,
OPERAND_UIMM7_LSB00,
OPERAND_UIMM7_LSB000,
OPERAND_UIMM8_LSB00,
OPERAND_UIMM8,
OPERAND_UIMM8_LSB000,
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 @@ -469,6 +469,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
3 changes: 3 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2095,6 +2095,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
165 changes: 153 additions & 12 deletions llvm/lib/Target/RISCV/RISCVInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,147 @@ def simm12 : RISCVSImmLeafOp<12> {
}];
}

// A 7-bit unsigned immediate where the least significant two bits are zero.
def uimm7_lsb00 : RISCVOp,
ImmLeaf<XLenVT, [{return isShiftedUInt<5, 2>(Imm);}]> {
let ParserMatchClass = UImmAsmOperand<7, "Lsb00">;
let EncoderMethod = "getImmOpValue";
let DecoderMethod = "decodeUImmOperand<7>";
let OperandType = "OPERAND_UIMM7_LSB00";
let MCOperandPredicate = [{
int64_t Imm;
if (!MCOp.evaluateAsConstantImm(Imm))
return false;
return isShiftedUInt<5, 2>(Imm);
}];
}

// A 7-bit unsigned immediate where the least significant three bits are zero.
def uimm7_lsb000 : RISCVOp,
ImmLeaf<XLenVT, [{return isShiftedUInt<4, 3>(Imm);}]> {
let ParserMatchClass = UImmAsmOperand<7, "Lsb000">;
let EncoderMethod = "getImmOpValue";
let DecoderMethod = "decodeUImmOperand<7>";
let OperandType = "OPERAND_UIMM7_LSB000";
let MCOperandPredicate = [{
int64_t Imm;
if (!MCOp.evaluateAsConstantImm(Imm))
return false;
return isShiftedUInt<4, 3>(Imm);
}];
}

// A 8-bit unsigned immediate where the least significant two bits are zero.
def uimm8_lsb00 : RISCVOp,
ImmLeaf<XLenVT, [{return isShiftedUInt<6, 2>(Imm);}]> {
let ParserMatchClass = UImmAsmOperand<8, "Lsb00">;
let EncoderMethod = "getImmOpValue";
let DecoderMethod = "decodeUImmOperand<8>";
let OperandType = "OPERAND_UIMM8_LSB00";
let MCOperandPredicate = [{
int64_t Imm;
if (!MCOp.evaluateAsConstantImm(Imm))
return false;
return isShiftedUInt<6, 2>(Imm);
}];
}

// A 8-bit unsigned immediate where the least significant three bits are zero.
def uimm8_lsb000 : RISCVOp,
ImmLeaf<XLenVT, [{return isShiftedUInt<5, 3>(Imm);}]> {
let ParserMatchClass = UImmAsmOperand<8, "Lsb000">;
let EncoderMethod = "getImmOpValue";
let DecoderMethod = "decodeUImmOperand<8>";
let OperandType = "OPERAND_UIMM8_LSB000";
let MCOperandPredicate = [{
int64_t Imm;
if (!MCOp.evaluateAsConstantImm(Imm))
return false;
return isShiftedUInt<5, 3>(Imm);
}];
}

// A 9-bit signed immediate where the least significant bit is zero.
def simm9_lsb0 : Operand<OtherVT>,
ImmLeaf<XLenVT, [{return isShiftedInt<8, 1>(Imm);}]> {
let ParserMatchClass = SImmAsmOperand<9, "Lsb0">;
let PrintMethod = "printBranchOperand";
let EncoderMethod = "getImmOpValueAsr1";
let DecoderMethod = "decodeSImmOperandAndLsl1<9>";
let MCOperandPredicate = [{
int64_t Imm;
if (MCOp.evaluateAsConstantImm(Imm))
return isShiftedInt<8, 1>(Imm);
return MCOp.isBareSymbolRef();

}];
let OperandType = "OPERAND_PCREL";
}

// A 9-bit unsigned immediate where the least significant three bits are zero.
def uimm9_lsb000 : RISCVOp,
ImmLeaf<XLenVT, [{return isShiftedUInt<6, 3>(Imm);}]> {
let ParserMatchClass = UImmAsmOperand<9, "Lsb000">;
let EncoderMethod = "getImmOpValue";
let DecoderMethod = "decodeUImmOperand<9>";
let OperandType = "OPERAND_UIMM9_LSB000";
let MCOperandPredicate = [{
int64_t Imm;
if (!MCOp.evaluateAsConstantImm(Imm))
return false;
return isShiftedUInt<6, 3>(Imm);
}];
}

// A 10-bit unsigned immediate where the least significant two bits are zero
// and the immediate can't be zero.
def uimm10_lsb00nonzero : RISCVOp,
ImmLeaf<XLenVT,
[{return isShiftedUInt<8, 2>(Imm) && (Imm != 0);}]> {
let ParserMatchClass = UImmAsmOperand<10, "Lsb00NonZero">;
let EncoderMethod = "getImmOpValue";
let DecoderMethod = "decodeUImmNonZeroOperand<10>";
let OperandType = "OPERAND_UIMM10_LSB00_NONZERO";
let MCOperandPredicate = [{
int64_t Imm;
if (!MCOp.evaluateAsConstantImm(Imm))
return false;
return isShiftedUInt<8, 2>(Imm) && (Imm != 0);
}];
}

// A 10-bit signed immediate where the least significant four bits are zero.
def simm10_lsb0000nonzero : RISCVOp,
ImmLeaf<XLenVT,
[{return (Imm != 0) && isShiftedInt<6, 4>(Imm);}]> {
let ParserMatchClass = SImmAsmOperand<10, "Lsb0000NonZero">;
let EncoderMethod = "getImmOpValue";
let DecoderMethod = "decodeSImmNonZeroOperand<10>";
let OperandType = "OPERAND_SIMM10_LSB0000_NONZERO";
let MCOperandPredicate = [{
int64_t Imm;
if (!MCOp.evaluateAsConstantImm(Imm))
return false;
return isShiftedInt<6, 4>(Imm) && (Imm != 0);
}];
}

// A 12-bit signed immediate where the least significant bit is zero.
def simm12_lsb0 : Operand<XLenVT>,
ImmLeaf<XLenVT, [{return isShiftedInt<11, 1>(Imm);}]> {
let ParserMatchClass = SImmAsmOperand<12, "Lsb0">;
let PrintMethod = "printBranchOperand";
let EncoderMethod = "getImmOpValueAsr1";
let DecoderMethod = "decodeSImmOperandAndLsl1<12>";
let MCOperandPredicate = [{
int64_t Imm;
if (MCOp.evaluateAsConstantImm(Imm))
return isShiftedInt<11, 1>(Imm);
return MCOp.isBareSymbolRef();
}];
let OperandType = "OPERAND_PCREL";
}

// A 12-bit signed immediate which cannot fit in 6-bit signed immediate,
// but even negative value fit in 12-bit.
def simm12_no6 : ImmLeaf<XLenVT, [{
Expand Down Expand Up @@ -1999,27 +2140,27 @@ def : Pat<(select (XLenVT GPR:$rs2), (XLenVT GPR:$rs1), (XLenVT GPR:$rs3)),
//===----------------------------------------------------------------------===//

let Predicates = [UsesLoadStorePairs], hasSideEffects = 0 in {
def LWP : Pseudo<(outs GPR:$rd1, GPR:$rd2), (ins GPR:$rs1, uimm7:$imm7), [],
"lwp", "$rd1, $rd2, ${imm7}(${rs1})">,
Sched<[WriteLDW, WriteLDW, ReadMemBase]> {
def LWP : LWPFormat<(outs GPR:$rd1, GPR:$rd2), (ins GPR:$rs1, uimm7_lsb00:$imm7),
"lwp", "$rd1, $rd2, ${imm7}(${rs1})">,
Sched<[WriteLDW, WriteLDW, ReadMemBase]> {
let mayLoad = 1;
let mayStore = 0;
}
def LDP : Pseudo<(outs GPR:$rd1, GPR:$rd2), (ins GPR:$rs1, uimm7:$imm7), [],
"ldp", "$rd1, $rd2, ${imm7}(${rs1})">,
Sched<[WriteLDD, WriteLDD, ReadMemBase]> {
def LDP : LDPFormat<(outs GPR:$rd1, GPR:$rd2), (ins GPR:$rs1, uimm7_lsb000:$imm7),
"ldp", "$rd1, $rd2, ${imm7}(${rs1})">,
Sched<[WriteLDD, WriteLDD, ReadMemBase]> {
let mayLoad = 1;
let mayStore = 0;
}
def SWP : Pseudo<(outs), (ins GPR:$rs2, GPR:$rs3, GPR:$rs1, uimm7:$imm7), [],
"swp", "$rs2, $rs3, ${imm7}(${rs1})">,
Sched<[WriteSTW, ReadStoreData, ReadStoreData, ReadMemBase]> {
def SWP : SWPFormat<(outs), (ins GPR:$rs2, GPR:$rs3, GPR:$rs1, uimm7_lsb00:$imm7),
"swp", "$rs2, $rs3, ${imm7}(${rs1})">,
Sched<[WriteSTW, ReadStoreData, ReadStoreData, ReadMemBase]> {
let mayLoad = 0;
let mayStore = 1;
}
def SDP : Pseudo<(outs), (ins GPR:$rs2, GPR:$rs3, GPR:$rs1, uimm7:$imm7), [],
"sdp", "$rs2, $rs3, ${imm7}(${rs1})">,
Sched<[WriteSTD, ReadStoreData, ReadStoreData, ReadMemBase]> {
def SDP : SDPFormat<(outs), (ins GPR:$rs2, GPR:$rs3, GPR:$rs1, uimm7_lsb000:$imm7),
"sdp", "$rs2, $rs3, ${imm7}(${rs1})">,
Sched<[WriteSTD, ReadStoreData, ReadStoreData, ReadMemBase]> {
let mayLoad = 0;
let mayStore = 1;
}
Expand Down
Loading

0 comments on commit ae9e3dd

Please sign in to comment.