diff options
Diffstat (limited to 'llvm/lib/Target/RISCV/RISCVInstrInfo.cpp')
-rw-r--r-- | llvm/lib/Target/RISCV/RISCVInstrInfo.cpp | 206 |
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(); +} |