-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[RISCV][MC] Add MC support of Zibi experimental extension #127463
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
base: main
Are you sure you want to change the base?
Conversation
✅ With the latest revision this PR passed the C/C++ code formatter. |
fa402ab
to
582580f
Compare
582580f
to
63ba04f
Compare
0184e36
to
a1ea637
Compare
Please update RISCVUsage.rst and the release notes |
@llvm/pr-subscribers-backend-risc-v @llvm/pr-subscribers-clang-driver Author: Boyao Wang (BoyaoWang430) ChangesThis adds the support of Zibi v0.1 experimental extension. References: Patch is 30.18 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/127463.diff 20 Files Affected:
diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c
index 5008c2b7f789d..adfd2c41b16ec 100644
--- a/clang/test/Driver/print-supported-extensions-riscv.c
+++ b/clang/test/Driver/print-supported-extensions-riscv.c
@@ -205,6 +205,7 @@
// CHECK-EMPTY:
// CHECK-NEXT: Experimental extensions
// CHECK-NEXT: p 0.14 'P' ('Base P' (Packed SIMD))
+// CHECK-NEXT: zibi 0.1 'Zibi' (Branch with Immediate)
// CHECK-NEXT: zicfilp 1.0 'Zicfilp' (Landing pad)
// CHECK-NEXT: zicfiss 1.0 'Zicfiss' (Shadow stack)
// CHECK-NEXT: zalasr 0.1 'Zalasr' (Load-Acquire and Store-Release Instructions)
diff --git a/clang/test/Preprocessor/riscv-target-features.c b/clang/test/Preprocessor/riscv-target-features.c
index 86085c21a95aa..52a483100f829 100644
--- a/clang/test/Preprocessor/riscv-target-features.c
+++ b/clang/test/Preprocessor/riscv-target-features.c
@@ -122,6 +122,7 @@
// CHECK-NOT: __riscv_zfinx {{.*$}}
// CHECK-NOT: __riscv_zhinx {{.*$}}
// CHECK-NOT: __riscv_zhinxmin {{.*$}}
+// CHECK-NOT: __riscv_zibi {{.*$}}
// CHECK-NOT: __riscv_zic64b {{.*$}}
// CHECK-NOT: __riscv_zicbom {{.*$}}
// CHECK-NOT: __riscv_zicbop {{.*$}}
@@ -1029,6 +1030,14 @@
// RUN: -o - | FileCheck --check-prefix=CHECK-ZHINXMIN-EXT %s
// CHECK-ZHINXMIN-EXT: __riscv_zhinxmin 1000000{{$}}
+// RUN: %clang --target=riscv32 -menable-experimental-extensions \
+// RUN: -march=rv32i_zibi0p1 -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-ZIBI-EXT %s
+// RUN: %clang --target=riscv64 -menable-experimental-extensions \
+// RUN: -march=rv64i_zibi0p1 -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-ZIBI-EXT %s
+// CHECK-ZIBI-EXT: __riscv_zibi
+
// RUN: %clang --target=riscv32-unknown-linux-gnu \
// RUN: -march=rv32izic64b -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-ZIC64B-EXT %s
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index e5d8ab07891ac..de7f9c07c6c75 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -744,6 +744,11 @@ struct RISCVOperand final : public MCParsedAsmOperand {
return isUImmPred([](int64_t Imm) { return Imm != 0 && isUInt<5>(Imm); });
}
+ bool isUImm5Zibi() const {
+ return isUImmPred(
+ [](int64_t Imm) { return (Imm != 0 && isUInt<5>(Imm)) || Imm == -1; });
+ }
+
bool isUImm5GT3() const {
return isUImmPred([](int64_t Imm) { return isUInt<5>(Imm) && Imm > 3; });
}
@@ -1466,6 +1471,10 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
case Match_InvalidUImm5NonZero:
return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5) - 1);
+ case Match_InvalidUImm5Zibi:
+ return generateImmOutOfRangeError(
+ Operands, ErrorInfo, -1, (1 << 5) - 1,
+ "immediate must be non-zero in the range");
case Match_InvalidUImm5GT3:
return generateImmOutOfRangeError(Operands, ErrorInfo, 4, (1 << 5) - 1);
case Match_InvalidUImm5Plus1:
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index 27e04c0cb1f8b..a8d673f662cbd 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -457,6 +457,14 @@ static DecodeStatus decodeUImmNonZeroOperand(MCInst &Inst, uint32_t Imm,
return decodeUImmOperand<N>(Inst, Imm, Address, Decoder);
}
+static DecodeStatus decodeUImmZibiOperand(MCInst &Inst, uint32_t Imm,
+ int64_t Address,
+ const MCDisassembler *Decoder) {
+ assert(isUInt<5>(Imm) && "Invalid immediate");
+ Inst.addOperand(MCOperand::createImm(Imm ? Imm : -1LL));
+ return MCDisassembler::Success;
+}
+
static DecodeStatus
decodeUImmLog2XLenNonZeroOperand(MCInst &Inst, uint32_t Imm, int64_t Address,
const MCDisassembler *Decoder) {
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index f83c2b6da8923..18ce5407f816c 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -789,7 +789,7 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
RISCVCC::CondCode CC;
getOperandsForBranch(MI.getOperand(0).getReg(), CC, LHS, RHS, *MRI);
- auto Bcc = MIB.buildInstr(RISCVCC::getBrCond(CC), {}, {LHS, RHS})
+ auto Bcc = MIB.buildInstr(RISCVCC::getBrCond(STI, CC), {}, {LHS, RHS})
.addMBB(MI.getOperand(1).getMBB());
MI.eraseFromParent();
return constrainSelectedInstRegOperands(*Bcc, TII, TRI, RBI);
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
index 3d304842fac13..d488785d8297d 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
@@ -301,6 +301,7 @@ enum OperandType : unsigned {
OPERAND_UIMM4,
OPERAND_UIMM5,
OPERAND_UIMM5_NONZERO,
+ OPERAND_UIMM5_ZIBI,
OPERAND_UIMM5_GT3,
OPERAND_UIMM5_PLUS1,
OPERAND_UIMM5_GE6_PLUS1,
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
index ce0fbc0ac0654..d6fd6a9323dd4 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
@@ -97,6 +97,10 @@ class RISCVMCCodeEmitter : public MCCodeEmitter {
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
+ uint64_t getImmOpValueZibi(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
uint64_t getImmOpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
@@ -545,6 +549,19 @@ RISCVMCCodeEmitter::getImmOpValueAsrN(const MCInst &MI, unsigned OpNo,
return getImmOpValue(MI, OpNo, Fixups, STI);
}
+uint64_t
+RISCVMCCodeEmitter::getImmOpValueZibi(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ const MCOperand &MO = MI.getOperand(OpNo);
+ assert(MO.isImm() && "Zibi operand must be an immediate");
+ int64_t Res = MO.getImm();
+ if (Res == -1)
+ return 0;
+
+ return Res;
+}
+
uint64_t RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index 36b3aff51cda9..8f97ddedb859d 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -78,6 +78,12 @@ def FeatureStdExtE
: RISCVExtension<2, 0, "Embedded Instruction Set with 16 GPRs">,
RISCVExtensionBitmask<0, 4>;
+def FeatureStdExtZibi
+ : RISCVExperimentalExtension<0, 1, "Branch with Immediate">;
+def HasStdExtZibi : Predicate<"Subtarget->hasStdExtZibi()">,
+ AssemblerPredicate<(all_of FeatureStdExtZibi),
+ "'Zibi' (Branch with Immediate)">;
+
def FeatureStdExtZic64b
: RISCVExtension<1, 0, "Cache Block Size Is 64 Bytes">;
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 13ee3ee63d1a6..7c54f9af1f144 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -21483,7 +21483,7 @@ static MachineBasicBlock *emitSelectPseudo(MachineInstr &MI,
// Insert appropriate branch.
if (MI.getOperand(2).isImm())
- BuildMI(HeadMBB, DL, TII.getBrCond(CC))
+ BuildMI(HeadMBB, DL, TII.getBrCond(CC, true))
.addReg(LHS)
.addImm(MI.getOperand(2).getImm())
.addMBB(TailMBB);
diff --git a/llvm/lib/Target/RISCV/RISCVInstrFormats.td b/llvm/lib/Target/RISCV/RISCVInstrFormats.td
index b6b64b57b1b3e..19de5a0ac4005 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrFormats.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrFormats.td
@@ -496,6 +496,22 @@ class RVInstB<bits<3> funct3, RISCVOpcode opcode, dag outs, dag ins,
let Inst{6-0} = opcode.Value;
}
+class RVInstBIMM<bits<3> funct3, RISCVOpcode opcode, dag outs, dag ins,
+ string opcodestr, string argstr>
+ : RVInst<outs, ins, opcodestr, argstr, [], InstFormatB> {
+ bits<12> imm12;
+ bits<5> cimm;
+ bits<5> rs1;
+ let Inst{31} = imm12{11};
+ let Inst{30-25} = imm12{9-4};
+ let Inst{24-20} = cimm;
+ let Inst{19-15} = rs1;
+ let Inst{14-12} = funct3;
+ let Inst{11-8} = imm12{3-0};
+ let Inst{7} = imm12{10};
+ let Inst{6-0} = opcode.Value;
+}
+
class RVInstU<RISCVOpcode opcode, dag outs, dag ins, string opcodestr,
string argstr>
: RVInst<outs, ins, opcodestr, argstr, [], InstFormatU> {
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index 6e30ffce99c4d..96c6eaf05fc12 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -962,6 +962,10 @@ static RISCVCC::CondCode getCondFromBranchOpc(unsigned Opc) {
switch (Opc) {
default:
return RISCVCC::COND_INVALID;
+ case RISCV::BEQI:
+ return RISCVCC::COND_EQ;
+ case RISCV::BNEI:
+ return RISCVCC::COND_NE;
case RISCV::BEQ:
return RISCVCC::COND_EQ;
case RISCV::BNE:
@@ -1039,14 +1043,15 @@ static void parseCondBranch(MachineInstr &LastInst, MachineBasicBlock *&Target,
Cond.push_back(LastInst.getOperand(1));
}
-unsigned RISCVCC::getBrCond(RISCVCC::CondCode CC) {
+unsigned RISCVCC::getBrCond(const RISCVSubtarget &STI, RISCVCC::CondCode CC,
+ bool Imm) {
switch (CC) {
default:
llvm_unreachable("Unknown condition code!");
case RISCVCC::COND_EQ:
- return RISCV::BEQ;
+ return (Imm && STI.hasStdExtZibi()) ? RISCV::BEQI : RISCV::BEQ;
case RISCVCC::COND_NE:
- return RISCV::BNE;
+ return (Imm && STI.hasStdExtZibi()) ? RISCV::BNEI : RISCV::BNE;
case RISCVCC::COND_LT:
return RISCV::BLT;
case RISCVCC::COND_GE:
@@ -1086,8 +1091,9 @@ unsigned RISCVCC::getBrCond(RISCVCC::CondCode CC) {
}
}
-const MCInstrDesc &RISCVInstrInfo::getBrCond(RISCVCC::CondCode CC) const {
- return get(RISCVCC::getBrCond(CC));
+const MCInstrDesc &RISCVInstrInfo::getBrCond(RISCVCC::CondCode CC,
+ bool Imm) const {
+ return get(RISCVCC::getBrCond(STI, CC, Imm));
}
RISCVCC::CondCode RISCVCC::getOppositeBranchCondition(RISCVCC::CondCode CC) {
@@ -1264,8 +1270,10 @@ unsigned RISCVInstrInfo::insertBranch(
// Either a one or two-way conditional branch.
auto CC = static_cast<RISCVCC::CondCode>(Cond[0].getImm());
- MachineInstr &CondMI =
- *BuildMI(&MBB, DL, getBrCond(CC)).add(Cond[1]).add(Cond[2]).addMBB(TBB);
+ MachineInstr &CondMI = *BuildMI(&MBB, DL, getBrCond(CC, Cond[2].isImm()))
+ .add(Cond[1])
+ .add(Cond[2])
+ .addMBB(TBB);
if (BytesAdded)
*BytesAdded += getInstSizeInBytes(CondMI);
@@ -1507,6 +1515,8 @@ bool RISCVInstrInfo::isBranchOffsetInRange(unsigned BranchOp,
case RISCV::BGE:
case RISCV::BLTU:
case RISCV::BGEU:
+ case RISCV::BEQI:
+ case RISCV::BNEI:
case RISCV::CV_BEQIMM:
case RISCV::CV_BNEIMM:
case RISCV::QC_BEQI:
@@ -2703,6 +2713,9 @@ bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI,
case RISCVOp::OPERAND_UIMM2_LSB0:
Ok = isShiftedUInt<1, 1>(Imm);
break;
+ case RISCVOp::OPERAND_UIMM5_ZIBI:
+ Ok = (isUInt<5>(Imm) && Imm != 0) || Imm == -1;
+ break;
case RISCVOp::OPERAND_UIMM5_LSB0:
Ok = isShiftedUInt<4, 1>(Imm);
break;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.h b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
index 020be91e90e0b..4735670c3e96f 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.h
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
@@ -59,7 +59,7 @@ enum CondCode {
};
CondCode getOppositeBranchCondition(CondCode);
-unsigned getBrCond(CondCode CC);
+unsigned getBrCond(const RISCVSubtarget &STI, CondCode CC, bool Imm = false);
} // end of namespace RISCVCC
@@ -79,7 +79,7 @@ class RISCVInstrInfo : public RISCVGenInstrInfo {
explicit RISCVInstrInfo(RISCVSubtarget &STI);
MCInst getNop() const override;
- const MCInstrDesc &getBrCond(RISCVCC::CondCode CC) const;
+ const MCInstrDesc &getBrCond(RISCVCC::CondCode CC, bool Imm = false) const;
Register isLoadFromStackSlot(const MachineInstr &MI,
int &FrameIndex) const override;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index aa1ebba567824..1f3e21015f89b 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -2249,6 +2249,7 @@ include "RISCVInstrInfoZicbo.td"
include "RISCVInstrInfoZicond.td"
include "RISCVInstrInfoZicfiss.td"
include "RISCVInstrInfoZilsd.td"
+include "RISCVInstrInfoZibi.td"
// Scalar FP
include "RISCVInstrInfoF.td"
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZibi.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZibi.td
new file mode 100644
index 0000000000000..c61bcefdfc4ac
--- /dev/null
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZibi.td
@@ -0,0 +1,51 @@
+//===-- RISCVInstrInfoZibi.td - 'Zibi' instructions ------*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// This file describes the RISC-V instructions for 'Zibi' (branch with imm).
+///
+//===----------------------------------------------------------------------===//
+// A 5-bit unsigned immediate representing 1-31 and -1. 00000 represents -1.
+def uimm5_zibi : RISCVOp<XLenVT>, ImmLeaf<XLenVT, [{
+ return (Imm != 0 && isUInt<5>(Imm)) || Imm == -1;
+}]> {
+ let ParserMatchClass = UImmAsmOperand<5, "Zibi">;
+ let EncoderMethod = "getImmOpValueZibi";
+ let DecoderMethod = "decodeUImmZibiOperand";
+ let MCOperandPredicate = [{
+ int64_t Imm;
+ if (!MCOp.evaluateAsConstantImm(Imm))
+ return false;
+ return (Imm >= 1 && Imm <= 31) || Imm == -1;
+ }];
+ let OperandType = "OPERAND_UIMM5_ZIBI";
+}
+
+class Branch_imm<bits<3> funct3, string opcodestr>
+ : RVInstBIMM<funct3, OPC_BRANCH, (outs),
+ (ins GPR:$rs1, uimm5_zibi:$cimm, bare_simm13_lsb0:$imm12),
+ opcodestr, "$rs1, $cimm, $imm12">,
+ Sched<[WriteJmp, ReadJmp]> {
+ let isBranch = 1;
+ let isTerminator = 1;
+ let hasSideEffects = 0;
+ let mayLoad = 0;
+ let mayStore = 0;
+}
+let Predicates = [HasStdExtZibi] in {
+def BEQI : Branch_imm<0b010, "beqi">;
+def BNEI : Branch_imm<0b011, "bnei">;
+} // Predicates = [HasStdExtZibi]
+
+let Predicates = [HasStdExtZibi] in {
+multiclass BccImmPat<CondCode Cond, Branch_imm Inst> {
+ def : Pat<(riscv_brcc (XLenVT GPR:$rs1), uimm5_zibi:$cimm, Cond, bb:$imm12),
+ (Inst GPR:$rs1, uimm5_zibi:$cimm, bare_simm13_lsb0_bb:$imm12)>;
+}
+defm : BccImmPat<SETEQ, BEQI>;
+defm : BccImmPat<SETNE, BNEI>;
+}// Predicates = [HasStdExtZibi]
\ No newline at end of file
diff --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll
index c5188aa1918bf..a01c7272da0ae 100644
--- a/llvm/test/CodeGen/RISCV/attributes.ll
+++ b/llvm/test/CodeGen/RISCV/attributes.ll
@@ -173,6 +173,7 @@
; RUN: llc -mtriple=riscv32 -mattr=+supm %s -o - | FileCheck --check-prefix=RV32SUPM %s
; RUN: llc -mtriple=riscv32 -mattr=+experimental-smctr %s -o - | FileCheck --check-prefix=RV32SMCTR %s
; RUN: llc -mtriple=riscv32 -mattr=+experimental-ssctr %s -o - | FileCheck --check-prefix=RV32SSCTR %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zibi %s -o - | FileCheck --check-prefix=RV32ZIBI %s
; RUN: llc -mtriple=riscv64 %s -o - | FileCheck %s
; RUN: llc -mtriple=riscv64 -mattr=+m %s -o - | FileCheck --check-prefixes=CHECK,RV64M %s
@@ -337,7 +338,7 @@
; RUN: llc -mtriple=riscv64 -mattr=+sdext %s -o - | FileCheck --check-prefix=RV64SDEXT %s
; RUN: llc -mtriple=riscv64 -mattr=+sdtrig %s -o - | FileCheck --check-prefix=RV64SDTRIG %s
; RUN: llc -mtriple=riscv64 -mattr=+experimental-xqccmp %s -o - | FileCheck --check-prefix=RV64XQCCMP %s
-
+; RUN: llc -mtriple=riscv64 -mattr=+experimental-zibi %s -o - | FileCheck --check-prefix=RV64ZIBI %s
; Tests for profile features.
; RUN: llc -mtriple=riscv32 -mattr=+rvi20u32 %s -o - | FileCheck --check-prefix=RVI20U32 %s
@@ -526,6 +527,7 @@
; RV32SUPM: .attribute 5, "rv32i2p1_supm1p0"
; RV32SMCTR: .attribute 5, "rv32i2p1_smctr1p0_sscsrind1p0"
; RV32SSCTR: .attribute 5, "rv32i2p1_sscsrind1p0_ssctr1p0"
+; RV32ZIBI: .attribute 5, "rv32i2p1_zibi0p1"
; RV64M: .attribute 5, "rv64i2p1_m2p0_zmmul1p0"
; RV64ZMMUL: .attribute 5, "rv64i2p1_zmmul1p0"
@@ -688,6 +690,7 @@
; RV64SDEXT: .attribute 5, "rv64i2p1_sdext1p0"
; RV64SDTRIG: .attribute 5, "rv64i2p1_sdtrig1p0"
; RV64XQCCMP: .attribute 5, "rv64i2p1_zca1p0_xqccmp0p3"
+; RV64ZIBI: .attribute 5, "rv64i2p1_zibi0p1"
; RVI20U32: .attribute 5, "rv32i2p1"
; RVI20U64: .attribute 5, "rv64i2p1"
diff --git a/llvm/test/CodeGen/RISCV/features-info.ll b/llvm/test/CodeGen/RISCV/features-info.ll
index 8b931f70aa5cc..c999550b7e713 100644
--- a/llvm/test/CodeGen/RISCV/features-info.ll
+++ b/llvm/test/CodeGen/RISCV/features-info.ll
@@ -46,6 +46,7 @@
; CHECK-NEXT: experimental-xsfmclic - 'XSfmclic' (SiFive CLIC Machine-mode CSRs).
; CHECK-NEXT: experimental-xsfsclic - 'XSfsclic' (SiFive CLIC Supervisor-mode CSRs).
; CHECK-NEXT: experimental-zalasr - 'Zalasr' (Load-Acquire and Store-Release Instructions).
+; CHECK-NEXT: experimental-zibi - 'Zibi' (Branch with Immediate).
; CHECK-NEXT: experimental-zicfilp - 'Zicfilp' (Landing pad).
; CHECK-NEXT: experimental-zicfiss - 'Zicfiss' (Shadow stack).
; CHECK-NEXT: experimental-zvbc32e - 'Zvbc32e' (Vector Carryless Multiplication with 32-bits elements).
diff --git a/llvm/test/CodeGen/RISCV/zibi.ll b/llvm/test/CodeGen/RISCV/zibi.ll
new file mode 100644
index 0000000000000..e77acd0dc749d
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/zibi.ll
@@ -0,0 +1,207 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zibi -verify-machineinstrs < %s \
+; RUN: | FileCheck -check-prefix=ZIBI %s
+; RUN: llc -mtriple=riscv64 -mattr=+experimental-zibi -verify-machineinstrs < %s \
+; RUN: | FileCheck -check-prefix=ZIBI %s
+
+define void @test_bne_neg(ptr %b) nounwind {
+; ZIBI-LABEL: test_bne_neg:
+; ZIBI: # %bb.0:
+; ZIBI-NEXT: lw a1, 0(a0)
+; ZIBI-NEXT: bnei a1, -1, .LBB0_2
+; ZIBI-NEXT: # %bb.1: # %test2
+; ZIBI-NEXT: lw zero, 0(a0)
+; ZIBI-NEXT: .LBB0_2: # %end
+; ZIBI-NEXT: ret
+ %val1 = load volatile i32, ptr %b
+ %tst1 = icmp ne i32 %val1, -1
+ br i1 %tst1, label %end, label %test2, !prof !0
+test2:
+ %val2 = load volatile i32, ptr %b
+ br label %end
+end:
+ ret void
+}
+!0 = !{!"branch_weights", i32 1, i32 99}
+
+define void @test_beq_neg(ptr %b) nounwind {
+; ZIBI-LABEL: test_beq_neg:
+; ZIBI: # %bb.0:
+; ZIBI-NEXT: lw a1, 0(a0)
+; ZIBI-NEXT: beqi a1, -1, .LBB1_2
+; ZIBI-NEXT: # %bb.1: # %test2
+; ZIBI-NEXT: lw zero, 0(a0)
+; ZIBI-NEXT: .LBB1_2: # %end
+; ZIBI-NEXT: ret
+ %val1 = load volatile i32, ptr %b
+ %tst1 = icmp eq i32 %val1, -1
+ br i1 %tst1, label %en...
[truncated]
|
@llvm/pr-subscribers-clang Author: Boyao Wang (BoyaoWang430) ChangesThis adds the support of Zibi v0.1 experimental extension. References: Patch is 30.18 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/127463.diff 20 Files Affected:
diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c
index 5008c2b7f789d..adfd2c41b16ec 100644
--- a/clang/test/Driver/print-supported-extensions-riscv.c
+++ b/clang/test/Driver/print-supported-extensions-riscv.c
@@ -205,6 +205,7 @@
// CHECK-EMPTY:
// CHECK-NEXT: Experimental extensions
// CHECK-NEXT: p 0.14 'P' ('Base P' (Packed SIMD))
+// CHECK-NEXT: zibi 0.1 'Zibi' (Branch with Immediate)
// CHECK-NEXT: zicfilp 1.0 'Zicfilp' (Landing pad)
// CHECK-NEXT: zicfiss 1.0 'Zicfiss' (Shadow stack)
// CHECK-NEXT: zalasr 0.1 'Zalasr' (Load-Acquire and Store-Release Instructions)
diff --git a/clang/test/Preprocessor/riscv-target-features.c b/clang/test/Preprocessor/riscv-target-features.c
index 86085c21a95aa..52a483100f829 100644
--- a/clang/test/Preprocessor/riscv-target-features.c
+++ b/clang/test/Preprocessor/riscv-target-features.c
@@ -122,6 +122,7 @@
// CHECK-NOT: __riscv_zfinx {{.*$}}
// CHECK-NOT: __riscv_zhinx {{.*$}}
// CHECK-NOT: __riscv_zhinxmin {{.*$}}
+// CHECK-NOT: __riscv_zibi {{.*$}}
// CHECK-NOT: __riscv_zic64b {{.*$}}
// CHECK-NOT: __riscv_zicbom {{.*$}}
// CHECK-NOT: __riscv_zicbop {{.*$}}
@@ -1029,6 +1030,14 @@
// RUN: -o - | FileCheck --check-prefix=CHECK-ZHINXMIN-EXT %s
// CHECK-ZHINXMIN-EXT: __riscv_zhinxmin 1000000{{$}}
+// RUN: %clang --target=riscv32 -menable-experimental-extensions \
+// RUN: -march=rv32i_zibi0p1 -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-ZIBI-EXT %s
+// RUN: %clang --target=riscv64 -menable-experimental-extensions \
+// RUN: -march=rv64i_zibi0p1 -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-ZIBI-EXT %s
+// CHECK-ZIBI-EXT: __riscv_zibi
+
// RUN: %clang --target=riscv32-unknown-linux-gnu \
// RUN: -march=rv32izic64b -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-ZIC64B-EXT %s
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index e5d8ab07891ac..de7f9c07c6c75 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -744,6 +744,11 @@ struct RISCVOperand final : public MCParsedAsmOperand {
return isUImmPred([](int64_t Imm) { return Imm != 0 && isUInt<5>(Imm); });
}
+ bool isUImm5Zibi() const {
+ return isUImmPred(
+ [](int64_t Imm) { return (Imm != 0 && isUInt<5>(Imm)) || Imm == -1; });
+ }
+
bool isUImm5GT3() const {
return isUImmPred([](int64_t Imm) { return isUInt<5>(Imm) && Imm > 3; });
}
@@ -1466,6 +1471,10 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
case Match_InvalidUImm5NonZero:
return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5) - 1);
+ case Match_InvalidUImm5Zibi:
+ return generateImmOutOfRangeError(
+ Operands, ErrorInfo, -1, (1 << 5) - 1,
+ "immediate must be non-zero in the range");
case Match_InvalidUImm5GT3:
return generateImmOutOfRangeError(Operands, ErrorInfo, 4, (1 << 5) - 1);
case Match_InvalidUImm5Plus1:
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index 27e04c0cb1f8b..a8d673f662cbd 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -457,6 +457,14 @@ static DecodeStatus decodeUImmNonZeroOperand(MCInst &Inst, uint32_t Imm,
return decodeUImmOperand<N>(Inst, Imm, Address, Decoder);
}
+static DecodeStatus decodeUImmZibiOperand(MCInst &Inst, uint32_t Imm,
+ int64_t Address,
+ const MCDisassembler *Decoder) {
+ assert(isUInt<5>(Imm) && "Invalid immediate");
+ Inst.addOperand(MCOperand::createImm(Imm ? Imm : -1LL));
+ return MCDisassembler::Success;
+}
+
static DecodeStatus
decodeUImmLog2XLenNonZeroOperand(MCInst &Inst, uint32_t Imm, int64_t Address,
const MCDisassembler *Decoder) {
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index f83c2b6da8923..18ce5407f816c 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -789,7 +789,7 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
RISCVCC::CondCode CC;
getOperandsForBranch(MI.getOperand(0).getReg(), CC, LHS, RHS, *MRI);
- auto Bcc = MIB.buildInstr(RISCVCC::getBrCond(CC), {}, {LHS, RHS})
+ auto Bcc = MIB.buildInstr(RISCVCC::getBrCond(STI, CC), {}, {LHS, RHS})
.addMBB(MI.getOperand(1).getMBB());
MI.eraseFromParent();
return constrainSelectedInstRegOperands(*Bcc, TII, TRI, RBI);
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
index 3d304842fac13..d488785d8297d 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
@@ -301,6 +301,7 @@ enum OperandType : unsigned {
OPERAND_UIMM4,
OPERAND_UIMM5,
OPERAND_UIMM5_NONZERO,
+ OPERAND_UIMM5_ZIBI,
OPERAND_UIMM5_GT3,
OPERAND_UIMM5_PLUS1,
OPERAND_UIMM5_GE6_PLUS1,
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
index ce0fbc0ac0654..d6fd6a9323dd4 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
@@ -97,6 +97,10 @@ class RISCVMCCodeEmitter : public MCCodeEmitter {
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
+ uint64_t getImmOpValueZibi(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
uint64_t getImmOpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
@@ -545,6 +549,19 @@ RISCVMCCodeEmitter::getImmOpValueAsrN(const MCInst &MI, unsigned OpNo,
return getImmOpValue(MI, OpNo, Fixups, STI);
}
+uint64_t
+RISCVMCCodeEmitter::getImmOpValueZibi(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ const MCOperand &MO = MI.getOperand(OpNo);
+ assert(MO.isImm() && "Zibi operand must be an immediate");
+ int64_t Res = MO.getImm();
+ if (Res == -1)
+ return 0;
+
+ return Res;
+}
+
uint64_t RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index 36b3aff51cda9..8f97ddedb859d 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -78,6 +78,12 @@ def FeatureStdExtE
: RISCVExtension<2, 0, "Embedded Instruction Set with 16 GPRs">,
RISCVExtensionBitmask<0, 4>;
+def FeatureStdExtZibi
+ : RISCVExperimentalExtension<0, 1, "Branch with Immediate">;
+def HasStdExtZibi : Predicate<"Subtarget->hasStdExtZibi()">,
+ AssemblerPredicate<(all_of FeatureStdExtZibi),
+ "'Zibi' (Branch with Immediate)">;
+
def FeatureStdExtZic64b
: RISCVExtension<1, 0, "Cache Block Size Is 64 Bytes">;
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 13ee3ee63d1a6..7c54f9af1f144 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -21483,7 +21483,7 @@ static MachineBasicBlock *emitSelectPseudo(MachineInstr &MI,
// Insert appropriate branch.
if (MI.getOperand(2).isImm())
- BuildMI(HeadMBB, DL, TII.getBrCond(CC))
+ BuildMI(HeadMBB, DL, TII.getBrCond(CC, true))
.addReg(LHS)
.addImm(MI.getOperand(2).getImm())
.addMBB(TailMBB);
diff --git a/llvm/lib/Target/RISCV/RISCVInstrFormats.td b/llvm/lib/Target/RISCV/RISCVInstrFormats.td
index b6b64b57b1b3e..19de5a0ac4005 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrFormats.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrFormats.td
@@ -496,6 +496,22 @@ class RVInstB<bits<3> funct3, RISCVOpcode opcode, dag outs, dag ins,
let Inst{6-0} = opcode.Value;
}
+class RVInstBIMM<bits<3> funct3, RISCVOpcode opcode, dag outs, dag ins,
+ string opcodestr, string argstr>
+ : RVInst<outs, ins, opcodestr, argstr, [], InstFormatB> {
+ bits<12> imm12;
+ bits<5> cimm;
+ bits<5> rs1;
+ let Inst{31} = imm12{11};
+ let Inst{30-25} = imm12{9-4};
+ let Inst{24-20} = cimm;
+ let Inst{19-15} = rs1;
+ let Inst{14-12} = funct3;
+ let Inst{11-8} = imm12{3-0};
+ let Inst{7} = imm12{10};
+ let Inst{6-0} = opcode.Value;
+}
+
class RVInstU<RISCVOpcode opcode, dag outs, dag ins, string opcodestr,
string argstr>
: RVInst<outs, ins, opcodestr, argstr, [], InstFormatU> {
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index 6e30ffce99c4d..96c6eaf05fc12 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -962,6 +962,10 @@ static RISCVCC::CondCode getCondFromBranchOpc(unsigned Opc) {
switch (Opc) {
default:
return RISCVCC::COND_INVALID;
+ case RISCV::BEQI:
+ return RISCVCC::COND_EQ;
+ case RISCV::BNEI:
+ return RISCVCC::COND_NE;
case RISCV::BEQ:
return RISCVCC::COND_EQ;
case RISCV::BNE:
@@ -1039,14 +1043,15 @@ static void parseCondBranch(MachineInstr &LastInst, MachineBasicBlock *&Target,
Cond.push_back(LastInst.getOperand(1));
}
-unsigned RISCVCC::getBrCond(RISCVCC::CondCode CC) {
+unsigned RISCVCC::getBrCond(const RISCVSubtarget &STI, RISCVCC::CondCode CC,
+ bool Imm) {
switch (CC) {
default:
llvm_unreachable("Unknown condition code!");
case RISCVCC::COND_EQ:
- return RISCV::BEQ;
+ return (Imm && STI.hasStdExtZibi()) ? RISCV::BEQI : RISCV::BEQ;
case RISCVCC::COND_NE:
- return RISCV::BNE;
+ return (Imm && STI.hasStdExtZibi()) ? RISCV::BNEI : RISCV::BNE;
case RISCVCC::COND_LT:
return RISCV::BLT;
case RISCVCC::COND_GE:
@@ -1086,8 +1091,9 @@ unsigned RISCVCC::getBrCond(RISCVCC::CondCode CC) {
}
}
-const MCInstrDesc &RISCVInstrInfo::getBrCond(RISCVCC::CondCode CC) const {
- return get(RISCVCC::getBrCond(CC));
+const MCInstrDesc &RISCVInstrInfo::getBrCond(RISCVCC::CondCode CC,
+ bool Imm) const {
+ return get(RISCVCC::getBrCond(STI, CC, Imm));
}
RISCVCC::CondCode RISCVCC::getOppositeBranchCondition(RISCVCC::CondCode CC) {
@@ -1264,8 +1270,10 @@ unsigned RISCVInstrInfo::insertBranch(
// Either a one or two-way conditional branch.
auto CC = static_cast<RISCVCC::CondCode>(Cond[0].getImm());
- MachineInstr &CondMI =
- *BuildMI(&MBB, DL, getBrCond(CC)).add(Cond[1]).add(Cond[2]).addMBB(TBB);
+ MachineInstr &CondMI = *BuildMI(&MBB, DL, getBrCond(CC, Cond[2].isImm()))
+ .add(Cond[1])
+ .add(Cond[2])
+ .addMBB(TBB);
if (BytesAdded)
*BytesAdded += getInstSizeInBytes(CondMI);
@@ -1507,6 +1515,8 @@ bool RISCVInstrInfo::isBranchOffsetInRange(unsigned BranchOp,
case RISCV::BGE:
case RISCV::BLTU:
case RISCV::BGEU:
+ case RISCV::BEQI:
+ case RISCV::BNEI:
case RISCV::CV_BEQIMM:
case RISCV::CV_BNEIMM:
case RISCV::QC_BEQI:
@@ -2703,6 +2713,9 @@ bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI,
case RISCVOp::OPERAND_UIMM2_LSB0:
Ok = isShiftedUInt<1, 1>(Imm);
break;
+ case RISCVOp::OPERAND_UIMM5_ZIBI:
+ Ok = (isUInt<5>(Imm) && Imm != 0) || Imm == -1;
+ break;
case RISCVOp::OPERAND_UIMM5_LSB0:
Ok = isShiftedUInt<4, 1>(Imm);
break;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.h b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
index 020be91e90e0b..4735670c3e96f 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.h
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
@@ -59,7 +59,7 @@ enum CondCode {
};
CondCode getOppositeBranchCondition(CondCode);
-unsigned getBrCond(CondCode CC);
+unsigned getBrCond(const RISCVSubtarget &STI, CondCode CC, bool Imm = false);
} // end of namespace RISCVCC
@@ -79,7 +79,7 @@ class RISCVInstrInfo : public RISCVGenInstrInfo {
explicit RISCVInstrInfo(RISCVSubtarget &STI);
MCInst getNop() const override;
- const MCInstrDesc &getBrCond(RISCVCC::CondCode CC) const;
+ const MCInstrDesc &getBrCond(RISCVCC::CondCode CC, bool Imm = false) const;
Register isLoadFromStackSlot(const MachineInstr &MI,
int &FrameIndex) const override;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index aa1ebba567824..1f3e21015f89b 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -2249,6 +2249,7 @@ include "RISCVInstrInfoZicbo.td"
include "RISCVInstrInfoZicond.td"
include "RISCVInstrInfoZicfiss.td"
include "RISCVInstrInfoZilsd.td"
+include "RISCVInstrInfoZibi.td"
// Scalar FP
include "RISCVInstrInfoF.td"
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZibi.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZibi.td
new file mode 100644
index 0000000000000..c61bcefdfc4ac
--- /dev/null
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZibi.td
@@ -0,0 +1,51 @@
+//===-- RISCVInstrInfoZibi.td - 'Zibi' instructions ------*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// This file describes the RISC-V instructions for 'Zibi' (branch with imm).
+///
+//===----------------------------------------------------------------------===//
+// A 5-bit unsigned immediate representing 1-31 and -1. 00000 represents -1.
+def uimm5_zibi : RISCVOp<XLenVT>, ImmLeaf<XLenVT, [{
+ return (Imm != 0 && isUInt<5>(Imm)) || Imm == -1;
+}]> {
+ let ParserMatchClass = UImmAsmOperand<5, "Zibi">;
+ let EncoderMethod = "getImmOpValueZibi";
+ let DecoderMethod = "decodeUImmZibiOperand";
+ let MCOperandPredicate = [{
+ int64_t Imm;
+ if (!MCOp.evaluateAsConstantImm(Imm))
+ return false;
+ return (Imm >= 1 && Imm <= 31) || Imm == -1;
+ }];
+ let OperandType = "OPERAND_UIMM5_ZIBI";
+}
+
+class Branch_imm<bits<3> funct3, string opcodestr>
+ : RVInstBIMM<funct3, OPC_BRANCH, (outs),
+ (ins GPR:$rs1, uimm5_zibi:$cimm, bare_simm13_lsb0:$imm12),
+ opcodestr, "$rs1, $cimm, $imm12">,
+ Sched<[WriteJmp, ReadJmp]> {
+ let isBranch = 1;
+ let isTerminator = 1;
+ let hasSideEffects = 0;
+ let mayLoad = 0;
+ let mayStore = 0;
+}
+let Predicates = [HasStdExtZibi] in {
+def BEQI : Branch_imm<0b010, "beqi">;
+def BNEI : Branch_imm<0b011, "bnei">;
+} // Predicates = [HasStdExtZibi]
+
+let Predicates = [HasStdExtZibi] in {
+multiclass BccImmPat<CondCode Cond, Branch_imm Inst> {
+ def : Pat<(riscv_brcc (XLenVT GPR:$rs1), uimm5_zibi:$cimm, Cond, bb:$imm12),
+ (Inst GPR:$rs1, uimm5_zibi:$cimm, bare_simm13_lsb0_bb:$imm12)>;
+}
+defm : BccImmPat<SETEQ, BEQI>;
+defm : BccImmPat<SETNE, BNEI>;
+}// Predicates = [HasStdExtZibi]
\ No newline at end of file
diff --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll
index c5188aa1918bf..a01c7272da0ae 100644
--- a/llvm/test/CodeGen/RISCV/attributes.ll
+++ b/llvm/test/CodeGen/RISCV/attributes.ll
@@ -173,6 +173,7 @@
; RUN: llc -mtriple=riscv32 -mattr=+supm %s -o - | FileCheck --check-prefix=RV32SUPM %s
; RUN: llc -mtriple=riscv32 -mattr=+experimental-smctr %s -o - | FileCheck --check-prefix=RV32SMCTR %s
; RUN: llc -mtriple=riscv32 -mattr=+experimental-ssctr %s -o - | FileCheck --check-prefix=RV32SSCTR %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zibi %s -o - | FileCheck --check-prefix=RV32ZIBI %s
; RUN: llc -mtriple=riscv64 %s -o - | FileCheck %s
; RUN: llc -mtriple=riscv64 -mattr=+m %s -o - | FileCheck --check-prefixes=CHECK,RV64M %s
@@ -337,7 +338,7 @@
; RUN: llc -mtriple=riscv64 -mattr=+sdext %s -o - | FileCheck --check-prefix=RV64SDEXT %s
; RUN: llc -mtriple=riscv64 -mattr=+sdtrig %s -o - | FileCheck --check-prefix=RV64SDTRIG %s
; RUN: llc -mtriple=riscv64 -mattr=+experimental-xqccmp %s -o - | FileCheck --check-prefix=RV64XQCCMP %s
-
+; RUN: llc -mtriple=riscv64 -mattr=+experimental-zibi %s -o - | FileCheck --check-prefix=RV64ZIBI %s
; Tests for profile features.
; RUN: llc -mtriple=riscv32 -mattr=+rvi20u32 %s -o - | FileCheck --check-prefix=RVI20U32 %s
@@ -526,6 +527,7 @@
; RV32SUPM: .attribute 5, "rv32i2p1_supm1p0"
; RV32SMCTR: .attribute 5, "rv32i2p1_smctr1p0_sscsrind1p0"
; RV32SSCTR: .attribute 5, "rv32i2p1_sscsrind1p0_ssctr1p0"
+; RV32ZIBI: .attribute 5, "rv32i2p1_zibi0p1"
; RV64M: .attribute 5, "rv64i2p1_m2p0_zmmul1p0"
; RV64ZMMUL: .attribute 5, "rv64i2p1_zmmul1p0"
@@ -688,6 +690,7 @@
; RV64SDEXT: .attribute 5, "rv64i2p1_sdext1p0"
; RV64SDTRIG: .attribute 5, "rv64i2p1_sdtrig1p0"
; RV64XQCCMP: .attribute 5, "rv64i2p1_zca1p0_xqccmp0p3"
+; RV64ZIBI: .attribute 5, "rv64i2p1_zibi0p1"
; RVI20U32: .attribute 5, "rv32i2p1"
; RVI20U64: .attribute 5, "rv64i2p1"
diff --git a/llvm/test/CodeGen/RISCV/features-info.ll b/llvm/test/CodeGen/RISCV/features-info.ll
index 8b931f70aa5cc..c999550b7e713 100644
--- a/llvm/test/CodeGen/RISCV/features-info.ll
+++ b/llvm/test/CodeGen/RISCV/features-info.ll
@@ -46,6 +46,7 @@
; CHECK-NEXT: experimental-xsfmclic - 'XSfmclic' (SiFive CLIC Machine-mode CSRs).
; CHECK-NEXT: experimental-xsfsclic - 'XSfsclic' (SiFive CLIC Supervisor-mode CSRs).
; CHECK-NEXT: experimental-zalasr - 'Zalasr' (Load-Acquire and Store-Release Instructions).
+; CHECK-NEXT: experimental-zibi - 'Zibi' (Branch with Immediate).
; CHECK-NEXT: experimental-zicfilp - 'Zicfilp' (Landing pad).
; CHECK-NEXT: experimental-zicfiss - 'Zicfiss' (Shadow stack).
; CHECK-NEXT: experimental-zvbc32e - 'Zvbc32e' (Vector Carryless Multiplication with 32-bits elements).
diff --git a/llvm/test/CodeGen/RISCV/zibi.ll b/llvm/test/CodeGen/RISCV/zibi.ll
new file mode 100644
index 0000000000000..e77acd0dc749d
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/zibi.ll
@@ -0,0 +1,207 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zibi -verify-machineinstrs < %s \
+; RUN: | FileCheck -check-prefix=ZIBI %s
+; RUN: llc -mtriple=riscv64 -mattr=+experimental-zibi -verify-machineinstrs < %s \
+; RUN: | FileCheck -check-prefix=ZIBI %s
+
+define void @test_bne_neg(ptr %b) nounwind {
+; ZIBI-LABEL: test_bne_neg:
+; ZIBI: # %bb.0:
+; ZIBI-NEXT: lw a1, 0(a0)
+; ZIBI-NEXT: bnei a1, -1, .LBB0_2
+; ZIBI-NEXT: # %bb.1: # %test2
+; ZIBI-NEXT: lw zero, 0(a0)
+; ZIBI-NEXT: .LBB0_2: # %end
+; ZIBI-NEXT: ret
+ %val1 = load volatile i32, ptr %b
+ %tst1 = icmp ne i32 %val1, -1
+ br i1 %tst1, label %end, label %test2, !prof !0
+test2:
+ %val2 = load volatile i32, ptr %b
+ br label %end
+end:
+ ret void
+}
+!0 = !{!"branch_weights", i32 1, i32 99}
+
+define void @test_beq_neg(ptr %b) nounwind {
+; ZIBI-LABEL: test_beq_neg:
+; ZIBI: # %bb.0:
+; ZIBI-NEXT: lw a1, 0(a0)
+; ZIBI-NEXT: beqi a1, -1, .LBB1_2
+; ZIBI-NEXT: # %bb.1: # %test2
+; ZIBI-NEXT: lw zero, 0(a0)
+; ZIBI-NEXT: .LBB1_2: # %end
+; ZIBI-NEXT: ret
+ %val1 = load volatile i32, ptr %b
+ %tst1 = icmp eq i32 %val1, -1
+ br i1 %tst1, label %en...
[truncated]
|
I cannot for the life of me find an actual specification linked from that page, nor from searching. Where is the GitHub repo in the riscv organisation with it? |
There’s no public GitHub repo for Zibi yet. It’s currently going through the ratification process, the repo hasn’t been created at this stage. Please refer to the attachment in RVS-3828 for more details. |
Sorry, we are still working on the repo. This extension has been approved as fast-track, but we are not familiar with the process (and the process has some changes recently). You may refer to the mailing list (https://lists.riscv.org/g/sig-scalar-efficiency/topic/111893156). We will make all the resouces publicly accessible ASAP, sorry for the inconvenience. |
Note the pdf linked there seems to be missing the image that contains the immediate format. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with one tiny nit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please separate this PR into two commits: one for MC and another for CodeGen.
cf9aad7
to
aea8133
Compare
I’m not sure we should be merging support for extensions that are so early in the development process that they don’t even have a GitHub repository in the riscv organisation with a specification. |
I agree we should wait for the formalized specification. We will not merge this until it is ready. |
d67405b
to
4d51141
Compare
386f41e
to
2876e88
Compare
This adds the MC support of Zibi v0.1 experimental extension. References: https://lf-riscv.atlassian.net/wiki/spaces/USXX/pages/599261201/Branch+with+Immediate+Zibi+Ratification+Plan https://lf-riscv.atlassian.net/browse/RVS-3828
bfadcf5
to
5196dd3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. We will hold this PR for one more day to see if there are more comments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice to see an actual encodings spec PDF to be able to verify that the opcode encoding in this PR is actually correct.
The PDF I downloaded from JIRA did not seem to have any encodings.
Two minor comments inline.
llvm/test/MC/RISCV/zibi-invalid.s
Outdated
# CHECK-ERROR-LABEL: bnei a2, 0x10, 0x1000 | ||
bnei a2, 0x10, 0x111 | ||
# CHECK-ERROR: [[@LINE-1]]:16: error: immediate must be a multiple of 2 bytes in the range [-4096, 4094] | ||
# CHECK-ERROR-LABEL: bnei a2, 0x10, 0x111 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing newline at end
//===----------------------------------------------------------------------===// | ||
|
||
// A 5-bit unsigned immediate representing 1-31 and -1. 00000 represents -1. | ||
def uimm5_zibi : RISCVOp<XLenVT>, ImmLeaf<XLenVT, [{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is not unsigned, the uimm prefix is somewhat misleading. How about zibi_imm5 or imm5_zibi?
Thanks @arichardson ! We will release an v0.1 PDF in https://github.com/riscv/zibi this week and then update this PR. :-) |
This adds the MC support of Zibi v0.1 experimental extension.
References: