36 #define DEBUG_TYPE "hexagon-subtarget" 38 #define GET_SUBTARGETINFO_CTOR 39 #define GET_SUBTARGETINFO_TARGET_DESC 40 #include "HexagonGenSubtargetInfo.inc" 51 cl::desc(
"Enable the scheduler to generate .cur"));
55 cl::desc(
"Disable Hexagon MI Scheduling"));
59 cl::desc(
"Enable subregister liveness tracking for Hexagon"));
63 cl::desc(
"If present, forces/disables the use of long calls"));
67 cl::desc(
"Consider calls to be predicable"));
77 cl::desc(
"Enable checking for cache bank conflicts"));
84 InstrInfo(initializeSubtargetDependencies(CPU, FS)),
85 RegInfo(getHwMode()), TLInfo(TM, *this),
86 InstrItins(getInstrItineraryForCPU(CPUString)) {
94 static std::map<StringRef, Hexagon::ArchEnum> CpuTable{
104 auto FoundIt = CpuTable.find(CPUString);
105 if (FoundIt != CpuTable.end())
110 UseHVX128BOps =
false;
111 UseHVX64BOps =
false;
112 UseLongCalls =
false;
123 setFeatureBits(Features.set(Hexagon::FeatureDuplex,
false));
135 if (
D.getKind() ==
SDep::Output &&
D.getReg() == Hexagon::USR_OVF)
137 for (
auto &
E : Erase)
150 bool IsLoadMI1 = MI1.
mayLoad();
151 if (!QII->isHVXVec(MI1) || !(IsStoreMI1 || IsLoadMI1))
157 if (!QII->isHVXVec(MI2))
164 if (PI.getSUnit() != &SU || PI.getKind() !=
SDep::Order)
181 bool HexagonSubtarget::CallMutation::shouldTFRICallBind(
183 const SUnit &Inst2)
const {
195 SUnit* LastSequentialCall =
nullptr;
206 for (
unsigned su = 0, e = DAG->
SUnits.size(); su != e; ++su) {
208 if (DAG->
SUnits[su].getInstr()->isCall())
209 LastSequentialCall = &DAG->
SUnits[su];
211 else if (DAG->
SUnits[su].getInstr()->isCompare() && LastSequentialCall)
215 shouldTFRICallBind(HII, DAG->
SUnits[su], DAG->
SUnits[su+1]))
246 LastVRegUse[VRegHoldingReg[MO.
getReg()]] = &DAG->
SUnits[su];
247 }
else if (MO.
isDef() &&
251 if (LastVRegUse.
count(*AI) &&
252 LastVRegUse[*AI] != &DAG->
SUnits[su])
255 LastVRegUse.
erase(*AI);
273 for (
unsigned i = 0, e = DAG->
SUnits.size(); i != e; ++i) {
283 if (BaseOp0 ==
nullptr || !BaseOp0->
isReg() || Size0 >= 32)
286 for (
unsigned j = i+1, m = std::min(i+32, e); j != m; ++j) {
295 if (BaseOp1 ==
nullptr || !BaseOp1->
isReg() || Size1 >= 32 ||
300 if (((Offset0 ^ Offset1) & 0x18) != 0)
334 isBestZeroLatency(Src, Dst, QII, ExclSrc, ExclDst)) {
351 unsigned UseIdx = -1;
352 for (
unsigned OpNum = 0; OpNum < DDst->
getNumOperands(); OpNum++) {
369 isBestZeroLatency(Src, Dst, QII, ExclSrc, ExclDst)) {
374 updateLatency(*SrcInst, *DstInst, Dep);
378 std::vector<std::unique_ptr<ScheduleDAGMutation>> &Mutations)
const {
379 Mutations.push_back(llvm::make_unique<UsrOverflowMutation>());
380 Mutations.push_back(llvm::make_unique<HVXMemLatencyMutation>());
381 Mutations.push_back(llvm::make_unique<BankConflictMutation>());
385 std::vector<std::unique_ptr<ScheduleDAGMutation>> &Mutations)
const {
386 Mutations.push_back(llvm::make_unique<UsrOverflowMutation>());
387 Mutations.push_back(llvm::make_unique<HVXMemLatencyMutation>());
391 void HexagonSubtarget::anchor() {}
403 void HexagonSubtarget::updateLatency(
MachineInstr &SrcInst,
420 void HexagonSubtarget::restoreLatency(
SUnit *Src,
SUnit *Dst)
const {
422 for (
auto &
I : Src->
Succs) {
423 if (!
I.isAssignedRegDep() ||
I.getSUnit() != Dst)
425 unsigned DepR =
I.getReg();
427 for (
unsigned OpNum = 0; OpNum < SrcI->
getNumOperands(); OpNum++) {
432 assert(DefIdx >= 0 &&
"Def Reg not found in Src MI");
435 for (
unsigned OpNum = 0; OpNum < DstI->
getNumOperands(); OpNum++) {
439 DefIdx, *DstI, OpNum));
445 I.setLatency(Latency);
446 updateLatency(*SrcI, *DstI,
I);
454 F->setLatency(
I.getLatency());
459 void HexagonSubtarget::changeLatency(
SUnit *Src,
SUnit *Dst,
unsigned Lat)
461 for (
auto &
I : Src->
Succs) {
462 if (!
I.isAssignedRegDep() ||
I.getSUnit() != Dst)
478 if (
I.isAssignedRegDep() &&
I.getLatency() == 0 &&
479 !
I.getSUnit()->getInstr()->isPseudo())
488 bool HexagonSubtarget::isBestZeroLatency(
SUnit *Src,
SUnit *Dst,
512 SUnit *Best =
nullptr;
513 SUnit *DstBest =
nullptr;
526 if ((Src == SrcBest && Dst == DstBest ) ||
527 (SrcBest ==
nullptr && Dst == DstBest) ||
528 (Src == SrcBest && Dst ==
nullptr))
533 if (SrcBest !=
nullptr) {
535 changeLatency(SrcBest, Dst, 1);
537 restoreLatency(SrcBest, Dst);
539 if (DstBest !=
nullptr) {
541 changeLatency(Src, DstBest, 1);
543 restoreLatency(Src, DstBest);
548 if (SrcBest && DstBest)
551 changeLatency(SrcBest, DstBest, 0);
556 for (
auto &
I : DstBest->
Preds)
557 if (ExclSrc.
count(
I.getSUnit()) == 0 &&
558 isBestZeroLatency(
I.getSUnit(), DstBest,
TII, ExclSrc, ExclDst))
559 changeLatency(
I.getSUnit(), DstBest, 0);
560 }
else if (SrcBest) {
564 for (
auto &
I : SrcBest->
Succs)
565 if (ExclDst.
count(
I.getSUnit()) == 0 &&
566 isBestZeroLatency(SrcBest,
I.getSUnit(),
TII, ExclSrc, ExclDst))
567 changeLatency(SrcBest,
I.getSUnit(), 0);
void apply(ScheduleDAGInstrs *DAG) override
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
static SUnit * getZeroLatency(SUnit *N, SmallVector< SDep, 4 > &Deps)
If the SUnit has a zero latency edge, return the other SUnit.
This class represents lattice values for constants.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
void push_back(const T &Elt)
unsigned getReg() const
getReg - Returns the register number.
Hexagon::ArchEnum HexagonArchVersion
const FeatureBitset Features
bool isRegSequence() const
void getSMSMutations(std::vector< std::unique_ptr< ScheduleDAGMutation >> &Mutations) const override
unsigned const TargetRegisterInfo * TRI
void removePred(const SDep &D)
Removes the specified edge as a pred of the current node if it exists.
ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...
HexagonSubtarget & initializeSubtargetDependencies(StringRef CPU, StringRef FS)
unsigned getL1CacheLineSize() const
SmallVector< SDep, 4 > Preds
All sunit predecessors.
bool isToBeScheduledASAP(const MachineInstr &MI1, const MachineInstr &MI2) const
static cl::opt< bool > EnableTCLatencySched("enable-tc-latency-sched", cl::Hidden, cl::ZeroOrMore, cl::init(false))
MachineFunction & MF
Machine function.
unsigned NumSuccs
of SDep::Data sucss.
unsigned getLatency() const
Returns the latency value for this edge, which roughly means the minimum number of cycles that must e...
const HexagonInstrInfo * TII
unsigned getNumOperands() const
Retuns the total number of operands.
const InstrItinerary * Itineraries
Array of itineraries selected.
static cl::opt< bool > OverrideLongCalls("hexagon-long-calls", cl::Hidden, cl::ZeroOrMore, cl::init(false), cl::desc("If present, forces/disables the use of long calls"))
bool canExecuteInBundle(const MachineInstr &First, const MachineInstr &Second) const
Can these instructions execute at the same time in a bundle.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool useBSBScheduling() const
A register output-dependence (aka WAW).
unsigned getL1PrefetchDistance() const
HexagonSubtarget(const Triple &TT, StringRef CPU, StringRef FS, const TargetMachine &TM)
bool isBoundaryNode() const
Boundary nodes are placeholders for the boundary of the scheduling region.
StringRef selectHexagonCPU(StringRef CPU)
MachineOperand * getBaseAndOffset(const MachineInstr &MI, int64_t &Offset, unsigned &AccessSize) const
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
initializer< Ty > init(const Ty &Val)
bool erase(const KeyT &Val)
void setDepthDirty()
Sets a flag in this node to indicate that its stored Depth value will require recomputation the next ...
MachineInstr * getInstr() const
Returns the representative MachineInstr for this SUnit.
* if(!EatIfPresent(lltok::kw_thread_local)) return false
ParseOptionalThreadLocal := /*empty.
bool isArtificial() const
Tests if this is an Order dependence that is marked as "artificial", meaning it isn't necessary for c...
Container class for subtarget features.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
The instances of the Type class are immutable: once they are created, they are never changed...
FeatureBitset completeHVXFeatures(const FeatureBitset &FB)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
void apply(ScheduleDAGInstrs *DAG) override
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
static cl::opt< bool > EnableCheckBankConflict("hexagon-check-bank-conflict", cl::Hidden, cl::ZeroOrMore, cl::init(true), cl::desc("Enable checking for cache bank conflicts"))
CodeGenOpt::Level OptLevel
unsigned getAddrMode(const MachineInstr &MI) const
void apply(ScheduleDAGInstrs *DAG) override
bool addEdge(SUnit *SuccSU, const SDep &PredDep)
Add a DAG edge to the given SU with the given predecessor dependence data.
void apply(ScheduleDAGInstrs *DAG) override
MCRegAliasIterator enumerates all registers aliasing Reg.
static cl::opt< bool > EnableSubregLiveness("hexagon-subreg-liveness", cl::Hidden, cl::ZeroOrMore, cl::init(true), cl::desc("Enable subregister liveness tracking for Hexagon"))
std::pair< NoneType, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
static cl::opt< bool > EnablePredicatedCalls("hexagon-pred-calls", cl::Hidden, cl::ZeroOrMore, cl::init(false), cl::desc("Consider calls to be predicable"))
Any other ordering dependency.
auto find(R &&Range, const T &Val) -> decltype(adl_begin(Range))
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly...
static cl::opt< bool > SchedPredsCloser("sched-preds-closer", cl::Hidden, cl::ZeroOrMore, cl::init(true))
bool useAA() const override
Enable use of alias analysis during code generation (during MI scheduling, DAGCombine, etc.).
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Triple - Helper class for working with autoconf configuration names.
An unknown scheduling barrier.
bool enableMachineScheduler() const override
bool usePredicatedCalls() const
static cl::opt< bool > SchedRetvalOptimization("sched-retval-optimization", cl::Hidden, cl::ZeroOrMore, cl::init(true))
void getPostRAMutations(std::vector< std::unique_ptr< ScheduleDAGMutation >> &Mutations) const override
MachineOperand class - Representation of each machine instruction operand.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
bool UseBSBScheduling
True if the target should use Back-Skip-Back scheduling.
uint64_t getType(const MachineInstr &MI) const
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
bool enableSubRegLiveness() const override
void adjustSchedDependency(SUnit *def, SUnit *use, SDep &dep) const override
Perform target specific adjustments to the latency of a schedule dependency.
void setLatency(unsigned Lat)
Sets the latency for this edge.
A ScheduleDAG for scheduling lists of MachineInstr.
Representation of each machine instruction.
void ParseSubtargetFeatures(StringRef CPU, StringRef FS)
ParseSubtargetFeatures - Parses features string setting specified subtarget options.
static bool isPhysicalRegister(unsigned Reg)
Return true if the specified register number is in the physical register namespace.
const TargetInstrInfo * TII
Target instruction information.
Kind getKind() const
Returns an enum value representing the kind of the dependence.
int getOperandLatency(const InstrItineraryData *ItinData, const MachineInstr &DefMI, unsigned DefIdx, const MachineInstr &UseMI, unsigned UseIdx) const override
getOperandLatency - Compute and return the use operand latency of a given pair of def and use...
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
unsigned NodeNum
Entry # of node in the node vector.
void setHeightDirty()
Sets a flag in this node to indicate that its stored Height value will require recomputation the next...
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool addPred(const SDep &D, bool Required=true)
Adds the specified edge as a pred of the current node if not already.
const HexagonInstrInfo * getInstrInfo() const override
SmallVector< SDep, 4 > Succs
All sunit successors.
Arbitrary strong DAG edge (no real dependence).
Primary interface to the complete machine description for the target machine.
static cl::opt< bool > EnableBSBSched("enable-bsb-sched", cl::Hidden, cl::ZeroOrMore, cl::init(true))
StringRef - Represent a constant reference to a string, i.e.
static cl::opt< bool > DisableHexagonMISched("disable-hexagon-misched", cl::Hidden, cl::ZeroOrMore, cl::init(false), cl::desc("Disable Hexagon MI Scheduling"))
std::vector< SUnit > SUnits
The scheduling units.
const MachineOperand & getOperand(unsigned i) const
bool isInstr() const
Returns true if this SUnit refers to a machine instruction as opposed to an SDNode.
cl::opt< bool > HexagonDisableDuplex
Scheduling unit. This is a node in the scheduling DAG.
static cl::opt< bool > EnableDotCurSched("enable-cur-sched", cl::Hidden, cl::ZeroOrMore, cl::init(true), cl::desc("Enable the scheduler to generate .cur"))
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.