003 File Manager
Current Path:
/usr/src/contrib/llvm-project/llvm/lib/Target/Hexagon
usr
/
src
/
contrib
/
llvm-project
/
llvm
/
lib
/
Target
/
Hexagon
/
📁
..
📁
AsmParser
📄
BitTracker.cpp
(35.36 KB)
📄
BitTracker.h
(17.25 KB)
📁
Disassembler
📄
Hexagon.h
(1004 B)
📄
Hexagon.td
(17.33 KB)
📄
HexagonArch.h
(1.2 KB)
📄
HexagonAsmPrinter.cpp
(26.65 KB)
📄
HexagonAsmPrinter.h
(2.03 KB)
📄
HexagonBitSimplify.cpp
(107.45 KB)
📄
HexagonBitTracker.cpp
(39.88 KB)
📄
HexagonBitTracker.h
(2.5 KB)
📄
HexagonBlockRanges.cpp
(15.85 KB)
📄
HexagonBlockRanges.h
(6.97 KB)
📄
HexagonBranchRelaxation.cpp
(7.78 KB)
📄
HexagonCFGOptimizer.cpp
(8.4 KB)
📄
HexagonCallingConv.td
(4.46 KB)
📄
HexagonCommonGEP.cpp
(41.47 KB)
📄
HexagonConstExtenders.cpp
(70.64 KB)
📄
HexagonConstPropagation.cpp
(97.75 KB)
📄
HexagonCopyToCombine.cpp
(32.2 KB)
📄
HexagonDepArch.h
(2.04 KB)
📄
HexagonDepArch.td
(1.87 KB)
📄
HexagonDepDecoders.inc
(2.55 KB)
📄
HexagonDepIICHVX.td
(113.05 KB)
📄
HexagonDepIICScalar.td
(224.12 KB)
📄
HexagonDepITypes.h
(1.51 KB)
📄
HexagonDepITypes.td
(1.91 KB)
📄
HexagonDepInstrFormats.td
(91.89 KB)
📄
HexagonDepInstrInfo.td
(1021.44 KB)
📄
HexagonDepMapAsm2Intrin.td
(255.17 KB)
📄
HexagonDepMappings.td
(64.27 KB)
📄
HexagonDepMask.h
(51.94 KB)
📄
HexagonDepOperands.td
(12.12 KB)
📄
HexagonDepTimingClasses.h
(4.69 KB)
📄
HexagonEarlyIfConv.cpp
(37.36 KB)
📄
HexagonExpandCondsets.cpp
(48.55 KB)
📄
HexagonFixupHwLoops.cpp
(6.54 KB)
📄
HexagonFrameLowering.cpp
(97.16 KB)
📄
HexagonFrameLowering.h
(7.85 KB)
📄
HexagonGenExtract.cpp
(8.61 KB)
📄
HexagonGenInsert.cpp
(53.24 KB)
📄
HexagonGenMux.cpp
(12.71 KB)
📄
HexagonGenPredicate.cpp
(16.25 KB)
📄
HexagonHardwareLoops.cpp
(70.32 KB)
📄
HexagonHazardRecognizer.cpp
(5.85 KB)
📄
HexagonHazardRecognizer.h
(3.58 KB)
📄
HexagonIICHVX.td
(1.21 KB)
📄
HexagonIICScalar.td
(1.34 KB)
📄
HexagonISelDAGToDAG.cpp
(78.63 KB)
📄
HexagonISelDAGToDAG.h
(5.88 KB)
📄
HexagonISelDAGToDAGHVX.cpp
(68.26 KB)
📄
HexagonISelLowering.cpp
(134.65 KB)
📄
HexagonISelLowering.h
(22.5 KB)
📄
HexagonISelLoweringHVX.cpp
(70.57 KB)
📄
HexagonInstrFormats.td
(12.04 KB)
📄
HexagonInstrFormatsV60.td
(1.03 KB)
📄
HexagonInstrFormatsV65.td
(1.54 KB)
📄
HexagonInstrInfo.cpp
(161.08 KB)
📄
HexagonInstrInfo.h
(25.31 KB)
📄
HexagonIntrinsics.td
(19.21 KB)
📄
HexagonIntrinsicsV5.td
(16.8 KB)
📄
HexagonIntrinsicsV60.td
(28.9 KB)
📄
HexagonLoopIdiomRecognition.cpp
(79.16 KB)
📄
HexagonMCInstLower.cpp
(6.25 KB)
📄
HexagonMachineFunctionInfo.cpp
(507 B)
📄
HexagonMachineFunctionInfo.h
(3.32 KB)
📄
HexagonMachineScheduler.cpp
(34.25 KB)
📄
HexagonMachineScheduler.h
(8.66 KB)
📄
HexagonMapAsm2IntrinV62.gen.td
(8.71 KB)
📄
HexagonMapAsm2IntrinV65.gen.td
(12.43 KB)
📄
HexagonNewValueJump.cpp
(25.57 KB)
📄
HexagonOperands.td
(1.62 KB)
📄
HexagonOptAddrMode.cpp
(29.37 KB)
📄
HexagonOptimizeSZextends.cpp
(4.74 KB)
📄
HexagonPatterns.td
(142.35 KB)
📄
HexagonPatternsHVX.td
(22.06 KB)
📄
HexagonPatternsV65.td
(2.96 KB)
📄
HexagonPeephole.cpp
(10.18 KB)
📄
HexagonPseudo.td
(21.62 KB)
📄
HexagonRDFOpt.cpp
(9.94 KB)
📄
HexagonRegisterInfo.cpp
(12.03 KB)
📄
HexagonRegisterInfo.h
(2.88 KB)
📄
HexagonRegisterInfo.td
(20.42 KB)
📄
HexagonSchedule.td
(2.33 KB)
📄
HexagonScheduleV5.td
(1.73 KB)
📄
HexagonScheduleV55.td
(1.81 KB)
📄
HexagonScheduleV60.td
(4.31 KB)
📄
HexagonScheduleV62.td
(1.53 KB)
📄
HexagonScheduleV65.td
(1.57 KB)
📄
HexagonScheduleV66.td
(1.57 KB)
📄
HexagonScheduleV67.td
(1.57 KB)
📄
HexagonScheduleV67T.td
(2.51 KB)
📄
HexagonSelectionDAGInfo.cpp
(2.35 KB)
📄
HexagonSelectionDAGInfo.h
(1.24 KB)
📄
HexagonSplitConst32AndConst64.cpp
(4.15 KB)
📄
HexagonSplitDouble.cpp
(37.86 KB)
📄
HexagonStoreWidening.cpp
(20.47 KB)
📄
HexagonSubtarget.cpp
(20.97 KB)
📄
HexagonSubtarget.h
(10.59 KB)
📄
HexagonTargetMachine.cpp
(16 KB)
📄
HexagonTargetMachine.h
(1.77 KB)
📄
HexagonTargetObjectFile.cpp
(16.8 KB)
📄
HexagonTargetObjectFile.h
(2.17 KB)
📄
HexagonTargetStreamer.h
(1.2 KB)
📄
HexagonTargetTransformInfo.cpp
(13.11 KB)
📄
HexagonTargetTransformInfo.h
(6.27 KB)
📄
HexagonVExtract.cpp
(6.64 KB)
📄
HexagonVLIWPacketizer.cpp
(67.01 KB)
📄
HexagonVLIWPacketizer.h
(6.09 KB)
📄
HexagonVectorLoopCarriedReuse.cpp
(23.99 KB)
📄
HexagonVectorPrint.cpp
(7.06 KB)
📁
MCTargetDesc
📄
RDFCopy.cpp
(6.37 KB)
📄
RDFCopy.h
(1.69 KB)
📄
RDFDeadCode.cpp
(7.5 KB)
📄
RDFDeadCode.h
(2.33 KB)
📁
TargetInfo
Editing: RDFDeadCode.cpp
//===--- RDFDeadCode.cpp --------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // RDF-based generic dead code elimination. #include "RDFDeadCode.h" #include "llvm/ADT/SetVector.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/RDFGraph.h" #include "llvm/CodeGen/RDFLiveness.h" #include "llvm/Support/Debug.h" #include <queue> using namespace llvm; using namespace rdf; // This drastically improves execution time in "collect" over using // SetVector as a work queue, and popping the first element from it. template<typename T> struct DeadCodeElimination::SetQueue { SetQueue() : Set(), Queue() {} bool empty() const { return Queue.empty(); } T pop_front() { T V = Queue.front(); Queue.pop(); Set.erase(V); return V; } void push_back(T V) { if (Set.count(V)) return; Queue.push(V); Set.insert(V); } private: DenseSet<T> Set; std::queue<T> Queue; }; // Check if the given instruction has observable side-effects, i.e. if // it should be considered "live". It is safe for this function to be // overly conservative (i.e. return "true" for all instructions), but it // is not safe to return "false" for an instruction that should not be // considered removable. bool DeadCodeElimination::isLiveInstr(const MachineInstr *MI) const { if (MI->mayStore() || MI->isBranch() || MI->isCall() || MI->isReturn()) return true; if (MI->hasOrderedMemoryRef() || MI->hasUnmodeledSideEffects() || MI->isPosition()) return true; if (MI->isPHI()) return false; for (auto &Op : MI->operands()) { if (Op.isReg() && MRI.isReserved(Op.getReg())) return true; if (Op.isRegMask()) { const uint32_t *BM = Op.getRegMask(); for (unsigned R = 0, RN = DFG.getTRI().getNumRegs(); R != RN; ++R) { if (BM[R/32] & (1u << (R%32))) continue; if (MRI.isReserved(R)) return true; } } } return false; } void DeadCodeElimination::scanInstr(NodeAddr<InstrNode*> IA, SetQueue<NodeId> &WorkQ) { if (!DFG.IsCode<NodeAttrs::Stmt>(IA)) return; if (!isLiveInstr(NodeAddr<StmtNode*>(IA).Addr->getCode())) return; for (NodeAddr<RefNode*> RA : IA.Addr->members(DFG)) { if (!LiveNodes.count(RA.Id)) WorkQ.push_back(RA.Id); } } void DeadCodeElimination::processDef(NodeAddr<DefNode*> DA, SetQueue<NodeId> &WorkQ) { NodeAddr<InstrNode*> IA = DA.Addr->getOwner(DFG); for (NodeAddr<UseNode*> UA : IA.Addr->members_if(DFG.IsUse, DFG)) { if (!LiveNodes.count(UA.Id)) WorkQ.push_back(UA.Id); } for (NodeAddr<DefNode*> TA : DFG.getRelatedRefs(IA, DA)) LiveNodes.insert(TA.Id); } void DeadCodeElimination::processUse(NodeAddr<UseNode*> UA, SetQueue<NodeId> &WorkQ) { for (NodeAddr<DefNode*> DA : LV.getAllReachingDefs(UA)) { if (!LiveNodes.count(DA.Id)) WorkQ.push_back(DA.Id); } } // Traverse the DFG and collect the set dead RefNodes and the set of // dead instructions. Return "true" if any of these sets is non-empty, // "false" otherwise. bool DeadCodeElimination::collect() { // This function works by first finding all live nodes. The dead nodes // are then the complement of the set of live nodes. // // Assume that all nodes are dead. Identify instructions which must be // considered live, i.e. instructions with observable side-effects, such // as calls and stores. All arguments of such instructions are considered // live. For each live def, all operands used in the corresponding // instruction are considered live. For each live use, all its reaching // defs are considered live. LiveNodes.clear(); SetQueue<NodeId> WorkQ; for (NodeAddr<BlockNode*> BA : DFG.getFunc().Addr->members(DFG)) for (NodeAddr<InstrNode*> IA : BA.Addr->members(DFG)) scanInstr(IA, WorkQ); while (!WorkQ.empty()) { NodeId N = WorkQ.pop_front(); LiveNodes.insert(N); auto RA = DFG.addr<RefNode*>(N); if (DFG.IsDef(RA)) processDef(RA, WorkQ); else processUse(RA, WorkQ); } if (trace()) { dbgs() << "Live nodes:\n"; for (NodeId N : LiveNodes) { auto RA = DFG.addr<RefNode*>(N); dbgs() << PrintNode<RefNode*>(RA, DFG) << "\n"; } } auto IsDead = [this] (NodeAddr<InstrNode*> IA) -> bool { for (NodeAddr<DefNode*> DA : IA.Addr->members_if(DFG.IsDef, DFG)) if (LiveNodes.count(DA.Id)) return false; return true; }; for (NodeAddr<BlockNode*> BA : DFG.getFunc().Addr->members(DFG)) { for (NodeAddr<InstrNode*> IA : BA.Addr->members(DFG)) { for (NodeAddr<RefNode*> RA : IA.Addr->members(DFG)) if (!LiveNodes.count(RA.Id)) DeadNodes.insert(RA.Id); if (DFG.IsCode<NodeAttrs::Stmt>(IA)) if (isLiveInstr(NodeAddr<StmtNode*>(IA).Addr->getCode())) continue; if (IsDead(IA)) { DeadInstrs.insert(IA.Id); if (trace()) dbgs() << "Dead instr: " << PrintNode<InstrNode*>(IA, DFG) << "\n"; } } } return !DeadNodes.empty(); } // Erase the nodes given in the Nodes set from DFG. In addition to removing // them from the DFG, if a node corresponds to a statement, the corresponding // machine instruction is erased from the function. bool DeadCodeElimination::erase(const SetVector<NodeId> &Nodes) { if (Nodes.empty()) return false; // Prepare the actual set of ref nodes to remove: ref nodes from Nodes // are included directly, for each InstrNode in Nodes, include the set // of all RefNodes from it. NodeList DRNs, DINs; for (auto I : Nodes) { auto BA = DFG.addr<NodeBase*>(I); uint16_t Type = BA.Addr->getType(); if (Type == NodeAttrs::Ref) { DRNs.push_back(DFG.addr<RefNode*>(I)); continue; } // If it's a code node, add all ref nodes from it. uint16_t Kind = BA.Addr->getKind(); if (Kind == NodeAttrs::Stmt || Kind == NodeAttrs::Phi) { for (auto N : NodeAddr<CodeNode*>(BA).Addr->members(DFG)) DRNs.push_back(N); DINs.push_back(DFG.addr<InstrNode*>(I)); } else { llvm_unreachable("Unexpected code node"); return false; } } // Sort the list so that use nodes are removed first. This makes the // "unlink" functions a bit faster. auto UsesFirst = [] (NodeAddr<RefNode*> A, NodeAddr<RefNode*> B) -> bool { uint16_t KindA = A.Addr->getKind(), KindB = B.Addr->getKind(); if (KindA == NodeAttrs::Use && KindB == NodeAttrs::Def) return true; if (KindA == NodeAttrs::Def && KindB == NodeAttrs::Use) return false; return A.Id < B.Id; }; llvm::sort(DRNs, UsesFirst); if (trace()) dbgs() << "Removing dead ref nodes:\n"; for (NodeAddr<RefNode*> RA : DRNs) { if (trace()) dbgs() << " " << PrintNode<RefNode*>(RA, DFG) << '\n'; if (DFG.IsUse(RA)) DFG.unlinkUse(RA, true); else if (DFG.IsDef(RA)) DFG.unlinkDef(RA, true); } // Now, remove all dead instruction nodes. for (NodeAddr<InstrNode*> IA : DINs) { NodeAddr<BlockNode*> BA = IA.Addr->getOwner(DFG); BA.Addr->removeMember(IA, DFG); if (!DFG.IsCode<NodeAttrs::Stmt>(IA)) continue; MachineInstr *MI = NodeAddr<StmtNode*>(IA).Addr->getCode(); if (trace()) dbgs() << "erasing: " << *MI; MI->eraseFromParent(); } return true; }
Upload File
Create Folder