Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:28

0001 //==-- llvm/CodeGen/ExecutionDomainFix.h - Execution Domain Fix -*- C++ -*--==//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 /// \file Execution Domain Fix pass.
0010 ///
0011 /// Some X86 SSE instructions like mov, and, or, xor are available in different
0012 /// variants for different operand types. These variant instructions are
0013 /// equivalent, but on Nehalem and newer cpus there is extra latency
0014 /// transferring data between integer and floating point domains.  ARM cores
0015 /// have similar issues when they are configured with both VFP and NEON
0016 /// pipelines.
0017 ///
0018 /// This pass changes the variant instructions to minimize domain crossings.
0019 //
0020 //===----------------------------------------------------------------------===//
0021 
0022 #ifndef LLVM_CODEGEN_EXECUTIONDOMAINFIX_H
0023 #define LLVM_CODEGEN_EXECUTIONDOMAINFIX_H
0024 
0025 #include "llvm/ADT/SmallVector.h"
0026 #include "llvm/CodeGen/LoopTraversal.h"
0027 #include "llvm/CodeGen/MachineFunctionPass.h"
0028 #include "llvm/CodeGen/ReachingDefAnalysis.h"
0029 #include "llvm/CodeGen/TargetRegisterInfo.h"
0030 
0031 namespace llvm {
0032 
0033 class MachineInstr;
0034 class TargetInstrInfo;
0035 
0036 /// A DomainValue is a bit like LiveIntervals' ValNo, but it also keeps track
0037 /// of execution domains.
0038 ///
0039 /// An open DomainValue represents a set of instructions that can still switch
0040 /// execution domain. Multiple registers may refer to the same open
0041 /// DomainValue - they will eventually be collapsed to the same execution
0042 /// domain.
0043 ///
0044 /// A collapsed DomainValue represents a single register that has been forced
0045 /// into one of more execution domains. There is a separate collapsed
0046 /// DomainValue for each register, but it may contain multiple execution
0047 /// domains. A register value is initially created in a single execution
0048 /// domain, but if we were forced to pay the penalty of a domain crossing, we
0049 /// keep track of the fact that the register is now available in multiple
0050 /// domains.
0051 struct DomainValue {
0052   /// Basic reference counting.
0053   unsigned Refs = 0;
0054 
0055   /// Bitmask of available domains. For an open DomainValue, it is the still
0056   /// possible domains for collapsing. For a collapsed DomainValue it is the
0057   /// domains where the register is available for free.
0058   unsigned AvailableDomains;
0059 
0060   /// Pointer to the next DomainValue in a chain.  When two DomainValues are
0061   /// merged, Victim.Next is set to point to Victor, so old DomainValue
0062   /// references can be updated by following the chain.
0063   DomainValue *Next;
0064 
0065   /// Twiddleable instructions using or defining these registers.
0066   SmallVector<MachineInstr *, 8> Instrs;
0067 
0068   DomainValue() { clear(); }
0069 
0070   /// A collapsed DomainValue has no instructions to twiddle - it simply keeps
0071   /// track of the domains where the registers are already available.
0072   bool isCollapsed() const { return Instrs.empty(); }
0073 
0074   /// Is domain available?
0075   bool hasDomain(unsigned domain) const {
0076     assert(domain <
0077                static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
0078            "undefined behavior");
0079     return AvailableDomains & (1u << domain);
0080   }
0081 
0082   /// Mark domain as available.
0083   void addDomain(unsigned domain) {
0084     assert(domain <
0085                static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
0086            "undefined behavior");
0087     AvailableDomains |= 1u << domain;
0088   }
0089 
0090   // Restrict to a single domain available.
0091   void setSingleDomain(unsigned domain) {
0092     assert(domain <
0093                static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
0094            "undefined behavior");
0095     AvailableDomains = 1u << domain;
0096   }
0097 
0098   /// Return bitmask of domains that are available and in mask.
0099   unsigned getCommonDomains(unsigned mask) const {
0100     return AvailableDomains & mask;
0101   }
0102 
0103   /// First domain available.
0104   unsigned getFirstDomain() const {
0105     return llvm::countr_zero(AvailableDomains);
0106   }
0107 
0108   /// Clear this DomainValue and point to next which has all its data.
0109   void clear() {
0110     AvailableDomains = 0;
0111     Next = nullptr;
0112     Instrs.clear();
0113   }
0114 };
0115 
0116 class ExecutionDomainFix : public MachineFunctionPass {
0117   SpecificBumpPtrAllocator<DomainValue> Allocator;
0118   SmallVector<DomainValue *, 16> Avail;
0119 
0120   const TargetRegisterClass *const RC;
0121   MachineFunction *MF = nullptr;
0122   const TargetInstrInfo *TII = nullptr;
0123   const TargetRegisterInfo *TRI = nullptr;
0124   std::vector<SmallVector<int, 1>> AliasMap;
0125   const unsigned NumRegs;
0126   /// Value currently in each register, or NULL when no value is being tracked.
0127   /// This counts as a DomainValue reference.
0128   using LiveRegsDVInfo = std::vector<DomainValue *>;
0129   LiveRegsDVInfo LiveRegs;
0130   /// Keeps domain information for all registers. Note that this
0131   /// is different from the usual definition notion of liveness. The CPU
0132   /// doesn't care whether or not we consider a register killed.
0133   using OutRegsInfoMap = SmallVector<LiveRegsDVInfo, 4>;
0134   OutRegsInfoMap MBBOutRegsInfos;
0135 
0136   ReachingDefAnalysis *RDA = nullptr;
0137 
0138 public:
0139   ExecutionDomainFix(char &PassID, const TargetRegisterClass &RC)
0140       : MachineFunctionPass(PassID), RC(&RC), NumRegs(RC.getNumRegs()) {}
0141 
0142   void getAnalysisUsage(AnalysisUsage &AU) const override {
0143     AU.setPreservesAll();
0144     AU.addRequired<ReachingDefAnalysis>();
0145     MachineFunctionPass::getAnalysisUsage(AU);
0146   }
0147 
0148   bool runOnMachineFunction(MachineFunction &MF) override;
0149 
0150   MachineFunctionProperties getRequiredProperties() const override {
0151     return MachineFunctionProperties().set(
0152         MachineFunctionProperties::Property::NoVRegs);
0153   }
0154 
0155 private:
0156   /// Translate TRI register number to a list of indices into our smaller tables
0157   /// of interesting registers.
0158   iterator_range<SmallVectorImpl<int>::const_iterator>
0159   regIndices(unsigned Reg) const;
0160 
0161   /// DomainValue allocation.
0162   DomainValue *alloc(int domain = -1);
0163 
0164   /// Add reference to DV.
0165   DomainValue *retain(DomainValue *DV) {
0166     if (DV)
0167       ++DV->Refs;
0168     return DV;
0169   }
0170 
0171   /// Release a reference to DV.  When the last reference is released,
0172   /// collapse if needed.
0173   void release(DomainValue *);
0174 
0175   /// Follow the chain of dead DomainValues until a live DomainValue is reached.
0176   /// Update the referenced pointer when necessary.
0177   DomainValue *resolve(DomainValue *&);
0178 
0179   /// Set LiveRegs[rx] = dv, updating reference counts.
0180   void setLiveReg(int rx, DomainValue *DV);
0181 
0182   /// Kill register rx, recycle or collapse any DomainValue.
0183   void kill(int rx);
0184 
0185   /// Force register rx into domain.
0186   void force(int rx, unsigned domain);
0187 
0188   /// Collapse open DomainValue into given domain. If there are multiple
0189   /// registers using dv, they each get a unique collapsed DomainValue.
0190   void collapse(DomainValue *dv, unsigned domain);
0191 
0192   /// All instructions and registers in B are moved to A, and B is released.
0193   bool merge(DomainValue *A, DomainValue *B);
0194 
0195   /// Set up LiveRegs by merging predecessor live-out values.
0196   void enterBasicBlock(const LoopTraversal::TraversedMBBInfo &TraversedMBB);
0197 
0198   /// Update live-out values.
0199   void leaveBasicBlock(const LoopTraversal::TraversedMBBInfo &TraversedMBB);
0200 
0201   /// Process he given basic block.
0202   void processBasicBlock(const LoopTraversal::TraversedMBBInfo &TraversedMBB);
0203 
0204   /// Visit given insturcion.
0205   bool visitInstr(MachineInstr *);
0206 
0207   /// Update def-ages for registers defined by MI.
0208   /// If Kill is set, also kill off DomainValues clobbered by the defs.
0209   void processDefs(MachineInstr *, bool Kill);
0210 
0211   /// A soft instruction can be changed to work in other domains given by mask.
0212   void visitSoftInstr(MachineInstr *, unsigned mask);
0213 
0214   /// A hard instruction only works in one domain. All input registers will be
0215   /// forced into that domain.
0216   void visitHardInstr(MachineInstr *, unsigned domain);
0217 };
0218 
0219 } // namespace llvm
0220 
0221 #endif // LLVM_CODEGEN_EXECUTIONDOMAINFIX_H