Mercurial > hg > CbC > CbC_llvm
diff llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp @ 236:c4bab56944e8 llvm-original
LLVM 16
author | kono |
---|---|
date | Wed, 09 Nov 2022 17:45:10 +0900 |
parents | 79ff65ed7e25 |
children | 1f2b6ac9f198 |
line wrap: on
line diff
--- a/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp Wed Jul 21 10:27:27 2021 +0900 +++ b/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp Wed Nov 09 17:45:10 2022 +0900 @@ -40,6 +40,7 @@ #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/IR/DebugLoc.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCInstBuilder.h" #include "llvm/MC/MCInstrDesc.h" #include "llvm/MC/MCInstrItineraries.h" #include "llvm/MC/MCRegisterInfo.h" @@ -76,9 +77,9 @@ static cl::opt<bool> EnableBranchPrediction("hexagon-enable-branch-prediction", cl::Hidden, cl::init(true), cl::desc("Enable branch prediction")); -static cl::opt<bool> DisableNVSchedule("disable-hexagon-nv-schedule", - cl::Hidden, cl::ZeroOrMore, cl::init(false), - cl::desc("Disable schedule adjustment for new value stores.")); +static cl::opt<bool> DisableNVSchedule( + "disable-hexagon-nv-schedule", cl::Hidden, + cl::desc("Disable schedule adjustment for new value stores.")); static cl::opt<bool> EnableTimingClassLatency( "enable-timing-class-latency", cl::Hidden, cl::init(false), @@ -93,11 +94,12 @@ cl::desc("Enable vec acc forwarding")); static cl::opt<bool> BranchRelaxAsmLarge("branch-relax-asm-large", - cl::init(true), cl::Hidden, cl::ZeroOrMore, cl::desc("branch relax asm")); - -static cl::opt<bool> UseDFAHazardRec("dfa-hazard-rec", - cl::init(true), cl::Hidden, cl::ZeroOrMore, - cl::desc("Use the DFA based hazard recognizer.")); + cl::init(true), cl::Hidden, + cl::desc("branch relax asm")); + +static cl::opt<bool> + UseDFAHazardRec("dfa-hazard-rec", cl::init(true), cl::Hidden, + cl::desc("Use the DFA based hazard recognizer.")); /// Constants for Hexagon instructions. const int Hexagon_MEMW_OFFSET_MAX = 4095; @@ -145,6 +147,48 @@ return Count; } +// Check if the A2_tfrsi instruction is cheap or not. If the operand has +// to be constant-extendend it is not cheap since it occupies two slots +// in a packet. +bool HexagonInstrInfo::isAsCheapAsAMove(const MachineInstr &MI) const { + // Enable the following steps only at Os/Oz + if (!(MI.getMF()->getFunction().hasOptSize())) + return MI.isAsCheapAsAMove(); + + if (MI.getOpcode() == Hexagon::A2_tfrsi) { + auto Op = MI.getOperand(1); + // If the instruction has a global address as operand, it is not cheap + // since the operand will be constant extended. + if (Op.isGlobal()) + return false; + // If the instruction has an operand of size > 16bits, its will be + // const-extended and hence, it is not cheap. + if (Op.isImm()) { + int64_t Imm = Op.getImm(); + if (!isInt<16>(Imm)) + return false; + } + } + return MI.isAsCheapAsAMove(); +} + +// Do not sink floating point instructions that updates USR register. +// Example: +// feclearexcept +// F2_conv_w2sf +// fetestexcept +// MachineSink sinks F2_conv_w2sf and we are not able to catch exceptions. +// TODO: On some of these floating point instructions, USR is marked as Use. +// In reality, these instructions also Def the USR. If USR is marked as Def, +// some of the assumptions in assembler packetization are broken. +bool HexagonInstrInfo::shouldSink(const MachineInstr &MI) const { + // Assumption: A floating point instruction that reads the USR will write + // the USR as well. + if (isFloat(MI) && MI.hasRegisterImplicitUseOperand(Hexagon::USR)) + return false; + return true; +} + /// Find the hardware loop instruction used to set-up the specified loop. /// On Hexagon, we have two instructions used to set-up the hardware loop /// (LOOP0, LOOP1) with corresponding endloop (ENDLOOP0, ENDLOOP1) instructions @@ -169,13 +213,13 @@ continue; if (PB == BB) continue; - for (auto I = PB->instr_rbegin(), E = PB->instr_rend(); I != E; ++I) { - unsigned Opc = I->getOpcode(); + for (MachineInstr &I : llvm::reverse(PB->instrs())) { + unsigned Opc = I.getOpcode(); if (Opc == LOOPi || Opc == LOOPr) - return &*I; + return &I; // We've reached a different loop, which means the loop01 has been // removed. - if (Opc == EndLoopOp && I->getOperand(0).getMBB() != TargetBB) + if (Opc == EndLoopOp && I.getOperand(0).getMBB() != TargetBB) return nullptr; } // Check the predecessors for the LOOP instruction. @@ -193,9 +237,7 @@ Defs.clear(); Uses.clear(); - for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { - const MachineOperand &MO = MI.getOperand(i); - + for (const MachineOperand &MO : MI.operands()) { if (!MO.isReg()) continue; @@ -1031,6 +1073,43 @@ }; switch (Opc) { + case Hexagon::PS_call_instrprof_custom: { + auto Op0 = MI.getOperand(0); + assert(Op0.isGlobal() && + "First operand must be a global containing handler name."); + const GlobalValue *NameVar = Op0.getGlobal(); + const GlobalVariable *GV = dyn_cast<GlobalVariable>(NameVar); + auto *Arr = cast<ConstantDataArray>(GV->getInitializer()); + StringRef NameStr = Arr->isCString() ? Arr->getAsCString() : Arr->getAsString(); + + MachineOperand &Op1 = MI.getOperand(1); + // Set R0 with the imm value to be passed to the custom profiling handler. + BuildMI(MBB, MI, DL, get(Hexagon::A2_tfrsi), Hexagon::R0) + .addImm(Op1.getImm()); + // The call to the custom handler is being treated as a special one as the + // callee is responsible for saving and restoring all the registers + // (including caller saved registers) it needs to modify. This is + // done to reduce the impact of instrumentation on the code being + // instrumented/profiled. + // NOTE: R14, R15 and R28 are reserved for PLT handling. These registers + // are in the Def list of the Hexagon::PS_call_instrprof_custom and + // therefore will be handled appropriately duing register allocation. + + // TODO: It may be a good idea to add a separate pseudo instruction for + // static relocation which doesn't need to reserve r14, r15 and r28. + + auto MIB = BuildMI(MBB, MI, DL, get(Hexagon::J2_call)) + .addUse(Hexagon::R0, RegState::Implicit|RegState::InternalRead) + .addDef(Hexagon::R29, RegState::ImplicitDefine) + .addDef(Hexagon::R30, RegState::ImplicitDefine) + .addDef(Hexagon::R14, RegState::ImplicitDefine) + .addDef(Hexagon::R15, RegState::ImplicitDefine) + .addDef(Hexagon::R28, RegState::ImplicitDefine); + const char *cstr = MF.createExternalSymbolName(NameStr); + MIB.addExternalSymbol(cstr); + MBB.erase(MI); + return true; + } case TargetOpcode::COPY: { MachineOperand &MD = MI.getOperand(0); MachineOperand &MS = MI.getOperand(1); @@ -1351,8 +1430,8 @@ // Generate a misaligned load that is guaranteed to cause a crash. class CrashPseudoSourceValue : public PseudoSourceValue { public: - CrashPseudoSourceValue(const TargetInstrInfo &TII) - : PseudoSourceValue(TargetCustom, TII) {} + CrashPseudoSourceValue(const TargetMachine &TM) + : PseudoSourceValue(TargetCustom, TM) {} bool isConstant(const MachineFrameInfo *) const override { return false; @@ -1368,7 +1447,7 @@ } }; - static const CrashPseudoSourceValue CrashPSV(*this); + static const CrashPseudoSourceValue CrashPSV(MF.getTarget()); MachineMemOperand *MMO = MF.getMachineMemOperand( MachinePointerInfo(&CrashPSV), MachineMemOperand::MOLoad | MachineMemOperand::MOVolatile, 8, @@ -1465,75 +1544,75 @@ switch (Opc) { case Hexagon::V6_vgathermh_pseudo: First = BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermh)) - .add(MI.getOperand(1)) .add(MI.getOperand(2)) - .add(MI.getOperand(3)); + .add(MI.getOperand(3)) + .add(MI.getOperand(4)); BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai)) .add(MI.getOperand(0)) - .addImm(0) + .addImm(MI.getOperand(1).getImm()) .addReg(Hexagon::VTMP); MBB.erase(MI); return First.getInstrIterator(); case Hexagon::V6_vgathermw_pseudo: First = BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermw)) - .add(MI.getOperand(1)) .add(MI.getOperand(2)) - .add(MI.getOperand(3)); + .add(MI.getOperand(3)) + .add(MI.getOperand(4)); BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai)) .add(MI.getOperand(0)) - .addImm(0) + .addImm(MI.getOperand(1).getImm()) .addReg(Hexagon::VTMP); MBB.erase(MI); return First.getInstrIterator(); case Hexagon::V6_vgathermhw_pseudo: First = BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermhw)) - .add(MI.getOperand(1)) .add(MI.getOperand(2)) - .add(MI.getOperand(3)); + .add(MI.getOperand(3)) + .add(MI.getOperand(4)); BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai)) .add(MI.getOperand(0)) - .addImm(0) + .addImm(MI.getOperand(1).getImm()) .addReg(Hexagon::VTMP); MBB.erase(MI); return First.getInstrIterator(); case Hexagon::V6_vgathermhq_pseudo: First = BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermhq)) - .add(MI.getOperand(1)) .add(MI.getOperand(2)) .add(MI.getOperand(3)) - .add(MI.getOperand(4)); + .add(MI.getOperand(4)) + .add(MI.getOperand(5)); BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai)) .add(MI.getOperand(0)) - .addImm(0) + .addImm(MI.getOperand(1).getImm()) .addReg(Hexagon::VTMP); MBB.erase(MI); return First.getInstrIterator(); case Hexagon::V6_vgathermwq_pseudo: First = BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermwq)) - .add(MI.getOperand(1)) .add(MI.getOperand(2)) .add(MI.getOperand(3)) - .add(MI.getOperand(4)); + .add(MI.getOperand(4)) + .add(MI.getOperand(5)); BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai)) .add(MI.getOperand(0)) - .addImm(0) + .addImm(MI.getOperand(1).getImm()) .addReg(Hexagon::VTMP); MBB.erase(MI); return First.getInstrIterator(); case Hexagon::V6_vgathermhwq_pseudo: First = BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermhwq)) - .add(MI.getOperand(1)) .add(MI.getOperand(2)) .add(MI.getOperand(3)) - .add(MI.getOperand(4)); + .add(MI.getOperand(4)) + .add(MI.getOperand(5)); BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai)) .add(MI.getOperand(0)) - .addImm(0) + .addImm(MI.getOperand(1).getImm()) .addReg(Hexagon::VTMP); MBB.erase(MI); return First.getInstrIterator(); @@ -1621,7 +1700,7 @@ MI.setDesc(get(PredOpc)); while (unsigned n = MI.getNumOperands()) - MI.RemoveOperand(n-1); + MI.removeOperand(n-1); for (unsigned i = 0, n = T->getNumOperands(); i < n; ++i) MI.addOperand(T->getOperand(i)); @@ -1644,8 +1723,7 @@ bool SkipDead) const { const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo(); - for (unsigned oper = 0; oper < MI.getNumOperands(); ++oper) { - MachineOperand MO = MI.getOperand(oper); + for (const MachineOperand &MO : MI.operands()) { if (MO.isReg()) { if (!MO.isDef()) continue; @@ -1722,7 +1800,7 @@ return true; // If any of the block's successors is a landing pad, this could be a // throwing call. - for (auto I : MBB->successors()) + for (auto *I : MBB->successors()) if (I->isEHPad()) return true; } @@ -1791,8 +1869,8 @@ /// compares against in CmpValue. Return true if the comparison instruction /// can be analyzed. bool HexagonInstrInfo::analyzeCompare(const MachineInstr &MI, Register &SrcReg, - Register &SrcReg2, int &Mask, - int &Value) const { + Register &SrcReg2, int64_t &Mask, + int64_t &Value) const { unsigned Opc = MI.getOpcode(); // Set mask and the first source register. @@ -1853,6 +1931,7 @@ case Hexagon::C4_cmplte: case Hexagon::C4_cmplteu: SrcReg2 = MI.getOperand(2).getReg(); + Value = 0; return true; case Hexagon::C2_cmpeqi: @@ -2048,7 +2127,7 @@ !isMemOp(MI) && !MI.isBranch() && !MI.isReturn() && !MI.isCall(); } -// Return true if the instruction is a compund branch instruction. +// Return true if the instruction is a compound branch instruction. bool HexagonInstrInfo::isCompoundBranchInstr(const MachineInstr &MI) const { return getType(MI) == HexagonII::TypeCJ && MI.isBranch(); } @@ -2174,15 +2253,6 @@ return (isDuplexPairMatch(MIaG, MIbG) || isDuplexPairMatch(MIbG, MIaG)); } -bool HexagonInstrInfo::isEarlySourceInstr(const MachineInstr &MI) const { - if (MI.mayLoadOrStore() || MI.isCompare()) - return true; - - // Multiply - unsigned SchedClass = MI.getDesc().getSchedClass(); - return is_TC4x(SchedClass) || is_TC3x(SchedClass); -} - bool HexagonInstrInfo::isEndLoopN(unsigned Opcode) const { return (Opcode == Hexagon::ENDLOOP0 || Opcode == Hexagon::ENDLOOP1); @@ -2338,43 +2408,6 @@ } } -bool HexagonInstrInfo::isLateInstrFeedsEarlyInstr(const MachineInstr &LRMI, - const MachineInstr &ESMI) const { - bool isLate = isLateResultInstr(LRMI); - bool isEarly = isEarlySourceInstr(ESMI); - - LLVM_DEBUG(dbgs() << "V60" << (isLate ? "-LR " : " -- ")); - LLVM_DEBUG(LRMI.dump()); - LLVM_DEBUG(dbgs() << "V60" << (isEarly ? "-ES " : " -- ")); - LLVM_DEBUG(ESMI.dump()); - - if (isLate && isEarly) { - LLVM_DEBUG(dbgs() << "++Is Late Result feeding Early Source\n"); - return true; - } - - return false; -} - -bool HexagonInstrInfo::isLateResultInstr(const MachineInstr &MI) const { - switch (MI.getOpcode()) { - case TargetOpcode::EXTRACT_SUBREG: - case TargetOpcode::INSERT_SUBREG: - case TargetOpcode::SUBREG_TO_REG: - case TargetOpcode::REG_SEQUENCE: - case TargetOpcode::IMPLICIT_DEF: - case TargetOpcode::COPY: - case TargetOpcode::INLINEASM: - case TargetOpcode::PHI: - return false; - default: - break; - } - - unsigned SchedClass = MI.getDesc().getSchedClass(); - return !is_TC1(SchedClass); -} - bool HexagonInstrInfo::isLateSourceInstr(const MachineInstr &MI) const { // Instructions with iclass A_CVI_VX and attribute A_CVI_LATE uses a multiply // resource, but all operands can be received late like an ALU instruction. @@ -2727,7 +2760,13 @@ case Hexagon::V6_vL32b_nt_ai: case Hexagon::V6_vS32b_nt_ai: case Hexagon::V6_vL32Ub_ai: - case Hexagon::V6_vS32Ub_ai: { + case Hexagon::V6_vS32Ub_ai: + case Hexagon::V6_vgathermh_pseudo: + case Hexagon::V6_vgathermw_pseudo: + case Hexagon::V6_vgathermhw_pseudo: + case Hexagon::V6_vgathermhq_pseudo: + case Hexagon::V6_vgathermwq_pseudo: + case Hexagon::V6_vgathermhwq_pseudo: { unsigned VectorSize = TRI->getSpillSize(Hexagon::HvxVRRegClass); assert(isPowerOf2_32(VectorSize)); if (Offset & (VectorSize-1)) @@ -2753,6 +2792,11 @@ case Hexagon::S4_storeirit_io: case Hexagon::S4_storeirif_io: return isShiftedUInt<6,2>(Offset); + // Handle these two compare instructions that are not extendable. + case Hexagon::A4_cmpbeqi: + return isUInt<8>(Offset); + case Hexagon::A4_cmpbgti: + return isInt<8>(Offset); } if (Extend) @@ -2790,6 +2834,8 @@ case Hexagon::L4_isub_memopw_io: case Hexagon::L4_add_memopw_io: case Hexagon::L4_sub_memopw_io: + case Hexagon::L4_iand_memopw_io: + case Hexagon::L4_ior_memopw_io: case Hexagon::L4_and_memopw_io: case Hexagon::L4_or_memopw_io: return (0 <= Offset && Offset <= 255); @@ -2798,6 +2844,8 @@ case Hexagon::L4_isub_memoph_io: case Hexagon::L4_add_memoph_io: case Hexagon::L4_sub_memoph_io: + case Hexagon::L4_iand_memoph_io: + case Hexagon::L4_ior_memoph_io: case Hexagon::L4_and_memoph_io: case Hexagon::L4_or_memoph_io: return (0 <= Offset && Offset <= 127); @@ -2806,6 +2854,8 @@ case Hexagon::L4_isub_memopb_io: case Hexagon::L4_add_memopb_io: case Hexagon::L4_sub_memopb_io: + case Hexagon::L4_iand_memopb_io: + case Hexagon::L4_ior_memopb_io: case Hexagon::L4_and_memopb_io: case Hexagon::L4_or_memopb_io: return (0 <= Offset && Offset <= 63); @@ -2850,8 +2900,18 @@ case Hexagon::S2_pstorerdt_io: case Hexagon::S2_pstorerdf_io: return isShiftedUInt<6,3>(Offset); + + case Hexagon::L2_loadbsw2_io: + case Hexagon::L2_loadbzw2_io: + return isShiftedInt<11,1>(Offset); + + case Hexagon::L2_loadbsw4_io: + case Hexagon::L2_loadbzw4_io: + return isShiftedInt<11,2>(Offset); } // switch + dbgs() << "Failed Opcode is : " << Opcode << " (" << getName(Opcode) + << ")\n"; llvm_unreachable("No offset range is defined for this opcode. " "Please define it in the above switch statement!"); } @@ -3488,9 +3548,9 @@ if (Iter != DupMap.end()) return Iter->second; } else { // Conversion to Tiny core. - for (auto Iter = DupMap.begin(), End = DupMap.end(); Iter != End; ++Iter) - if (Iter->second == OpNum) - return Iter->first; + for (const auto &Iter : DupMap) + if (Iter.second == OpNum) + return Iter.first; } return -1; } @@ -3518,6 +3578,10 @@ return Hexagon::V6_vL32b_nt_cur_pi; case Hexagon::V6_vL32b_nt_ai: return Hexagon::V6_vL32b_nt_cur_ai; + case Hexagon::V6_vL32b_ppu: + return Hexagon::V6_vL32b_cur_ppu; + case Hexagon::V6_vL32b_nt_ppu: + return Hexagon::V6_vL32b_nt_cur_ppu; } return 0; } @@ -3534,6 +3598,10 @@ return Hexagon::V6_vL32b_nt_pi; case Hexagon::V6_vL32b_nt_cur_ai: return Hexagon::V6_vL32b_nt_ai; + case Hexagon::V6_vL32b_cur_ppu: + return Hexagon::V6_vL32b_ppu; + case Hexagon::V6_vL32b_nt_cur_ppu: + return Hexagon::V6_vL32b_nt_ppu; } return 0; } @@ -3627,8 +3695,8 @@ switch (MI.getOpcode()) { default: - report_fatal_error(std::string("Unknown .new type: ") + - std::to_string(MI.getOpcode())); + report_fatal_error(Twine("Unknown .new type: ") + + std::to_string(MI.getOpcode())); case Hexagon::S4_storerb_ur: return Hexagon::S4_storerbnew_ur; @@ -4388,6 +4456,9 @@ unsigned Size = getMemAccessSizeInBytes(MemAccessSize(S)); if (Size != 0) return Size; + // Y2_dcfetchbo is special + if (MI.getOpcode() == Hexagon::Y2_dcfetchbo) + return HexagonII::DoubleWordAccess; // Handle vector access sizes. const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo(); @@ -4658,3 +4729,11 @@ short HexagonInstrInfo::changeAddrMode_ur_rr(short Opc) const { return Opc >= 0 ? Hexagon::changeAddrMode_ur_rr(Opc) : Opc; } + +MCInst HexagonInstrInfo::getNop() const { + static const MCInst Nop = MCInstBuilder(Hexagon::A2_nop); + + return MCInstBuilder(Hexagon::BUNDLE) + .addImm(0) + .addInst(&Nop); +}