38#define DEBUG_TYPE "aarch64-ptrue-coalesce"
42 cl::desc(
"Enable coalescing of compatible AArch64 SVE PTRUE instructions"));
46class AArch64PTrueCoalescingImpl {
54 bool run(MachineFunction &MF);
57 struct PredicateInfo {
59 MachineInstr *MI =
nullptr;
67 "PTRUE missing element size!");
77 std::optional<PredicateInfo> createPredicateInfo(MachineInstr &
MI)
const {
83 unsigned SmallestUsedElementSize = getSmallestElementSizeInUse(Pred);
84 unsigned ElementSize = TII->getElementSizeForOpcode(
MI.getOpcode());
86 "PTRUE missing element size!");
91 return PredicateInfo{&
MI, ElementSize, SmallestUsedElementSize};
96 unsigned getSmallestElementSizeInUse(
Register Reg)
const;
100 bool tryCoalesce(PredicateInfo &DomPred, PredicateInfo &CanPred)
const;
107 AArch64PTrueCoalescingLegacy() : MachineFunctionPass(ID) {}
109 bool runOnMachineFunction(MachineFunction &MF)
override;
111 StringRef getPassName()
const override {
return "AArch64 PTRUE Coalescing"; }
113 void getAnalysisUsage(AnalysisUsage &AU)
const override {
120char AArch64PTrueCoalescingLegacy::ID = 0;
125 "AArch64 PTRUE Coalescing",
false,
false)
131AArch64PTrueCoalescingImpl::getSmallestElementSizeInUse(
Register Reg)
const {
133 if (!
Reg.isVirtual())
139 assert(UseMO.getSubReg() == 0 &&
"Unexpected SubReg!");
140 MachineInstr *UseMI = UseMO.getParent();
142 unsigned ElementSize = TII->getElementSizeForOpcode(UseMI->getOpcode());
143 if (ElementSize == AArch64::ElementSizeNone)
144 return AArch64::ElementSizeNone;
146 if (SmallestElementSize == AArch64::ElementSizeNone ||
147 SmallestElementSize > ElementSize)
148 SmallestElementSize = ElementSize;
151 return SmallestElementSize;
154bool AArch64PTrueCoalescingImpl::tryCoalesce(
PredicateInfo &DomPI,
156 assert(DomPI.isValid() && CanPI.isValid());
157 MachineInstr *DomMI = DomPI.MI;
158 MachineInstr *CanMI = CanPI.MI;
160 if (DomMI == CanMI || !MDT->
dominates(DomMI, CanMI))
169 bool MutateDomPTrue =
false;
170 if (std::max(CanPI.ElementSize, CanPI.SmallestUsedElementSize) !=
171 std::max(DomPI.ElementSize, CanPI.SmallestUsedElementSize)) {
172 if (std::max(CanPI.ElementSize, DomPI.SmallestUsedElementSize) !=
173 std::max(DomPI.ElementSize, DomPI.SmallestUsedElementSize))
176 MutateDomPTrue =
true;
187 if (MutateDomPTrue) {
190 DomPI.ElementSize = CanPI.ElementSize;
199 if (CanPI.SmallestUsedElementSize < DomPI.SmallestUsedElementSize)
200 DomPI.SmallestUsedElementSize = CanPI.SmallestUsedElementSize;
205bool AArch64PTrueCoalescingImpl::run(MachineFunction &MF) {
207 !MF.
getSubtarget<AArch64Subtarget>().isSVEorStreamingSVEAvailable())
210 TII =
static_cast<const AArch64InstrInfo *
>(MF.
getSubtarget().getInstrInfo());
213 assert(MRI->
isSSA() &&
"Expected to be run on SSA form!");
224 for (MachineBasicBlock &
MBB : MF)
225 for (MachineInstr &
MI :
MBB)
226 if (
auto PI = createPredicateInfo(
MI))
232 for (PredicateInfo &DominantPI : PIs) {
233 if (!DominantPI.isValid())
236 for (PredicateInfo &CandidatePI : PIs) {
237 if (!CandidatePI.isValid())
240 Changed |= tryCoalesce(DominantPI, CandidatePI);
247bool AArch64PTrueCoalescingLegacy::runOnMachineFunction(MachineFunction &MF) {
248 MachineDominatorTree &MDT =
249 getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
250 return AArch64PTrueCoalescingImpl(MDT).run(MF);
254 return new AArch64PTrueCoalescingLegacy();
261 const bool Changed = AArch64PTrueCoalescingImpl(MDT).run(MF);
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static cl::opt< bool > EnablePTrueCoalescing("aarch64-enable-ptrue-coalescing", cl::init(false), cl::Hidden, cl::desc("Enable coalescing of compatible AArch64 SVE PTRUE instructions"))
const HexagonInstrInfo * TII
Promote Memory to Register
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
This file defines the SmallVector class.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
AnalysisUsage & addRequired()
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Represents analyses that only rely on functions' control flow.
FunctionPass class - This class is used to implement most global optimizations.
Analysis pass which computes a MachineDominatorTree.
Analysis pass which computes a MachineDominatorTree.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
bool dominates(const MachineInstr *A, const MachineInstr *B) const
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
MachineOperand class - Representation of each machine instruction operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
iterator_range< use_nodbg_iterator > use_nodbg_operands(Register Reg) const
bool def_empty(Register RegNo) const
def_empty - Return true if there are no instructions defining the specified register (it may be live-...
LLVM_ABI const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
Encapsulates PredicateInfo, including all data associated with memory accesses.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Wrapper class representing virtual and physical registers.
void push_back(const T &Elt)
initializer< Ty > init(const Ty &Val)
DXILDebugInfoMap run(Module &M)
This is an optimization pass for GlobalISel generic memory operations.
static bool isPTrueOpcode(unsigned Opc)
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
FunctionPass * createAArch64PTrueCoalescingLegacyPass()
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...