Skip to content

[RISCV][CodeGen] Add CodeGen support of Zibi experimental extension #146858

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions clang/test/Driver/print-supported-extensions-riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
9 changes: 9 additions & 0 deletions clang/test/Preprocessor/riscv-target-features.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 {{.*$}}
Expand Down Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions llvm/docs/RISCVUsage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,9 @@ The primary goal of experimental support is to assist in the process of ratifica
``experimental-zalasr``
LLVM implements the `0.0.5 draft specification <https://github.com/mehnadnerd/riscv-zalasr>`__.

``experimental-zibi``
LLVM implements the `0.1 release specification <https://lf-riscv.atlassian.net/wiki/spaces/USXX/pages/599261201/Branch+with+Immediate+Zibi+Ratification+Plan>`__.

``experimental-zicfilp``, ``experimental-zicfiss``
LLVM implements the `1.0 release specification <https://github.com/riscv/riscv-cfi/releases/tag/v1.0>`__.

Expand Down
2 changes: 2 additions & 0 deletions llvm/docs/ReleaseNotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ Changes to the RISC-V Backend
extension.
* Adds experimental assembler support for the Qualcomm uC 'Xqciio` (External Input Output)
extension.
* Adds experimental assembler and code generation support for the 'Zibi` (Branch with Immediate)
extension.
* Adds assembler support for the 'Zilsd` (Load/Store Pair Instructions)
extension.
* Adds assembler support for the 'Zclsd` (Compressed Load/Store Pair Instructions)
Expand Down
9 changes: 9 additions & 0 deletions llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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; });
}
Expand Down Expand Up @@ -1470,6 +1475,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:
Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
5 changes: 3 additions & 2 deletions llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -789,8 +789,9 @@ 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})
.addMBB(MI.getOperand(1).getMBB());
auto Bcc =
MIB.buildInstr(RISCVCC::getBrCond(*Subtarget, CC), {}, {LHS, RHS})
.addMBB(MI.getOperand(1).getMBB());
MI.eraseFromParent();
return constrainSelectedInstRegOperands(*Bcc, TII, TRI, RBI);
}
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 @@ -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,
Expand Down
17 changes: 17 additions & 0 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ bool RISCVExpandPseudo::expandCCOp(MachineBasicBlock &MBB,
CC = RISCVCC::getOppositeBranchCondition(CC);

// Insert branch instruction.
BuildMI(MBB, MBBI, DL, TII->get(RISCVCC::getBrCond(CC)))
BuildMI(MBB, MBBI, DL, TII->get(RISCVCC::getBrCond(*STI, CC)))
.addReg(MI.getOperand(1).getReg())
.addReg(MI.getOperand(2).getReg())
.addMBB(MergeBB);
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/Target/RISCV/RISCVFeatures.td
Original file line number Diff line number Diff line change
Expand Up @@ -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">;

Expand Down
11 changes: 7 additions & 4 deletions llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21388,7 +21388,8 @@ EmitLoweredCascadedSelect(MachineInstr &First, MachineInstr &Second,
Register FLHS = First.getOperand(1).getReg();
Register FRHS = First.getOperand(2).getReg();
// Insert appropriate branch.
BuildMI(FirstMBB, DL, TII.get(RISCVCC::getBrCond(FirstCC, First.getOpcode())))
BuildMI(FirstMBB, DL,
TII.get(RISCVCC::getBrCond(Subtarget, FirstCC, First.getOpcode())))
.addReg(FLHS)
.addReg(FRHS)
.addMBB(SinkMBB);
Expand All @@ -21401,7 +21402,7 @@ EmitLoweredCascadedSelect(MachineInstr &First, MachineInstr &Second,
auto SecondCC = static_cast<RISCVCC::CondCode>(Second.getOperand(3).getImm());
// Insert appropriate branch.
BuildMI(ThisMBB, DL,
TII.get(RISCVCC::getBrCond(SecondCC, Second.getOpcode())))
TII.get(RISCVCC::getBrCond(Subtarget, SecondCC, Second.getOpcode())))
.addReg(SLHS)
.addReg(SRHS)
.addMBB(SinkMBB);
Expand Down Expand Up @@ -21536,12 +21537,14 @@ static MachineBasicBlock *emitSelectPseudo(MachineInstr &MI,

// Insert appropriate branch.
if (MI.getOperand(2).isImm())
BuildMI(HeadMBB, DL, TII.get(RISCVCC::getBrCond(CC, MI.getOpcode())))
BuildMI(HeadMBB, DL,
TII.get(RISCVCC::getBrCond(Subtarget, CC, MI.getOpcode(), true)))
.addReg(LHS)
.addImm(MI.getOperand(2).getImm())
.addMBB(TailMBB);
else
BuildMI(HeadMBB, DL, TII.get(RISCVCC::getBrCond(CC, MI.getOpcode())))
BuildMI(HeadMBB, DL,
TII.get(RISCVCC::getBrCond(Subtarget, CC, MI.getOpcode())))
.addReg(LHS)
.addReg(RHS)
.addMBB(TailMBB);
Expand Down
16 changes: 16 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrFormats.td
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down
22 changes: 18 additions & 4 deletions llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -961,11 +961,13 @@ RISCVCC::CondCode RISCVInstrInfo::getCondFromBranchOpc(unsigned Opc) {
default:
return RISCVCC::COND_INVALID;
case RISCV::BEQ:
case RISCV::BEQI:
case RISCV::CV_BEQIMM:
case RISCV::QC_BEQI:
case RISCV::QC_E_BEQI:
return RISCVCC::COND_EQ;
case RISCV::BNE:
case RISCV::BNEI:
case RISCV::QC_BNEI:
case RISCV::QC_E_BNEI:
case RISCV::CV_BNEIMM:
Expand Down Expand Up @@ -1023,16 +1025,17 @@ static void parseCondBranch(MachineInstr &LastInst, MachineBasicBlock *&Target,
Cond.push_back(LastInst.getOperand(1));
}

unsigned RISCVCC::getBrCond(RISCVCC::CondCode CC, unsigned SelectOpc) {
unsigned RISCVCC::getBrCond(const RISCVSubtarget &STI, CondCode CC,
unsigned SelectOpc, bool Imm) {
switch (SelectOpc) {
default:
switch (CC) {
default:
llvm_unreachable("Unexpected 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:
Expand Down Expand Up @@ -1341,9 +1344,15 @@ bool RISCVInstrInfo::reverseBranchCondition(
case RISCV::BEQ:
Cond[0].setImm(RISCV::BNE);
break;
case RISCV::BEQI:
Cond[0].setImm(RISCV::BNEI);
break;
case RISCV::BNE:
Cond[0].setImm(RISCV::BEQ);
break;
case RISCV::BNEI:
Cond[0].setImm(RISCV::BEQI);
break;
case RISCV::BLT:
Cond[0].setImm(RISCV::BGE);
break;
Expand Down Expand Up @@ -1506,7 +1515,7 @@ bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
return Register();
};

unsigned NewOpc = RISCVCC::getBrCond(getOppositeBranchCondition(CC));
unsigned NewOpc = RISCVCC::getBrCond(STI, getOppositeBranchCondition(CC));

// Might be case 1.
// Don't change 0 to 1 since we can use x0.
Expand Down Expand Up @@ -1576,6 +1585,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:
Expand Down Expand Up @@ -2775,6 +2786,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;
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/RISCV/RISCVInstrInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ enum CondCode {
};

CondCode getOppositeBranchCondition(CondCode);
unsigned getBrCond(CondCode CC, unsigned SelectOpc = 0);
unsigned getBrCond(const RISCVSubtarget &STI, CondCode CC,
unsigned SelectOpc = 0, bool Imm = false);

} // end of namespace RISCVCC

Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -2255,6 +2255,7 @@ include "RISCVInstrInfoZicbo.td"
include "RISCVInstrInfoZicond.td"
include "RISCVInstrInfoZicfiss.td"
include "RISCVInstrInfoZilsd.td"
include "RISCVInstrInfoZibi.td"

// Scalar FP
include "RISCVInstrInfoF.td"
Expand Down
51 changes: 51 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfoZibi.td
Original file line number Diff line number Diff line change
@@ -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]
Loading
Loading