49 cl::init(std::numeric_limits<unsigned>::max()));
51 "hexagon-aggressive-rdf-copy",
52 cl::desc(
"Enable aggressive RDF copy propagation with super-register "
64 void getAnalysisUsage(AnalysisUsage &AU)
const override {
66 AU.
addRequired<MachineDominanceFrontierWrapperPass>();
71 StringRef getPassName()
const override {
72 return "Hexagon RDF optimizations";
75 bool runOnMachineFunction(MachineFunction &MF)
override;
77 MachineFunctionProperties getRequiredProperties()
const override {
78 return MachineFunctionProperties().setNoVRegs();
84 MachineDominatorTree *MDT;
85 MachineRegisterInfo *MRI;
88struct HexagonCP :
public CopyPropagation {
89 HexagonCP(DataFlowGraph &
G) : CopyPropagation(
G) {}
91 bool interpretAsCopy(
const MachineInstr *
MI, EqualityMap &EM)
override;
95 HexagonAggressiveCP(DataFlowGraph &
G) : AggressiveCopyPropagation(
G) {}
97 bool interpretAsCopy(
const MachineInstr *
MI, EqualityMap &EM)
override;
100struct HexagonDCE :
public DeadCodeElimination {
101 HexagonDCE(DataFlowGraph &
G, MachineRegisterInfo &MRI)
102 : DeadCodeElimination(
G, MRI) {}
104 bool rewrite(NodeAddr<InstrNode*> IA, SetVector<NodeId> &Remove);
105 void removeOperand(NodeAddr<InstrNode*> IA,
unsigned OpNum);
112char HexagonRDFOpt::ID = 0;
115 "Hexagon RDF optimizations",
false,
false)
123 EM.insert(std::make_pair(DstR, SrcR));
127 unsigned Opc =
MI->getOpcode();
129 case Hexagon::A2_combinew: {
133 assert(
DstOp.getSubReg() == 0 &&
"Unexpected subregister");
140 case Hexagon::A2_addi: {
142 if (!
A.isImm() ||
A.getImm() != 0)
146 case Hexagon::A2_tfr: {
155 return CopyPropagation::interpretAsCopy(
MI, EM);
160 auto mapRegs = [&EM](RegisterRef DstR, RegisterRef SrcR) ->
void {
161 EM.insert(std::make_pair(DstR, SrcR));
164 DataFlowGraph &DFG = getDFG();
165 const TargetRegisterInfo &
TRI = DFG.
getTRI();
166 unsigned Opc =
MI->getOpcode();
168 case Hexagon::A2_combinew: {
171 const MachineOperand &DstOp =
MI->getOperand(0);
172 const MachineOperand &HiOp =
MI->getOperand(1);
173 const MachineOperand &LoOp =
MI->getOperand(2);
175 unsigned DoubleRegDest =
TRI.getMatchingSuperReg(
176 LoOp.
getReg(), Hexagon::isub_lo, &Hexagon::DoubleRegsRegClass);
177 if (DoubleRegDest != 0 &&
178 TRI.isSuperRegister(HiOp.
getReg(), DoubleRegDest))
186 case Hexagon::A2_addi: {
187 const MachineOperand &
A =
MI->getOperand(2);
188 if (!
A.isImm() ||
A.getImm() != 0)
192 case Hexagon::A2_tfr: {
193 const MachineOperand &DstOp =
MI->getOperand(0);
194 const MachineOperand &SrcOp =
MI->getOperand(1);
204bool HexagonDCE::run() {
205 bool Collected = collect();
209 const SetVector<NodeId> &DeadNodes = getDeadNodes();
210 const SetVector<NodeId> &DeadInstrs = getDeadInstrs();
212 using RefToInstrMap = DenseMap<NodeId, NodeId>;
215 SetVector<NodeId> PartlyDead;
216 DataFlowGraph &DFG = getDFG();
220 NodeAddr<StmtNode*> SA =
TA;
221 for (NodeAddr<RefNode*>
RA : SA.
Addr->members(DFG)) {
222 R2I.insert(std::make_pair(
RA.Id, SA.
Id));
231 SetVector<NodeId> Remove = DeadInstrs;
235 auto SA = DFG.
addr<StmtNode*>(
N);
237 dbgs() <<
"Partly dead: " << *SA.
Addr->getCode();
238 Changed |= rewrite(SA, Remove);
244void HexagonDCE::removeOperand(NodeAddr<InstrNode*> IA,
unsigned OpNum) {
245 MachineInstr *
MI = NodeAddr<StmtNode*>(IA).Addr->getCode();
247 auto getOpNum = [
MI] (MachineOperand &
Op) ->
unsigned {
248 for (
unsigned i = 0, n =
MI->getNumOperands(); i != n; ++i)
249 if (&
MI->getOperand(i) == &
Op)
253 DenseMap<NodeId,unsigned> OpMap;
254 DataFlowGraph &DFG = getDFG();
256 for (NodeAddr<RefNode*>
RA : Refs)
257 OpMap.
insert(std::make_pair(
RA.Id, getOpNum(
RA.Addr->getOp())));
259 MI->removeOperand(OpNum);
261 for (NodeAddr<RefNode*>
RA : Refs) {
262 unsigned N = OpMap[
RA.Id];
264 RA.Addr->setRegRef(&
MI->getOperand(
N), DFG);
266 RA.Addr->setRegRef(&
MI->getOperand(
N-1), DFG);
270bool HexagonDCE::rewrite(NodeAddr<InstrNode*> IA, SetVector<NodeId> &Remove) {
271 if (!getDFG().IsCode<NodeAttrs::Stmt>(IA))
273 DataFlowGraph &DFG = getDFG();
274 MachineInstr &
MI = *NodeAddr<StmtNode*>(IA).Addr->getCode();
275 auto &HII =
static_cast<const HexagonInstrInfo&
>(DFG.
getTII());
278 unsigned Opc =
MI.getOpcode();
279 unsigned OpNum, NewOpc;
281 case Hexagon::L2_loadri_pi:
282 NewOpc = Hexagon::L2_loadri_io;
285 case Hexagon::L2_loadrd_pi:
286 NewOpc = Hexagon::L2_loadrd_io;
289 case Hexagon::V6_vL32b_pi:
290 NewOpc = Hexagon::V6_vL32b_ai;
293 case Hexagon::S2_storeri_pi:
294 NewOpc = Hexagon::S2_storeri_io;
297 case Hexagon::S2_storerd_pi:
298 NewOpc = Hexagon::S2_storerd_io;
301 case Hexagon::V6_vS32b_pi:
302 NewOpc = Hexagon::V6_vS32b_ai;
308 auto IsDead = [
this] (NodeAddr<DefNode*>
DA) ->
bool {
309 return getDeadNodes().count(
DA.Id);
312 MachineOperand &
Op =
MI.getOperand(OpNum);
313 for (NodeAddr<DefNode*> DA :
IA.Addr->members_if(DFG.
IsDef, DFG)) {
314 if (&
DA.Addr->getOp() != &
Op)
327 dbgs() <<
"Rewriting: " <<
MI;
328 MI.setDesc(HII.get(NewOpc));
329 MI.getOperand(OpNum+2).setImm(0);
330 removeOperand(IA, OpNum);
337bool HexagonRDFOpt::runOnMachineFunction(MachineFunction &MF) {
345 dbgs() <<
"Skipping " << getPassName() <<
": too many basic blocks\n";
355 MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
356 const auto &MDF = getAnalysis<MachineDominanceFrontierWrapperPass>().getMDF();
357 const auto &HII = *MF.
getSubtarget<HexagonSubtarget>().getInstrInfo();
358 const auto &HRI = *MF.
getSubtarget<HexagonSubtarget>().getRegisterInfo();
363 MF.
print(
dbgs() <<
"Before " << getPassName() <<
"\n",
nullptr);
365 DataFlowGraph
G(MF, HII, HRI, *MDT, MDF);
369 DataFlowGraph::Config Cfg;
377 dbgs() <<
"Starting aggressive copy propagation on: " << MF.
getName()
379 << PrintNode<FuncNode *>(
G.getFunc(),
G) <<
'\n';
380 HexagonAggressiveCP CP(
G);
385 dbgs() <<
"Starting copy propagation on: " << MF.
getName() <<
'\n'
386 << PrintNode<FuncNode *>(
G.getFunc(),
G) <<
'\n';
393 dbgs() <<
"Starting dead code elimination on: " << MF.
getName() <<
'\n'
394 << PrintNode<FuncNode*>(
G.getFunc(),
G) <<
'\n';
395 HexagonDCE DCE(
G, *MRI);
401 dbgs() <<
"Starting liveness recomputation on: " << MF.
getName() <<
'\n'
402 << PrintNode<FuncNode*>(
G.getFunc(),
G) <<
'\n';
404 Liveness LV(*MRI,
G);
411 MachineBasicBlock &EntryMBB = MF.
front();
413 std::vector<MCRegister> Old;
414 for (
const MachineBasicBlock::RegisterMaskPair &LI : EntryMBB.
liveins())
415 Old.push_back(LI.PhysReg);
416 for (MCRegister R : Old)
418 for (RegisterRef R : LV.getLiveMap()[&EntryMBB].refs())
442 constexpr unsigned MaxLiveInSweeps = 8;
443 for (
unsigned Sweep = 0; Sweep != MaxLiveInSweeps; ++Sweep) {
444 bool AnyChanged =
false;
445 for (MachineBasicBlock *
MBB : Candidates)
456 MF.
print(
dbgs() <<
"After " << getPassName() <<
"\n",
nullptr);
462 return new HexagonRDFOpt();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
This file defines the DenseMap class.
cl::opt< unsigned > RDFFuncBlockLimit
static cl::opt< bool > RDFTrackReserved("hexagon-rdf-track-reserved", cl::Hidden)
static cl::opt< bool > EnableAggressiveRDFCopy("hexagon-aggressive-rdf-copy", cl::desc("Enable aggressive RDF copy propagation with super-register " "support"), cl::init(false), cl::Hidden)
static cl::opt< unsigned > RDFLimit("hexagon-rdf-limit", cl::init(std::numeric_limits< unsigned >::max()))
static cl::opt< bool > RDFDump("hexagon-rdf-dump", cl::Hidden)
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
Register const TargetRegisterInfo * TRI
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
SI optimize exec mask operations pre RA
This file implements a set that has insertion order iteration characteristics.
AnalysisUsage & addRequired()
void setPreservesAll()
Set by analyses that do not transform their input at all.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
FunctionPass class - This class is used to implement most global optimizations.
bool isEHPad() const
Returns true if the block is a landing pad.
iterator_range< livein_iterator > liveins() const
LLVM_ABI void removeLiveIn(MCRegister Reg, LaneBitmask LaneMask=LaneBitmask::getAll())
Remove the specified register from the live in set.
LLVM_ABI bool isEntryBlock() const
Returns true if this is the entry block of the function.
LLVM_ABI void sortUniqueLiveIns()
Sorts and uniques the LiveIns vector.
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
Analysis pass which computes a MachineDominatorTree.
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.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineBasicBlock & front() const
void print(raw_ostream &OS, const SlotIndexes *=nullptr) const
print - Print out the MachineFunction in a format suitable for debugging to the specified stream.
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
Register getReg() const
getReg - Returns the register number.
size_type count(const_arg_type key) const
Count the number of elements of a given key in the SetVector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
void push_back(const T &Elt)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
initializer< Ty > init(const Ty &Val)
DXILDebugInfoMap run(Module &M)
SmallVector< Node, 4 > NodeList
This is an optimization pass for GlobalISel generic memory operations.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
void erase(Container &C, ValueType V)
Wrapper function to remove a value from a container:
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...
auto post_order(const T &G)
Post-order traversal of a graph.
DWARFExpression::Operation Op
static bool recomputeLiveIns(MachineBasicBlock &MBB)
Convenience function for recomputing live-in's for a MBB.
FunctionPass * createHexagonRDFOpt()
virtual bool interpretAsCopy(const MachineInstr *MI, EqualityMap &EM)
LLVM_ABI NodeList members(const DataFlowGraph &G) const
LLVM_ABI RegisterRef makeRegRef(unsigned Reg, unsigned Sub) const
static bool IsDef(const Node BA)
LLVM_ABI NodeList getRelatedRefs(Instr IA, Ref RA) const
const TargetInstrInfo & getTII() const
static bool IsCode(const Node BA)
const TargetRegisterInfo & getTRI() const
NodeAddr< T > addr(NodeId N) const