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 {
121char AArch64PTrueCoalescingLegacy::ID = 0;
126 "AArch64 PTRUE Coalescing",
false,
false)
132AArch64PTrueCoalescingImpl::getSmallestElementSizeInUse(
Register Reg)
const {
134 if (!
Reg.isVirtual())
140 assert(UseMO.getSubReg() == 0 &&
"Unexpected SubReg!");
141 MachineInstr *UseMI = UseMO.getParent();
143 unsigned ElementSize = TII->getElementSizeForOpcode(UseMI->getOpcode());
144 if (ElementSize == AArch64::ElementSizeNone)
145 return AArch64::ElementSizeNone;
147 if (SmallestElementSize == AArch64::ElementSizeNone ||
148 SmallestElementSize > ElementSize)
149 SmallestElementSize = ElementSize;
152 return SmallestElementSize;
155bool AArch64PTrueCoalescingImpl::tryCoalesce(
PredicateInfo &DomPI,
157 assert(DomPI.isValid() && CanPI.isValid());
158 MachineInstr *DomMI = DomPI.MI;
159 MachineInstr *CanMI = CanPI.MI;
161 if (DomMI == CanMI || !MDT->
dominates(DomMI, CanMI))
170 bool MutateDomPTrue =
false;
171 if (std::max(CanPI.ElementSize, CanPI.SmallestUsedElementSize) !=
172 std::max(DomPI.ElementSize, CanPI.SmallestUsedElementSize)) {
173 if (std::max(CanPI.ElementSize, DomPI.SmallestUsedElementSize) !=
174 std::max(DomPI.ElementSize, DomPI.SmallestUsedElementSize))
177 MutateDomPTrue =
true;
188 if (MutateDomPTrue) {
191 DomPI.ElementSize = CanPI.ElementSize;
200 if (CanPI.SmallestUsedElementSize < DomPI.SmallestUsedElementSize)
201 DomPI.SmallestUsedElementSize = CanPI.SmallestUsedElementSize;
206bool AArch64PTrueCoalescingImpl::run(MachineFunction &MF) {
208 !MF.
getSubtarget<AArch64Subtarget>().isSVEorStreamingSVEAvailable())
211 TII =
static_cast<const AArch64InstrInfo *
>(MF.
getSubtarget().getInstrInfo());
214 assert(MRI->
isSSA() &&
"Expected to be run on SSA form!");
225 for (MachineBasicBlock &
MBB : MF)
226 for (MachineInstr &
MI :
MBB)
227 if (
auto PI = createPredicateInfo(
MI))
233 for (PredicateInfo &DominantPI : PIs) {
234 if (!DominantPI.isValid())
237 for (PredicateInfo &CandidatePI : PIs) {
238 if (!CandidatePI.isValid())
241 Changed |= tryCoalesce(DominantPI, CandidatePI);
248bool AArch64PTrueCoalescingLegacy::runOnMachineFunction(MachineFunction &MF) {
249 MachineDominatorTree &MDT =
250 getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
251 return AArch64PTrueCoalescingImpl(MDT).run(MF);
255 return new AArch64PTrueCoalescingLegacy();
262 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()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
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...