aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/RISCV/RISCVInstrInfo.cpp')
-rw-r--r--llvm/lib/Target/RISCV/RISCVInstrInfo.cpp206
1 files changed, 139 insertions, 67 deletions
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index 55f4a19b79eb..685604ad9a59 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -264,6 +264,16 @@ void RISCVInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
return;
}
+ // Handle copy from csr
+ if (RISCV::VCSRRegClass.contains(SrcReg) &&
+ RISCV::GPRRegClass.contains(DstReg)) {
+ const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
+ BuildMI(MBB, MBBI, DL, get(RISCV::CSRRS), DstReg)
+ .addImm(RISCVSysReg::lookupSysRegByName(TRI.getName(SrcReg))->Encoding)
+ .addReg(RISCV::X0);
+ return;
+ }
+
// FPR->FPR copies and VR->VR copies.
unsigned Opc;
bool IsScalableVector = true;
@@ -631,11 +641,7 @@ void RISCVInstrInfo::movImm(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
const DebugLoc &DL, Register DstReg, uint64_t Val,
MachineInstr::MIFlag Flag) const {
- MachineFunction *MF = MBB.getParent();
- MachineRegisterInfo &MRI = MF->getRegInfo();
Register SrcReg = RISCV::X0;
- Register Result = MRI.createVirtualRegister(&RISCV::GPRRegClass);
- unsigned Num = 0;
if (!STI.is64Bit() && !isInt<32>(Val))
report_fatal_error("Should only materialize 32-bit constants for RV32");
@@ -645,34 +651,34 @@ void RISCVInstrInfo::movImm(MachineBasicBlock &MBB,
assert(!Seq.empty());
for (RISCVMatInt::Inst &Inst : Seq) {
- // Write the final result to DstReg if it's the last instruction in the Seq.
- // Otherwise, write the result to the temp register.
- if (++Num == Seq.size())
- Result = DstReg;
-
- if (Inst.Opc == RISCV::LUI) {
- BuildMI(MBB, MBBI, DL, get(RISCV::LUI), Result)
+ switch (Inst.getOpndKind()) {
+ case RISCVMatInt::Imm:
+ BuildMI(MBB, MBBI, DL, get(Inst.Opc), DstReg)
.addImm(Inst.Imm)
.setMIFlag(Flag);
- } else if (Inst.Opc == RISCV::ADD_UW) {
- BuildMI(MBB, MBBI, DL, get(RISCV::ADD_UW), Result)
+ break;
+ case RISCVMatInt::RegX0:
+ BuildMI(MBB, MBBI, DL, get(Inst.Opc), DstReg)
.addReg(SrcReg, RegState::Kill)
.addReg(RISCV::X0)
.setMIFlag(Flag);
- } else if (Inst.Opc == RISCV::SH1ADD || Inst.Opc == RISCV::SH2ADD ||
- Inst.Opc == RISCV::SH3ADD) {
- BuildMI(MBB, MBBI, DL, get(Inst.Opc), Result)
+ break;
+ case RISCVMatInt::RegReg:
+ BuildMI(MBB, MBBI, DL, get(Inst.Opc), DstReg)
.addReg(SrcReg, RegState::Kill)
.addReg(SrcReg, RegState::Kill)
.setMIFlag(Flag);
- } else {
- BuildMI(MBB, MBBI, DL, get(Inst.Opc), Result)
+ break;
+ case RISCVMatInt::RegImm:
+ BuildMI(MBB, MBBI, DL, get(Inst.Opc), DstReg)
.addReg(SrcReg, RegState::Kill)
.addImm(Inst.Imm)
.setMIFlag(Flag);
+ break;
}
+
// Only the first instruction has X0 as its source.
- SrcReg = Result;
+ SrcReg = DstReg;
}
}
@@ -1052,29 +1058,25 @@ bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI,
switch (OpType) {
default:
llvm_unreachable("Unexpected operand type");
- case RISCVOp::OPERAND_UIMM2:
- Ok = isUInt<2>(Imm);
- break;
- case RISCVOp::OPERAND_UIMM3:
- Ok = isUInt<3>(Imm);
- break;
- case RISCVOp::OPERAND_UIMM4:
- Ok = isUInt<4>(Imm);
- break;
- case RISCVOp::OPERAND_UIMM5:
- Ok = isUInt<5>(Imm);
- break;
- case RISCVOp::OPERAND_UIMM7:
- Ok = isUInt<7>(Imm);
- break;
- case RISCVOp::OPERAND_UIMM12:
- Ok = isUInt<12>(Imm);
- break;
+
+ // clang-format off
+#define CASE_OPERAND_UIMM(NUM) \
+ case RISCVOp::OPERAND_UIMM##NUM: \
+ Ok = isUInt<NUM>(Imm); \
+ break;
+ CASE_OPERAND_UIMM(2)
+ CASE_OPERAND_UIMM(3)
+ CASE_OPERAND_UIMM(4)
+ CASE_OPERAND_UIMM(5)
+ CASE_OPERAND_UIMM(7)
+ CASE_OPERAND_UIMM(12)
+ CASE_OPERAND_UIMM(20)
+ // clang-format on
case RISCVOp::OPERAND_SIMM12:
Ok = isInt<12>(Imm);
break;
- case RISCVOp::OPERAND_UIMM20:
- Ok = isUInt<20>(Imm);
+ case RISCVOp::OPERAND_SIMM12_LSB00000:
+ Ok = isShiftedInt<7, 5>(Imm);
break;
case RISCVOp::OPERAND_UIMMLOG2XLEN:
if (STI.getTargetTriple().isArch64Bit())
@@ -1205,6 +1207,11 @@ enum MachineOutlinerConstructionID {
MachineOutlinerDefault
};
+bool RISCVInstrInfo::shouldOutlineFromFunctionByDefault(
+ MachineFunction &MF) const {
+ return MF.getFunction().hasMinSize();
+}
+
outliner::OutlinedFunction RISCVInstrInfo::getOutliningCandidateInfo(
std::vector<outliner::Candidate> &RepeatedSequenceLocs) const {
@@ -1212,10 +1219,7 @@ outliner::OutlinedFunction RISCVInstrInfo::getOutliningCandidateInfo(
// be used to setup the function call.
auto CannotInsertCall = [](outliner::Candidate &C) {
const TargetRegisterInfo *TRI = C.getMF()->getSubtarget().getRegisterInfo();
-
- C.initLRU(*TRI);
- LiveRegUnits LRU = C.LRU;
- return !LRU.available(RISCV::X5);
+ return !C.isAvailableAcrossAndOutOfSeq(RISCV::X5, *TRI);
};
llvm::erase_if(RepeatedSequenceLocs, CannotInsertCall);
@@ -1258,7 +1262,12 @@ RISCVInstrInfo::getOutliningType(MachineBasicBlock::iterator &MBBI,
if (MI.isPosition()) {
// We can manually strip out CFI instructions later.
if (MI.isCFIInstruction())
- return outliner::InstrType::Invisible;
+ // If current function has exception handling code, we can't outline &
+ // strip these CFI instructions since it may break .eh_frame section
+ // needed in unwinding.
+ return MI.getMF()->getFunction().needsUnwindTableEntry()
+ ? outliner::InstrType::Illegal
+ : outliner::InstrType::Invisible;
return outliner::InstrType::Illegal;
}
@@ -1325,7 +1334,7 @@ void RISCVInstrInfo::buildOutlinedFrame(
MachineBasicBlock::iterator RISCVInstrInfo::insertOutlinedCall(
Module &M, MachineBasicBlock &MBB, MachineBasicBlock::iterator &It,
- MachineFunction &MF, const outliner::Candidate &C) const {
+ MachineFunction &MF, outliner::Candidate &C) const {
// Add in a call instruction to the outlined function at the given location.
It = MBB.insert(It,
@@ -1335,6 +1344,53 @@ MachineBasicBlock::iterator RISCVInstrInfo::insertOutlinedCall(
return It;
}
+// MIR printer helper function to annotate Operands with a comment.
+std::string RISCVInstrInfo::createMIROperandComment(
+ const MachineInstr &MI, const MachineOperand &Op, unsigned OpIdx,
+ const TargetRegisterInfo *TRI) const {
+ // Print a generic comment for this operand if there is one.
+ std::string GenericComment =
+ TargetInstrInfo::createMIROperandComment(MI, Op, OpIdx, TRI);
+ if (!GenericComment.empty())
+ return GenericComment;
+
+ // If not, we must have an immediate operand.
+ if (!Op.isImm())
+ return std::string();
+
+ std::string Comment;
+ raw_string_ostream OS(Comment);
+
+ uint64_t TSFlags = MI.getDesc().TSFlags;
+
+ // Print the full VType operand of vsetvli/vsetivli instructions, and the SEW
+ // operand of vector codegen pseudos.
+ if ((MI.getOpcode() == RISCV::VSETVLI || MI.getOpcode() == RISCV::VSETIVLI ||
+ MI.getOpcode() == RISCV::PseudoVSETVLI ||
+ MI.getOpcode() == RISCV::PseudoVSETIVLI ||
+ MI.getOpcode() == RISCV::PseudoVSETVLIX0) &&
+ OpIdx == 2) {
+ unsigned Imm = MI.getOperand(OpIdx).getImm();
+ RISCVVType::printVType(Imm, OS);
+ } else if (RISCVII::hasSEWOp(TSFlags)) {
+ unsigned NumOperands = MI.getNumExplicitOperands();
+ bool HasPolicy = RISCVII::hasVecPolicyOp(TSFlags);
+
+ // The SEW operand is before any policy operand.
+ if (OpIdx != NumOperands - HasPolicy - 1)
+ return std::string();
+
+ unsigned Log2SEW = MI.getOperand(OpIdx).getImm();
+ unsigned SEW = Log2SEW ? 1 << Log2SEW : 8;
+ assert(RISCVVType::isValidSEW(SEW) && "Unexpected SEW");
+
+ OS << "e" << SEW;
+ }
+
+ OS.flush();
+ return Comment;
+}
+
// clang-format off
#define CASE_VFMA_OPCODE_COMMON(OP, TYPE, LMUL) \
RISCV::PseudoV##OP##_##TYPE##_##LMUL
@@ -1653,6 +1709,12 @@ MachineInstr *RISCVInstrInfo::convertToThreeAddress(MachineInstr &MI,
case CASE_WIDEOP_OPCODE_LMULS(WADDU_WV):
case CASE_WIDEOP_OPCODE_LMULS(WSUB_WV):
case CASE_WIDEOP_OPCODE_LMULS(WSUBU_WV): {
+ // If the tail policy is undisturbed we can't convert.
+ assert(RISCVII::hasVecPolicyOp(MI.getDesc().TSFlags) &&
+ MI.getNumExplicitOperands() == 6);
+ if ((MI.getOperand(5).getImm() & 1) == 0)
+ return nullptr;
+
// clang-format off
unsigned NewOpc;
switch (MI.getOpcode()) {
@@ -1722,11 +1784,10 @@ Register RISCVInstrInfo::getVLENFactoredAmount(MachineFunction &MF,
"Reserve the stack by the multiple of one vector size.");
MachineRegisterInfo &MRI = MF.getRegInfo();
- const RISCVInstrInfo *TII = MF.getSubtarget<RISCVSubtarget>().getInstrInfo();
int64_t NumOfVReg = Amount / 8;
Register VL = MRI.createVirtualRegister(&RISCV::GPRRegClass);
- BuildMI(MBB, II, DL, TII->get(RISCV::PseudoReadVLENB), VL)
+ BuildMI(MBB, II, DL, get(RISCV::PseudoReadVLENB), VL)
.setMIFlag(Flag);
assert(isInt<32>(NumOfVReg) &&
"Expect the number of vector registers within 32-bits.");
@@ -1734,47 +1795,55 @@ Register RISCVInstrInfo::getVLENFactoredAmount(MachineFunction &MF,
uint32_t ShiftAmount = Log2_32(NumOfVReg);
if (ShiftAmount == 0)
return VL;
- BuildMI(MBB, II, DL, TII->get(RISCV::SLLI), VL)
+ BuildMI(MBB, II, DL, get(RISCV::SLLI), VL)
.addReg(VL, RegState::Kill)
.addImm(ShiftAmount)
.setMIFlag(Flag);
+ } else if ((NumOfVReg == 3 || NumOfVReg == 5 || NumOfVReg == 9) &&
+ STI.hasStdExtZba()) {
+ // We can use Zba SHXADD instructions for multiply in some cases.
+ // TODO: Generalize to SHXADD+SLLI.
+ unsigned Opc;
+ switch (NumOfVReg) {
+ default: llvm_unreachable("Unexpected number of vregs");
+ case 3: Opc = RISCV::SH1ADD; break;
+ case 5: Opc = RISCV::SH2ADD; break;
+ case 9: Opc = RISCV::SH3ADD; break;
+ }
+ BuildMI(MBB, II, DL, get(Opc), VL)
+ .addReg(VL, RegState::Kill)
+ .addReg(VL)
+ .setMIFlag(Flag);
} else if (isPowerOf2_32(NumOfVReg - 1)) {
Register ScaledRegister = MRI.createVirtualRegister(&RISCV::GPRRegClass);
uint32_t ShiftAmount = Log2_32(NumOfVReg - 1);
- BuildMI(MBB, II, DL, TII->get(RISCV::SLLI), ScaledRegister)
+ BuildMI(MBB, II, DL, get(RISCV::SLLI), ScaledRegister)
.addReg(VL)
.addImm(ShiftAmount)
.setMIFlag(Flag);
- BuildMI(MBB, II, DL, TII->get(RISCV::ADD), VL)
+ BuildMI(MBB, II, DL, get(RISCV::ADD), VL)
.addReg(ScaledRegister, RegState::Kill)
.addReg(VL, RegState::Kill)
.setMIFlag(Flag);
} else if (isPowerOf2_32(NumOfVReg + 1)) {
Register ScaledRegister = MRI.createVirtualRegister(&RISCV::GPRRegClass);
uint32_t ShiftAmount = Log2_32(NumOfVReg + 1);
- BuildMI(MBB, II, DL, TII->get(RISCV::SLLI), ScaledRegister)
+ BuildMI(MBB, II, DL, get(RISCV::SLLI), ScaledRegister)
.addReg(VL)
.addImm(ShiftAmount)
.setMIFlag(Flag);
- BuildMI(MBB, II, DL, TII->get(RISCV::SUB), VL)
+ BuildMI(MBB, II, DL, get(RISCV::SUB), VL)
.addReg(ScaledRegister, RegState::Kill)
.addReg(VL, RegState::Kill)
.setMIFlag(Flag);
} else {
Register N = MRI.createVirtualRegister(&RISCV::GPRRegClass);
- if (!isInt<12>(NumOfVReg))
- movImm(MBB, II, DL, N, NumOfVReg);
- else {
- BuildMI(MBB, II, DL, TII->get(RISCV::ADDI), N)
- .addReg(RISCV::X0)
- .addImm(NumOfVReg)
- .setMIFlag(Flag);
- }
- if (!MF.getSubtarget<RISCVSubtarget>().hasStdExtM())
+ movImm(MBB, II, DL, N, NumOfVReg, Flag);
+ if (!STI.hasStdExtM())
MF.getFunction().getContext().diagnose(DiagnosticInfoUnsupported{
MF.getFunction(),
"M-extension must be enabled to calculate the vscaled size/offset."});
- BuildMI(MBB, II, DL, TII->get(RISCV::MUL), VL)
+ BuildMI(MBB, II, DL, get(RISCV::MUL), VL)
.addReg(VL, RegState::Kill)
.addReg(N, RegState::Kill)
.setMIFlag(Flag);
@@ -1811,20 +1880,18 @@ static bool isRVVWholeLoadStore(unsigned Opcode) {
}
}
-bool RISCVInstrInfo::isRVVSpill(const MachineInstr &MI, bool CheckFIs) const {
+bool RISCV::isRVVSpill(const MachineInstr &MI) {
// RVV lacks any support for immediate addressing for stack addresses, so be
// conservative.
unsigned Opcode = MI.getOpcode();
if (!RISCVVPseudosTable::getPseudoInfo(Opcode) &&
!isRVVWholeLoadStore(Opcode) && !isRVVSpillForZvlsseg(Opcode))
return false;
- return !CheckFIs || any_of(MI.operands(), [](const MachineOperand &MO) {
- return MO.isFI();
- });
+ return true;
}
Optional<std::pair<unsigned, unsigned>>
-RISCVInstrInfo::isRVVSpillForZvlsseg(unsigned Opcode) const {
+RISCV::isRVVSpillForZvlsseg(unsigned Opcode) {
switch (Opcode) {
default:
return None;
@@ -1863,3 +1930,8 @@ RISCVInstrInfo::isRVVSpillForZvlsseg(unsigned Opcode) const {
return std::make_pair(8u, 1u);
}
}
+
+bool RISCV::isFaultFirstLoad(const MachineInstr &MI) {
+ return MI.getNumExplicitDefs() == 2 && MI.modifiesRegister(RISCV::VL) &&
+ !MI.isInlineAsm();
+}