From af732203b8f7f006927528db5497f5cbc4c4742a Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sun, 13 Jun 2021 21:31:46 +0200 Subject: Merge llvm-project 12.0.1 release and follow-up fixes Merge llvm-project main llvmorg-12-init-17869-g8e464dd76bef This updates llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp to llvmorg-12-init-17869-g8e464dd76bef, the last commit before the upstream release/12.x branch was created. PR: 255570 (cherry picked from commit e8d8bef961a50d4dc22501cde4fb9fb0be1b2532) Merge llvm-project 12.0.0 release This updates llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp to llvmorg-12.0.0-0-gd28af7c654d8, a.k.a. 12.0.0 release. PR: 255570 (cherry picked from commit d409305fa3838fb39b38c26fc085fb729b8766d5) Disable strict-fp for powerpcspe, as it does not work properly yet Merge commit 5c18d1136665 from llvm git (by Qiu Chaofan) [SPE] Disable strict-fp for SPE by default As discussed in PR50385, strict-fp on PowerPC SPE has not been handled well. This patch disables it by default for SPE. Reviewed By: nemanjai, vit9696, jhibbits Differential Revision: https://reviews.llvm.org/D103235 PR: 255570 (cherry picked from commit 715df83abc049b23d9acddc81f2480bd4c056d64) Apply upstream libc++ fix to allow building with devel/xxx-xtoolchain-gcc Merge commit 52e9d80d5db2 from llvm git (by Jason Liu): [libc++] add `inline` for __open's definition in ifstream and ofstream Summary: When building with gcc on AIX, it seems that gcc does not like the `always_inline` without the `inline` keyword. So adding the inline keywords in for __open in ifstream and ofstream. That will also make it consistent with __open in basic_filebuf (it seems we added `inline` there before for gcc build as well). Differential Revision: https://reviews.llvm.org/D99422 PR: 255570 (cherry picked from commit d099db25464b826c5724cf2fb5b22292bbe15f6e) Undefine HAVE_(DE)REGISTER_FRAME in llvm's config.h on arm Otherwise, the lli tool (enable by WITH_CLANG_EXTRAS) won't link on arm, stating that __register_frame is undefined. This function is normally provided by libunwind, but explicitly not for the ARM Exception ABI. Reported by: oh PR: 255570 (cherry picked from commit f336b45e943c7f9a90ffcea1a6c4c7039e54c73c) Merge llvm-project 12.0.1 rc2 This updates llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp to llvmorg-12.0.1-rc2-0-ge7dac564cd0e, a.k.a. 12.0.1 rc2. PR: 255570 (cherry picked from commit 23408297fbf3089f0388a8873b02fa75ab3f5bb9) Revert libunwind change to fix backtrace segfault on aarch64 Revert commit 22b615a96593 from llvm git (by Daniel Kiss): [libunwind] Support for leaf function unwinding. Unwinding leaf function is useful in cases when the backtrace finds a leaf function for example when it caused a signal. This patch also add the support for the DW_CFA_undefined because it marks the end of the frames. Ryan Prichard provided code for the tests. Reviewed By: #libunwind, mstorsjo Differential Revision: https://reviews.llvm.org/D83573 Reland with limit the test to the x86_64-linux target. Bisection has shown that this particular upstream commit causes programs using backtrace(3) on aarch64 to segfault. This affects the lang/rust port, for instance. Until we can upstream to fix this problem, revert the commit for now. Reported by: mikael PR: 256864 (cherry picked from commit 5866c369e4fd917c0d456f0f10b92ee354b82279) Merge llvm-project 12.0.1 release This updates llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp to llvmorg-12.0.1-0-gfed41342a82f, a.k.a. 12.0.1 release. PR: 255570 (cherry picked from commit 4652422eb477731f284b1345afeefef7f269da50) compilert-rt: build out-of-line LSE atomics helpers for aarch64 Both clang >= 12 and gcc >= 10.1 now default to -moutline-atomics for aarch64. This requires a bunch of helper functions in libcompiler_rt.a, to avoid link errors like "undefined symbol: __aarch64_ldadd8_acq_rel". (Note: of course you can use -mno-outline-atomics as a workaround too, but this would negate the potential performance benefit of the faster LSE instructions.) Bump __FreeBSD_version so ports maintainers can easily detect this. PR: 257392 (cherry picked from commit cc55ee8009a550810d38777fd6ace9abf3a2f6b4) --- contrib/llvm-project/llvm/include/llvm-c/Core.h | 60 +- .../llvm-project/llvm/include/llvm-c/DataTypes.h | 4 - .../llvm-project/llvm/include/llvm-c/DebugInfo.h | 4 +- contrib/llvm-project/llvm/include/llvm-c/Error.h | 5 + contrib/llvm-project/llvm/include/llvm-c/LLJIT.h | 213 + .../llvm/include/llvm-c/LinkTimeOptimizer.h | 66 - contrib/llvm-project/llvm/include/llvm-c/Orc.h | 452 +- .../llvm-project/llvm/include/llvm-c/OrcBindings.h | 169 - contrib/llvm-project/llvm/include/llvm-c/OrcEE.h | 55 + .../llvm/include/llvm-c/Transforms/IPO.h | 3 - .../llvm/include/llvm-c/Transforms/Scalar.h | 6 +- .../llvm/include/llvm/ADT/APFixedPoint.h | 237 + .../llvm-project/llvm/include/llvm/ADT/APFloat.h | 5 +- contrib/llvm-project/llvm/include/llvm/ADT/APInt.h | 44 +- .../llvm-project/llvm/include/llvm/ADT/APSInt.h | 20 +- .../llvm/include/llvm/ADT/AllocatorList.h | 7 - contrib/llvm-project/llvm/include/llvm/ADT/Any.h | 7 +- .../llvm-project/llvm/include/llvm/ADT/BitVector.h | 40 +- .../llvm-project/llvm/include/llvm/ADT/DenseMap.h | 35 +- .../llvm/include/llvm/ADT/DenseMapInfo.h | 45 + .../llvm-project/llvm/include/llvm/ADT/DenseSet.h | 21 +- .../llvm/include/llvm/ADT/DepthFirstIterator.h | 2 +- .../llvm/include/llvm/ADT/DirectedGraph.h | 16 +- .../llvm/include/llvm/ADT/FloatingPointMode.h | 18 + .../llvm/include/llvm/ADT/FunctionExtras.h | 12 +- .../llvm-project/llvm/include/llvm/ADT/Hashing.h | 25 + .../llvm/include/llvm/ADT/IntervalMap.h | 10 +- .../llvm/include/llvm/ADT/IntrusiveRefCntPtr.h | 45 +- .../llvm-project/llvm/include/llvm/ADT/Optional.h | 165 +- .../llvm/include/llvm/ADT/PointerUnion.h | 7 - .../llvm-project/llvm/include/llvm/ADT/STLExtras.h | 104 +- .../llvm-project/llvm/include/llvm/ADT/Sequence.h | 4 + .../llvm-project/llvm/include/llvm/ADT/SetVector.h | 5 + .../llvm-project/llvm/include/llvm/ADT/SmallSet.h | 7 + .../llvm/include/llvm/ADT/SmallString.h | 61 +- .../llvm/include/llvm/ADT/SmallVector.h | 549 +- .../llvm-project/llvm/include/llvm/ADT/SparseSet.h | 9 +- .../llvm-project/llvm/include/llvm/ADT/Statistic.h | 2 + .../llvm/include/llvm/ADT/StringExtras.h | 109 +- .../llvm-project/llvm/include/llvm/ADT/StringMap.h | 12 +- .../llvm-project/llvm/include/llvm/ADT/StringSet.h | 3 + .../llvm-project/llvm/include/llvm/ADT/Triple.h | 67 +- .../llvm-project/llvm/include/llvm/ADT/iterator.h | 22 +- .../llvm/include/llvm/ADT/iterator_range.h | 1 - .../llvm/include/llvm/ADT/simple_ilist.h | 6 +- .../llvm/include/llvm/Analysis/AliasAnalysis.h | 104 +- .../llvm/include/llvm/Analysis/AliasSetTracker.h | 30 +- .../llvm/include/llvm/Analysis/AssumptionCache.h | 2 +- .../include/llvm/Analysis/BasicAliasAnalysis.h | 63 +- .../include/llvm/Analysis/BlockFrequencyInfoImpl.h | 12 +- .../include/llvm/Analysis/BranchProbabilityInfo.h | 287 +- .../llvm/include/llvm/Analysis/CFGPrinter.h | 22 +- .../llvm/include/llvm/Analysis/CGSCCPassManager.h | 540 +- .../llvm/include/llvm/Analysis/CallGraph.h | 7 - .../llvm/include/llvm/Analysis/CaptureTracking.h | 8 + .../llvm/include/llvm/Analysis/CodeMetrics.h | 3 +- .../llvm/include/llvm/Analysis/ConstantFolding.h | 6 +- .../llvm/include/llvm/Analysis/ConstraintSystem.h | 88 + .../llvm-project/llvm/include/llvm/Analysis/DDG.h | 28 +- .../llvm/include/llvm/Analysis/DDGPrinter.h | 91 + .../llvm/include/llvm/Analysis/Delinearization.h | 33 + .../llvm/include/llvm/Analysis/DemandedBits.h | 14 + .../include/llvm/Analysis/DivergenceAnalysis.h | 85 +- .../llvm/include/llvm/Analysis/DominanceFrontier.h | 1 - .../llvm/include/llvm/Analysis/EHPersonalities.h | 11 +- .../llvm/Analysis/FunctionPropertiesAnalysis.h | 86 + .../include/llvm/Analysis/IRSimilarityIdentifier.h | 789 +++ .../llvm/include/llvm/Analysis/IVDescriptors.h | 154 +- .../llvm/include/llvm/Analysis/InlineAdvisor.h | 82 +- .../include/llvm/Analysis/InlineFeaturesAnalysis.h | 45 - .../llvm/Analysis/InlineSizeEstimatorAnalysis.h | 12 +- .../llvm/include/llvm/Analysis/InstCount.h | 28 + .../include/llvm/Analysis/InstructionSimplify.h | 42 +- .../llvm/include/llvm/Analysis/Interval.h | 3 - .../llvm/include/llvm/Analysis/IntervalIterator.h | 6 +- .../llvm/Analysis/IteratedDominanceFrontier.h | 8 +- .../llvm/Analysis/LazyBranchProbabilityInfo.h | 2 +- .../llvm/include/llvm/Analysis/LazyCallGraph.h | 51 +- .../llvm/include/llvm/Analysis/LazyValueInfo.h | 18 +- .../llvm-project/llvm/include/llvm/Analysis/Lint.h | 28 +- .../llvm/include/llvm/Analysis/Loads.h | 9 + .../include/llvm/Analysis/LoopAccessAnalysis.h | 17 +- .../include/llvm/Analysis/LoopAnalysisManager.h | 1 + .../llvm/include/llvm/Analysis/LoopCacheAnalysis.h | 29 +- .../llvm/include/llvm/Analysis/LoopInfo.h | 22 +- .../llvm/include/llvm/Analysis/LoopInfoImpl.h | 22 +- .../llvm/include/llvm/Analysis/LoopNestAnalysis.h | 17 +- .../llvm/include/llvm/Analysis/MLInlineAdvisor.h | 13 +- .../llvm/include/llvm/Analysis/MemDerefPrinter.h | 24 + .../llvm/Analysis/MemoryDependenceAnalysis.h | 2 +- .../llvm/include/llvm/Analysis/MemoryLocation.h | 68 +- .../llvm/include/llvm/Analysis/MemorySSA.h | 61 +- .../llvm/include/llvm/Analysis/MemorySSAUpdater.h | 9 +- .../include/llvm/Analysis/ModuleDebugInfoPrinter.h | 29 + .../llvm/include/llvm/Analysis/MustExecute.h | 19 + .../include/llvm/Analysis/ObjCARCAnalysisUtils.h | 34 +- .../llvm/Analysis/OptimizationRemarkEmitter.h | 10 +- .../llvm/include/llvm/Analysis/PhiValues.h | 7 +- .../include/llvm/Analysis/ProfileSummaryInfo.h | 6 +- .../llvm/include/llvm/Analysis/RegionInfo.h | 3 - .../llvm/include/llvm/Analysis/RegionInfoImpl.h | 12 +- .../llvm/include/llvm/Analysis/RegionPass.h | 2 - .../include/llvm/Analysis/ReplayInlineAdvisor.h | 41 + .../llvm/include/llvm/Analysis/ScalarEvolution.h | 279 +- .../llvm/Analysis/ScalarEvolutionDivision.h | 1 + .../llvm/Analysis/ScalarEvolutionExpressions.h | 135 +- .../llvm/include/llvm/Analysis/SparsePropagation.h | 3 +- .../llvm/include/llvm/Analysis/StackLifetime.h | 16 +- .../include/llvm/Analysis/StackSafetyAnalysis.h | 3 +- .../include/llvm/Analysis/SyncDependenceAnalysis.h | 42 +- .../include/llvm/Analysis/TargetLibraryInfo.def | 21 + .../llvm/include/llvm/Analysis/TargetLibraryInfo.h | 1 + .../include/llvm/Analysis/TargetTransformInfo.h | 271 +- .../llvm/Analysis/TargetTransformInfoImpl.h | 346 +- .../Utils/ImportedFunctionsInliningStatistics.h | 112 + .../llvm/include/llvm/Analysis/Utils/Local.h | 76 +- .../llvm/include/llvm/Analysis/Utils/TFUtils.h | 203 +- .../llvm/include/llvm/Analysis/ValueLattice.h | 11 + .../llvm/include/llvm/Analysis/ValueTracking.h | 107 +- .../llvm/include/llvm/Analysis/VecFuncs.def | 146 + .../llvm/include/llvm/Analysis/VectorUtils.h | 56 +- .../llvm/include/llvm/BinaryFormat/COFF.h | 1 + .../llvm/include/llvm/BinaryFormat/Dwarf.def | 19 +- .../llvm/include/llvm/BinaryFormat/Dwarf.h | 93 +- .../llvm/include/llvm/BinaryFormat/DynamicTags.def | 1 + .../llvm/include/llvm/BinaryFormat/ELF.h | 92 +- .../include/llvm/BinaryFormat/ELFRelocs/CSKY.def | 74 + .../llvm/BinaryFormat/ELFRelocs/PowerPC64.def | 12 + .../llvm/include/llvm/BinaryFormat/MachO.h | 5 +- .../llvm/include/llvm/BinaryFormat/Wasm.h | 49 +- .../llvm/include/llvm/BinaryFormat/WasmRelocs.def | 5 + .../llvm/include/llvm/BinaryFormat/WasmTraits.h | 68 + .../llvm/include/llvm/BinaryFormat/XCOFF.h | 111 + .../llvm/include/llvm/Bitcode/BitcodeCommon.h | 30 + .../llvm/include/llvm/Bitcode/BitcodeConvenience.h | 486 ++ .../llvm/include/llvm/Bitcode/BitcodeWriter.h | 16 +- .../llvm/include/llvm/Bitcode/LLVMBitCodes.h | 25 +- .../llvm/include/llvm/Bitstream/BitCodes.h | 9 +- .../llvm/include/llvm/Bitstream/BitstreamWriter.h | 103 +- .../llvm/include/llvm/CodeGen/Analysis.h | 5 - .../llvm/include/llvm/CodeGen/AntiDepBreaker.h | 1 - .../llvm/include/llvm/CodeGen/AsmPrinter.h | 131 +- .../llvm/include/llvm/CodeGen/AsmPrinterHandler.h | 7 +- .../include/llvm/CodeGen/BasicBlockSectionUtils.h | 30 + .../llvm/include/llvm/CodeGen/BasicTTIImpl.h | 491 +- .../llvm/include/llvm/CodeGen/CalcSpillWeights.h | 70 +- .../llvm/include/llvm/CodeGen/CallingConvLower.h | 15 +- .../llvm/include/llvm/CodeGen/CodeGenPassBuilder.h | 1144 +++++ .../llvm/include/llvm/CodeGen/CommandFlags.h | 30 +- .../llvm-project/llvm/include/llvm/CodeGen/DIE.h | 27 +- .../llvm/CodeGen/DbgEntityHistoryCalculator.h | 24 + .../llvm/include/llvm/CodeGen/DebugHandlerBase.h | 12 +- .../include/llvm/CodeGen/DwarfStringPoolEntry.h | 4 +- .../llvm/include/llvm/CodeGen/FastISel.h | 43 +- .../include/llvm/CodeGen/FunctionLoweringInfo.h | 34 +- .../llvm/include/llvm/CodeGen/GlobalISel/CSEInfo.h | 8 +- .../include/llvm/CodeGen/GlobalISel/CallLowering.h | 150 +- .../llvm/CodeGen/GlobalISel/CombinerHelper.h | 268 +- .../llvm/CodeGen/GlobalISel/GISelChangeObserver.h | 2 +- .../llvm/CodeGen/GlobalISel/GISelKnownBits.h | 12 +- .../llvm/CodeGen/GlobalISel/GISelWorkList.h | 3 - .../include/llvm/CodeGen/GlobalISel/IRTranslator.h | 102 +- .../llvm/CodeGen/GlobalISel/InstructionSelector.h | 45 +- .../CodeGen/GlobalISel/InstructionSelectorImpl.h | 77 +- .../GlobalISel/LegalizationArtifactCombiner.h | 124 +- .../include/llvm/CodeGen/GlobalISel/Legalizer.h | 3 - .../llvm/CodeGen/GlobalISel/LegalizerHelper.h | 82 +- .../llvm/CodeGen/GlobalISel/LegalizerInfo.h | 80 +- .../include/llvm/CodeGen/GlobalISel/Localizer.h | 8 +- .../llvm/CodeGen/GlobalISel/MIPatternMatch.h | 102 +- .../llvm/CodeGen/GlobalISel/MachineIRBuilder.h | 162 +- .../llvm/CodeGen/GlobalISel/RegisterBankInfo.h | 23 +- .../llvm/include/llvm/CodeGen/GlobalISel/Utils.h | 130 +- .../llvm/include/llvm/CodeGen/ISDOpcodes.h | 108 +- .../llvm/include/llvm/CodeGen/LexicalScopes.h | 3 - .../llvm/include/llvm/CodeGen/LiveInterval.h | 34 +- .../llvm/include/llvm/CodeGen/LiveIntervalUnion.h | 3 + .../llvm/include/llvm/CodeGen/LiveIntervals.h | 25 +- .../llvm/include/llvm/CodeGen/LiveRangeEdit.h | 8 +- .../llvm/include/llvm/CodeGen/LiveRegMatrix.h | 17 +- .../llvm/include/llvm/CodeGen/LiveRegUnits.h | 3 +- .../llvm/include/llvm/CodeGen/LiveVariables.h | 54 +- .../llvm/include/llvm/CodeGen/LowLevelType.h | 4 + .../llvm/include/llvm/CodeGen/MBFIWrapper.h | 2 + .../llvm/include/llvm/CodeGen/MIRFormatter.h | 6 +- .../llvm/include/llvm/CodeGen/MIRYamlMapping.h | 51 +- .../llvm/include/llvm/CodeGen/MachineBasicBlock.h | 31 +- .../llvm/CodeGen/MachineBlockFrequencyInfo.h | 23 +- .../include/llvm/CodeGen/MachineCombinerPattern.h | 5 + .../include/llvm/CodeGen/MachineConstantPool.h | 6 +- .../llvm/CodeGen/MachineDominanceFrontier.h | 1 - .../llvm/include/llvm/CodeGen/MachineDominators.h | 1 - .../llvm/include/llvm/CodeGen/MachineFrameInfo.h | 7 +- .../llvm/include/llvm/CodeGen/MachineFunction.h | 58 +- .../llvm/include/llvm/CodeGen/MachineInstr.h | 40 +- .../include/llvm/CodeGen/MachineInstrBuilder.h | 41 +- .../include/llvm/CodeGen/MachineJumpTableInfo.h | 3 + .../llvm/include/llvm/CodeGen/MachineLoopInfo.h | 6 + .../llvm/include/llvm/CodeGen/MachineLoopUtils.h | 4 - .../llvm/include/llvm/CodeGen/MachineModuleInfo.h | 27 +- .../llvm/include/llvm/CodeGen/MachineOperand.h | 14 +- .../llvm/include/llvm/CodeGen/MachineOutliner.h | 3 +- .../llvm/include/llvm/CodeGen/MachinePassManager.h | 256 + .../include/llvm/CodeGen/MachinePassRegistry.def | 197 + .../llvm/include/llvm/CodeGen/MachinePipeliner.h | 17 +- .../include/llvm/CodeGen/MachineRegisterInfo.h | 42 +- .../llvm/include/llvm/CodeGen/MachineSSAUpdater.h | 4 +- .../llvm/include/llvm/CodeGen/MachineStableHash.h | 30 + .../include/llvm/CodeGen/MachineTraceMetrics.h | 4 +- .../include/llvm/CodeGen/MultiHazardRecognizer.h | 47 + .../llvm/CodeGen/NonRelocatableStringpool.h | 4 +- .../llvm/include/llvm/CodeGen/Passes.h | 32 +- .../llvm/include/llvm/CodeGen/RDFGraph.h | 4 - .../llvm/include/llvm/CodeGen/RDFLiveness.h | 38 +- .../llvm/include/llvm/CodeGen/RDFRegisters.h | 43 +- .../include/llvm/CodeGen/ReachingDefAnalysis.h | 45 +- .../llvm/include/llvm/CodeGen/RegAllocPBQP.h | 28 +- .../llvm/include/llvm/CodeGen/Register.h | 32 +- .../llvm/include/llvm/CodeGen/RegisterPressure.h | 34 +- .../llvm/include/llvm/CodeGen/RegisterScavenging.h | 13 +- .../include/llvm/CodeGen/ResourcePriorityQueue.h | 1 - .../llvm/include/llvm/CodeGen/RuntimeLibcalls.h | 5 + .../llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h | 20 +- .../llvm/CodeGen/ScheduleHazardRecognizer.h | 10 +- .../llvm/include/llvm/CodeGen/SelectionDAG.h | 138 +- .../llvm/include/llvm/CodeGen/SelectionDAGISel.h | 2 - .../llvm/include/llvm/CodeGen/SelectionDAGNodes.h | 240 +- .../include/llvm/CodeGen/SelectionDAGTargetInfo.h | 2 +- .../llvm/include/llvm/CodeGen/SlotIndexes.h | 45 +- .../llvm/include/llvm/CodeGen/StableHashing.h | 112 + .../llvm/include/llvm/CodeGen/StackMaps.h | 62 +- .../include/llvm/CodeGen/SwitchLoweringUtils.h | 11 +- .../llvm/include/llvm/CodeGen/TargetCallingConv.h | 62 +- .../include/llvm/CodeGen/TargetFrameLowering.h | 18 +- .../llvm/include/llvm/CodeGen/TargetInstrInfo.h | 121 +- .../llvm/include/llvm/CodeGen/TargetLowering.h | 130 +- .../llvm/CodeGen/TargetLoweringObjectFileImpl.h | 30 +- .../llvm/include/llvm/CodeGen/TargetPassConfig.h | 28 +- .../llvm/include/llvm/CodeGen/TargetRegisterInfo.h | 96 +- .../include/llvm/CodeGen/TargetSubtargetInfo.h | 4 +- .../llvm/include/llvm/CodeGen/TileShapeInfo.h | 97 + .../llvm/include/llvm/CodeGen/ValueTypes.h | 96 +- .../llvm/include/llvm/CodeGen/ValueTypes.td | 209 +- .../llvm/include/llvm/CodeGen/VirtRegMap.h | 35 +- .../llvm/include/llvm/CodeGen/WasmEHFuncInfo.h | 2 + .../llvm/include/llvm/DWARFLinker/DWARFLinker.h | 104 +- .../llvm/DWARFLinker/DWARFLinkerCompileUnit.h | 33 +- .../llvm/DWARFLinker/DWARFLinkerDeclContext.h | 31 +- .../llvm/include/llvm/DWARFLinker/DWARFStreamer.h | 2 +- .../include/llvm/DebugInfo/CodeView/CVRecord.h | 17 +- .../llvm/DebugInfo/CodeView/CVSymbolVisitor.h | 3 - .../llvm/DebugInfo/CodeView/CodeViewRecordIO.h | 3 +- .../llvm/DebugInfo/CodeView/CodeViewRegisters.def | 36 +- .../DebugInfo/CodeView/DebugSubsectionVisitor.h | 3 - .../DebugInfo/CodeView/DebugSymbolsSubsection.h | 2 +- .../DebugInfo/CodeView/LazyRandomTypeCollection.h | 1 - .../include/llvm/DebugInfo/CodeView/RecordName.h | 1 - .../include/llvm/DebugInfo/CodeView/SymbolDumper.h | 2 +- .../include/llvm/DebugInfo/CodeView/SymbolRecord.h | 3 - .../llvm/DebugInfo/CodeView/SymbolRecordHelpers.h | 3 +- .../llvm/DebugInfo/CodeView/TypeCollection.h | 3 +- .../include/llvm/DebugInfo/CodeView/TypeHashing.h | 17 +- .../include/llvm/DebugInfo/CodeView/TypeIndex.h | 11 +- .../llvm/DebugInfo/CodeView/TypeIndexDiscovery.h | 4 +- .../include/llvm/DebugInfo/CodeView/TypeRecord.h | 8 +- .../llvm/DebugInfo/CodeView/TypeRecordHelpers.h | 3 +- .../llvm/DebugInfo/CodeView/TypeStreamMerger.h | 2 +- .../llvm/include/llvm/DebugInfo/DIContext.h | 18 +- .../DebugInfo/DWARF/DWARFAbbreviationDeclaration.h | 10 + .../include/llvm/DebugInfo/DWARF/DWARFContext.h | 18 +- .../include/llvm/DebugInfo/DWARF/DWARFDebugAddr.h | 18 + .../llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h | 3 +- .../include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h | 17 +- .../include/llvm/DebugInfo/DWARF/DWARFDebugLine.h | 12 +- .../include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h | 2 + .../include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h | 7 +- .../llvm/DebugInfo/DWARF/DWARFDebugRnglists.h | 3 +- .../llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h | 6 +- .../include/llvm/DebugInfo/DWARF/DWARFExpression.h | 16 +- .../include/llvm/DebugInfo/DWARF/DWARFFormValue.h | 3 + .../include/llvm/DebugInfo/DWARF/DWARFListTable.h | 66 +- .../llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h | 37 +- .../include/llvm/DebugInfo/DWARF/DWARFVerifier.h | 7 +- .../include/llvm/DebugInfo/MSF/MappedBlockStream.h | 2 - .../PDB/Native/DbiModuleDescriptorBuilder.h | 63 +- .../llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h | 41 + .../DebugInfo/PDB/Native/NativeFunctionSymbol.h | 6 +- .../DebugInfo/PDB/Native/NativeInlineSiteSymbol.h | 46 + .../llvm/DebugInfo/PDB/Native/NativeLineNumber.h | 3 +- .../llvm/DebugInfo/PDB/Native/NativePublicSymbol.h | 1 - .../llvm/DebugInfo/PDB/Native/NativeSession.h | 11 + .../llvm/DebugInfo/PDB/Native/SymbolCache.h | 48 +- .../include/llvm/DebugInfo/PDB/Native/TpiStream.h | 2 +- .../llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h | 9 +- .../llvm/include/llvm/DebugInfo/PDB/PDBExtras.h | 6 +- .../llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h | 8 +- .../include/llvm/DebugInfo/Symbolize/Symbolize.h | 2 +- .../llvm/include/llvm/Demangle/ItaniumDemangle.h | 203 +- .../llvm/include/llvm/Demangle/Utility.h | 2 +- .../include/llvm/ExecutionEngine/ExecutionEngine.h | 21 - .../llvm/ExecutionEngine/JITEventListener.h | 1 - .../llvm/ExecutionEngine/JITLink/EHFrameSupport.h | 33 +- .../include/llvm/ExecutionEngine/JITLink/ELF.h | 13 +- .../llvm/ExecutionEngine/JITLink/ELF_x86_64.h | 14 +- .../include/llvm/ExecutionEngine/JITLink/JITLink.h | 91 +- .../llvm/ExecutionEngine/JITLink/JITLinkDylib.h | 24 + .../ExecutionEngine/JITLink/JITLinkMemoryManager.h | 19 +- .../include/llvm/ExecutionEngine/JITLink/MachO.h | 11 +- .../llvm/ExecutionEngine/JITLink/MachO_arm64.h | 11 +- .../llvm/ExecutionEngine/JITLink/MachO_x86_64.h | 13 +- .../llvm/include/llvm/ExecutionEngine/JITSymbol.h | 2 +- .../ExecutionEngine/Orc/CompileOnDemandLayer.h | 639 +-- .../llvm/ExecutionEngine/Orc/CompileUtils.h | 2 - .../llvm/include/llvm/ExecutionEngine/Orc/Core.h | 611 ++- .../llvm/ExecutionEngine/Orc/ExecutionUtils.h | 110 +- .../llvm/ExecutionEngine/Orc/GlobalMappingLayer.h | 111 - .../llvm/ExecutionEngine/Orc/IRCompileLayer.h | 100 +- .../llvm/ExecutionEngine/Orc/IRTransformLayer.h | 80 +- .../llvm/ExecutionEngine/Orc/IndirectionUtils.h | 55 +- .../llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h | 49 +- .../llvm/ExecutionEngine/Orc/LambdaResolver.h | 84 - .../llvm/include/llvm/ExecutionEngine/Orc/Layer.h | 42 +- .../llvm/ExecutionEngine/Orc/LazyEmittingLayer.h | 267 - .../llvm/ExecutionEngine/Orc/LazyReexports.h | 17 +- .../llvm/include/llvm/ExecutionEngine/Orc/Legacy.h | 211 - .../llvm/ExecutionEngine/Orc/MachOPlatform.h | 20 +- .../llvm/ExecutionEngine/Orc/NullResolver.h | 43 - .../llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h | 57 +- .../ExecutionEngine/Orc/ObjectTransformLayer.h | 84 +- .../include/llvm/ExecutionEngine/Orc/OrcError.h | 74 - .../Orc/OrcRPCTargetProcessControl.h | 415 ++ .../ExecutionEngine/Orc/OrcRemoteTargetClient.h | 263 +- .../ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h | 280 +- .../ExecutionEngine/Orc/OrcRemoteTargetServer.h | 21 +- .../ExecutionEngine/Orc/RPC/RPCSerialization.h | 702 --- .../llvm/ExecutionEngine/Orc/RPC/RPCUtils.h | 1687 ------- .../llvm/ExecutionEngine/Orc/RPC/RawByteChannel.h | 184 - .../ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h | 387 +- .../llvm/ExecutionEngine/Orc/RemoteObjectLayer.h | 564 --- .../ExecutionEngine/Orc/Shared/FDRawByteChannel.h | 79 + .../llvm/ExecutionEngine/Orc/Shared/OrcError.h | 74 + .../llvm/ExecutionEngine/Orc/Shared/RPCUtils.h | 1657 +++++++ .../ExecutionEngine/Orc/Shared/RawByteChannel.h | 183 + .../ExecutionEngine/Orc/Shared/Serialization.h | 769 +++ .../Orc/Shared/TargetProcessControlTypes.h | 165 + .../include/llvm/ExecutionEngine/Orc/Speculation.h | 7 +- .../Orc/TPCDynamicLibrarySearchGenerator.h | 66 + .../llvm/ExecutionEngine/Orc/TPCEHFrameRegistrar.h | 54 + .../llvm/ExecutionEngine/Orc/TPCIndirectionUtils.h | 222 + .../Orc/TargetProcess/OrcRPCTPCServer.h | 620 +++ .../Orc/TargetProcess/RegisterEHFrames.h | 41 + .../Orc/TargetProcess/TargetExecutionUtils.h | 38 + .../ExecutionEngine/Orc/TargetProcessControl.h | 218 + .../llvm/ExecutionEngine/Orc/ThreadSafeModule.h | 2 +- .../include/llvm/ExecutionEngine/RuntimeDyld.h | 11 +- .../llvm/include/llvm/FileCheck/FileCheck.h | 216 + .../llvm/Frontend/Directive/DirectiveBase.td | 52 +- .../llvm/include/llvm/Frontend/OpenACC/ACC.td | 132 +- .../llvm/include/llvm/Frontend/OpenMP/OMP.td | 234 +- .../include/llvm/Frontend/OpenMP/OMPConstants.h | 44 +- .../llvm/include/llvm/Frontend/OpenMP/OMPContext.h | 49 +- .../include/llvm/Frontend/OpenMP/OMPGridValues.h | 22 +- .../include/llvm/Frontend/OpenMP/OMPIRBuilder.h | 402 +- .../llvm/include/llvm/Frontend/OpenMP/OMPKinds.def | 1046 ++-- .../llvm/include/llvm/FuzzMutate/IRMutator.h | 11 + .../llvm-project/llvm/include/llvm/IR/Argument.h | 27 +- .../llvm/include/llvm/IR/Assumptions.h | 50 + .../llvm-project/llvm/include/llvm/IR/Attributes.h | 78 +- .../llvm/include/llvm/IR/Attributes.td | 32 +- .../llvm-project/llvm/include/llvm/IR/BasicBlock.h | 88 +- .../llvm/include/llvm/IR/CallingConv.h | 3 + .../llvm-project/llvm/include/llvm/IR/Constant.h | 32 +- .../llvm/include/llvm/IR/ConstantRange.h | 26 +- .../llvm-project/llvm/include/llvm/IR/Constants.h | 99 +- .../llvm-project/llvm/include/llvm/IR/DIBuilder.h | 44 +- .../llvm-project/llvm/include/llvm/IR/DataLayout.h | 54 +- .../llvm/include/llvm/IR/DebugInfoMetadata.h | 238 +- .../llvm-project/llvm/include/llvm/IR/DebugLoc.h | 16 +- .../llvm/include/llvm/IR/DerivedTypes.h | 76 +- .../llvm/include/llvm/IR/DiagnosticInfo.h | 24 +- .../llvm-project/llvm/include/llvm/IR/Dominators.h | 30 +- .../llvm/include/llvm/IR/FixedMetadataKinds.def | 5 +- .../llvm/include/llvm/IR/FixedPointBuilder.h | 465 ++ .../llvm-project/llvm/include/llvm/IR/Function.h | 46 +- .../include/llvm/IR/GetElementPtrTypeIterator.h | 2 +- .../llvm/include/llvm/IR/GlobalObject.h | 69 +- .../llvm/include/llvm/IR/GlobalVariable.h | 9 +- .../llvm-project/llvm/include/llvm/IR/IRBuilder.h | 175 +- .../llvm/include/llvm/IR/IRPrintingPasses.h | 23 +- .../llvm-project/llvm/include/llvm/IR/InstrTypes.h | 149 +- .../llvm/include/llvm/IR/Instruction.h | 70 +- .../llvm/include/llvm/IR/Instructions.h | 78 +- .../llvm/include/llvm/IR/IntrinsicInst.h | 79 + .../llvm-project/llvm/include/llvm/IR/Intrinsics.h | 12 +- .../llvm/include/llvm/IR/Intrinsics.td | 696 +-- .../llvm/include/llvm/IR/IntrinsicsAArch64.td | 471 +- .../llvm/include/llvm/IR/IntrinsicsAMDGPU.td | 142 +- .../llvm/include/llvm/IR/IntrinsicsARM.td | 25 +- .../llvm/include/llvm/IR/IntrinsicsBPF.td | 10 +- .../llvm/include/llvm/IR/IntrinsicsNVVM.td | 113 +- .../llvm/include/llvm/IR/IntrinsicsPowerPC.td | 584 ++- .../llvm/include/llvm/IR/IntrinsicsRISCV.td | 1024 ++++ .../llvm/include/llvm/IR/IntrinsicsVE.td | 35 + .../llvm/include/llvm/IR/IntrinsicsVEVL.gen.td | 1213 +++++ .../llvm/include/llvm/IR/IntrinsicsWebAssembly.td | 196 +- .../llvm/include/llvm/IR/IntrinsicsX86.td | 153 +- .../llvm/include/llvm/IR/LLVMContext.h | 16 +- .../llvm/include/llvm/IR/LLVMRemarkStreamer.h | 11 +- .../llvm/include/llvm/IR/LegacyPassManagers.h | 5 +- .../llvm-project/llvm/include/llvm/IR/MDBuilder.h | 5 +- .../llvm/include/llvm/IR/MatrixBuilder.h | 39 +- .../llvm-project/llvm/include/llvm/IR/Metadata.def | 2 + .../llvm-project/llvm/include/llvm/IR/Metadata.h | 48 +- contrib/llvm-project/llvm/include/llvm/IR/Module.h | 7 +- .../llvm/include/llvm/IR/ModuleSummaryIndex.h | 14 +- .../llvm-project/llvm/include/llvm/IR/Operator.h | 5 + .../llvm-project/llvm/include/llvm/IR/OptBisect.h | 20 +- .../llvm/include/llvm/IR/PassInstrumentation.h | 117 +- .../llvm/include/llvm/IR/PassManager.h | 138 +- .../llvm/include/llvm/IR/PassManagerImpl.h | 7 - .../llvm/include/llvm/IR/PassManagerInternal.h | 22 + .../llvm/include/llvm/IR/PassTimingInfo.h | 15 +- .../llvm/include/llvm/IR/PatternMatch.h | 272 +- .../llvm/include/llvm/IR/PredIteratorCache.h | 4 +- .../llvm/include/llvm/IR/PrintPasses.h | 44 + .../llvm/include/llvm/IR/PseudoProbe.h | 87 + .../llvm/include/llvm/IR/ReplaceConstant.h | 28 + .../llvm/include/llvm/IR/RuntimeLibcalls.def | 32 +- .../llvm-project/llvm/include/llvm/IR/Statepoint.h | 50 +- .../llvm/include/llvm/IR/StructuralHash.h | 34 + .../llvm/include/llvm/IR/SymbolTableListTraits.h | 8 +- contrib/llvm-project/llvm/include/llvm/IR/Type.h | 32 +- contrib/llvm-project/llvm/include/llvm/IR/User.h | 2 +- .../llvm/include/llvm/IR/VPIntrinsics.def | 140 +- .../llvm-project/llvm/include/llvm/IR/Value.def | 18 + contrib/llvm-project/llvm/include/llvm/IR/Value.h | 104 +- .../llvm/include/llvm/IR/ValueHandle.h | 26 +- .../llvm-project/llvm/include/llvm/IR/Verifier.h | 2 + .../llvm/include/llvm/InitializePasses.h | 63 +- .../include/llvm/InterfaceStub/ELFObjHandler.h | 47 + .../llvm/include/llvm/InterfaceStub/ELFStub.h | 66 + .../llvm/include/llvm/InterfaceStub/TBEHandler.h | 43 + .../llvm-project/llvm/include/llvm/LTO/Config.h | 29 +- contrib/llvm-project/llvm/include/llvm/LTO/LTO.h | 12 +- .../llvm/include/llvm/LTO/LTOBackend.h | 25 +- .../include/llvm/LTO/legacy/LTOCodeGenerator.h | 18 +- .../llvm/include/llvm/LTO/legacy/LTOModule.h | 2 - .../llvm-project/llvm/include/llvm/LinkAllPasses.h | 10 +- .../llvm/include/llvm/MC/MCAsmBackend.h | 8 +- .../llvm-project/llvm/include/llvm/MC/MCAsmInfo.h | 50 +- .../llvm-project/llvm/include/llvm/MC/MCAsmMacro.h | 6 + .../llvm/include/llvm/MC/MCAssembler.h | 8 +- .../llvm-project/llvm/include/llvm/MC/MCCodeView.h | 2 - .../llvm-project/llvm/include/llvm/MC/MCContext.h | 31 +- .../llvm-project/llvm/include/llvm/MC/MCDwarf.h | 11 +- .../llvm/include/llvm/MC/MCELFObjectWriter.h | 1 - contrib/llvm-project/llvm/include/llvm/MC/MCExpr.h | 32 +- .../llvm-project/llvm/include/llvm/MC/MCFixup.h | 1 - .../llvm-project/llvm/include/llvm/MC/MCFragment.h | 52 + contrib/llvm-project/llvm/include/llvm/MC/MCInst.h | 2 +- .../llvm/include/llvm/MC/MCInstPrinter.h | 12 + .../llvm/include/llvm/MC/MCInstrDesc.h | 31 +- .../llvm/include/llvm/MC/MCMachObjectWriter.h | 14 +- .../llvm/include/llvm/MC/MCObjectFileInfo.h | 17 +- .../llvm/include/llvm/MC/MCObjectStreamer.h | 2 + .../llvm/include/llvm/MC/MCParser/AsmLexer.h | 1 + .../llvm/include/llvm/MC/MCParser/MCAsmLexer.h | 22 +- .../llvm/include/llvm/MC/MCParser/MCAsmParser.h | 30 +- .../include/llvm/MC/MCParser/MCTargetAsmParser.h | 3 +- .../llvm/include/llvm/MC/MCPseudoProbe.h | 178 + .../llvm-project/llvm/include/llvm/MC/MCRegister.h | 25 +- .../llvm/include/llvm/MC/MCRegisterInfo.h | 1 + .../llvm-project/llvm/include/llvm/MC/MCSchedule.h | 2 +- .../llvm/include/llvm/MC/MCSectionXCOFF.h | 18 +- .../llvm-project/llvm/include/llvm/MC/MCStreamer.h | 51 +- .../llvm/include/llvm/MC/MCSubtargetInfo.h | 24 +- .../llvm-project/llvm/include/llvm/MC/MCSymbol.h | 5 +- .../llvm/include/llvm/MC/MCSymbolWasm.h | 18 + .../llvm/include/llvm/MC/MCSymbolXCOFF.h | 4 - .../llvm/include/llvm/MC/MCTargetOptions.h | 1 + .../llvm/include/llvm/MC/MCWasmObjectWriter.h | 4 + .../llvm/include/llvm/MC/MCWasmStreamer.h | 4 - .../llvm-project/llvm/include/llvm/MC/MCWin64EH.h | 7 +- .../llvm/include/llvm/MC/MCWinCOFFStreamer.h | 1 + .../llvm-project/llvm/include/llvm/MC/MCWinEH.h | 24 +- .../llvm/include/llvm/MC/StringTableBuilder.h | 12 +- .../llvm/include/llvm/MC/SubtargetFeature.h | 2 +- .../include/llvm/MCA/HardwareUnits/Scheduler.h | 6 +- .../llvm/include/llvm/Object/ArchiveWriter.h | 6 + .../llvm-project/llvm/include/llvm/Object/Binary.h | 13 +- .../llvm-project/llvm/include/llvm/Object/COFF.h | 23 +- .../llvm-project/llvm/include/llvm/Object/ELF.h | 736 ++- .../llvm/include/llvm/Object/ELFObjectFile.h | 294 +- .../llvm/include/llvm/Object/ELFTypes.h | 30 +- .../llvm-project/llvm/include/llvm/Object/MachO.h | 1 + .../llvm/include/llvm/Object/MachOUniversal.h | 8 + .../include/llvm/Object/MachOUniversalWriter.h | 102 + .../llvm/include/llvm/Object/ObjectFile.h | 6 +- .../llvm/include/llvm/Object/RelocationResolver.h | 10 +- .../llvm/include/llvm/Object/StackMapParser.h | 24 +- .../llvm/include/llvm/Object/SymbolicFile.h | 6 +- .../llvm-project/llvm/include/llvm/Object/Wasm.h | 20 +- .../llvm/include/llvm/Object/WasmTraits.h | 68 - .../llvm/include/llvm/Object/XCOFFObjectFile.h | 101 + .../llvm/include/llvm/ObjectYAML/ArchiveYAML.h | 77 + .../llvm/include/llvm/ObjectYAML/DWARFEmitter.h | 16 +- .../llvm/include/llvm/ObjectYAML/DWARFYAML.h | 197 +- .../llvm/include/llvm/ObjectYAML/ELFYAML.h | 332 +- .../llvm/include/llvm/ObjectYAML/MachOYAML.h | 2 +- .../llvm/include/llvm/ObjectYAML/MinidumpYAML.h | 2 +- .../llvm/include/llvm/ObjectYAML/ObjectYAML.h | 2 + .../llvm/include/llvm/ObjectYAML/WasmYAML.h | 3 + .../llvm/include/llvm/ObjectYAML/yaml2obj.h | 5 + .../llvm/include/llvm/Option/ArgList.h | 4 + .../llvm/include/llvm/Option/OptParser.td | 93 +- .../llvm/include/llvm/Option/OptTable.h | 28 +- .../llvm-project/llvm/include/llvm/Option/Option.h | 14 +- contrib/llvm-project/llvm/include/llvm/Pass.h | 20 + .../llvm/include/llvm/PassAnalysisSupport.h | 24 +- .../llvm/include/llvm/Passes/PassBuilder.h | 188 +- .../include/llvm/Passes/StandardInstrumentations.h | 232 +- .../llvm/ProfileData/Coverage/CoverageMapping.h | 70 +- .../ProfileData/Coverage/CoverageMappingReader.h | 4 +- .../llvm/include/llvm/ProfileData/GCOV.h | 184 +- .../llvm/include/llvm/ProfileData/InstrProf.h | 40 +- .../include/llvm/ProfileData/InstrProfData.inc | 139 +- .../include/llvm/ProfileData/InstrProfReader.h | 26 +- .../include/llvm/ProfileData/InstrProfWriter.h | 6 +- .../llvm/include/llvm/ProfileData/ProfileCommon.h | 7 +- .../llvm/include/llvm/ProfileData/SampleProf.h | 325 +- .../include/llvm/ProfileData/SampleProfReader.h | 164 +- .../include/llvm/ProfileData/SampleProfWriter.h | 197 +- .../include/llvm/Remarks/BitstreamRemarkParser.h | 6 +- .../include/llvm/Remarks/HotnessThresholdParser.h | 63 + .../include/llvm/Support/AArch64TargetParser.def | 35 + .../include/llvm/Support/AArch64TargetParser.h | 8 +- .../llvm/include/llvm/Support/AMDGPUMetadata.h | 3 +- .../include/llvm/Support/AMDHSAKernelDescriptor.h | 72 +- .../llvm/include/llvm/Support/ARMTargetParser.def | 15 +- .../llvm/include/llvm/Support/ARMTargetParser.h | 3 +- .../llvm/include/llvm/Support/ARMWinEH.h | 87 +- .../llvm/include/llvm/Support/AlignOf.h | 35 +- .../llvm/include/llvm/Support/Allocator.h | 25 +- .../llvm/include/llvm/Support/AtomicOrdering.h | 30 +- .../llvm/include/llvm/Support/BinaryItemStream.h | 3 +- .../llvm/include/llvm/Support/BinaryStreamRef.h | 8 +- .../llvm/include/llvm/Support/CFGDiff.h | 225 +- .../llvm/include/llvm/Support/CFGUpdate.h | 1 - .../llvm/include/llvm/Support/CheckedArithmetic.h | 4 +- .../llvm/include/llvm/Support/CommandLine.h | 32 +- .../llvm/include/llvm/Support/Compiler.h | 24 +- .../include/llvm/Support/CrashRecoveryContext.h | 12 +- .../llvm/include/llvm/Support/DOTGraphTraits.h | 3 +- .../llvm-project/llvm/include/llvm/Support/Error.h | 8 +- .../llvm/include/llvm/Support/ErrorHandling.h | 6 +- .../llvm/include/llvm/Support/ErrorOr.h | 6 +- .../llvm/include/llvm/Support/ExitCodes.h | 33 + .../llvm/include/llvm/Support/FileCheck.h | 191 - .../llvm/include/llvm/Support/FileCollector.h | 78 +- .../llvm/include/llvm/Support/FileSystem.h | 88 +- .../include/llvm/Support/FileSystem/UniqueID.h | 52 + .../llvm/include/llvm/Support/FormatVariadic.h | 4 +- .../llvm/include/llvm/Support/GenericDomTree.h | 62 +- .../llvm/Support/GenericDomTreeConstruction.h | 293 +- .../llvm/include/llvm/Support/GlobPattern.h | 10 + .../llvm/include/llvm/Support/GraphWriter.h | 8 +- .../llvm-project/llvm/include/llvm/Support/Host.h | 14 + .../llvm/include/llvm/Support/InitLLVM.h | 3 +- .../llvm/include/llvm/Support/InstructionCost.h | 238 + .../llvm-project/llvm/include/llvm/Support/JSON.h | 205 +- .../llvm/include/llvm/Support/KnownBits.h | 145 +- .../llvm/include/llvm/Support/LineIterator.h | 8 +- .../llvm/include/llvm/Support/MachineValueType.h | 342 +- .../llvm/include/llvm/Support/MathExtras.h | 2 +- .../llvm/include/llvm/Support/MemoryBuffer.h | 24 +- .../llvm/include/llvm/Support/MemoryBufferRef.h | 56 + .../llvm/include/llvm/Support/Parallel.h | 104 +- .../llvm-project/llvm/include/llvm/Support/Path.h | 38 + .../llvm/include/llvm/Support/PluginLoader.h | 4 + .../llvm/include/llvm/Support/Process.h | 10 +- .../llvm/include/llvm/Support/Program.h | 16 +- .../include/llvm/Support/RISCVTargetParser.def | 14 + .../llvm/include/llvm/Support/Signals.h | 6 +- .../llvm/include/llvm/Support/Signposts.h | 11 +- .../llvm/include/llvm/Support/SourceMgr.h | 5 + .../llvm/include/llvm/Support/SuffixTree.h | 4 +- .../llvm/include/llvm/Support/SwapByteOrder.h | 2 +- .../include/llvm/Support/SymbolRemappingReader.h | 2 +- .../llvm/include/llvm/Support/TargetOpcodes.def | 77 +- .../llvm/include/llvm/Support/TargetParser.h | 25 +- .../llvm/include/llvm/Support/TargetRegistry.h | 2 + .../llvm/include/llvm/Support/TaskQueue.h | 2 +- .../llvm/include/llvm/Support/Threading.h | 12 +- .../llvm/include/llvm/Support/ToolOutputFile.h | 4 + .../llvm/include/llvm/Support/TrigramIndex.h | 4 +- .../llvm/include/llvm/Support/TypeSize.h | 531 +- .../llvm/include/llvm/Support/VirtualFileSystem.h | 31 +- .../llvm/include/llvm/Support/Win64EH.h | 8 +- .../llvm/include/llvm/Support/X86TargetParser.def | 9 + .../llvm/include/llvm/Support/X86TargetParser.h | 19 +- .../llvm/include/llvm/Support/YAMLParser.h | 13 +- .../llvm/include/llvm/Support/YAMLTraits.h | 92 +- .../llvm/include/llvm/Support/raw_ostream.h | 114 +- .../llvm/include/llvm/TableGen/DirectiveEmitter.h | 211 + .../llvm/include/llvm/TableGen/Error.h | 19 +- .../llvm/include/llvm/TableGen/Record.h | 362 +- .../llvm/include/llvm/TableGen/SearchableTable.td | 26 +- .../llvm/include/llvm/Target/CGPassBuilderOption.h | 65 + .../llvm/include/llvm/Target/GenericOpcodes.td | 602 ++- .../llvm/include/llvm/Target/GlobalISel/Combine.td | 353 +- .../llvm/Target/GlobalISel/SelectionDAGCompat.td | 34 +- .../llvm/include/llvm/Target/Target.td | 396 +- .../llvm/include/llvm/Target/TargetCallingConv.td | 6 +- .../include/llvm/Target/TargetInstrPredicate.td | 27 +- .../llvm/include/llvm/Target/TargetItinerary.td | 2 +- .../include/llvm/Target/TargetLoweringObjectFile.h | 36 +- .../llvm/include/llvm/Target/TargetMachine.h | 70 +- .../llvm/include/llvm/Target/TargetOptions.h | 67 +- .../llvm/include/llvm/Target/TargetPfmCounters.td | 2 + .../llvm/include/llvm/Target/TargetSchedule.td | 28 +- .../llvm/include/llvm/Target/TargetSelectionDAG.td | 271 +- .../include/llvm/Testing/Support/SupportHelpers.h | 138 + .../llvm/include/llvm/TextAPI/ELF/ELFStub.h | 68 - .../llvm/include/llvm/TextAPI/ELF/TBEHandler.h | 43 - .../llvm/include/llvm/TextAPI/MachO/Platform.h | 5 +- .../AggressiveInstCombine/AggressiveInstCombine.h | 1 - .../llvm/include/llvm/Transforms/Coroutines.h | 2 +- .../llvm/Transforms/Coroutines/CoroCleanup.h | 1 + .../include/llvm/Transforms/Coroutines/CoroEarly.h | 1 + .../include/llvm/Transforms/Coroutines/CoroElide.h | 1 + .../include/llvm/Transforms/Coroutines/CoroSplit.h | 5 + .../include/llvm/Transforms/HelloNew/HelloWorld.h | 23 + .../llvm/include/llvm/Transforms/IPO.h | 18 +- .../include/llvm/Transforms/IPO/AlwaysInliner.h | 1 + .../llvm/Transforms/IPO/Annotation2Metadata.h | 30 + .../llvm/include/llvm/Transforms/IPO/Attributor.h | 658 ++- .../include/llvm/Transforms/IPO/BlockExtractor.h | 25 + .../llvm/Transforms/IPO/CalledValuePropagation.h | 1 - .../llvm/include/llvm/Transforms/IPO/CrossDSOCFI.h | 1 - .../llvm/Transforms/IPO/ForceFunctionAttrs.h | 1 - .../llvm/include/llvm/Transforms/IPO/IROutliner.h | 358 ++ .../llvm/include/llvm/Transforms/IPO/Inliner.h | 14 +- .../include/llvm/Transforms/IPO/LoopExtractor.h | 32 + .../include/llvm/Transforms/IPO/LowerTypeTests.h | 10 +- .../llvm/include/llvm/Transforms/IPO/OpenMPOpt.h | 10 + .../llvm/Transforms/IPO/SampleContextTracker.h | 152 + .../include/llvm/Transforms/IPO/SampleProfile.h | 9 +- .../llvm/Transforms/IPO/SampleProfileProbe.h | 147 + .../include/llvm/Transforms/IPO/StripSymbols.h | 47 + .../llvm/Transforms/IPO/WholeProgramDevirt.h | 3 + .../llvm/Transforms/InstCombine/InstCombiner.h | 528 ++ .../llvm/include/llvm/Transforms/Instrumentation.h | 8 +- .../Transforms/Instrumentation/AddressSanitizer.h | 2 + .../Transforms/Instrumentation/BoundsChecking.h | 1 + .../Transforms/Instrumentation/DataFlowSanitizer.h | 32 + .../llvm/Transforms/Instrumentation/GCOVProfiler.h | 2 +- .../Instrumentation/HWAddressSanitizer.h | 19 + .../Transforms/Instrumentation/InstrProfiling.h | 5 - .../llvm/Transforms/Instrumentation/MemProfiler.h | 51 + .../Transforms/Instrumentation/MemorySanitizer.h | 1 + .../Transforms/Instrumentation/SanitizerCoverage.h | 1 + .../Transforms/Instrumentation/ThreadSanitizer.h | 1 + .../llvm/include/llvm/Transforms/ObjCARC.h | 18 + .../llvm/include/llvm/Transforms/Scalar.h | 67 +- .../Transforms/Scalar/AlignmentFromAssumptions.h | 6 +- .../llvm/Transforms/Scalar/AnnotationRemarks.h | 26 + .../llvm/Transforms/Scalar/ConstantHoisting.h | 1 - .../llvm/Transforms/Scalar/ConstraintElimination.h | 24 + .../llvm/include/llvm/Transforms/Scalar/DCE.h | 6 + .../llvm/include/llvm/Transforms/Scalar/GVN.h | 15 +- .../llvm/Transforms/Scalar/IndVarSimplify.h | 4 + .../llvm/Transforms/Scalar/InferAddressSpaces.h | 27 + .../llvm/Transforms/Scalar/InstSimplifyPass.h | 4 - .../include/llvm/Transforms/Scalar/JumpThreading.h | 71 +- .../include/llvm/Transforms/Scalar/LoopFlatten.h | 32 + .../llvm/Transforms/Scalar/LoopIdiomRecognize.h | 13 + .../llvm/Transforms/Scalar/LoopInterchange.h | 24 + .../llvm/Transforms/Scalar/LoopPassManager.h | 414 +- .../include/llvm/Transforms/Scalar/LoopReroll.h | 27 + .../include/llvm/Transforms/Scalar/LoopRotation.h | 4 +- .../llvm/Transforms/Scalar/LoopUnrollPass.h | 2 +- .../llvm/Transforms/Scalar/LoopVersioningLICM.h | 25 + .../include/llvm/Transforms/Scalar/LowerAtomic.h | 1 + .../llvm/Transforms/Scalar/LowerExpectIntrinsic.h | 3 + .../llvm/Transforms/Scalar/LowerMatrixIntrinsics.h | 8 +- .../llvm/Transforms/Scalar/MemCpyOptimizer.h | 29 +- .../llvm/Transforms/Scalar/NaryReassociate.h | 2 +- .../llvm/include/llvm/Transforms/Scalar/Reg2Mem.h | 27 + .../llvm/include/llvm/Transforms/Scalar/SROA.h | 5 +- .../Transforms/Scalar/ScalarizeMaskedMemIntrin.h | 29 + .../Transforms/Scalar/SeparateConstOffsetFromGEP.h | 27 + .../include/llvm/Transforms/Scalar/SimplifyCFG.h | 10 +- .../Transforms/Scalar/StraightLineStrengthReduce.h | 24 + .../llvm/Transforms/Scalar/StructurizeCFG.h | 20 + .../llvm/include/llvm/Transforms/Utils.h | 2 +- .../llvm/Transforms/Utils/BasicBlockUtils.h | 129 +- .../include/llvm/Transforms/Utils/BuildLibCalls.h | 4 + .../llvm/Transforms/Utils/CallGraphUpdater.h | 2 +- .../llvm/include/llvm/Transforms/Utils/Cloning.h | 43 + .../llvm/include/llvm/Transforms/Utils/Debugify.h | 65 +- .../include/llvm/Transforms/Utils/FixIrreducible.h | 20 + .../Utils/ImportedFunctionsInliningStatistics.h | 106 - .../llvm/Transforms/Utils/InstructionNamer.h | 20 + .../llvm/include/llvm/Transforms/Utils/Local.h | 118 +- .../llvm/include/llvm/Transforms/Utils/LoopPeel.h | 40 + .../llvm/Transforms/Utils/LoopRotationUtils.h | 3 +- .../llvm/include/llvm/Transforms/Utils/LoopUtils.h | 105 +- .../include/llvm/Transforms/Utils/LoopVersioning.h | 24 +- .../include/llvm/Transforms/Utils/LowerSwitch.h | 26 + .../include/llvm/Transforms/Utils/MatrixUtils.h | 94 + .../include/llvm/Transforms/Utils/MetaRenamer.h | 26 + .../llvm/include/llvm/Transforms/Utils/MisExpect.h | 43 - .../include/llvm/Transforms/Utils/PredicateInfo.h | 34 +- .../Transforms/Utils/ScalarEvolutionExpander.h | 792 +-- .../llvm/Transforms/Utils/SimplifyCFGOptions.h | 77 + .../include/llvm/Transforms/Utils/SimplifyIndVar.h | 23 + .../llvm/Transforms/Utils/SimplifyLibCalls.h | 2 +- .../llvm/include/llvm/Transforms/Utils/SizeOpts.h | 11 - .../llvm/Transforms/Utils/StripGCRelocates.h | 25 + .../Transforms/Utils/StripNonLineTableDebugInfo.h | 26 + .../llvm/Transforms/Utils/UnifyFunctionExitNodes.h | 27 +- .../include/llvm/Transforms/Utils/UnifyLoopExits.h | 22 + .../include/llvm/Transforms/Utils/UnrollLoop.h | 17 - .../Vectorize/LoopVectorizationLegality.h | 74 +- .../llvm/Transforms/Vectorize/SLPVectorizer.h | 7 +- .../llvm/include/llvm/module.modulemap | 20 +- .../llvm/lib/Analysis/AliasAnalysis.cpp | 100 +- .../llvm/lib/Analysis/AliasAnalysisEvaluator.cpp | 6 +- .../llvm/lib/Analysis/AliasSetTracker.cpp | 39 +- .../llvm-project/llvm/lib/Analysis/Analysis.cpp | 7 +- .../llvm/lib/Analysis/AssumeBundleQueries.cpp | 18 +- .../llvm/lib/Analysis/AssumptionCache.cpp | 21 +- .../llvm/lib/Analysis/BasicAliasAnalysis.cpp | 875 ++-- .../llvm/lib/Analysis/BranchProbabilityInfo.cpp | 914 ++-- contrib/llvm-project/llvm/lib/Analysis/CFG.cpp | 15 +- .../llvm-project/llvm/lib/Analysis/CFGPrinter.cpp | 12 +- .../llvm/lib/Analysis/CFLAndersAliasAnalysis.cpp | 3 +- .../llvm/lib/Analysis/CGSCCPassManager.cpp | 558 ++- .../llvm-project/llvm/lib/Analysis/CallGraph.cpp | 48 +- .../llvm/lib/Analysis/CallGraphSCCPass.cpp | 33 +- .../llvm-project/llvm/lib/Analysis/CallPrinter.cpp | 5 +- .../llvm/lib/Analysis/CaptureTracking.cpp | 105 +- .../llvm-project/llvm/lib/Analysis/CodeMetrics.cpp | 15 +- .../llvm/lib/Analysis/ConstantFolding.cpp | 335 +- .../llvm/lib/Analysis/ConstraintSystem.cpp | 158 + .../llvm-project/llvm/lib/Analysis/CostModel.cpp | 13 +- contrib/llvm-project/llvm/lib/Analysis/DDG.cpp | 8 +- .../llvm-project/llvm/lib/Analysis/DDGPrinter.cpp | 150 + .../llvm/lib/Analysis/Delinearization.cpp | 48 +- .../llvm/lib/Analysis/DemandedBits.cpp | 107 +- .../llvm/lib/Analysis/DependenceAnalysis.cpp | 79 +- .../llvm/lib/Analysis/DependenceGraphBuilder.cpp | 137 +- .../lib/Analysis/DevelopmentModeInlineAdvisor.cpp | 531 ++ .../llvm/lib/Analysis/DivergenceAnalysis.cpp | 342 +- .../llvm/lib/Analysis/DomTreeUpdater.cpp | 5 +- .../llvm/lib/Analysis/EHPersonalities.cpp | 38 +- .../lib/Analysis/FunctionPropertiesAnalysis.cpp | 88 + .../llvm/lib/Analysis/GlobalsModRef.cpp | 39 +- .../llvm/lib/Analysis/IRSimilarityIdentifier.cpp | 937 ++++ .../llvm/lib/Analysis/IVDescriptors.cpp | 350 +- .../ImportedFunctionsInliningStatistics.cpp | 212 + .../lib/Analysis/IndirectCallPromotionAnalysis.cpp | 4 +- .../llvm/lib/Analysis/InlineAdvisor.cpp | 190 +- .../llvm-project/llvm/lib/Analysis/InlineCost.cpp | 263 +- .../llvm/lib/Analysis/InlineFeaturesAnalysis.cpp | 41 - .../lib/Analysis/InlineSizeEstimatorAnalysis.cpp | 142 +- .../llvm-project/llvm/lib/Analysis/InstCount.cpp | 87 +- .../llvm/lib/Analysis/InstructionSimplify.cpp | 1238 +++-- .../llvm-project/llvm/lib/Analysis/Interval.cpp | 11 - .../llvm/lib/Analysis/LazyCallGraph.cpp | 297 +- .../llvm/lib/Analysis/LazyValueInfo.cpp | 342 +- .../llvm/lib/Analysis/LegacyDivergenceAnalysis.cpp | 6 +- contrib/llvm-project/llvm/lib/Analysis/Lint.cpp | 399 +- contrib/llvm-project/llvm/lib/Analysis/Loads.cpp | 69 +- .../llvm/lib/Analysis/LoopAccessAnalysis.cpp | 106 +- .../llvm/lib/Analysis/LoopAnalysisManager.cpp | 1 + .../llvm/lib/Analysis/LoopCacheAnalysis.cpp | 17 +- .../llvm-project/llvm/lib/Analysis/LoopInfo.cpp | 32 +- .../llvm/lib/Analysis/LoopNestAnalysis.cpp | 136 +- .../llvm-project/llvm/lib/Analysis/LoopPass.cpp | 22 +- .../llvm/lib/Analysis/MLInlineAdvisor.cpp | 65 +- .../llvm/lib/Analysis/MemDepPrinter.cpp | 4 +- .../llvm/lib/Analysis/MemDerefPrinter.cpp | 34 + .../llvm/lib/Analysis/MemoryBuiltins.cpp | 27 +- .../llvm/lib/Analysis/MemoryDependenceAnalysis.cpp | 63 +- .../llvm/lib/Analysis/MemoryLocation.cpp | 86 +- .../llvm-project/llvm/lib/Analysis/MemorySSA.cpp | 248 +- .../llvm/lib/Analysis/MemorySSAUpdater.cpp | 102 +- .../llvm/lib/Analysis/ModuleDebugInfoPrinter.cpp | 56 +- .../llvm/lib/Analysis/ModuleSummaryAnalysis.cpp | 4 +- .../llvm-project/llvm/lib/Analysis/MustExecute.cpp | 98 +- .../llvm/lib/Analysis/ObjCARCAliasAnalysis.cpp | 15 +- .../llvm/lib/Analysis/ObjCARCAnalysisUtils.cpp | 20 + .../llvm/lib/Analysis/ObjCARCInstKind.cpp | 1 - .../lib/Analysis/OptimizationRemarkEmitter.cpp | 30 +- .../llvm-project/llvm/lib/Analysis/PhiValues.cpp | 1 - .../llvm-project/llvm/lib/Analysis/RegionInfo.cpp | 3 - .../llvm-project/llvm/lib/Analysis/RegionPass.cpp | 72 +- .../llvm/lib/Analysis/ReleaseModeModelRunner.cpp | 7 +- .../llvm/lib/Analysis/ReplayInlineAdvisor.cpp | 82 + .../llvm/lib/Analysis/ScalarEvolution.cpp | 2002 +++++--- .../lib/Analysis/ScalarEvolutionAliasAnalysis.cpp | 6 +- .../llvm/lib/Analysis/ScalarEvolutionDivision.cpp | 12 +- .../llvm/lib/Analysis/ScopedNoAliasAA.cpp | 28 +- .../llvm/lib/Analysis/StackLifetime.cpp | 83 +- .../llvm/lib/Analysis/StackSafetyAnalysis.cpp | 256 +- .../llvm/lib/Analysis/SyncDependenceAnalysis.cpp | 469 +- contrib/llvm-project/llvm/lib/Analysis/TFUtils.cpp | 338 +- .../llvm/lib/Analysis/TargetLibraryInfo.cpp | 38 +- .../llvm/lib/Analysis/TargetTransformInfo.cpp | 168 +- .../llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp | 82 + .../llvm/lib/Analysis/VFABIDemangling.cpp | 10 +- .../llvm/lib/Analysis/ValueTracking.cpp | 1485 +++--- .../llvm-project/llvm/lib/Analysis/VectorUtils.cpp | 77 +- .../llvm/lib/Analysis/models/inliner/README.txt | 3 + .../lib/Analysis/models/inliner/output_spec.json | 14 + .../llvm-project/llvm/lib/AsmParser/LLLexer.cpp | 8 + .../llvm-project/llvm/lib/AsmParser/LLParser.cpp | 3734 +++++++------- contrib/llvm-project/llvm/lib/AsmParser/LLParser.h | 444 +- contrib/llvm-project/llvm/lib/AsmParser/LLToken.h | 7 + .../llvm-project/llvm/lib/BinaryFormat/Dwarf.cpp | 25 + .../llvm-project/llvm/lib/BinaryFormat/MachO.cpp | 8 +- .../llvm/lib/BinaryFormat/MsgPackDocument.cpp | 3 +- .../llvm-project/llvm/lib/BinaryFormat/Wasm.cpp | 4 + .../llvm-project/llvm/lib/BinaryFormat/XCOFF.cpp | 78 + .../llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp | 5 + .../llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 291 +- .../llvm/lib/Bitcode/Reader/MetadataLoader.cpp | 192 +- .../llvm/lib/Bitcode/Reader/ValueList.cpp | 3 - .../llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 223 +- .../llvm/lib/Bitcode/Writer/ValueEnumerator.cpp | 37 +- .../llvm/lib/Bitstream/Reader/BitstreamReader.cpp | 12 +- .../llvm/lib/CodeGen/AllocationOrder.cpp | 17 +- .../llvm/lib/CodeGen/AllocationOrder.h | 128 +- contrib/llvm-project/llvm/lib/CodeGen/Analysis.cpp | 61 +- .../llvm/lib/CodeGen/AsmPrinter/AIXException.cpp | 79 + .../llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp | 14 +- .../llvm/lib/CodeGen/AsmPrinter/AddressPool.cpp | 4 +- .../llvm/lib/CodeGen/AsmPrinter/AddressPool.h | 2 +- .../llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 589 ++- .../lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp | 49 +- .../lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp | 42 +- .../llvm/lib/CodeGen/AsmPrinter/ByteStreamer.h | 8 +- .../llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 176 +- .../llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h | 11 +- .../llvm/lib/CodeGen/AsmPrinter/DIE.cpp | 90 +- .../llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp | 11 +- .../llvm/lib/CodeGen/AsmPrinter/DIEHash.h | 4 +- .../AsmPrinter/DbgEntityHistoryCalculator.cpp | 185 +- .../lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp | 76 +- .../lib/CodeGen/AsmPrinter/DwarfCFIException.cpp | 7 +- .../lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 86 +- .../llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h | 12 +- .../llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 482 +- .../llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h | 64 +- .../llvm/lib/CodeGen/AsmPrinter/DwarfException.h | 14 + .../lib/CodeGen/AsmPrinter/DwarfExpression.cpp | 46 +- .../llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h | 14 +- .../llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp | 12 +- .../llvm/lib/CodeGen/AsmPrinter/DwarfFile.h | 3 +- .../lib/CodeGen/AsmPrinter/DwarfStringPool.cpp | 10 +- .../llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.h | 2 +- .../llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 282 +- .../llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h | 34 +- .../llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp | 397 +- .../llvm/lib/CodeGen/AsmPrinter/EHStreamer.h | 43 +- .../llvm/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp | 7 +- .../lib/CodeGen/AsmPrinter/PseudoProbePrinter.cpp | 84 + .../lib/CodeGen/AsmPrinter/PseudoProbePrinter.h | 53 + .../llvm/lib/CodeGen/AsmPrinter/WasmException.cpp | 11 +- .../llvm/lib/CodeGen/AsmPrinter/WasmException.h | 1 + .../llvm/lib/CodeGen/AsmPrinter/WinCFGuard.cpp | 53 +- .../llvm/lib/CodeGen/AsmPrinter/WinCFGuard.h | 1 + .../llvm/lib/CodeGen/AsmPrinter/WinException.cpp | 56 +- .../llvm/lib/CodeGen/AtomicExpandPass.cpp | 17 +- .../llvm/lib/CodeGen/BBSectionsPrepare.cpp | 457 -- .../llvm/lib/CodeGen/BasicBlockSections.cpp | 484 ++ .../llvm/lib/CodeGen/BranchFolding.cpp | 16 +- .../llvm-project/llvm/lib/CodeGen/BranchFolding.h | 3 +- .../llvm/lib/CodeGen/BranchRelaxation.cpp | 40 +- .../llvm/lib/CodeGen/BreakFalseDeps.cpp | 32 +- .../llvm/lib/CodeGen/CalcSpillWeights.cpp | 289 +- .../llvm/lib/CodeGen/CallingConvLower.cpp | 23 +- contrib/llvm-project/llvm/lib/CodeGen/CodeGen.cpp | 6 +- .../llvm/lib/CodeGen/CodeGenPassBuilder.cpp | 25 + .../llvm/lib/CodeGen/CodeGenPrepare.cpp | 387 +- .../llvm-project/llvm/lib/CodeGen/CommandFlags.cpp | 96 +- .../lib/CodeGen/DeadMachineInstructionElim.cpp | 21 +- .../llvm/lib/CodeGen/DetectDeadLanes.cpp | 5 +- .../llvm/lib/CodeGen/DwarfEHPrepare.cpp | 232 +- .../llvm/lib/CodeGen/EarlyIfConversion.cpp | 106 +- .../llvm/lib/CodeGen/ExpandReductions.cpp | 128 +- .../lib/CodeGen/FixupStatepointCallerSaved.cpp | 362 +- .../llvm/lib/CodeGen/GCRootLowering.cpp | 5 +- .../llvm/lib/CodeGen/GlobalISel/CSEInfo.cpp | 28 +- .../llvm/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp | 34 +- .../llvm/lib/CodeGen/GlobalISel/CallLowering.cpp | 624 ++- .../llvm/lib/CodeGen/GlobalISel/Combiner.cpp | 5 +- .../llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp | 2031 +++++++- .../lib/CodeGen/GlobalISel/GISelChangeObserver.cpp | 2 +- .../llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp | 249 +- .../llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 893 +++- .../lib/CodeGen/GlobalISel/InlineAsmLowering.cpp | 6 + .../lib/CodeGen/GlobalISel/InstructionSelect.cpp | 2 +- .../lib/CodeGen/GlobalISel/InstructionSelector.cpp | 14 +- .../lib/CodeGen/GlobalISel/LegalityPredicates.cpp | 24 +- .../lib/CodeGen/GlobalISel/LegalizeMutations.cpp | 10 + .../llvm/lib/CodeGen/GlobalISel/Legalizer.cpp | 2 +- .../lib/CodeGen/GlobalISel/LegalizerHelper.cpp | 1612 ++++-- .../llvm/lib/CodeGen/GlobalISel/LegalizerInfo.cpp | 6 +- .../llvm/lib/CodeGen/GlobalISel/Localizer.cpp | 23 + .../lib/CodeGen/GlobalISel/MachineIRBuilder.cpp | 145 +- .../lib/CodeGen/GlobalISel/RegisterBankInfo.cpp | 3 +- .../llvm/lib/CodeGen/GlobalISel/Utils.cpp | 390 +- .../llvm-project/llvm/lib/CodeGen/GlobalMerge.cpp | 5 +- .../llvm/lib/CodeGen/HardwareLoops.cpp | 51 +- .../llvm-project/llvm/lib/CodeGen/IfConversion.cpp | 7 +- .../llvm/lib/CodeGen/ImplicitNullChecks.cpp | 258 +- .../llvm/lib/CodeGen/InlineSpiller.cpp | 107 +- .../llvm/lib/CodeGen/InterferenceCache.cpp | 10 +- .../llvm/lib/CodeGen/InterferenceCache.h | 18 +- .../llvm/lib/CodeGen/InterleavedAccessPass.cpp | 119 +- .../lib/CodeGen/InterleavedLoadCombinePass.cpp | 17 +- .../llvm/lib/CodeGen/IntrinsicLowering.cpp | 1 + .../llvm/lib/CodeGen/LLVMTargetMachine.cpp | 63 +- .../llvm/lib/CodeGen/LexicalScopes.cpp | 2 +- .../llvm/lib/CodeGen/LiveDebugValues.cpp | 1976 -------- .../CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp | 3363 +++++++++++++ .../CodeGen/LiveDebugValues/LiveDebugValues.cpp | 97 + .../lib/CodeGen/LiveDebugValues/LiveDebugValues.h | 32 + .../CodeGen/LiveDebugValues/VarLocBasedImpl.cpp | 1994 ++++++++ .../llvm/lib/CodeGen/LiveDebugVariables.cpp | 71 +- .../llvm/lib/CodeGen/LiveDebugVariables.h | 1 - .../llvm-project/llvm/lib/CodeGen/LiveInterval.cpp | 23 +- .../llvm/lib/CodeGen/LiveIntervalCalc.cpp | 6 +- .../llvm/lib/CodeGen/LiveIntervalUnion.cpp | 16 +- .../llvm/lib/CodeGen/LiveIntervals.cpp | 79 +- .../llvm/lib/CodeGen/LiveRangeEdit.cpp | 29 +- .../llvm/lib/CodeGen/LiveRangeShrink.cpp | 3 +- .../llvm/lib/CodeGen/LiveRegMatrix.cpp | 52 +- .../llvm-project/llvm/lib/CodeGen/LiveRegUnits.cpp | 4 - .../llvm/lib/CodeGen/LiveVariables.cpp | 61 +- .../llvm/lib/CodeGen/LocalStackSlotAllocation.cpp | 11 +- .../llvm-project/llvm/lib/CodeGen/LowLevelType.cpp | 16 + .../llvm-project/llvm/lib/CodeGen/LowerEmuTLS.cpp | 3 +- .../llvm-project/llvm/lib/CodeGen/MBFIWrapper.cpp | 12 + .../llvm/lib/CodeGen/MIRCanonicalizerPass.cpp | 15 +- .../llvm/lib/CodeGen/MIRParser/MILexer.cpp | 11 +- .../llvm/lib/CodeGen/MIRParser/MILexer.h | 2 + .../llvm/lib/CodeGen/MIRParser/MIParser.cpp | 34 +- .../llvm/lib/CodeGen/MIRParser/MIRParser.cpp | 37 +- .../llvm-project/llvm/lib/CodeGen/MIRPrinter.cpp | 137 +- .../llvm/lib/CodeGen/MIRVRegNamerUtils.cpp | 14 + .../llvm/lib/CodeGen/MachineBasicBlock.cpp | 244 +- .../llvm/lib/CodeGen/MachineBlockFrequencyInfo.cpp | 15 +- .../llvm/lib/CodeGen/MachineBlockPlacement.cpp | 84 +- .../llvm-project/llvm/lib/CodeGen/MachineCSE.cpp | 48 +- .../llvm/lib/CodeGen/MachineCheckDebugify.cpp | 126 + .../llvm/lib/CodeGen/MachineCombiner.cpp | 72 +- .../llvm/lib/CodeGen/MachineCopyPropagation.cpp | 126 +- .../llvm/lib/CodeGen/MachineDebugify.cpp | 32 +- .../llvm/lib/CodeGen/MachineFunction.cpp | 125 +- .../llvm/lib/CodeGen/MachineFunctionPass.cpp | 1 - .../lib/CodeGen/MachineFunctionPrinterPass.cpp | 4 +- .../llvm/lib/CodeGen/MachineFunctionSplitter.cpp | 155 + .../llvm-project/llvm/lib/CodeGen/MachineInstr.cpp | 179 +- .../llvm-project/llvm/lib/CodeGen/MachineLICM.cpp | 169 +- .../llvm/lib/CodeGen/MachineLoopInfo.cpp | 56 + .../llvm/lib/CodeGen/MachineLoopUtils.cpp | 11 - .../llvm/lib/CodeGen/MachineModuleInfo.cpp | 27 +- .../llvm/lib/CodeGen/MachineOperand.cpp | 30 +- .../llvm/lib/CodeGen/MachineOutliner.cpp | 21 +- .../llvm/lib/CodeGen/MachinePassManager.cpp | 121 + .../llvm/lib/CodeGen/MachinePipeliner.cpp | 51 +- .../llvm/lib/CodeGen/MachineRegisterInfo.cpp | 25 +- .../llvm/lib/CodeGen/MachineSSAUpdater.cpp | 11 +- .../llvm/lib/CodeGen/MachineScheduler.cpp | 256 +- .../llvm-project/llvm/lib/CodeGen/MachineSink.cpp | 290 +- .../llvm/lib/CodeGen/MachineStableHash.cpp | 194 + .../llvm/lib/CodeGen/MachineTraceMetrics.cpp | 28 +- .../llvm/lib/CodeGen/MachineVerifier.cpp | 412 +- .../llvm/lib/CodeGen/ModuloSchedule.cpp | 2 - .../llvm/lib/CodeGen/MultiHazardRecognizer.cpp | 92 + .../llvm/lib/CodeGen/PHIElimination.cpp | 74 +- .../llvm/lib/CodeGen/PHIEliminationUtils.cpp | 2 +- .../llvm-project/llvm/lib/CodeGen/ParallelCG.cpp | 2 + .../llvm/lib/CodeGen/PeepholeOptimizer.cpp | 165 +- .../llvm/lib/CodeGen/PostRAHazardRecognizer.cpp | 8 +- .../llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp | 2 +- .../llvm/lib/CodeGen/PrologEpilogInserter.cpp | 40 +- .../llvm/lib/CodeGen/PseudoProbeInserter.cpp | 95 + contrib/llvm-project/llvm/lib/CodeGen/RDFGraph.cpp | 5 - .../llvm-project/llvm/lib/CodeGen/RDFLiveness.cpp | 151 +- .../llvm-project/llvm/lib/CodeGen/RDFRegisters.cpp | 35 +- .../llvm/lib/CodeGen/ReachingDefAnalysis.cpp | 186 +- .../llvm-project/llvm/lib/CodeGen/RegAllocBase.cpp | 34 +- .../llvm-project/llvm/lib/CodeGen/RegAllocBase.h | 4 +- .../llvm/lib/CodeGen/RegAllocBasic.cpp | 51 +- .../llvm-project/llvm/lib/CodeGen/RegAllocFast.cpp | 1486 +++--- .../llvm/lib/CodeGen/RegAllocGreedy.cpp | 537 +- .../llvm-project/llvm/lib/CodeGen/RegAllocPBQP.cpp | 117 +- .../llvm/lib/CodeGen/RegisterClassInfo.cpp | 13 +- .../llvm/lib/CodeGen/RegisterCoalescer.cpp | 270 +- .../llvm/lib/CodeGen/RegisterCoalescer.h | 14 +- .../llvm/lib/CodeGen/RegisterPressure.cpp | 80 +- .../llvm/lib/CodeGen/RegisterScavenging.cpp | 43 +- .../llvm/lib/CodeGen/RenameIndependentSubregs.cpp | 10 +- .../llvm-project/llvm/lib/CodeGen/SafeStack.cpp | 35 +- .../llvm/lib/CodeGen/SafeStackLayout.cpp | 9 +- .../llvm/lib/CodeGen/ScalarizeMaskedMemIntrin.cpp | 911 ---- .../llvm/lib/CodeGen/ScheduleDAGInstrs.cpp | 15 +- .../llvm/lib/CodeGen/ScheduleDAGPrinter.cpp | 2 +- .../llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 2396 +++++---- .../llvm/lib/CodeGen/SelectionDAG/FastISel.cpp | 257 +- .../CodeGen/SelectionDAG/FunctionLoweringInfo.cpp | 10 +- .../llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp | 103 +- .../llvm/lib/CodeGen/SelectionDAG/InstrEmitter.h | 12 +- .../llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 551 +- .../CodeGen/SelectionDAG/LegalizeFloatTypes.cpp | 289 +- .../CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp | 396 +- .../lib/CodeGen/SelectionDAG/LegalizeTypes.cpp | 17 +- .../llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h | 62 +- .../CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp | 11 +- .../lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp | 25 +- .../CodeGen/SelectionDAG/LegalizeVectorTypes.cpp | 1082 ++-- .../lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp | 2 +- .../lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp | 17 +- .../CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp | 31 +- .../llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 946 ++-- .../SelectionDAG/SelectionDAGAddressAnalysis.cpp | 31 +- .../CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 776 +-- .../lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h | 22 +- .../CodeGen/SelectionDAG/SelectionDAGDumper.cpp | 53 +- .../lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 164 +- .../CodeGen/SelectionDAG/StatepointLowering.cpp | 322 +- .../lib/CodeGen/SelectionDAG/TargetLowering.cpp | 1071 +++- .../llvm-project/llvm/lib/CodeGen/ShrinkWrap.cpp | 13 +- .../llvm/lib/CodeGen/SjLjEHPrepare.cpp | 2 +- .../llvm/lib/CodeGen/SpillPlacement.cpp | 4 - contrib/llvm-project/llvm/lib/CodeGen/SplitKit.cpp | 78 +- contrib/llvm-project/llvm/lib/CodeGen/SplitKit.h | 13 +- .../llvm/lib/CodeGen/StackColoring.cpp | 56 +- .../llvm-project/llvm/lib/CodeGen/StackMaps.cpp | 180 +- .../llvm/lib/CodeGen/StackProtector.cpp | 48 +- .../llvm/lib/CodeGen/StackSlotColoring.cpp | 17 +- .../llvm/lib/CodeGen/SwiftErrorValueTracking.cpp | 4 +- .../llvm/lib/CodeGen/SwitchLoweringUtils.cpp | 4 +- .../llvm/lib/CodeGen/TailDuplicator.cpp | 3 +- .../llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp | 11 +- .../llvm/lib/CodeGen/TargetInstrInfo.cpp | 44 +- .../llvm/lib/CodeGen/TargetLoweringBase.cpp | 272 +- .../lib/CodeGen/TargetLoweringObjectFileImpl.cpp | 443 +- .../llvm/lib/CodeGen/TargetOptionsImpl.cpp | 8 +- .../llvm/lib/CodeGen/TargetPassConfig.cpp | 303 +- .../llvm/lib/CodeGen/TargetRegisterInfo.cpp | 53 +- .../llvm/lib/CodeGen/TargetSubtargetInfo.cpp | 11 +- .../llvm/lib/CodeGen/TwoAddressInstructionPass.cpp | 270 +- .../llvm/lib/CodeGen/TypePromotion.cpp | 12 +- .../llvm-project/llvm/lib/CodeGen/ValueTypes.cpp | 51 +- .../llvm-project/llvm/lib/CodeGen/VirtRegMap.cpp | 17 +- .../llvm/lib/CodeGen/WasmEHPrepare.cpp | 31 +- .../llvm-project/llvm/lib/CodeGen/WinEHPrepare.cpp | 8 +- .../llvm/lib/CodeGen/XRayInstrumentation.cpp | 12 +- .../llvm/lib/DWARFLinker/DWARFLinker.cpp | 417 +- .../lib/DWARFLinker/DWARFLinkerCompileUnit.cpp | 6 +- .../lib/DWARFLinker/DWARFLinkerDeclContext.cpp | 80 +- .../llvm/lib/DWARFLinker/DWARFStreamer.cpp | 50 +- .../lib/DebugInfo/CodeView/CodeViewRecordIO.cpp | 2 - .../CodeView/DebugFrameDataSubsection.cpp | 7 +- .../llvm/lib/DebugInfo/CodeView/EnumTables.cpp | 12 +- .../CodeView/LazyRandomTypeCollection.cpp | 10 +- .../llvm/lib/DebugInfo/CodeView/RecordName.cpp | 8 +- .../lib/DebugInfo/CodeView/RecordSerialization.cpp | 2 +- .../lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp | 3 +- .../lib/DebugInfo/CodeView/TypeRecordMapping.cpp | 2 +- .../lib/DebugInfo/CodeView/TypeStreamMerger.cpp | 2 +- .../llvm/lib/DebugInfo/DWARF/DWARFAddressRange.cpp | 5 +- .../llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp | 7 +- .../llvm/lib/DebugInfo/DWARF/DWARFContext.cpp | 113 +- .../lib/DebugInfo/DWARF/DWARFDataExtractor.cpp | 14 +- .../lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp | 16 +- .../llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp | 3 +- .../llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp | 53 +- .../lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp | 3 +- .../llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp | 84 +- .../llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp | 14 +- .../llvm/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp | 14 +- .../lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp | 7 + .../lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp | 139 +- .../llvm/lib/DebugInfo/DWARF/DWARFDie.cpp | 74 +- .../llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp | 29 +- .../llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp | 13 +- .../llvm/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp | 4 +- .../llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp | 9 +- .../llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp | 7 +- .../llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp | 194 +- .../llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp | 42 + .../llvm/lib/DebugInfo/GSYM/GsymCreator.cpp | 2 +- .../llvm/lib/DebugInfo/MSF/MSFBuilder.cpp | 6 +- .../PDB/Native/DbiModuleDescriptorBuilder.cpp | 81 +- .../lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp | 10 +- .../lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp | 2 +- .../lib/DebugInfo/PDB/Native/NamedStreamMap.cpp | 2 +- .../lib/DebugInfo/PDB/Native/NativeEnumSymbols.cpp | 41 + .../DebugInfo/PDB/Native/NativeFunctionSymbol.cpp | 98 +- .../PDB/Native/NativeInlineSiteSymbol.cpp | 177 + .../lib/DebugInfo/PDB/Native/NativeLineNumber.cpp | 7 +- .../DebugInfo/PDB/Native/NativePublicSymbol.cpp | 6 +- .../lib/DebugInfo/PDB/Native/NativeSession.cpp | 81 +- .../lib/DebugInfo/PDB/Native/NativeSourceFile.cpp | 2 +- .../lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp | 2 +- .../llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp | 195 +- .../lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp | 62 +- .../llvm/lib/DebugInfo/PDB/PDBContext.cpp | 39 +- .../llvm/lib/DebugInfo/PDB/PDBExtras.cpp | 16 +- .../llvm/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp | 4 +- .../llvm/lib/DebugInfo/PDB/PDBSymbol.cpp | 17 + .../llvm/lib/DebugInfo/PDB/UDTLayout.cpp | 8 +- .../llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp | 6 +- .../DebugInfo/Symbolize/SymbolizableObjectFile.cpp | 9 - .../DebugInfo/Symbolize/SymbolizableObjectFile.h | 6 +- .../llvm/lib/DebugInfo/Symbolize/Symbolize.cpp | 19 +- .../llvm-project/llvm/lib/Demangle/Demangle.cpp | 2 +- .../llvm/lib/Demangle/MicrosoftDemangleNodes.cpp | 1 - .../llvm/lib/ExecutionEngine/ExecutionEngine.cpp | 15 +- .../IntelJITEvents/IntelJITEventListener.cpp | 396 +- .../IntelJITEvents/IntelJITEventsWrapper.h | 45 +- .../Interpreter/ExternalFunctions.cpp | 2 +- .../lib/ExecutionEngine/JITLink/EHFrameSupport.cpp | 334 +- .../ExecutionEngine/JITLink/EHFrameSupportImpl.h | 24 +- .../llvm/lib/ExecutionEngine/JITLink/ELF.cpp | 66 +- .../lib/ExecutionEngine/JITLink/ELF_x86_64.cpp | 544 +- .../llvm/lib/ExecutionEngine/JITLink/JITLink.cpp | 58 +- .../lib/ExecutionEngine/JITLink/JITLinkGeneric.cpp | 62 +- .../lib/ExecutionEngine/JITLink/JITLinkGeneric.h | 16 +- .../JITLink/JITLinkMemoryManager.cpp | 3 +- .../llvm/lib/ExecutionEngine/JITLink/MachO.cpp | 60 +- .../JITLink/MachOLinkGraphBuilder.cpp | 10 +- .../JITLink/MachOLinkGraphBuilder.h | 4 +- .../lib/ExecutionEngine/JITLink/MachO_arm64.cpp | 111 +- .../lib/ExecutionEngine/JITLink/MachO_x86_64.cpp | 65 +- .../llvm/lib/ExecutionEngine/MCJIT/MCJIT.h | 10 +- .../ExecutionEngine/Orc/CompileOnDemandLayer.cpp | 76 +- .../llvm/lib/ExecutionEngine/Orc/Core.cpp | 2636 ++++++---- .../lib/ExecutionEngine/Orc/ExecutionUtils.cpp | 40 +- .../lib/ExecutionEngine/Orc/IRCompileLayer.cpp | 6 +- .../lib/ExecutionEngine/Orc/IRTransformLayer.cpp | 6 +- .../lib/ExecutionEngine/Orc/IndirectionUtils.cpp | 21 +- .../llvm/lib/ExecutionEngine/Orc/LLJIT.cpp | 188 +- .../llvm/lib/ExecutionEngine/Orc/Layer.cpp | 67 +- .../llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp | 72 +- .../llvm/lib/ExecutionEngine/Orc/Legacy.cpp | 68 - .../llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp | 57 +- .../llvm/lib/ExecutionEngine/Orc/NullResolver.cpp | 37 - .../lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp | 339 +- .../ExecutionEngine/Orc/ObjectTransformLayer.cpp | 7 +- .../llvm/lib/ExecutionEngine/Orc/OrcCBindings.cpp | 158 - .../lib/ExecutionEngine/Orc/OrcCBindingsStack.h | 534 -- .../ExecutionEngine/Orc/OrcMCJITReplacement.cpp | 138 - .../lib/ExecutionEngine/Orc/OrcMCJITReplacement.h | 502 -- .../lib/ExecutionEngine/Orc/OrcV2CBindings.cpp | 303 +- .../Orc/RTDyldObjectLinkingLayer.cpp | 149 +- .../lib/ExecutionEngine/Orc/Shared/OrcError.cpp | 120 + .../lib/ExecutionEngine/Orc/Shared/RPCError.cpp | 58 + .../Orc/Shared/TargetProcessControlTypes.cpp | 44 + .../lib/ExecutionEngine/Orc/SpeculateAnalyses.cpp | 9 +- .../llvm/lib/ExecutionEngine/Orc/Speculation.cpp | 7 +- .../Orc/TPCDynamicLibrarySearchGenerator.cpp | 70 + .../ExecutionEngine/Orc/TPCEHFrameRegistrar.cpp | 80 + .../ExecutionEngine/Orc/TPCIndirectionUtils.cpp | 423 ++ .../Orc/TargetProcess/RegisterEHFrames.cpp | 208 + .../Orc/TargetProcess/TargetExecutionUtils.cpp | 43 + .../ExecutionEngine/Orc/TargetProcessControl.cpp | 153 + .../lib/ExecutionEngine/Orc/ThreadSafeModule.cpp | 2 +- .../llvm/lib/ExecutionEngine/OrcError/OrcError.cpp | 121 - .../llvm/lib/ExecutionEngine/OrcError/RPCError.cpp | 59 - .../RuntimeDyld/RTDyldMemoryManager.cpp | 12 +- .../ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp | 37 +- .../RuntimeDyld/RuntimeDyldChecker.cpp | 4 +- .../ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp | 25 +- .../ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h | 7 +- .../RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h | 9 +- .../lib/ExecutionEngine/SectionMemoryManager.cpp | 20 +- .../llvm-project/llvm/lib/FileCheck/FileCheck.cpp | 2754 ++++++++++ .../llvm/lib/FileCheck/FileCheckImpl.h | 859 ++++ .../llvm/lib/Frontend/OpenMP/OMPContext.cpp | 38 +- .../llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp | 830 +++- .../llvm-project/llvm/lib/FuzzMutate/IRMutator.cpp | 43 + contrib/llvm-project/llvm/lib/IR/AsmWriter.cpp | 146 +- contrib/llvm-project/llvm/lib/IR/Assumptions.cpp | 36 + contrib/llvm-project/llvm/lib/IR/AttributeImpl.h | 7 +- contrib/llvm-project/llvm/lib/IR/Attributes.cpp | 241 +- contrib/llvm-project/llvm/lib/IR/AutoUpgrade.cpp | 490 +- contrib/llvm-project/llvm/lib/IR/BasicBlock.cpp | 142 +- contrib/llvm-project/llvm/lib/IR/ConstantFold.cpp | 151 +- contrib/llvm-project/llvm/lib/IR/ConstantRange.cpp | 97 +- contrib/llvm-project/llvm/lib/IR/Constants.cpp | 415 +- contrib/llvm-project/llvm/lib/IR/Core.cpp | 54 +- contrib/llvm-project/llvm/lib/IR/DIBuilder.cpp | 47 +- contrib/llvm-project/llvm/lib/IR/DataLayout.cpp | 414 +- contrib/llvm-project/llvm/lib/IR/DebugInfo.cpp | 35 +- .../llvm-project/llvm/lib/IR/DebugInfoMetadata.cpp | 142 +- contrib/llvm-project/llvm/lib/IR/DebugLoc.cpp | 18 +- .../llvm-project/llvm/lib/IR/DiagnosticInfo.cpp | 26 +- contrib/llvm-project/llvm/lib/IR/Dominators.cpp | 24 +- contrib/llvm-project/llvm/lib/IR/Function.cpp | 128 +- contrib/llvm-project/llvm/lib/IR/Globals.cpp | 8 +- contrib/llvm-project/llvm/lib/IR/IRBuilder.cpp | 212 +- .../llvm-project/llvm/lib/IR/IRPrintingPasses.cpp | 4 +- contrib/llvm-project/llvm/lib/IR/Instruction.cpp | 35 +- contrib/llvm-project/llvm/lib/IR/Instructions.cpp | 338 +- contrib/llvm-project/llvm/lib/IR/IntrinsicInst.cpp | 37 +- contrib/llvm-project/llvm/lib/IR/LLVMContext.cpp | 9 +- .../llvm-project/llvm/lib/IR/LLVMContextImpl.cpp | 40 +- contrib/llvm-project/llvm/lib/IR/LLVMContextImpl.h | 225 +- .../llvm/lib/IR/LLVMRemarkStreamer.cpp | 17 +- .../llvm-project/llvm/lib/IR/LegacyPassManager.cpp | 156 +- contrib/llvm-project/llvm/lib/IR/MDBuilder.cpp | 32 +- contrib/llvm-project/llvm/lib/IR/Mangler.cpp | 32 +- contrib/llvm-project/llvm/lib/IR/Metadata.cpp | 391 +- contrib/llvm-project/llvm/lib/IR/Module.cpp | 9 +- .../llvm/lib/IR/ModuleSummaryIndex.cpp | 28 +- contrib/llvm-project/llvm/lib/IR/Operator.cpp | 20 +- contrib/llvm-project/llvm/lib/IR/OptBisect.cpp | 2 + contrib/llvm-project/llvm/lib/IR/Pass.cpp | 13 +- .../llvm/lib/IR/PassInstrumentation.cpp | 19 + contrib/llvm-project/llvm/lib/IR/PassManager.cpp | 48 + contrib/llvm-project/llvm/lib/IR/PassRegistry.cpp | 6 +- .../llvm-project/llvm/lib/IR/PassTimingInfo.cpp | 60 +- contrib/llvm-project/llvm/lib/IR/PrintPasses.cpp | 88 + .../llvm-project/llvm/lib/IR/ProfileSummary.cpp | 2 +- contrib/llvm-project/llvm/lib/IR/PseudoProbe.cpp | 99 + .../llvm-project/llvm/lib/IR/ReplaceConstant.cpp | 70 + .../llvm/lib/IR/SafepointIRVerifier.cpp | 3 +- .../llvm-project/llvm/lib/IR/StructuralHash.cpp | 84 + contrib/llvm-project/llvm/lib/IR/Type.cpp | 63 +- contrib/llvm-project/llvm/lib/IR/Use.cpp | 29 +- contrib/llvm-project/llvm/lib/IR/User.cpp | 2 +- contrib/llvm-project/llvm/lib/IR/Value.cpp | 86 +- contrib/llvm-project/llvm/lib/IR/Verifier.cpp | 431 +- .../llvm-project/llvm/lib/IRReader/IRReader.cpp | 8 +- .../llvm/lib/InterfaceStub/ELFObjHandler.cpp | 680 +++ .../llvm/lib/InterfaceStub/ELFStub.cpp | 28 + .../llvm/lib/InterfaceStub/TBEHandler.cpp | 143 + contrib/llvm-project/llvm/lib/LTO/Caching.cpp | 1 + contrib/llvm-project/llvm/lib/LTO/LTO.cpp | 75 +- contrib/llvm-project/llvm/lib/LTO/LTOBackend.cpp | 240 +- .../llvm-project/llvm/lib/LTO/LTOCodeGenerator.cpp | 54 +- contrib/llvm-project/llvm/lib/LTO/LTOModule.cpp | 3 + .../llvm/lib/LTO/ThinLTOCodeGenerator.cpp | 68 +- contrib/llvm-project/llvm/lib/Linker/IRMover.cpp | 158 +- .../llvm-project/llvm/lib/Linker/LinkModules.cpp | 2 +- .../llvm-project/llvm/lib/MC/ELFObjectWriter.cpp | 46 +- contrib/llvm-project/llvm/lib/MC/MCAsmBackend.cpp | 15 +- contrib/llvm-project/llvm/lib/MC/MCAsmInfo.cpp | 11 +- .../llvm-project/llvm/lib/MC/MCAsmInfoXCOFF.cpp | 9 + contrib/llvm-project/llvm/lib/MC/MCAsmMacro.cpp | 5 + contrib/llvm-project/llvm/lib/MC/MCAsmStreamer.cpp | 152 +- contrib/llvm-project/llvm/lib/MC/MCAssembler.cpp | 94 +- contrib/llvm-project/llvm/lib/MC/MCCodeView.cpp | 5 +- contrib/llvm-project/llvm/lib/MC/MCContext.cpp | 57 +- contrib/llvm-project/llvm/lib/MC/MCDwarf.cpp | 29 +- contrib/llvm-project/llvm/lib/MC/MCELFStreamer.cpp | 35 +- contrib/llvm-project/llvm/lib/MC/MCExpr.cpp | 142 +- contrib/llvm-project/llvm/lib/MC/MCFragment.cpp | 24 + .../llvm-project/llvm/lib/MC/MCObjectFileInfo.cpp | 132 +- .../llvm-project/llvm/lib/MC/MCObjectStreamer.cpp | 90 +- .../llvm-project/llvm/lib/MC/MCParser/AsmLexer.cpp | 174 +- .../llvm/lib/MC/MCParser/AsmParser.cpp | 131 +- .../llvm/lib/MC/MCParser/COFFAsmParser.cpp | 10 +- .../llvm/lib/MC/MCParser/COFFMasmParser.cpp | 119 +- .../llvm/lib/MC/MCParser/DarwinAsmParser.cpp | 1 + .../llvm/lib/MC/MCParser/ELFAsmParser.cpp | 14 +- .../llvm/lib/MC/MCParser/MasmParser.cpp | 1903 ++++--- .../llvm/lib/MC/MCParser/WasmAsmParser.cpp | 82 +- contrib/llvm-project/llvm/lib/MC/MCPseudoProbe.cpp | 213 + contrib/llvm-project/llvm/lib/MC/MCSchedule.cpp | 4 +- contrib/llvm-project/llvm/lib/MC/MCSection.cpp | 3 +- contrib/llvm-project/llvm/lib/MC/MCSectionELF.cpp | 8 +- .../llvm-project/llvm/lib/MC/MCSectionMachO.cpp | 20 +- contrib/llvm-project/llvm/lib/MC/MCSectionWasm.cpp | 10 +- .../llvm-project/llvm/lib/MC/MCSectionXCOFF.cpp | 1 + contrib/llvm-project/llvm/lib/MC/MCStreamer.cpp | 63 +- .../llvm-project/llvm/lib/MC/MCSubtargetInfo.cpp | 42 +- contrib/llvm-project/llvm/lib/MC/MCSymbolXCOFF.cpp | 10 +- .../llvm-project/llvm/lib/MC/MCWasmStreamer.cpp | 12 - contrib/llvm-project/llvm/lib/MC/MCWin64EH.cpp | 487 +- .../llvm-project/llvm/lib/MC/MCWinCOFFStreamer.cpp | 14 +- .../llvm/lib/MC/StringTableBuilder.cpp | 15 +- .../llvm-project/llvm/lib/MC/WasmObjectWriter.cpp | 936 ++-- .../llvm/lib/MC/WinCOFFObjectWriter.cpp | 5 +- .../llvm-project/llvm/lib/MC/XCOFFObjectWriter.cpp | 27 +- .../llvm/lib/MCA/HardwareUnits/RegisterFile.cpp | 17 +- .../llvm/lib/MCA/HardwareUnits/Scheduler.cpp | 2 +- contrib/llvm-project/llvm/lib/MCA/InstrBuilder.cpp | 16 +- .../llvm/lib/MCA/Stages/InstructionTables.cpp | 3 +- contrib/llvm-project/llvm/lib/Object/Archive.cpp | 4 +- .../llvm-project/llvm/lib/Object/ArchiveWriter.cpp | 161 +- contrib/llvm-project/llvm/lib/Object/Binary.cpp | 10 +- .../llvm/lib/Object/COFFObjectFile.cpp | 74 +- contrib/llvm-project/llvm/lib/Object/ELF.cpp | 58 +- .../llvm-project/llvm/lib/Object/ELFObjectFile.cpp | 155 +- .../llvm/lib/Object/MachOObjectFile.cpp | 40 +- .../llvm/lib/Object/MachOUniversal.cpp | 29 + .../llvm/lib/Object/MachOUniversalWriter.cpp | 337 ++ .../llvm-project/llvm/lib/Object/ObjectFile.cpp | 5 +- .../llvm/lib/Object/RelocationResolver.cpp | 286 +- .../llvm-project/llvm/lib/Object/SymbolSize.cpp | 2 +- .../llvm-project/llvm/lib/Object/SymbolicFile.cpp | 59 +- .../llvm/lib/Object/WasmObjectFile.cpp | 350 +- .../llvm/lib/Object/XCOFFObjectFile.cpp | 303 +- .../llvm/lib/ObjectYAML/ArchiveEmitter.cpp | 51 + .../llvm/lib/ObjectYAML/ArchiveYAML.cpp | 58 + .../llvm/lib/ObjectYAML/COFFEmitter.cpp | 1 - .../llvm/lib/ObjectYAML/CodeViewYAMLSymbols.cpp | 25 +- .../llvm/lib/ObjectYAML/DWARFEmitter.cpp | 1051 +++- .../llvm/lib/ObjectYAML/DWARFVisitor.cpp | 196 - .../llvm/lib/ObjectYAML/DWARFVisitor.h | 97 - .../llvm-project/llvm/lib/ObjectYAML/DWARFYAML.cpp | 168 +- .../llvm/lib/ObjectYAML/ELFEmitter.cpp | 677 +-- .../llvm-project/llvm/lib/ObjectYAML/ELFYAML.cpp | 478 +- .../llvm/lib/ObjectYAML/MachOEmitter.cpp | 48 +- .../llvm-project/llvm/lib/ObjectYAML/MachOYAML.cpp | 4 +- .../llvm/lib/ObjectYAML/MinidumpYAML.cpp | 4 +- .../llvm/lib/ObjectYAML/ObjectYAML.cpp | 9 +- .../llvm/lib/ObjectYAML/WasmEmitter.cpp | 42 +- .../llvm-project/llvm/lib/ObjectYAML/WasmYAML.cpp | 13 +- .../llvm-project/llvm/lib/ObjectYAML/yaml2obj.cpp | 2 + contrib/llvm-project/llvm/lib/Option/OptTable.cpp | 109 +- contrib/llvm-project/llvm/lib/Option/Option.cpp | 15 +- .../llvm-project/llvm/lib/Passes/PassBuilder.cpp | 847 +++- .../llvm-project/llvm/lib/Passes/PassRegistry.def | 84 +- .../llvm/lib/Passes/StandardInstrumentations.cpp | 743 ++- .../lib/ProfileData/Coverage/CoverageMapping.cpp | 34 +- .../ProfileData/Coverage/CoverageMappingReader.cpp | 53 +- .../ProfileData/Coverage/CoverageMappingWriter.cpp | 16 +- contrib/llvm-project/llvm/lib/ProfileData/GCOV.cpp | 940 ++-- .../llvm/lib/ProfileData/InstrProf.cpp | 41 +- .../llvm/lib/ProfileData/InstrProfReader.cpp | 36 +- .../llvm/lib/ProfileData/InstrProfWriter.cpp | 12 +- .../llvm/lib/ProfileData/ProfileSummaryBuilder.cpp | 45 +- .../llvm/lib/ProfileData/SampleProf.cpp | 83 +- .../llvm/lib/ProfileData/SampleProfReader.cpp | 340 +- .../llvm/lib/ProfileData/SampleProfWriter.cpp | 272 +- .../llvm/lib/Remarks/BitstreamRemarkParser.cpp | 1 - .../llvm/lib/Remarks/BitstreamRemarkParser.h | 6 +- .../llvm/lib/Support/AArch64TargetParser.cpp | 16 +- .../llvm/lib/Support/AMDGPUMetadata.cpp | 3 +- .../llvm-project/llvm/lib/Support/APFixedPoint.cpp | 574 +++ contrib/llvm-project/llvm/lib/Support/APFloat.cpp | 108 +- contrib/llvm-project/llvm/lib/Support/APInt.cpp | 17 +- .../llvm/lib/Support/ARMAttributeParser.cpp | 2 +- .../llvm/lib/Support/ARMTargetParser.cpp | 33 +- contrib/llvm-project/llvm/lib/Support/CRC.cpp | 2 +- .../llvm-project/llvm/lib/Support/CachePruning.cpp | 5 +- .../llvm-project/llvm/lib/Support/CommandLine.cpp | 95 +- .../llvm-project/llvm/lib/Support/Compression.cpp | 4 +- .../llvm/lib/Support/ConvertUTFWrapper.cpp | 2 + .../llvm/lib/Support/CrashRecoveryContext.cpp | 39 +- .../llvm-project/llvm/lib/Support/DebugCounter.cpp | 2 +- .../llvm/lib/Support/DynamicLibrary.cpp | 4 +- .../llvm/lib/Support/ELFAttributeParser.cpp | 2 +- contrib/llvm-project/llvm/lib/Support/Error.cpp | 4 + .../llvm/lib/Support/ErrorHandling.cpp | 11 +- .../llvm-project/llvm/lib/Support/FileCheck.cpp | 2580 ---------- .../llvm-project/llvm/lib/Support/FileCheckImpl.h | 832 ---- .../llvm/lib/Support/FileCollector.cpp | 128 +- .../llvm/lib/Support/FormatVariadic.cpp | 23 +- contrib/llvm-project/llvm/lib/Support/Host.cpp | 298 +- contrib/llvm-project/llvm/lib/Support/InitLLVM.cpp | 11 +- .../llvm/lib/Support/InstructionCost.cpp | 24 + contrib/llvm-project/llvm/lib/Support/JSON.cpp | 219 +- .../llvm-project/llvm/lib/Support/KnownBits.cpp | 397 ++ .../llvm-project/llvm/lib/Support/LineIterator.cpp | 8 +- .../llvm-project/llvm/lib/Support/LowLevelType.cpp | 2 +- .../llvm/lib/Support/MemoryBufferRef.cpp | 19 + contrib/llvm-project/llvm/lib/Support/Path.cpp | 52 +- .../llvm/lib/Support/PrettyStackTrace.cpp | 13 +- contrib/llvm-project/llvm/lib/Support/Process.cpp | 21 +- contrib/llvm-project/llvm/lib/Support/Program.cpp | 14 +- contrib/llvm-project/llvm/lib/Support/SHA1.cpp | 2 +- contrib/llvm-project/llvm/lib/Support/Signals.cpp | 9 +- .../llvm-project/llvm/lib/Support/Signposts.cpp | 41 +- .../llvm-project/llvm/lib/Support/SmallVector.cpp | 68 +- .../llvm-project/llvm/lib/Support/SourceMgr.cpp | 56 +- .../llvm-project/llvm/lib/Support/TargetParser.cpp | 111 +- contrib/llvm-project/llvm/lib/Support/Timer.cpp | 14 +- .../llvm-project/llvm/lib/Support/TrigramIndex.cpp | 7 +- contrib/llvm-project/llvm/lib/Support/Triple.cpp | 98 +- contrib/llvm-project/llvm/lib/Support/Unicode.cpp | 11 + .../llvm-project/llvm/lib/Support/Unix/Path.inc | 76 +- .../llvm-project/llvm/lib/Support/Unix/Process.inc | 6 +- .../llvm-project/llvm/lib/Support/Unix/Program.inc | 6 +- .../llvm-project/llvm/lib/Support/Unix/Signals.inc | 29 +- .../llvm/lib/Support/VirtualFileSystem.cpp | 158 +- .../llvm-project/llvm/lib/Support/Windows/Path.inc | 61 +- .../llvm/lib/Support/Windows/Process.inc | 3 +- .../llvm/lib/Support/Windows/Program.inc | 59 +- .../llvm/lib/Support/Windows/Signals.inc | 5 +- .../llvm/lib/Support/Windows/Threading.inc | 25 +- .../llvm/lib/Support/X86TargetParser.cpp | 372 +- .../llvm-project/llvm/lib/Support/YAMLParser.cpp | 155 +- .../llvm-project/llvm/lib/Support/YAMLTraits.cpp | 75 +- .../llvm-project/llvm/lib/Support/raw_ostream.cpp | 59 +- .../llvm/lib/TableGen/DetailedRecordsBackend.cpp | 203 + contrib/llvm-project/llvm/lib/TableGen/Error.cpp | 85 +- .../llvm-project/llvm/lib/TableGen/JSONBackend.cpp | 5 +- contrib/llvm-project/llvm/lib/TableGen/Main.cpp | 43 +- contrib/llvm-project/llvm/lib/TableGen/Record.cpp | 519 +- contrib/llvm-project/llvm/lib/TableGen/TGLexer.cpp | 53 +- contrib/llvm-project/llvm/lib/TableGen/TGLexer.h | 28 +- .../llvm-project/llvm/lib/TableGen/TGParser.cpp | 722 ++- contrib/llvm-project/llvm/lib/TableGen/TGParser.h | 5 + .../llvm/lib/TableGen/TableGenBackendSkeleton.cpp | 64 + .../llvm-project/llvm/lib/Target/AArch64/AArch64.h | 8 +- .../llvm/lib/Target/AArch64/AArch64.td | 200 +- .../Target/AArch64/AArch64AdvSIMDScalarPass.cpp | 2 +- .../llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | 401 +- .../lib/Target/AArch64/AArch64BranchTargets.cpp | 5 +- .../Target/AArch64/AArch64CallingConvention.cpp | 57 +- .../llvm/lib/Target/AArch64/AArch64Combine.td | 64 +- .../Target/AArch64/AArch64CompressJumpTables.cpp | 41 +- .../Target/AArch64/AArch64ExpandPseudoInsts.cpp | 44 + .../lib/Target/AArch64/AArch64FalkorHWPFFix.cpp | 10 +- .../llvm/lib/Target/AArch64/AArch64FastISel.cpp | 18 +- .../lib/Target/AArch64/AArch64FrameLowering.cpp | 575 ++- .../llvm/lib/Target/AArch64/AArch64FrameLowering.h | 30 +- .../lib/Target/AArch64/AArch64ISelDAGToDAG.cpp | 87 +- .../lib/Target/AArch64/AArch64ISelLowering.cpp | 3183 +++++++++--- .../llvm/lib/Target/AArch64/AArch64ISelLowering.h | 137 +- .../llvm/lib/Target/AArch64/AArch64InstrFormats.td | 130 +- .../llvm/lib/Target/AArch64/AArch64InstrGISel.td | 60 + .../llvm/lib/Target/AArch64/AArch64InstrInfo.cpp | 527 +- .../llvm/lib/Target/AArch64/AArch64InstrInfo.h | 52 +- .../llvm/lib/Target/AArch64/AArch64InstrInfo.td | 334 +- .../Target/AArch64/AArch64LoadStoreOptimizer.cpp | 43 +- .../llvm/lib/Target/AArch64/AArch64MCInstLower.cpp | 6 + .../Target/AArch64/AArch64MachineFunctionInfo.cpp | 82 + .../Target/AArch64/AArch64MachineFunctionInfo.h | 74 +- .../llvm/lib/Target/AArch64/AArch64MacroFusion.cpp | 16 +- .../AArch64/AArch64RedundantCopyElimination.cpp | 5 + .../lib/Target/AArch64/AArch64RegisterInfo.cpp | 111 +- .../llvm/lib/Target/AArch64/AArch64RegisterInfo.h | 18 +- .../llvm/lib/Target/AArch64/AArch64RegisterInfo.td | 26 + .../lib/Target/AArch64/AArch64SIMDInstrOpt.cpp | 10 +- .../llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td | 684 ++- .../llvm/lib/Target/AArch64/AArch64SchedA55.td | 339 ++ .../llvm/lib/Target/AArch64/AArch64SchedA57.td | 61 +- .../lib/Target/AArch64/AArch64SchedA57WriteRes.td | 19 + .../llvm/lib/Target/AArch64/AArch64SchedA64FX.td | 3890 +++++++++++++++ .../llvm/lib/Target/AArch64/AArch64SchedTSV110.td | 745 +++ .../lib/Target/AArch64/AArch64SelectionDAGInfo.cpp | 6 +- .../llvm/lib/Target/AArch64/AArch64StackOffset.h | 151 - .../lib/Target/AArch64/AArch64StackTagging.cpp | 22 +- .../Target/AArch64/AArch64StackTaggingPreRA.cpp | 167 +- .../llvm/lib/Target/AArch64/AArch64Subtarget.cpp | 22 +- .../llvm/lib/Target/AArch64/AArch64Subtarget.h | 52 +- .../lib/Target/AArch64/AArch64SystemOperands.td | 253 +- .../lib/Target/AArch64/AArch64TargetMachine.cpp | 57 +- .../llvm/lib/Target/AArch64/AArch64TargetMachine.h | 6 + .../Target/AArch64/AArch64TargetTransformInfo.cpp | 196 +- .../Target/AArch64/AArch64TargetTransformInfo.h | 52 +- .../Target/AArch64/AsmParser/AArch64AsmParser.cpp | 596 ++- .../AArch64/Disassembler/AArch64Disassembler.cpp | 45 +- .../Target/AArch64/GISel/AArch64CallLowering.cpp | 106 +- .../lib/Target/AArch64/GISel/AArch64CallLowering.h | 5 +- .../Target/AArch64/GISel/AArch64GlobalISelUtils.h | 29 + .../AArch64/GISel/AArch64InstructionSelector.cpp | 1677 ++++--- .../Target/AArch64/GISel/AArch64LegalizerInfo.cpp | 336 +- .../Target/AArch64/GISel/AArch64LegalizerInfo.h | 2 + .../AArch64/GISel/AArch64PostLegalizerCombiner.cpp | 523 +- .../AArch64/GISel/AArch64PostLegalizerLowering.cpp | 704 +++ .../AArch64/GISel/AArch64PostSelectOptimize.cpp | 187 + .../AArch64/GISel/AArch64PreLegalizerCombiner.cpp | 29 +- .../AArch64/GISel/AArch64RegisterBankInfo.cpp | 92 +- .../Target/AArch64/GISel/AArch64RegisterBankInfo.h | 15 +- .../llvm/lib/Target/AArch64/GISel/select-saddo.mir | 158 + .../llvm/lib/Target/AArch64/GISel/select-ssubo.mir | 158 + .../AArch64/MCTargetDesc/AArch64AddressingModes.h | 6 +- .../AArch64/MCTargetDesc/AArch64AsmBackend.cpp | 27 +- .../MCTargetDesc/AArch64ELFObjectWriter.cpp | 6 +- .../AArch64/MCTargetDesc/AArch64ELFStreamer.cpp | 55 + .../AArch64/MCTargetDesc/AArch64InstPrinter.cpp | 34 +- .../AArch64/MCTargetDesc/AArch64InstPrinter.h | 8 +- .../AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp | 4 +- .../Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp | 1 + .../Target/AArch64/MCTargetDesc/AArch64MCExpr.h | 2 + .../AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp | 8 +- .../MCTargetDesc/AArch64MachObjectWriter.cpp | 6 +- .../AArch64/MCTargetDesc/AArch64TargetStreamer.cpp | 57 +- .../AArch64/MCTargetDesc/AArch64TargetStreamer.h | 18 + .../MCTargetDesc/AArch64WinCOFFStreamer.cpp | 37 +- .../llvm/lib/Target/AArch64/SVEInstrFormats.td | 557 ++- .../llvm/lib/Target/AArch64/SVEIntrinsicOpts.cpp | 58 +- .../lib/Target/AArch64/Utils/AArch64BaseInfo.cpp | 9 +- .../lib/Target/AArch64/Utils/AArch64BaseInfo.h | 20 +- .../llvm-project/llvm/lib/Target/AMDGPU/AMDGPU.h | 99 +- .../llvm-project/llvm/lib/Target/AMDGPU/AMDGPU.td | 197 +- .../llvm/lib/Target/AMDGPU/AMDGPUAliasAnalysis.cpp | 58 +- .../llvm/lib/Target/AMDGPU/AMDGPUAliasAnalysis.h | 22 +- .../lib/Target/AMDGPU/AMDGPUAlwaysInlinePass.cpp | 31 +- .../Target/AMDGPU/AMDGPUAnnotateKernelFeatures.cpp | 21 +- .../Target/AMDGPU/AMDGPUAnnotateUniformValues.cpp | 16 +- .../lib/Target/AMDGPU/AMDGPUArgumentUsageInfo.cpp | 4 +- .../lib/Target/AMDGPU/AMDGPUArgumentUsageInfo.h | 7 +- .../llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp | 162 +- .../llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.h | 24 +- .../lib/Target/AMDGPU/AMDGPUAtomicOptimizer.cpp | 18 +- .../llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp | 856 +++- .../llvm/lib/Target/AMDGPU/AMDGPUCallLowering.h | 41 +- .../llvm/lib/Target/AMDGPU/AMDGPUCallingConv.td | 76 +- .../lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp | 39 +- .../llvm/lib/Target/AMDGPU/AMDGPUCombine.td | 32 +- .../lib/Target/AMDGPU/AMDGPUExportClustering.cpp | 10 +- .../lib/Target/AMDGPU/AMDGPUExportClustering.h | 3 +- .../llvm/lib/Target/AMDGPU/AMDGPUGISel.td | 39 +- .../Target/AMDGPU/AMDGPUGenRegisterBankInfo.def | 12 +- .../lib/Target/AMDGPU/AMDGPUGlobalISelUtils.cpp | 12 +- .../llvm/lib/Target/AMDGPU/AMDGPUGlobalISelUtils.h | 38 +- .../Target/AMDGPU/AMDGPUHSAMetadataStreamer.cpp | 122 +- .../lib/Target/AMDGPU/AMDGPUHSAMetadataStreamer.h | 23 +- .../llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp | 601 ++- .../llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp | 237 +- .../llvm/lib/Target/AMDGPU/AMDGPUISelLowering.h | 24 +- .../llvm/lib/Target/AMDGPU/AMDGPUInline.cpp | 226 - .../Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp | 1075 ++++ .../llvm/lib/Target/AMDGPU/AMDGPUInstrInfo.cpp | 10 +- .../llvm/lib/Target/AMDGPU/AMDGPUInstrInfo.h | 25 +- .../Target/AMDGPU/AMDGPUInstructionSelector.cpp | 1101 ++-- .../lib/Target/AMDGPU/AMDGPUInstructionSelector.h | 62 +- .../llvm/lib/Target/AMDGPU/AMDGPUInstructions.td | 159 +- .../lib/Target/AMDGPU/AMDGPULateCodeGenPrepare.cpp | 195 + .../llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp | 1259 +++-- .../llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.h | 48 +- .../llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp | 93 +- .../llvm/lib/Target/AMDGPU/AMDGPULibFunc.cpp | 5 +- .../lib/Target/AMDGPU/AMDGPULowerIntrinsics.cpp | 10 +- .../Target/AMDGPU/AMDGPULowerKernelArguments.cpp | 53 +- .../Target/AMDGPU/AMDGPULowerKernelAttributes.cpp | 38 +- .../llvm/lib/Target/AMDGPU/AMDGPUMCInstLower.cpp | 7 +- .../llvm/lib/Target/AMDGPU/AMDGPUMIRFormatter.cpp | 38 + .../llvm/lib/Target/AMDGPU/AMDGPUMIRFormatter.h | 47 + .../Target/AMDGPU/AMDGPUMachineCFGStructurizer.cpp | 62 +- .../lib/Target/AMDGPU/AMDGPUMachineFunction.cpp | 36 +- .../llvm/lib/Target/AMDGPU/AMDGPUMachineFunction.h | 24 +- .../lib/Target/AMDGPU/AMDGPUMachineModuleInfo.cpp | 1 - .../lib/Target/AMDGPU/AMDGPUMachineModuleInfo.h | 4 - .../llvm/lib/Target/AMDGPU/AMDGPUMacroFusion.cpp | 4 +- .../llvm/lib/Target/AMDGPU/AMDGPUMacroFusion.h | 3 +- .../AMDGPU/AMDGPUOpenCLEnqueuedBlockLowering.cpp | 5 - .../llvm/lib/Target/AMDGPU/AMDGPUPTNote.h | 7 +- .../lib/Target/AMDGPU/AMDGPUPerfHintAnalysis.cpp | 4 - .../lib/Target/AMDGPU/AMDGPUPerfHintAnalysis.h | 1 - .../Target/AMDGPU/AMDGPUPostLegalizerCombiner.cpp | 120 +- .../Target/AMDGPU/AMDGPUPreLegalizerCombiner.cpp | 8 +- .../Target/AMDGPU/AMDGPUPrintfRuntimeBinding.cpp | 154 +- .../llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp | 281 +- .../Target/AMDGPU/AMDGPUPropagateAttributes.cpp | 49 +- .../lib/Target/AMDGPU/AMDGPURegBankCombiner.cpp | 10 +- .../lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp | 372 +- .../lib/Target/AMDGPU/AMDGPURegisterBankInfo.h | 8 +- .../llvm/lib/Target/AMDGPU/AMDGPURegisterBanks.td | 2 +- .../Target/AMDGPU/AMDGPURewriteOutArguments.cpp | 33 +- .../lib/Target/AMDGPU/AMDGPUSearchableTables.td | 2 + .../llvm/lib/Target/AMDGPU/AMDGPUSubtarget.cpp | 172 +- .../llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h | 1204 +---- .../llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp | 252 +- .../llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.h | 23 +- .../lib/Target/AMDGPU/AMDGPUTargetObjectFile.cpp | 9 +- .../Target/AMDGPU/AMDGPUTargetTransformInfo.cpp | 365 +- .../lib/Target/AMDGPU/AMDGPUTargetTransformInfo.h | 106 +- .../AMDGPU/AMDGPUUnifyDivergentExitNodes.cpp | 63 +- .../llvm/lib/Target/AMDGPU/AMDGPUUnifyMetadata.cpp | 66 +- .../lib/Target/AMDGPU/AMDILCFGStructurizer.cpp | 29 +- .../llvm/lib/Target/AMDGPU/AMDKernelCodeT.h | 8 +- .../Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp | 1997 +++++--- .../llvm/lib/Target/AMDGPU/BUFInstructions.td | 237 +- .../llvm/lib/Target/AMDGPU/DSInstructions.td | 119 +- .../AMDGPU/Disassembler/AMDGPUDisassembler.cpp | 435 +- .../AMDGPU/Disassembler/AMDGPUDisassembler.h | 39 +- .../llvm/lib/Target/AMDGPU/EXPInstructions.td | 125 + .../lib/Target/AMDGPU/EvergreenInstructions.td | 138 +- .../llvm/lib/Target/AMDGPU/FLATInstructions.td | 704 ++- .../llvm/lib/Target/AMDGPU/GCNDPPCombine.cpp | 22 +- .../llvm/lib/Target/AMDGPU/GCNHazardRecognizer.cpp | 220 +- .../llvm/lib/Target/AMDGPU/GCNHazardRecognizer.h | 3 +- .../llvm/lib/Target/AMDGPU/GCNILPSched.cpp | 1 - .../lib/Target/AMDGPU/GCNIterativeScheduler.cpp | 21 - .../llvm/lib/Target/AMDGPU/GCNIterativeScheduler.h | 6 - .../llvm/lib/Target/AMDGPU/GCNMinRegStrategy.cpp | 13 - .../llvm/lib/Target/AMDGPU/GCNNSAReassign.cpp | 39 +- .../llvm/lib/Target/AMDGPU/GCNProcessors.td | 44 +- .../llvm/lib/Target/AMDGPU/GCNRegBankReassign.cpp | 256 +- .../llvm/lib/Target/AMDGPU/GCNRegPressure.cpp | 38 +- .../llvm/lib/Target/AMDGPU/GCNRegPressure.h | 12 +- .../llvm/lib/Target/AMDGPU/GCNSchedStrategy.cpp | 10 +- .../llvm/lib/Target/AMDGPU/GCNSubtarget.h | 1064 ++++ .../llvm/lib/Target/AMDGPU/InstCombineTables.td | 11 + .../AMDGPU/MCTargetDesc/AMDGPUAsmBackend.cpp | 9 +- .../AMDGPU/MCTargetDesc/AMDGPUELFObjectWriter.cpp | 6 - .../AMDGPU/MCTargetDesc/AMDGPUELFStreamer.cpp | 3 +- .../Target/AMDGPU/MCTargetDesc/AMDGPUELFStreamer.h | 6 +- .../AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp | 217 +- .../Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.h | 12 +- .../Target/AMDGPU/MCTargetDesc/AMDGPUMCAsmInfo.cpp | 1 - .../AMDGPU/MCTargetDesc/AMDGPUMCCodeEmitter.h | 2 +- .../AMDGPU/MCTargetDesc/AMDGPUMCTargetDesc.cpp | 12 +- .../AMDGPU/MCTargetDesc/AMDGPUMCTargetDesc.h | 14 +- .../AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp | 81 +- .../AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.h | 18 +- .../AMDGPU/MCTargetDesc/R600MCCodeEmitter.cpp | 9 +- .../Target/AMDGPU/MCTargetDesc/SIMCCodeEmitter.cpp | 16 +- .../llvm/lib/Target/AMDGPU/MIMGInstructions.td | 129 +- .../llvm/lib/Target/AMDGPU/R600AsmPrinter.cpp | 4 +- .../llvm/lib/Target/AMDGPU/R600ClauseMergePass.cpp | 11 +- .../lib/Target/AMDGPU/R600ControlFlowFinalizer.cpp | 36 +- .../llvm/lib/Target/AMDGPU/R600Defines.h | 2 - .../lib/Target/AMDGPU/R600EmitClauseMarkers.cpp | 20 +- .../lib/Target/AMDGPU/R600ExpandSpecialInstrs.cpp | 16 +- .../llvm/lib/Target/AMDGPU/R600FrameLowering.cpp | 13 +- .../llvm/lib/Target/AMDGPU/R600FrameLowering.h | 4 +- .../llvm/lib/Target/AMDGPU/R600ISelLowering.cpp | 59 +- .../llvm/lib/Target/AMDGPU/R600InstrInfo.cpp | 44 +- .../llvm/lib/Target/AMDGPU/R600InstrInfo.h | 4 +- .../llvm/lib/Target/AMDGPU/R600Instructions.td | 8 +- .../lib/Target/AMDGPU/R600MachineScheduler.cpp | 15 +- .../llvm/lib/Target/AMDGPU/R600MachineScheduler.h | 2 +- .../AMDGPU/R600OpenCLImageTypeLoweringPass.cpp | 15 - .../Target/AMDGPU/R600OptimizeVectorRegisters.cpp | 23 +- .../llvm/lib/Target/AMDGPU/R600Packetizer.cpp | 7 +- .../llvm/lib/Target/AMDGPU/R600RegisterInfo.cpp | 10 +- .../llvm/lib/Target/AMDGPU/R600RegisterInfo.h | 2 +- .../llvm/lib/Target/AMDGPU/R600Subtarget.h | 174 + .../llvm/lib/Target/AMDGPU/SIAddIMGInit.cpp | 13 +- .../lib/Target/AMDGPU/SIAnnotateControlFlow.cpp | 37 +- .../llvm/lib/Target/AMDGPU/SIDefines.h | 257 +- .../llvm/lib/Target/AMDGPU/SIFixSGPRCopies.cpp | 144 +- .../llvm/lib/Target/AMDGPU/SIFixVGPRCopies.cpp | 3 +- .../llvm/lib/Target/AMDGPU/SIFixupVectorISel.cpp | 239 - .../llvm/lib/Target/AMDGPU/SIFoldOperands.cpp | 283 +- .../llvm/lib/Target/AMDGPU/SIFormMemoryClauses.cpp | 55 +- .../llvm/lib/Target/AMDGPU/SIFrameLowering.cpp | 406 +- .../llvm/lib/Target/AMDGPU/SIFrameLowering.h | 6 +- .../llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 2013 ++++---- .../llvm/lib/Target/AMDGPU/SIISelLowering.h | 56 +- .../llvm/lib/Target/AMDGPU/SIInsertHardClauses.cpp | 5 +- .../llvm/lib/Target/AMDGPU/SIInsertSkips.cpp | 163 +- .../llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp | 241 +- .../llvm/lib/Target/AMDGPU/SIInstrFormats.td | 52 +- .../llvm/lib/Target/AMDGPU/SIInstrInfo.cpp | 1551 +++--- .../llvm/lib/Target/AMDGPU/SIInstrInfo.h | 104 +- .../llvm/lib/Target/AMDGPU/SIInstrInfo.td | 552 +-- .../llvm/lib/Target/AMDGPU/SIInstructions.td | 570 ++- .../lib/Target/AMDGPU/SILoadStoreOptimizer.cpp | 52 +- .../llvm/lib/Target/AMDGPU/SILowerControlFlow.cpp | 316 +- .../llvm/lib/Target/AMDGPU/SILowerI1Copies.cpp | 38 +- .../llvm/lib/Target/AMDGPU/SILowerSGPRSpills.cpp | 109 +- .../lib/Target/AMDGPU/SIMachineFunctionInfo.cpp | 72 +- .../llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.h | 65 +- .../llvm/lib/Target/AMDGPU/SIMachineScheduler.cpp | 42 +- .../llvm/lib/Target/AMDGPU/SIMachineScheduler.h | 10 +- .../llvm/lib/Target/AMDGPU/SIMemoryLegalizer.cpp | 586 ++- .../llvm/lib/Target/AMDGPU/SIModeRegister.cpp | 24 +- .../lib/Target/AMDGPU/SIOptimizeExecMasking.cpp | 59 +- .../Target/AMDGPU/SIOptimizeExecMaskingPreRA.cpp | 208 +- .../llvm/lib/Target/AMDGPU/SIPeepholeSDWA.cpp | 76 +- .../llvm/lib/Target/AMDGPU/SIPostRABundler.cpp | 6 +- .../lib/Target/AMDGPU/SIPreAllocateWWMRegs.cpp | 17 +- .../llvm/lib/Target/AMDGPU/SIPreEmitPeephole.cpp | 20 +- .../llvm/lib/Target/AMDGPU/SIProgramInfo.cpp | 56 + .../llvm/lib/Target/AMDGPU/SIProgramInfo.h | 12 +- .../llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp | 744 ++- .../llvm/lib/Target/AMDGPU/SIRegisterInfo.h | 42 +- .../llvm/lib/Target/AMDGPU/SIRegisterInfo.td | 52 +- .../Target/AMDGPU/SIRemoveShortExecBranches.cpp | 3 +- .../llvm/lib/Target/AMDGPU/SISchedule.td | 15 +- .../lib/Target/AMDGPU/SIShrinkInstructions.cpp | 170 +- .../llvm/lib/Target/AMDGPU/SIWholeQuadMode.cpp | 204 +- .../llvm/lib/Target/AMDGPU/SMInstructions.td | 4 +- .../llvm/lib/Target/AMDGPU/SOPInstructions.td | 629 ++- .../lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.cpp | 247 + .../llvm/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.h | 15 + .../lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp | 460 +- .../llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h | 188 +- .../lib/Target/AMDGPU/Utils/AMDGPUPALMetadata.cpp | 50 +- .../lib/Target/AMDGPU/Utils/AMDGPUPALMetadata.h | 18 +- .../Target/AMDGPU/Utils/AMDKernelCodeTUtils.cpp | 4 +- .../lib/Target/AMDGPU/Utils/AMDKernelCodeTUtils.h | 2 +- .../llvm/lib/Target/AMDGPU/VOP1Instructions.td | 29 +- .../llvm/lib/Target/AMDGPU/VOP2Instructions.td | 225 +- .../llvm/lib/Target/AMDGPU/VOP3Instructions.td | 592 +-- .../llvm/lib/Target/AMDGPU/VOP3PInstructions.td | 269 +- .../llvm/lib/Target/AMDGPU/VOPCInstructions.td | 2 +- .../llvm/lib/Target/AMDGPU/VOPInstructions.td | 38 +- .../llvm/lib/Target/ARC/ARCISelLowering.cpp | 1 - .../llvm/lib/Target/ARC/ARCSubtarget.cpp | 2 +- .../llvm/lib/Target/ARC/ARCSubtarget.h | 2 +- .../llvm/lib/Target/ARC/ARCTargetMachine.cpp | 4 +- .../lib/Target/ARC/MCTargetDesc/ARCInstPrinter.h | 1 + .../Target/ARC/MCTargetDesc/ARCMCTargetDesc.cpp | 2 +- .../llvm/lib/Target/ARM/A15SDOptimizer.cpp | 3 +- contrib/llvm-project/llvm/lib/Target/ARM/ARM.h | 5 + contrib/llvm-project/llvm/lib/Target/ARM/ARM.td | 109 +- .../llvm/lib/Target/ARM/ARMAsmPrinter.cpp | 48 +- .../llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp | 721 ++- .../llvm/lib/Target/ARM/ARMBaseInstrInfo.h | 221 +- .../llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp | 21 +- .../llvm/lib/Target/ARM/ARMBaseRegisterInfo.h | 10 +- .../llvm/lib/Target/ARM/ARMBlockPlacement.cpp | 228 + .../llvm/lib/Target/ARM/ARMCallLowering.cpp | 68 +- .../llvm/lib/Target/ARM/ARMCallLowering.h | 6 +- .../llvm/lib/Target/ARM/ARMConstantIslandPass.cpp | 79 +- .../llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp | 92 +- .../llvm/lib/Target/ARM/ARMFastISel.cpp | 18 +- .../llvm-project/llvm/lib/Target/ARM/ARMFeatures.h | 1 + .../llvm/lib/Target/ARM/ARMFrameLowering.cpp | 13 +- .../llvm/lib/Target/ARM/ARMFrameLowering.h | 5 +- .../llvm/lib/Target/ARM/ARMHazardRecognizer.cpp | 190 +- .../llvm/lib/Target/ARM/ARMHazardRecognizer.h | 46 +- .../llvm/lib/Target/ARM/ARMISelLowering.cpp | 737 ++- .../llvm/lib/Target/ARM/ARMISelLowering.h | 46 +- .../llvm/lib/Target/ARM/ARMInstrFormats.td | 5 +- .../llvm/lib/Target/ARM/ARMInstrInfo.td | 92 +- .../llvm/lib/Target/ARM/ARMInstrMVE.td | 801 +-- .../llvm/lib/Target/ARM/ARMInstrNEON.td | 147 +- .../llvm/lib/Target/ARM/ARMInstrThumb.td | 13 +- .../llvm/lib/Target/ARM/ARMInstrThumb2.td | 51 +- .../llvm/lib/Target/ARM/ARMInstrVFP.td | 51 +- .../llvm/lib/Target/ARM/ARMInstructionSelector.cpp | 2 - .../llvm/lib/Target/ARM/ARMLegalizerInfo.cpp | 2 +- .../llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp | 449 +- .../llvm/lib/Target/ARM/ARMLowOverheadLoops.cpp | 1525 +++--- .../llvm/lib/Target/ARM/ARMParallelDSP.cpp | 6 +- .../llvm/lib/Target/ARM/ARMPredicates.td | 5 + .../llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp | 12 +- .../llvm/lib/Target/ARM/ARMRegisterInfo.td | 17 + .../llvm/lib/Target/ARM/ARMSLSHardening.cpp | 416 ++ .../llvm/lib/Target/ARM/ARMSchedule.td | 66 +- .../llvm/lib/Target/ARM/ARMScheduleA57.td | 147 +- .../llvm/lib/Target/ARM/ARMScheduleA57WriteRes.td | 11 +- .../llvm/lib/Target/ARM/ARMScheduleA9.td | 4 +- .../llvm/lib/Target/ARM/ARMScheduleM7.td | 488 ++ .../llvm/lib/Target/ARM/ARMScheduleR52.td | 4 +- .../llvm/lib/Target/ARM/ARMScheduleSwift.td | 4 +- .../llvm/lib/Target/ARM/ARMSubtarget.cpp | 14 +- .../llvm/lib/Target/ARM/ARMSubtarget.h | 19 +- .../llvm/lib/Target/ARM/ARMTargetMachine.cpp | 28 +- .../llvm/lib/Target/ARM/ARMTargetMachine.h | 6 + .../llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp | 858 +++- .../llvm/lib/Target/ARM/ARMTargetTransformInfo.h | 58 +- .../llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 28 +- .../Target/ARM/Disassembler/ARMDisassembler.cpp | 7 +- .../Target/ARM/MCTargetDesc/ARMAddressingModes.h | 26 + .../lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp | 1 + .../llvm/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h | 2 +- .../lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp | 2 - .../lib/Target/ARM/MCTargetDesc/ARMInstPrinter.h | 1 + .../lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp | 1 + .../Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp | 132 +- .../lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h | 15 + .../lib/Target/ARM/MVEGatherScatterLowering.cpp | 256 +- .../llvm/lib/Target/ARM/MVETailPredUtils.h | 157 + .../llvm/lib/Target/ARM/MVETailPredication.cpp | 505 +- .../llvm/lib/Target/ARM/MVEVPTBlockPass.cpp | 36 +- .../lib/Target/ARM/MVEVPTOptimisationsPass.cpp | 460 +- .../llvm/lib/Target/ARM/Thumb2InstrInfo.cpp | 47 + .../llvm/lib/Target/ARM/Thumb2InstrInfo.h | 8 + .../llvm/lib/Target/ARM/Thumb2SizeReduction.cpp | 2 +- .../llvm-project/llvm/lib/Target/AVR/AVRDevices.td | 21 +- .../llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp | 147 + .../llvm/lib/Target/AVR/AVRFrameLowering.cpp | 33 +- .../llvm/lib/Target/AVR/AVRISelDAGToDAG.cpp | 5 +- .../llvm/lib/Target/AVR/AVRISelLowering.cpp | 129 +- .../llvm/lib/Target/AVR/AVRISelLowering.h | 7 + .../llvm/lib/Target/AVR/AVRInstrInfo.td | 35 +- .../llvm/lib/Target/AVR/AVRSubtarget.cpp | 6 +- .../llvm/lib/Target/AVR/AVRSubtarget.h | 2 +- .../llvm/lib/Target/AVR/AVRTargetMachine.cpp | 2 +- .../llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp | 5 +- .../lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp | 2 +- .../lib/Target/AVR/MCTargetDesc/AVRAsmBackend.h | 6 +- .../lib/Target/AVR/MCTargetDesc/AVRInstPrinter.h | 1 + .../llvm/lib/Target/AVR/MCTargetDesc/AVRMCExpr.cpp | 14 +- .../Target/AVR/MCTargetDesc/AVRMCTargetDesc.cpp | 2 +- contrib/llvm-project/llvm/lib/Target/BPF/BPF.h | 37 +- .../lib/Target/BPF/BPFAbstractMemberAccess.cpp | 323 +- .../llvm/lib/Target/BPF/BPFAdjustOpt.cpp | 323 ++ contrib/llvm-project/llvm/lib/Target/BPF/BPFCORE.h | 30 + .../llvm/lib/Target/BPF/BPFCheckAndAdjustIR.cpp | 130 + .../llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp | 2 - .../llvm/lib/Target/BPF/BPFISelLowering.cpp | 1 - .../llvm/lib/Target/BPF/BPFInstrFormats.td | 11 +- .../llvm/lib/Target/BPF/BPFInstrInfo.td | 190 +- .../llvm/lib/Target/BPF/BPFMIChecking.cpp | 78 +- .../llvm/lib/Target/BPF/BPFMIPeephole.cpp | 3 + .../llvm/lib/Target/BPF/BPFPreserveDIType.cpp | 131 +- .../llvm/lib/Target/BPF/BPFSubtarget.cpp | 4 +- .../llvm/lib/Target/BPF/BPFSubtarget.h | 2 +- .../llvm/lib/Target/BPF/BPFTargetMachine.cpp | 63 +- .../llvm/lib/Target/BPF/BPFTargetMachine.h | 6 + .../llvm/lib/Target/BPF/BPFTargetTransformInfo.h | 61 + contrib/llvm-project/llvm/lib/Target/BPF/BTF.def | 1 + .../llvm-project/llvm/lib/Target/BPF/BTFDebug.cpp | 106 +- .../llvm-project/llvm/lib/Target/BPF/BTFDebug.h | 21 +- .../Target/BPF/Disassembler/BPFDisassembler.cpp | 4 +- .../lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp | 5 - .../lib/Target/BPF/MCTargetDesc/BPFInstPrinter.h | 1 + .../Target/BPF/MCTargetDesc/BPFMCCodeEmitter.cpp | 11 +- .../Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp | 2 +- contrib/llvm-project/llvm/lib/Target/CSKY/CSKY.td | 32 + .../llvm/lib/Target/CSKY/CSKYInstrFormats.td | 528 ++ .../llvm/lib/Target/CSKY/CSKYInstrInfo.td | 108 + .../llvm/lib/Target/CSKY/CSKYRegisterInfo.td | 182 + .../llvm/lib/Target/CSKY/CSKYTargetMachine.cpp | 68 + .../llvm/lib/Target/CSKY/CSKYTargetMachine.h | 38 + .../Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp | 69 + .../lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.h | 39 + .../CSKY/MCTargetDesc/CSKYELFObjectWriter.cpp | 45 + .../lib/Target/CSKY/MCTargetDesc/CSKYMCAsmInfo.cpp | 25 + .../lib/Target/CSKY/MCTargetDesc/CSKYMCAsmInfo.h | 29 + .../Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.cpp | 71 + .../Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.h | 61 + .../Target/CSKY/MCTargetDesc/CSKYMCTargetDesc.cpp | 62 + .../Target/CSKY/MCTargetDesc/CSKYMCTargetDesc.h | 48 + .../lib/Target/CSKY/TargetInfo/CSKYTargetInfo.cpp | 20 + .../lib/Target/CSKY/TargetInfo/CSKYTargetInfo.h | 20 + .../Target/Hexagon/AsmParser/HexagonAsmParser.cpp | 6 +- .../llvm/lib/Target/Hexagon/BitTracker.cpp | 27 +- .../llvm/lib/Target/Hexagon/BitTracker.h | 17 +- .../Hexagon/Disassembler/HexagonDisassembler.cpp | 6 +- .../llvm-project/llvm/lib/Target/Hexagon/Hexagon.h | 5 +- .../llvm/lib/Target/Hexagon/HexagonBitSimplify.cpp | 76 +- .../llvm/lib/Target/Hexagon/HexagonBitTracker.cpp | 8 +- .../llvm/lib/Target/Hexagon/HexagonBitTracker.h | 4 +- .../llvm/lib/Target/Hexagon/HexagonBlockRanges.cpp | 6 +- .../llvm/lib/Target/Hexagon/HexagonBlockRanges.h | 5 +- .../lib/Target/Hexagon/HexagonCFGOptimizer.cpp | 1 + .../llvm/lib/Target/Hexagon/HexagonCommonGEP.cpp | 16 +- .../lib/Target/Hexagon/HexagonConstExtenders.cpp | 12 +- .../lib/Target/Hexagon/HexagonConstPropagation.cpp | 41 +- .../lib/Target/Hexagon/HexagonCopyToCombine.cpp | 2 + .../llvm/lib/Target/Hexagon/HexagonEarlyIfConv.cpp | 6 +- .../lib/Target/Hexagon/HexagonExpandCondsets.cpp | 91 +- .../lib/Target/Hexagon/HexagonFrameLowering.cpp | 13 +- .../llvm/lib/Target/Hexagon/HexagonFrameLowering.h | 5 +- .../llvm/lib/Target/Hexagon/HexagonGenInsert.cpp | 16 +- .../lib/Target/Hexagon/HexagonGenPredicate.cpp | 17 +- .../lib/Target/Hexagon/HexagonHardwareLoops.cpp | 6 +- .../lib/Target/Hexagon/HexagonISelDAGToDAG.cpp | 4 +- .../lib/Target/Hexagon/HexagonISelDAGToDAGHVX.cpp | 229 +- .../lib/Target/Hexagon/HexagonISelLowering.cpp | 162 +- .../llvm/lib/Target/Hexagon/HexagonISelLowering.h | 909 ++-- .../lib/Target/Hexagon/HexagonISelLoweringHVX.cpp | 738 ++- .../llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp | 7 +- .../llvm/lib/Target/Hexagon/HexagonInstrInfo.h | 4 +- .../lib/Target/Hexagon/HexagonIntrinsicsV60.td | 2 +- .../Target/Hexagon/HexagonLoopIdiomRecognition.cpp | 265 +- .../Target/Hexagon/HexagonLoopIdiomRecognition.h | 24 + .../llvm/lib/Target/Hexagon/HexagonMCInstLower.cpp | 2 +- .../llvm/lib/Target/Hexagon/HexagonOptAddrMode.cpp | 2 +- .../Target/Hexagon/HexagonOptimizeSZextends.cpp | 4 +- .../llvm/lib/Target/Hexagon/HexagonPatterns.td | 119 +- .../llvm/lib/Target/Hexagon/HexagonPatternsHVX.td | 240 +- .../llvm/lib/Target/Hexagon/HexagonPeephole.cpp | 11 +- .../lib/Target/Hexagon/HexagonRegisterInfo.cpp | 2 +- .../llvm/lib/Target/Hexagon/HexagonSplitDouble.cpp | 23 +- .../llvm/lib/Target/Hexagon/HexagonSubtarget.cpp | 89 +- .../llvm/lib/Target/Hexagon/HexagonSubtarget.h | 30 +- .../lib/Target/Hexagon/HexagonTargetMachine.cpp | 71 +- .../llvm/lib/Target/Hexagon/HexagonTargetMachine.h | 2 + .../lib/Target/Hexagon/HexagonTargetObjectFile.cpp | 1 + .../Target/Hexagon/HexagonTargetTransformInfo.cpp | 47 +- .../Target/Hexagon/HexagonTargetTransformInfo.h | 11 +- .../lib/Target/Hexagon/HexagonVectorCombine.cpp | 1487 ++++++ .../Hexagon/HexagonVectorLoopCarriedReuse.cpp | 165 +- .../Target/Hexagon/HexagonVectorLoopCarriedReuse.h | 139 + .../Hexagon/MCTargetDesc/HexagonAsmBackend.cpp | 4 +- .../Hexagon/MCTargetDesc/HexagonInstPrinter.h | 1 + .../Hexagon/MCTargetDesc/HexagonMCCompound.cpp | 19 +- .../Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp | 2 +- .../Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp | 3 +- .../Hexagon/MCTargetDesc/HexagonShuffler.cpp | 5 +- .../llvm/lib/Target/Hexagon/RDFDeadCode.cpp | 3 +- .../llvm/lib/Target/Lanai/LanaiISelLowering.cpp | 5 +- .../llvm/lib/Target/Lanai/LanaiSubtarget.cpp | 4 +- .../llvm/lib/Target/Lanai/LanaiSubtarget.h | 3 +- .../llvm/lib/Target/Lanai/LanaiTargetMachine.cpp | 4 +- .../llvm/lib/Target/Lanai/LanaiTargetMachine.h | 2 - .../lib/Target/Lanai/LanaiTargetTransformInfo.h | 3 +- .../Target/Lanai/MCTargetDesc/LanaiAsmBackend.cpp | 5 - .../Target/Lanai/MCTargetDesc/LanaiInstPrinter.h | 1 + .../Lanai/MCTargetDesc/LanaiMCTargetDesc.cpp | 2 +- .../Target/MSP430/AsmParser/MSP430AsmParser.cpp | 1 - .../MSP430/MCTargetDesc/MSP430AsmBackend.cpp | 5 - .../Target/MSP430/MCTargetDesc/MSP430InstPrinter.h | 1 + .../MSP430/MCTargetDesc/MSP430MCTargetDesc.cpp | 2 +- .../llvm/lib/Target/MSP430/MSP430ISelLowering.cpp | 12 +- .../llvm/lib/Target/MSP430/MSP430Subtarget.cpp | 4 +- .../llvm/lib/Target/MSP430/MSP430Subtarget.h | 2 +- .../llvm/lib/Target/MSP430/MSP430TargetMachine.h | 2 +- .../lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 8 +- .../lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp | 1 - .../lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h | 9 - .../lib/Target/Mips/MCTargetDesc/MipsInstPrinter.h | 1 + .../Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp | 2 +- contrib/llvm-project/llvm/lib/Target/Mips/Mips.td | 2 +- .../llvm/lib/Target/Mips/MipsAsmPrinter.cpp | 2 +- .../llvm/lib/Target/Mips/MipsCallLowering.cpp | 82 +- .../llvm/lib/Target/Mips/MipsCallLowering.h | 7 +- .../lib/Target/Mips/MipsConstantIslandPass.cpp | 9 +- .../llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp | 19 +- .../llvm/lib/Target/Mips/MipsExpandPseudo.cpp | 4 +- .../llvm/lib/Target/Mips/MipsISelLowering.cpp | 21 +- .../llvm/lib/Target/Mips/MipsISelLowering.h | 14 - .../llvm/lib/Target/Mips/MipsInstrFPU.td | 9 + .../llvm/lib/Target/Mips/MipsInstrInfo.cpp | 2 +- .../llvm/lib/Target/Mips/MipsInstrInfo.td | 2 +- .../llvm/lib/Target/Mips/MipsLegalizerInfo.cpp | 11 +- .../llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp | 13 +- .../llvm/lib/Target/Mips/MipsRegisterBankInfo.h | 2 +- .../llvm/lib/Target/Mips/MipsSEFrameLowering.cpp | 11 +- .../llvm/lib/Target/Mips/MipsSEFrameLowering.h | 5 +- .../llvm/lib/Target/Mips/MipsSEISelLowering.cpp | 4 +- .../llvm/lib/Target/Mips/MipsSchedule.td | 3 + .../llvm/lib/Target/Mips/MipsScheduleGeneric.td | 5 +- .../llvm/lib/Target/Mips/MipsScheduleP5600.td | 4 +- .../llvm/lib/Target/Mips/MipsSubtarget.cpp | 32 +- .../llvm/lib/Target/Mips/MipsSubtarget.h | 2 +- .../llvm/lib/Target/Mips/MipsTargetMachine.cpp | 29 +- .../llvm/lib/Target/Mips/MipsTargetMachine.h | 8 + .../Target/NVPTX/MCTargetDesc/NVPTXInstPrinter.h | 1 + .../Target/NVPTX/MCTargetDesc/NVPTXMCAsmInfo.cpp | 1 + .../NVPTX/MCTargetDesc/NVPTXMCTargetDesc.cpp | 2 +- contrib/llvm-project/llvm/lib/Target/NVPTX/NVPTX.h | 19 + .../llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp | 6 +- .../llvm/lib/Target/NVPTX/NVPTXFrameLowering.cpp | 9 +- .../llvm/lib/Target/NVPTX/NVPTXFrameLowering.h | 5 +- .../llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp | 9 +- .../llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp | 37 +- .../llvm/lib/Target/NVPTX/NVPTXISelLowering.h | 3 +- .../llvm/lib/Target/NVPTX/NVPTXInstrFormats.td | 32 +- .../llvm/lib/Target/NVPTX/NVPTXInstrInfo.td | 36 +- .../llvm/lib/Target/NVPTX/NVPTXIntrinsics.td | 68 +- .../llvm/lib/Target/NVPTX/NVPTXLowerArgs.cpp | 9 +- .../lib/Target/NVPTX/NVPTXPrologEpilogPass.cpp | 3 +- .../llvm/lib/Target/NVPTX/NVPTXRegisterInfo.td | 4 +- .../llvm/lib/Target/NVPTX/NVPTXSubtarget.cpp | 8 +- .../llvm/lib/Target/NVPTX/NVPTXSubtarget.h | 2 +- .../llvm/lib/Target/NVPTX/NVPTXTargetMachine.cpp | 31 +- .../llvm/lib/Target/NVPTX/NVPTXTargetMachine.h | 4 +- .../lib/Target/NVPTX/NVPTXTargetTransformInfo.cpp | 257 + .../lib/Target/NVPTX/NVPTXTargetTransformInfo.h | 3 + .../llvm/lib/Target/NVPTX/NVVMIntrRange.cpp | 40 +- .../llvm/lib/Target/NVPTX/NVVMReflect.cpp | 15 +- .../lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp | 257 +- .../PowerPC/Disassembler/PPCDisassembler.cpp | 38 +- .../lib/Target/PowerPC/GISel/PPCCallLowering.cpp | 53 + .../lib/Target/PowerPC/GISel/PPCCallLowering.h | 40 + .../PowerPC/GISel/PPCInstructionSelector.cpp | 92 + .../lib/Target/PowerPC/GISel/PPCLegalizerInfo.cpp | 20 + .../lib/Target/PowerPC/GISel/PPCLegalizerInfo.h | 28 + .../Target/PowerPC/GISel/PPCRegisterBankInfo.cpp | 27 + .../lib/Target/PowerPC/GISel/PPCRegisterBankInfo.h | 39 + .../lib/Target/PowerPC/GISel/PPCRegisterBanks.td | 15 + .../Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp | 10 +- .../PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp | 24 + .../Target/PowerPC/MCTargetDesc/PPCELFStreamer.cpp | 118 + .../Target/PowerPC/MCTargetDesc/PPCELFStreamer.h | 7 + .../Target/PowerPC/MCTargetDesc/PPCFixupKinds.h | 3 + .../Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp | 163 +- .../Target/PowerPC/MCTargetDesc/PPCInstPrinter.h | 86 +- .../Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp | 5 +- .../lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.h | 1 - .../PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp | 63 +- .../Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h | 12 +- .../PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp | 26 +- .../Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h | 13 +- .../PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp | 11 +- .../llvm/lib/Target/PowerPC/P9InstrResources.td | 2 +- contrib/llvm-project/llvm/lib/Target/PowerPC/PPC.h | 63 +- .../llvm-project/llvm/lib/Target/PowerPC/PPC.td | 56 +- .../llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp | 674 ++- .../llvm/lib/Target/PowerPC/PPCBoolRetToInt.cpp | 11 +- .../llvm/lib/Target/PowerPC/PPCCCState.cpp | 2 +- .../llvm/lib/Target/PowerPC/PPCCTRLoops.cpp | 92 +- .../llvm/lib/Target/PowerPC/PPCCallingConv.td | 28 +- .../llvm/lib/Target/PowerPC/PPCEarlyReturn.cpp | 26 +- .../llvm/lib/Target/PowerPC/PPCFastISel.cpp | 19 +- .../llvm/lib/Target/PowerPC/PPCFrameLowering.cpp | 586 +-- .../llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp | 841 ++-- .../llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 3810 ++++++-------- .../llvm/lib/Target/PowerPC/PPCISelLowering.h | 130 +- .../llvm/lib/Target/PowerPC/PPCInstr64Bit.td | 99 +- .../llvm/lib/Target/PowerPC/PPCInstrAltivec.td | 170 +- .../llvm/lib/Target/PowerPC/PPCInstrFormats.td | 55 +- .../llvm/lib/Target/PowerPC/PPCInstrHTM.td | 5 +- .../llvm/lib/Target/PowerPC/PPCInstrInfo.cpp | 1019 +++- .../llvm/lib/Target/PowerPC/PPCInstrInfo.h | 106 +- .../llvm/lib/Target/PowerPC/PPCInstrInfo.td | 441 +- .../llvm/lib/Target/PowerPC/PPCInstrPrefix.td | 1735 ++++++- .../llvm/lib/Target/PowerPC/PPCInstrQPX.td | 1212 ----- .../llvm/lib/Target/PowerPC/PPCInstrSPE.td | 10 - .../llvm/lib/Target/PowerPC/PPCInstrVSX.td | 375 +- .../lib/Target/PowerPC/PPCLoopInstrFormPrep.cpp | 40 +- .../lib/Target/PowerPC/PPCLowerMASSVEntries.cpp | 6 +- .../llvm/lib/Target/PowerPC/PPCMCInstLower.cpp | 14 +- .../llvm/lib/Target/PowerPC/PPCMIPeephole.cpp | 278 +- .../lib/Target/PowerPC/PPCMachineFunctionInfo.cpp | 34 + .../lib/Target/PowerPC/PPCMachineFunctionInfo.h | 37 +- .../lib/Target/PowerPC/PPCMachineScheduler.cpp | 140 +- .../llvm/lib/Target/PowerPC/PPCMacroFusion.cpp | 4 +- .../llvm/lib/Target/PowerPC/PPCPreEmitPeephole.cpp | 240 +- .../llvm/lib/Target/PowerPC/PPCQPXLoadSplat.cpp | 161 - .../lib/Target/PowerPC/PPCReduceCRLogicals.cpp | 4 +- .../llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp | 170 +- .../llvm/lib/Target/PowerPC/PPCRegisterInfo.h | 27 +- .../llvm/lib/Target/PowerPC/PPCRegisterInfo.td | 113 +- .../llvm/lib/Target/PowerPC/PPCScheduleP9.td | 11 +- .../llvm/lib/Target/PowerPC/PPCSubtarget.cpp | 56 +- .../llvm/lib/Target/PowerPC/PPCSubtarget.h | 44 +- .../llvm/lib/Target/PowerPC/PPCTLSDynamicCall.cpp | 49 +- .../llvm/lib/Target/PowerPC/PPCTargetMachine.cpp | 111 +- .../llvm/lib/Target/PowerPC/PPCTargetMachine.h | 5 + .../lib/Target/PowerPC/PPCTargetTransformInfo.cpp | 326 +- .../lib/Target/PowerPC/PPCTargetTransformInfo.h | 14 +- .../llvm/lib/Target/PowerPC/PPCVSXFMAMutate.cpp | 6 +- .../llvm/lib/Target/PowerPC/PPCVSXSwapRemoval.cpp | 30 +- .../PowerPC/TargetInfo/PowerPCTargetInfo.cpp | 9 +- .../Target/PowerPC/TargetInfo/PowerPCTargetInfo.h | 1 + .../lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp | 657 ++- .../RISCV/Disassembler/RISCVDisassembler.cpp | 30 +- .../Target/RISCV/MCTargetDesc/RISCVAsmBackend.h | 2 +- .../Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp | 142 + .../lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h | 406 ++ .../Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp | 4 +- .../Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp | 39 +- .../Target/RISCV/MCTargetDesc/RISCVInstPrinter.h | 5 +- .../RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp | 15 +- .../lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp | 1 - .../RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp | 7 +- .../lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp | 91 + .../lib/Target/RISCV/MCTargetDesc/RISCVMatInt.h | 43 + .../RISCV/MCTargetDesc/RISCVTargetStreamer.cpp | 34 +- contrib/llvm-project/llvm/lib/Target/RISCV/RISCV.h | 5 +- .../llvm-project/llvm/lib/Target/RISCV/RISCV.td | 92 +- .../llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp | 4 +- .../llvm/lib/Target/RISCV/RISCVCallLowering.cpp | 11 +- .../llvm/lib/Target/RISCV/RISCVCallLowering.h | 6 +- .../llvm/lib/Target/RISCV/RISCVCleanupVSETVLI.cpp | 154 + .../lib/Target/RISCV/RISCVExpandPseudoInsts.cpp | 65 + .../llvm/lib/Target/RISCV/RISCVFrameLowering.cpp | 145 +- .../llvm/lib/Target/RISCV/RISCVFrameLowering.h | 5 +- .../llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp | 1095 ++-- .../llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h | 27 +- .../llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 1969 +++++++- .../llvm/lib/Target/RISCV/RISCVISelLowering.h | 125 +- .../llvm/lib/Target/RISCV/RISCVInstrFormats.td | 85 +- .../llvm/lib/Target/RISCV/RISCVInstrFormatsV.td | 141 +- .../llvm/lib/Target/RISCV/RISCVInstrInfo.cpp | 117 +- .../llvm/lib/Target/RISCV/RISCVInstrInfo.h | 21 +- .../llvm/lib/Target/RISCV/RISCVInstrInfo.td | 141 +- .../llvm/lib/Target/RISCV/RISCVInstrInfoB.td | 1029 ++-- .../llvm/lib/Target/RISCV/RISCVInstrInfoC.td | 22 +- .../llvm/lib/Target/RISCV/RISCVInstrInfoD.td | 22 +- .../llvm/lib/Target/RISCV/RISCVInstrInfoF.td | 30 +- .../llvm/lib/Target/RISCV/RISCVInstrInfoM.td | 6 +- .../llvm/lib/Target/RISCV/RISCVInstrInfoV.td | 695 ++- .../lib/Target/RISCV/RISCVInstrInfoVPseudos.td | 4416 +++++++++++++++++ .../lib/Target/RISCV/RISCVInstrInfoVSDPatterns.td | 643 +++ .../llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td | 371 ++ .../llvm/lib/Target/RISCV/RISCVMCInstLower.cpp | 98 + .../llvm/lib/Target/RISCV/RISCVMergeBaseOffset.cpp | 4 +- .../llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp | 23 +- .../llvm/lib/Target/RISCV/RISCVRegisterInfo.td | 389 +- .../llvm/lib/Target/RISCV/RISCVSchedRocket.td | 233 + .../llvm/lib/Target/RISCV/RISCVSchedRocket32.td | 227 - .../llvm/lib/Target/RISCV/RISCVSchedRocket64.td | 228 - .../llvm/lib/Target/RISCV/RISCVSchedSiFive7.td | 222 + .../llvm/lib/Target/RISCV/RISCVSchedule.td | 2 +- .../llvm/lib/Target/RISCV/RISCVSubtarget.cpp | 14 +- .../llvm/lib/Target/RISCV/RISCVSubtarget.h | 20 +- .../llvm/lib/Target/RISCV/RISCVSystemOperands.td | 2 + .../llvm/lib/Target/RISCV/RISCVTargetMachine.cpp | 49 +- .../llvm/lib/Target/RISCV/RISCVTargetMachine.h | 5 +- .../lib/Target/RISCV/RISCVTargetTransformInfo.cpp | 8 +- .../lib/Target/RISCV/RISCVTargetTransformInfo.h | 5 +- .../llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.cpp | 81 - .../llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h | 223 - .../llvm/lib/Target/RISCV/Utils/RISCVMatInt.cpp | 93 - .../llvm/lib/Target/RISCV/Utils/RISCVMatInt.h | 44 - .../lib/Target/Sparc/AsmParser/SparcAsmParser.cpp | 158 +- .../llvm/lib/Target/Sparc/LeonPasses.cpp | 7 +- .../llvm/lib/Target/Sparc/LeonPasses.h | 9 +- .../Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp | 6 - .../Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp | 30 +- .../Target/Sparc/MCTargetDesc/SparcInstPrinter.h | 1 + .../Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp | 52 +- .../lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp | 77 +- .../lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h | 1 + .../Sparc/MCTargetDesc/SparcMCTargetDesc.cpp | 2 +- .../llvm/lib/Target/Sparc/SparcAsmPrinter.cpp | 2 +- .../llvm/lib/Target/Sparc/SparcFrameLowering.cpp | 10 +- .../llvm/lib/Target/Sparc/SparcFrameLowering.h | 5 +- .../llvm/lib/Target/Sparc/SparcISelLowering.cpp | 56 +- .../llvm/lib/Target/Sparc/SparcInstr64Bit.td | 6 +- .../llvm/lib/Target/Sparc/SparcInstrFormats.td | 4 +- .../llvm/lib/Target/Sparc/SparcInstrInfo.td | 25 +- .../llvm/lib/Target/Sparc/SparcRegisterInfo.cpp | 2 +- .../llvm/lib/Target/Sparc/SparcSubtarget.cpp | 8 +- .../llvm/lib/Target/Sparc/SparcSubtarget.h | 4 +- .../llvm/lib/Target/Sparc/SparcTargetMachine.cpp | 14 +- .../Target/SystemZ/AsmParser/SystemZAsmParser.cpp | 36 +- .../SystemZ/Disassembler/SystemZDisassembler.cpp | 4 +- .../SystemZ/MCTargetDesc/SystemZInstPrinter.h | 1 + .../SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp | 4 - .../SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp | 2 + .../SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp | 2 +- .../llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp | 21 +- .../llvm/lib/Target/SystemZ/SystemZElimCompare.cpp | 16 +- .../llvm/lib/Target/SystemZ/SystemZFeatures.td | 2 +- .../lib/Target/SystemZ/SystemZFrameLowering.cpp | 88 +- .../llvm/lib/Target/SystemZ/SystemZFrameLowering.h | 12 +- .../lib/Target/SystemZ/SystemZHazardRecognizer.cpp | 6 +- .../lib/Target/SystemZ/SystemZHazardRecognizer.h | 2 +- .../lib/Target/SystemZ/SystemZISelDAGToDAG.cpp | 44 + .../lib/Target/SystemZ/SystemZISelLowering.cpp | 101 +- .../llvm/lib/Target/SystemZ/SystemZISelLowering.h | 5 +- .../llvm/lib/Target/SystemZ/SystemZInstrFormats.td | 54 + .../llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp | 12 +- .../llvm/lib/Target/SystemZ/SystemZInstrInfo.td | 104 +- .../llvm/lib/Target/SystemZ/SystemZInstrVector.td | 8 +- .../lib/Target/SystemZ/SystemZMachineScheduler.cpp | 1 + .../llvm/lib/Target/SystemZ/SystemZOperators.td | 35 +- .../lib/Target/SystemZ/SystemZRegisterInfo.cpp | 14 +- .../llvm/lib/Target/SystemZ/SystemZScheduleZ13.td | 2 +- .../llvm/lib/Target/SystemZ/SystemZScheduleZ14.td | 2 +- .../llvm/lib/Target/SystemZ/SystemZScheduleZ15.td | 2 +- .../llvm/lib/Target/SystemZ/SystemZScheduleZ196.td | 2 +- .../lib/Target/SystemZ/SystemZScheduleZEC12.td | 2 +- .../lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp | 5 +- .../llvm/lib/Target/SystemZ/SystemZSubtarget.cpp | 22 +- .../llvm/lib/Target/SystemZ/SystemZSubtarget.h | 2 +- .../lib/Target/SystemZ/SystemZTargetMachine.cpp | 10 +- .../Target/SystemZ/SystemZTargetTransformInfo.cpp | 33 +- .../Target/SystemZ/SystemZTargetTransformInfo.h | 6 +- .../llvm/lib/Target/TargetLoweringObjectFile.cpp | 58 + .../llvm-project/llvm/lib/Target/TargetMachine.cpp | 85 +- .../llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp | 103 +- .../lib/Target/VE/Disassembler/VEDisassembler.cpp | 55 +- contrib/llvm-project/llvm/lib/Target/VE/LVLGen.cpp | 137 + .../lib/Target/VE/MCTargetDesc/VEInstPrinter.h | 1 + .../lib/Target/VE/MCTargetDesc/VEMCTargetDesc.cpp | 6 +- .../llvm/lib/Target/VE/TargetInfo/VETargetInfo.cpp | 2 +- contrib/llvm-project/llvm/lib/Target/VE/VE.h | 23 +- contrib/llvm-project/llvm/lib/Target/VE/VE.td | 5 +- .../llvm/lib/Target/VE/VEAsmPrinter.cpp | 48 +- .../llvm/lib/Target/VE/VECallingConv.td | 138 +- .../llvm/lib/Target/VE/VEFrameLowering.cpp | 402 +- .../llvm/lib/Target/VE/VEFrameLowering.h | 9 +- .../llvm/lib/Target/VE/VEISelDAGToDAG.cpp | 40 +- .../llvm/lib/Target/VE/VEISelLowering.cpp | 2238 ++++++++- .../llvm/lib/Target/VE/VEISelLowering.h | 150 +- .../llvm/lib/Target/VE/VEInstrBuilder.h | 41 + .../llvm/lib/Target/VE/VEInstrFormats.td | 89 + .../llvm/lib/Target/VE/VEInstrInfo.cpp | 534 +- .../llvm-project/llvm/lib/Target/VE/VEInstrInfo.h | 32 + .../llvm-project/llvm/lib/Target/VE/VEInstrInfo.td | 845 +++- .../llvm/lib/Target/VE/VEInstrIntrinsicVL.gen.td | 1604 ++++++ .../llvm/lib/Target/VE/VEInstrIntrinsicVL.td | 64 + .../llvm/lib/Target/VE/VEInstrPatternsVec.td | 91 + .../llvm-project/llvm/lib/Target/VE/VEInstrVec.td | 1510 ++++++ .../llvm/lib/Target/VE/VEMCInstLower.cpp | 8 +- .../llvm/lib/Target/VE/VERegisterInfo.cpp | 105 +- .../llvm/lib/Target/VE/VERegisterInfo.h | 2 - .../llvm/lib/Target/VE/VERegisterInfo.td | 104 +- .../llvm/lib/Target/VE/VESubtarget.cpp | 64 +- .../llvm-project/llvm/lib/Target/VE/VESubtarget.h | 21 +- .../llvm/lib/Target/VE/VETargetMachine.cpp | 32 +- .../llvm/lib/Target/VE/VETargetTransformInfo.h | 25 +- .../llvm/lib/Target/VE/VVPInstrInfo.td | 46 + .../llvm/lib/Target/VE/VVPInstrPatternsVec.td | 71 + .../llvm-project/llvm/lib/Target/VE/VVPNodes.def | 41 + .../WebAssembly/AsmParser/WebAssemblyAsmParser.cpp | 140 +- .../Disassembler/WebAssemblyDisassembler.cpp | 23 + .../MCTargetDesc/WebAssemblyAsmBackend.cpp | 5 - .../MCTargetDesc/WebAssemblyInstPrinter.cpp | 116 +- .../MCTargetDesc/WebAssemblyInstPrinter.h | 7 +- .../MCTargetDesc/WebAssemblyMCCodeEmitter.cpp | 12 +- .../MCTargetDesc/WebAssemblyMCTargetDesc.cpp | 8 +- .../MCTargetDesc/WebAssemblyMCTargetDesc.h | 95 +- .../MCTargetDesc/WebAssemblyTargetStreamer.cpp | 13 +- .../MCTargetDesc/WebAssemblyTargetStreamer.h | 5 + .../MCTargetDesc/WebAssemblyWasmObjectWriter.cpp | 18 +- .../Target/WebAssembly/WebAssemblyAsmPrinter.cpp | 133 +- .../lib/Target/WebAssembly/WebAssemblyAsmPrinter.h | 3 + .../lib/Target/WebAssembly/WebAssemblyCFGSort.cpp | 91 +- .../Target/WebAssembly/WebAssemblyCFGStackify.cpp | 676 +-- .../WebAssembly/WebAssemblyDebugValueManager.cpp | 14 +- .../WebAssembly/WebAssemblyExplicitLocals.cpp | 34 +- .../lib/Target/WebAssembly/WebAssemblyFastISel.cpp | 44 +- .../WebAssembly/WebAssemblyFixBrTableDefaults.cpp | 45 +- .../llvm/lib/Target/WebAssembly/WebAssemblyISD.def | 5 + .../Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp | 38 - .../Target/WebAssembly/WebAssemblyISelLowering.cpp | 329 +- .../Target/WebAssembly/WebAssemblyISelLowering.h | 1 + .../Target/WebAssembly/WebAssemblyInstrAtomics.td | 212 +- .../WebAssembly/WebAssemblyInstrBulkMemory.td | 2 +- .../Target/WebAssembly/WebAssemblyInstrControl.td | 45 +- .../Target/WebAssembly/WebAssemblyInstrInfo.cpp | 42 +- .../lib/Target/WebAssembly/WebAssemblyInstrInfo.td | 39 +- .../Target/WebAssembly/WebAssemblyInstrMemory.td | 2 +- .../lib/Target/WebAssembly/WebAssemblyInstrRef.td | 36 +- .../lib/Target/WebAssembly/WebAssemblyInstrSIMD.td | 1199 +++-- .../Target/WebAssembly/WebAssemblyInstrTable.td | 64 + .../WebAssembly/WebAssemblyLateEHPrepare.cpp | 325 +- .../WebAssemblyLowerEmscriptenEHSjLj.cpp | 123 +- .../Target/WebAssembly/WebAssemblyMCInstLower.cpp | 49 +- .../WebAssemblyOptimizeLiveIntervals.cpp | 2 +- .../lib/Target/WebAssembly/WebAssemblyPeephole.cpp | 7 +- .../Target/WebAssembly/WebAssemblyRegColoring.cpp | 22 +- .../Target/WebAssembly/WebAssemblyRegStackify.cpp | 44 +- .../Target/WebAssembly/WebAssemblyRegisterInfo.td | 6 +- .../Target/WebAssembly/WebAssemblySortRegion.cpp | 78 + .../lib/Target/WebAssembly/WebAssemblySortRegion.h | 91 + .../Target/WebAssembly/WebAssemblySubtarget.cpp | 9 +- .../lib/Target/WebAssembly/WebAssemblySubtarget.h | 2 +- .../WebAssembly/WebAssemblyTargetMachine.cpp | 34 +- .../Target/WebAssembly/WebAssemblyTargetMachine.h | 1 + .../WebAssembly/WebAssemblyTargetTransformInfo.cpp | 18 + .../WebAssembly/WebAssemblyTargetTransformInfo.h | 3 + .../Target/WebAssembly/WebAssemblyUtilities.cpp | 33 + .../lib/Target/WebAssembly/WebAssemblyUtilities.h | 28 +- .../llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp | 1218 ++++- .../Target/X86/Disassembler/X86Disassembler.cpp | 7 +- .../Target/X86/MCTargetDesc/X86ATTInstPrinter.cpp | 11 + .../Target/X86/MCTargetDesc/X86ATTInstPrinter.h | 1 + .../lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp | 42 +- .../llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h | 25 +- .../Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp | 9 + .../X86/MCTargetDesc/X86InstPrinterCommon.cpp | 19 + .../X86/MCTargetDesc/X86IntelInstPrinter.cpp | 10 + .../Target/X86/MCTargetDesc/X86IntelInstPrinter.h | 1 + .../Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp | 225 +- .../Target/X86/MCTargetDesc/X86MCTargetDesc.cpp | 13 +- .../lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h | 6 +- .../X86/MCTargetDesc/X86MachObjectWriter.cpp | 2 +- .../Target/X86/MCTargetDesc/X86ShuffleDecode.cpp | 2 +- .../Target/X86/MCTargetDesc/X86WinCOFFStreamer.cpp | 9 +- contrib/llvm-project/llvm/lib/Target/X86/X86.h | 11 +- contrib/llvm-project/llvm/lib/Target/X86/X86.td | 868 ++-- .../llvm/lib/Target/X86/X86AsmPrinter.cpp | 10 +- .../llvm/lib/Target/X86/X86AsmPrinter.h | 6 +- .../Target/X86/X86AvoidStoreForwardingBlocks.cpp | 4 +- .../lib/Target/X86/X86CallFrameOptimization.cpp | 23 +- .../llvm/lib/Target/X86/X86CallLowering.cpp | 70 +- .../llvm/lib/Target/X86/X86CallLowering.h | 6 +- .../llvm/lib/Target/X86/X86CallingConv.cpp | 10 + .../llvm/lib/Target/X86/X86CallingConv.td | 15 +- .../llvm/lib/Target/X86/X86CmovConversion.cpp | 6 +- .../llvm/lib/Target/X86/X86CondBrFolding.cpp | 579 --- .../llvm/lib/Target/X86/X86DomainReassignment.cpp | 48 +- .../llvm/lib/Target/X86/X86EvexToVex.cpp | 31 +- .../llvm/lib/Target/X86/X86ExpandPseudo.cpp | 77 +- .../llvm/lib/Target/X86/X86FastISel.cpp | 104 +- .../llvm/lib/Target/X86/X86FixupBWInsts.cpp | 5 +- .../llvm/lib/Target/X86/X86FixupLEAs.cpp | 15 +- .../llvm/lib/Target/X86/X86FixupSetCC.cpp | 17 +- .../llvm/lib/Target/X86/X86FlagsCopyLowering.cpp | 8 +- .../llvm/lib/Target/X86/X86FrameLowering.cpp | 168 +- .../llvm/lib/Target/X86/X86FrameLowering.h | 23 +- .../llvm/lib/Target/X86/X86ISelDAGToDAG.cpp | 648 ++- .../llvm/lib/Target/X86/X86ISelLowering.cpp | 4966 +++++++++++------- .../llvm/lib/Target/X86/X86ISelLowering.h | 60 +- .../lib/Target/X86/X86IndirectBranchTracking.cpp | 2 +- .../llvm/lib/Target/X86/X86IndirectThunks.cpp | 1 - .../llvm/lib/Target/X86/X86InsertPrefetch.cpp | 8 +- .../llvm/lib/Target/X86/X86InsertWait.cpp | 6 +- .../lib/Target/X86/X86InstCombineIntrinsic.cpp | 2017 ++++++++ .../llvm/lib/Target/X86/X86InstrAMX.td | 54 +- .../llvm/lib/Target/X86/X86InstrAVX512.td | 738 +-- .../llvm/lib/Target/X86/X86InstrArithmetic.td | 9 + .../llvm/lib/Target/X86/X86InstrCompiler.td | 192 +- .../llvm/lib/Target/X86/X86InstrFMA.td | 22 +- .../llvm/lib/Target/X86/X86InstrFPStack.td | 8 +- .../llvm/lib/Target/X86/X86InstrFoldTables.cpp | 14 + .../llvm/lib/Target/X86/X86InstrFormats.td | 6 + .../llvm/lib/Target/X86/X86InstrFragmentsSIMD.td | 36 +- .../llvm/lib/Target/X86/X86InstrInfo.cpp | 255 +- .../llvm/lib/Target/X86/X86InstrInfo.h | 32 +- .../llvm/lib/Target/X86/X86InstrInfo.td | 150 +- .../llvm-project/llvm/lib/Target/X86/X86InstrKL.td | 86 + .../llvm/lib/Target/X86/X86InstrMMX.td | 2 + .../llvm/lib/Target/X86/X86InstrSNP.td | 47 + .../llvm/lib/Target/X86/X86InstrSSE.td | 221 +- .../llvm/lib/Target/X86/X86InstrSVM.td | 28 +- .../llvm/lib/Target/X86/X86InstrSystem.td | 14 +- .../llvm/lib/Target/X86/X86InstrTDX.td | 39 + .../llvm/lib/Target/X86/X86InstructionSelector.cpp | 99 +- .../llvm/lib/Target/X86/X86InterleavedAccess.cpp | 24 +- .../llvm/lib/Target/X86/X86IntrinsicsInfo.h | 40 +- .../llvm/lib/Target/X86/X86LegalizerInfo.cpp | 35 +- .../X86/X86LoadValueInjectionLoadHardening.cpp | 184 +- .../X86/X86LoadValueInjectionRetHardening.cpp | 81 +- .../llvm/lib/Target/X86/X86LowerAMXType.cpp | 351 ++ .../llvm/lib/Target/X86/X86MCInstLower.cpp | 69 +- .../llvm/lib/Target/X86/X86PartialReduction.cpp | 9 +- .../llvm/lib/Target/X86/X86PreTileConfig.cpp | 265 + .../llvm/lib/Target/X86/X86RegisterInfo.cpp | 139 +- .../llvm/lib/Target/X86/X86RegisterInfo.h | 14 +- .../llvm/lib/Target/X86/X86RegisterInfo.td | 12 +- .../llvm/lib/Target/X86/X86SelectionDAGInfo.cpp | 8 + .../Target/X86/X86ShuffleDecodeConstantPool.cpp | 53 +- .../lib/Target/X86/X86ShuffleDecodeConstantPool.h | 8 - ...86SpeculativeExecutionSideEffectSuppression.cpp | 1 + .../lib/Target/X86/X86SpeculativeLoadHardening.cpp | 17 +- .../llvm/lib/Target/X86/X86Subtarget.cpp | 102 +- .../llvm/lib/Target/X86/X86Subtarget.h | 68 +- .../llvm/lib/Target/X86/X86TargetMachine.cpp | 117 +- .../llvm/lib/Target/X86/X86TargetMachine.h | 2 + .../llvm/lib/Target/X86/X86TargetObjectFile.cpp | 8 - .../llvm/lib/Target/X86/X86TargetObjectFile.h | 2 +- .../llvm/lib/Target/X86/X86TargetTransformInfo.cpp | 358 +- .../llvm/lib/Target/X86/X86TargetTransformInfo.h | 26 +- .../llvm/lib/Target/X86/X86TileConfig.cpp | 248 + .../llvm/lib/Target/X86/X86WinEHState.cpp | 2 +- .../Target/XCore/MCTargetDesc/XCoreInstPrinter.h | 1 + .../XCore/MCTargetDesc/XCoreMCTargetDesc.cpp | 2 +- .../llvm/lib/Target/XCore/XCoreISelLowering.cpp | 18 +- .../lib/Target/XCore/XCoreLowerThreadLocal.cpp | 56 +- .../llvm/lib/Target/XCore/XCoreSubtarget.cpp | 4 +- .../llvm/lib/Target/XCore/XCoreSubtarget.h | 2 +- .../llvm/lib/Target/XCore/XCoreTargetMachine.cpp | 4 +- .../llvm/lib/Testing/Support/Annotations.cpp | 12 +- .../llvm-project/llvm/lib/TextAPI/ELF/ELFStub.cpp | 28 - .../llvm/lib/TextAPI/ELF/TBEHandler.cpp | 160 - .../llvm/lib/TextAPI/MachO/InterfaceFile.cpp | 2 - .../llvm/lib/TextAPI/MachO/Platform.cpp | 4 +- .../llvm-project/llvm/lib/TextAPI/MachO/Target.cpp | 1 + .../llvm/lib/TextAPI/MachO/TextStub.cpp | 27 +- .../llvm/lib/TextAPI/MachO/TextStubCommon.cpp | 3 + .../llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp | 44 +- .../AggressiveInstCombine.cpp | 149 +- .../AggressiveInstCombine/TruncInstCombine.cpp | 13 +- .../llvm/lib/Transforms/Coroutines/CoroCleanup.cpp | 1 + .../llvm/lib/Transforms/Coroutines/CoroEarly.cpp | 20 +- .../llvm/lib/Transforms/Coroutines/CoroElide.cpp | 25 +- .../llvm/lib/Transforms/Coroutines/CoroFrame.cpp | 1518 ++++-- .../llvm/lib/Transforms/Coroutines/CoroInstr.h | 181 +- .../llvm/lib/Transforms/Coroutines/CoroInternal.h | 59 +- .../llvm/lib/Transforms/Coroutines/CoroSplit.cpp | 595 ++- .../llvm/lib/Transforms/Coroutines/Coroutines.cpp | 109 +- .../llvm/lib/Transforms/HelloNew/HelloWorld.cpp | 17 + .../llvm/lib/Transforms/IPO/AlwaysInliner.cpp | 55 +- .../lib/Transforms/IPO/Annotation2Metadata.cpp | 106 + .../llvm/lib/Transforms/IPO/ArgumentPromotion.cpp | 44 +- .../llvm/lib/Transforms/IPO/Attributor.cpp | 542 +- .../lib/Transforms/IPO/AttributorAttributes.cpp | 1306 ++++- .../llvm/lib/Transforms/IPO/BlockExtractor.cpp | 79 +- .../llvm/lib/Transforms/IPO/ConstantMerge.cpp | 2 + .../lib/Transforms/IPO/DeadArgumentElimination.cpp | 2 +- .../llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp | 47 +- .../llvm/lib/Transforms/IPO/FunctionAttrs.cpp | 271 +- .../llvm/lib/Transforms/IPO/FunctionImport.cpp | 49 +- .../llvm/lib/Transforms/IPO/GlobalOpt.cpp | 24 +- .../llvm/lib/Transforms/IPO/HotColdSplitting.cpp | 100 +- .../lib/Transforms/IPO/IPConstantPropagation.cpp | 308 -- .../llvm-project/llvm/lib/Transforms/IPO/IPO.cpp | 11 +- .../llvm/lib/Transforms/IPO/IROutliner.cpp | 1764 +++++++ .../llvm/lib/Transforms/IPO/Inliner.cpp | 100 +- .../llvm/lib/Transforms/IPO/LoopExtractor.cpp | 137 +- .../llvm/lib/Transforms/IPO/LowerTypeTests.cpp | 32 +- .../llvm/lib/Transforms/IPO/MergeFunctions.cpp | 6 +- .../llvm/lib/Transforms/IPO/OpenMPOpt.cpp | 1350 ++++- .../llvm/lib/Transforms/IPO/PartialInlining.cpp | 329 +- .../llvm/lib/Transforms/IPO/PassManagerBuilder.cpp | 161 +- .../llvm/lib/Transforms/IPO/PruneEH.cpp | 72 +- .../lib/Transforms/IPO/SampleContextTracker.cpp | 585 +++ .../llvm/lib/Transforms/IPO/SampleProfile.cpp | 980 +++- .../llvm/lib/Transforms/IPO/SampleProfileProbe.cpp | 434 ++ .../llvm/lib/Transforms/IPO/StripSymbols.cpp | 56 +- .../lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp | 6 +- .../llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp | 22 +- .../Transforms/InstCombine/InstCombineAddSub.cpp | 335 +- .../Transforms/InstCombine/InstCombineAndOrXor.cpp | 774 +-- .../InstCombine/InstCombineAtomicRMW.cpp | 18 +- .../Transforms/InstCombine/InstCombineCalls.cpp | 3340 ++----------- .../Transforms/InstCombine/InstCombineCasts.cpp | 376 +- .../Transforms/InstCombine/InstCombineCompares.cpp | 502 +- .../Transforms/InstCombine/InstCombineInternal.h | 407 +- .../InstCombine/InstCombineLoadStoreAlloca.cpp | 232 +- .../InstCombine/InstCombineMulDivRem.cpp | 209 +- .../Transforms/InstCombine/InstCombineNegator.cpp | 149 +- .../lib/Transforms/InstCombine/InstCombinePHI.cpp | 253 +- .../Transforms/InstCombine/InstCombineSelect.cpp | 421 +- .../Transforms/InstCombine/InstCombineShifts.cpp | 266 +- .../InstCombine/InstCombineSimplifyDemanded.cpp | 604 +-- .../Transforms/InstCombine/InstCombineTables.td | 11 - .../InstCombine/InstCombineVectorOps.cpp | 434 +- .../InstCombine/InstructionCombining.cpp | 422 +- .../Instrumentation/AddressSanitizer.cpp | 166 +- .../llvm/lib/Transforms/Instrumentation/CFGMST.h | 17 +- .../lib/Transforms/Instrumentation/CGProfile.cpp | 3 +- .../Instrumentation/ControlHeightReduction.cpp | 38 +- .../Instrumentation/DataFlowSanitizer.cpp | 859 +++- .../Transforms/Instrumentation/GCOVProfiling.cpp | 682 +-- .../Instrumentation/HWAddressSanitizer.cpp | 311 +- .../Instrumentation/IndirectCallPromotion.cpp | 9 +- .../Transforms/Instrumentation/InstrProfiling.cpp | 109 +- .../Transforms/Instrumentation/Instrumentation.cpp | 4 +- .../lib/Transforms/Instrumentation/MemProfiler.cpp | 638 +++ .../Transforms/Instrumentation/MemorySanitizer.cpp | 411 +- .../Instrumentation/PGOInstrumentation.cpp | 324 +- .../Transforms/Instrumentation/PGOMemOPSizeOpt.cpp | 38 +- .../Transforms/Instrumentation/PoisonChecking.cpp | 10 +- .../Instrumentation/SanitizerCoverage.cpp | 124 +- .../Transforms/Instrumentation/ThreadSanitizer.cpp | 186 +- .../Instrumentation/ValueProfileCollector.cpp | 2 +- .../Instrumentation/ValueProfileCollector.h | 9 +- .../lib/Transforms/ObjCARC/DependencyAnalysis.cpp | 67 +- .../lib/Transforms/ObjCARC/DependencyAnalysis.h | 12 +- .../llvm/lib/Transforms/ObjCARC/ObjCARC.cpp | 4 +- .../llvm/lib/Transforms/ObjCARC/ObjCARC.h | 2 - .../llvm/lib/Transforms/ObjCARC/ObjCARCAPElim.cpp | 78 +- .../lib/Transforms/ObjCARC/ObjCARCContract.cpp | 226 +- .../llvm/lib/Transforms/ObjCARC/ObjCARCExpand.cpp | 78 +- .../llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp | 337 +- .../lib/Transforms/ObjCARC/ProvenanceAnalysis.cpp | 25 +- .../lib/Transforms/ObjCARC/ProvenanceAnalysis.h | 12 +- .../ObjCARC/ProvenanceAnalysisEvaluator.cpp | 4 +- .../llvm/lib/Transforms/ObjCARC/PtrState.cpp | 4 +- .../llvm/lib/Transforms/Scalar/ADCE.cpp | 4 +- .../Transforms/Scalar/AlignmentFromAssumptions.cpp | 121 +- .../lib/Transforms/Scalar/AnnotationRemarks.cpp | 90 + .../lib/Transforms/Scalar/CallSiteSplitting.cpp | 2 +- .../lib/Transforms/Scalar/ConstantHoisting.cpp | 15 +- .../llvm/lib/Transforms/Scalar/ConstantProp.cpp | 121 - .../Transforms/Scalar/ConstraintElimination.cpp | 407 ++ .../Scalar/CorrelatedValuePropagation.cpp | 339 +- .../llvm/lib/Transforms/Scalar/DCE.cpp | 66 +- .../lib/Transforms/Scalar/DeadStoreElimination.cpp | 1066 ++-- .../llvm/lib/Transforms/Scalar/DivRemPairs.cpp | 10 +- .../llvm/lib/Transforms/Scalar/EarlyCSE.cpp | 432 +- .../llvm/lib/Transforms/Scalar/FlattenCFGPass.cpp | 1 + .../llvm/lib/Transforms/Scalar/Float2Int.cpp | 1 - .../llvm/lib/Transforms/Scalar/GVN.cpp | 417 +- .../llvm/lib/Transforms/Scalar/GVNHoist.cpp | 1383 +++--- .../llvm/lib/Transforms/Scalar/GVNSink.cpp | 13 +- .../llvm/lib/Transforms/Scalar/GuardWidening.cpp | 14 +- .../llvm/lib/Transforms/Scalar/IndVarSimplify.cpp | 1308 +---- .../Scalar/InductiveRangeCheckElimination.cpp | 104 +- .../lib/Transforms/Scalar/InferAddressSpaces.cpp | 160 +- .../lib/Transforms/Scalar/InstSimplifyPass.cpp | 2 + .../llvm/lib/Transforms/Scalar/JumpThreading.cpp | 352 +- .../llvm/lib/Transforms/Scalar/LICM.cpp | 333 +- .../lib/Transforms/Scalar/LoopDataPrefetch.cpp | 2 +- .../llvm/lib/Transforms/Scalar/LoopDeletion.cpp | 129 +- .../llvm/lib/Transforms/Scalar/LoopDistribute.cpp | 16 +- .../llvm/lib/Transforms/Scalar/LoopFlatten.cpp | 728 +++ .../llvm/lib/Transforms/Scalar/LoopFuse.cpp | 329 +- .../lib/Transforms/Scalar/LoopIdiomRecognize.cpp | 534 +- .../llvm/lib/Transforms/Scalar/LoopInterchange.cpp | 135 +- .../lib/Transforms/Scalar/LoopLoadElimination.cpp | 63 +- .../llvm/lib/Transforms/Scalar/LoopPassManager.cpp | 313 +- .../llvm/lib/Transforms/Scalar/LoopPredication.cpp | 15 +- .../llvm/lib/Transforms/Scalar/LoopRerollPass.cpp | 72 +- .../llvm/lib/Transforms/Scalar/LoopRotation.cpp | 45 +- .../llvm/lib/Transforms/Scalar/LoopSimplifyCFG.cpp | 28 +- .../llvm/lib/Transforms/Scalar/LoopSink.cpp | 148 +- .../lib/Transforms/Scalar/LoopStrengthReduce.cpp | 139 +- .../lib/Transforms/Scalar/LoopUnrollAndJamPass.cpp | 12 +- .../llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp | 92 +- .../llvm/lib/Transforms/Scalar/LoopUnswitch.cpp | 325 +- .../lib/Transforms/Scalar/LoopVersioningLICM.cpp | 110 +- .../Transforms/Scalar/LowerConstantIntrinsics.cpp | 10 +- .../lib/Transforms/Scalar/LowerExpectIntrinsic.cpp | 21 +- .../Transforms/Scalar/LowerMatrixIntrinsics.cpp | 291 +- .../llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp | 860 +++- .../llvm/lib/Transforms/Scalar/MergeICmps.cpp | 24 +- .../llvm/lib/Transforms/Scalar/NaryReassociate.cpp | 90 +- .../llvm/lib/Transforms/Scalar/NewGVN.cpp | 127 +- .../llvm/lib/Transforms/Scalar/PlaceSafepoints.cpp | 9 +- .../llvm/lib/Transforms/Scalar/Reassociate.cpp | 114 +- .../llvm/lib/Transforms/Scalar/Reg2Mem.cpp | 120 +- .../Transforms/Scalar/RewriteStatepointsForGC.cpp | 147 +- .../llvm/lib/Transforms/Scalar/SCCP.cpp | 419 +- .../llvm/lib/Transforms/Scalar/SROA.cpp | 351 +- .../llvm/lib/Transforms/Scalar/Scalar.cpp | 37 +- .../Transforms/Scalar/ScalarizeMaskedMemIntrin.cpp | 948 ++++ .../llvm/lib/Transforms/Scalar/Scalarizer.cpp | 9 +- .../Scalar/SeparateConstOffsetFromGEP.cpp | 84 +- .../lib/Transforms/Scalar/SimpleLoopUnswitch.cpp | 74 +- .../llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp | 188 +- .../llvm/lib/Transforms/Scalar/Sink.cpp | 80 +- .../lib/Transforms/Scalar/SpeculateAroundPHIs.cpp | 11 +- .../lib/Transforms/Scalar/SpeculativeExecution.cpp | 9 +- .../Scalar/StraightLineStrengthReduce.cpp | 101 +- .../llvm/lib/Transforms/Scalar/StructurizeCFG.cpp | 171 +- .../Transforms/Scalar/TailRecursionElimination.cpp | 146 +- .../lib/Transforms/Scalar/WarnMissedTransforms.cpp | 6 +- .../llvm/lib/Transforms/Utils/AMDGPUEmitPrintf.cpp | 3 - .../lib/Transforms/Utils/AssumeBundleBuilder.cpp | 5 +- .../llvm/lib/Transforms/Utils/BasicBlockUtils.cpp | 320 +- .../lib/Transforms/Utils/BreakCriticalEdges.cpp | 35 +- .../llvm/lib/Transforms/Utils/BuildLibCalls.cpp | 446 +- .../llvm/lib/Transforms/Utils/CallGraphUpdater.cpp | 5 +- .../lib/Transforms/Utils/CallPromotionUtils.cpp | 13 +- .../Transforms/Utils/CanonicalizeFreezeInLoops.cpp | 4 +- .../llvm/lib/Transforms/Utils/CloneFunction.cpp | 150 +- .../llvm/lib/Transforms/Utils/CloneModule.cpp | 15 +- .../llvm/lib/Transforms/Utils/CodeExtractor.cpp | 60 +- .../llvm/lib/Transforms/Utils/CodeMoverUtils.cpp | 45 +- .../llvm/lib/Transforms/Utils/Debugify.cpp | 103 +- .../lib/Transforms/Utils/EntryExitInstrumenter.cpp | 13 +- .../llvm/lib/Transforms/Utils/EscapeEnumerator.cpp | 5 +- .../llvm/lib/Transforms/Utils/Evaluator.cpp | 14 +- .../llvm/lib/Transforms/Utils/FixIrreducible.cpp | 32 +- .../lib/Transforms/Utils/FunctionComparator.cpp | 25 +- .../llvm/lib/Transforms/Utils/GlobalStatus.cpp | 3 +- .../llvm/lib/Transforms/Utils/GuardUtils.cpp | 2 +- .../Utils/ImportedFunctionsInliningStatistics.cpp | 202 - .../lib/Transforms/Utils/InjectTLIMappings.cpp | 4 +- .../llvm/lib/Transforms/Utils/InlineFunction.cpp | 273 +- .../llvm/lib/Transforms/Utils/InstructionNamer.cpp | 59 +- .../llvm/lib/Transforms/Utils/LCSSA.cpp | 82 +- .../llvm/lib/Transforms/Utils/Local.cpp | 753 +-- .../llvm/lib/Transforms/Utils/LoopPeel.cpp | 862 ++++ .../lib/Transforms/Utils/LoopRotationUtils.cpp | 108 +- .../llvm/lib/Transforms/Utils/LoopSimplify.cpp | 24 +- .../llvm/lib/Transforms/Utils/LoopUnroll.cpp | 129 +- .../llvm/lib/Transforms/Utils/LoopUnrollAndJam.cpp | 35 +- .../llvm/lib/Transforms/Utils/LoopUnrollPeel.cpp | 798 --- .../lib/Transforms/Utils/LoopUnrollRuntime.cpp | 33 +- .../llvm/lib/Transforms/Utils/LoopUtils.cpp | 485 +- .../llvm/lib/Transforms/Utils/LoopVersioning.cpp | 150 +- .../llvm/lib/Transforms/Utils/LowerInvoke.cpp | 2 +- .../llvm/lib/Transforms/Utils/LowerSwitch.cpp | 403 +- .../llvm/lib/Transforms/Utils/MatrixUtils.cpp | 104 + .../llvm/lib/Transforms/Utils/MetaRenamer.cpp | 235 +- .../llvm/lib/Transforms/Utils/MisExpect.cpp | 178 - .../llvm/lib/Transforms/Utils/PredicateInfo.cpp | 225 +- .../Transforms/Utils/PromoteMemoryToRegister.cpp | 118 +- .../llvm/lib/Transforms/Utils/SSAUpdater.cpp | 19 +- .../Transforms/Utils/ScalarEvolutionExpander.cpp | 753 +-- .../llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 1893 ++++--- .../llvm/lib/Transforms/Utils/SimplifyIndVar.cpp | 1130 ++++- .../llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp | 105 +- .../llvm/lib/Transforms/Utils/SizeOpts.cpp | 5 - .../llvm/lib/Transforms/Utils/StripGCRelocates.cpp | 46 +- .../Utils/StripNonLineTableDebugInfo.cpp | 23 +- .../Transforms/Utils/UnifyFunctionExitNodes.cpp | 113 +- .../llvm/lib/Transforms/Utils/UnifyLoopExits.cpp | 53 +- .../Utils/UniqueInternalLinkageNames.cpp | 23 +- .../llvm/lib/Transforms/Utils/Utils.cpp | 10 +- .../llvm/lib/Transforms/Utils/VNCoercion.cpp | 35 +- .../llvm/lib/Transforms/Utils/ValueMapper.cpp | 28 +- .../Transforms/Vectorize/LoadStoreVectorizer.cpp | 18 +- .../Vectorize/LoopVectorizationLegality.cpp | 110 +- .../Vectorize/LoopVectorizationPlanner.h | 52 +- .../lib/Transforms/Vectorize/LoopVectorize.cpp | 3673 ++++++++++---- .../lib/Transforms/Vectorize/SLPVectorizer.cpp | 2251 +++++---- .../lib/Transforms/Vectorize/VPRecipeBuilder.h | 10 +- .../llvm/lib/Transforms/Vectorize/VPlan.cpp | 302 +- .../llvm/lib/Transforms/Vectorize/VPlan.h | 606 ++- .../lib/Transforms/Vectorize/VPlanPredicator.cpp | 4 +- .../llvm/lib/Transforms/Vectorize/VPlanSLP.cpp | 25 +- .../lib/Transforms/Vectorize/VPlanTransforms.cpp | 10 +- .../llvm/lib/Transforms/Vectorize/VPlanValue.h | 214 +- .../lib/Transforms/Vectorize/VPlanVerifier.cpp | 8 +- .../lib/Transforms/Vectorize/VectorCombine.cpp | 207 +- .../lib/WindowsManifest/WindowsManifestMerger.cpp | 6 +- .../llvm/lib/XRay/InstrumentationMap.cpp | 24 +- .../llvm/tools/bugpoint/CrashDebugger.cpp | 2 +- .../llvm/tools/bugpoint/ExecutionDriver.cpp | 18 +- .../llvm/tools/bugpoint/ExtractFunction.cpp | 2 +- .../llvm/tools/bugpoint/OptimizerDriver.cpp | 3 + .../llvm/tools/bugpoint/ToolRunner.cpp | 2 +- contrib/llvm-project/llvm/tools/llc/llc.cpp | 124 +- .../llvm/tools/lli/ChildTarget/ChildTarget.cpp | 6 +- .../llvm-project/llvm/tools/lli/RemoteJITUtils.h | 72 +- contrib/llvm-project/llvm/tools/lli/lli.cpp | 28 +- .../llvm-project/llvm/tools/llvm-ar/llvm-ar.cpp | 2 +- .../llvm/tools/llvm-cov/CodeCoverage.cpp | 96 +- .../llvm/tools/llvm-cov/CoverageExporterJson.cpp | 100 +- .../llvm/tools/llvm-cov/CoverageExporterLcov.cpp | 99 +- .../llvm/tools/llvm-cov/CoverageReport.cpp | 49 +- .../llvm/tools/llvm-cov/CoverageSummaryInfo.cpp | 38 +- .../llvm/tools/llvm-cov/CoverageSummaryInfo.h | 54 +- .../llvm/tools/llvm-cov/CoverageViewOptions.h | 6 + .../llvm/tools/llvm-cov/SourceCoverageView.cpp | 23 +- .../llvm/tools/llvm-cov/SourceCoverageView.h | 28 + .../llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp | 76 +- .../llvm/tools/llvm-cov/SourceCoverageViewHTML.h | 3 + .../llvm/tools/llvm-cov/SourceCoverageViewText.cpp | 50 +- .../llvm/tools/llvm-cov/SourceCoverageViewText.h | 3 + contrib/llvm-project/llvm/tools/llvm-cov/gcov.cpp | 26 +- .../llvm/tools/llvm-diff/DifferenceEngine.cpp | 2 +- .../llvm/tools/llvm-dwarfdump/Statistics.cpp | 202 +- .../llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp | 4 +- .../llvm-project/llvm/tools/llvm-dwp/llvm-dwp.cpp | 56 +- .../llvm/tools/llvm-link/llvm-link.cpp | 53 +- .../llvm-project/llvm/tools/llvm-lto/llvm-lto.cpp | 46 +- .../llvm/tools/llvm-lto2/llvm-lto2.cpp | 21 +- .../llvm-project/llvm/tools/llvm-mc/llvm-mc.cpp | 8 + .../llvm/tools/llvm-mca/CodeRegion.cpp | 1 - .../llvm/tools/llvm-mca/PipelinePrinter.cpp | 2 +- .../llvm/tools/llvm-mca/PipelinePrinter.h | 4 +- .../tools/llvm-mca/Views/BottleneckAnalysis.cpp | 47 +- .../llvm/tools/llvm-mca/Views/BottleneckAnalysis.h | 13 +- .../llvm/tools/llvm-mca/Views/DispatchStatistics.h | 1 + .../tools/llvm-mca/Views/InstructionInfoView.cpp | 127 +- .../tools/llvm-mca/Views/InstructionInfoView.h | 28 +- .../llvm/tools/llvm-mca/Views/InstructionView.cpp | 60 + .../llvm/tools/llvm-mca/Views/InstructionView.h | 67 + .../tools/llvm-mca/Views/RegisterFileStatistics.h | 3 + .../tools/llvm-mca/Views/ResourcePressureView.cpp | 52 +- .../tools/llvm-mca/Views/ResourcePressureView.h | 10 +- .../llvm-mca/Views/RetireControlUnitStatistics.h | 3 + .../tools/llvm-mca/Views/SchedulerStatistics.h | 1 + .../llvm/tools/llvm-mca/Views/SummaryView.cpp | 54 +- .../llvm/tools/llvm-mca/Views/SummaryView.h | 18 +- .../llvm/tools/llvm-mca/Views/TimelineView.cpp | 68 +- .../llvm/tools/llvm-mca/Views/TimelineView.h | 11 +- .../llvm/tools/llvm-mca/Views/View.cpp | 3 + .../llvm-project/llvm/tools/llvm-mca/Views/View.h | 18 + .../llvm-project/llvm/tools/llvm-mca/llvm-mca.cpp | 22 +- .../llvm-project/llvm/tools/llvm-nm/llvm-nm.cpp | 1082 ++-- .../llvm/tools/llvm-objcopy/BitcodeStripOpts.td | 24 + .../llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp | 38 +- .../llvm/tools/llvm-objcopy/COFF/Object.cpp | 69 +- .../llvm/tools/llvm-objcopy/COFF/Object.h | 4 +- .../llvm/tools/llvm-objcopy/CopyConfig.cpp | 130 +- .../llvm/tools/llvm-objcopy/CopyConfig.h | 9 + .../llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp | 153 +- .../llvm/tools/llvm-objcopy/ELF/Object.cpp | 891 ++-- .../llvm/tools/llvm-objcopy/ELF/Object.h | 264 +- .../llvm/tools/llvm-objcopy/InstallNameToolOpts.td | 10 + .../llvm-objcopy/MachO/MachOLayoutBuilder.cpp | 14 +- .../tools/llvm-objcopy/MachO/MachOLayoutBuilder.h | 8 +- .../llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp | 148 +- .../llvm/tools/llvm-objcopy/MachO/MachOObjcopy.h | 4 + .../llvm/tools/llvm-objcopy/MachO/MachOReader.cpp | 51 +- .../llvm/tools/llvm-objcopy/MachO/MachOReader.h | 6 +- .../llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp | 14 +- .../llvm/tools/llvm-objcopy/MachO/Object.cpp | 59 +- .../llvm/tools/llvm-objcopy/MachO/Object.h | 15 +- .../llvm/tools/llvm-objcopy/llvm-objcopy.cpp | 108 +- .../llvm/tools/llvm-objcopy/llvm-objcopy.h | 34 +- .../llvm/tools/llvm-objcopy/wasm/Object.cpp | 4 +- .../llvm/tools/llvm-objcopy/wasm/WasmObjcopy.cpp | 1 - .../llvm/tools/llvm-objdump/ELFDump.cpp | 49 +- .../llvm/tools/llvm-objdump/MachODump.cpp | 90 +- .../llvm/tools/llvm-objdump/llvm-objdump.cpp | 281 +- .../llvm/tools/llvm-objdump/llvm-objdump.h | 6 +- .../llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp | 17 +- .../llvm/tools/llvm-pdbutil/FormatUtil.cpp | 7 +- .../llvm/tools/llvm-pdbutil/FormatUtil.h | 4 +- .../tools/llvm-pdbutil/MinimalSymbolDumper.cpp | 13 +- .../llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp | 4 +- .../llvm/tools/llvm-profdata/llvm-profdata.cpp | 1204 ++++- .../llvm/tools/llvm-readobj/ARMEHABIPrinter.h | 135 +- .../llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp | 211 +- .../llvm/tools/llvm-readobj/ARMWinEHPrinter.h | 12 + .../llvm/tools/llvm-readobj/COFFDumper.cpp | 64 +- .../llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h | 82 +- .../llvm/tools/llvm-readobj/ELFDumper.cpp | 5244 +++++++++----------- .../llvm-project/llvm/tools/llvm-readobj/Error.cpp | 56 - .../llvm-project/llvm/tools/llvm-readobj/Error.h | 40 - .../llvm/tools/llvm-readobj/MachODumper.cpp | 41 +- .../llvm/tools/llvm-readobj/ObjDumper.cpp | 52 +- .../llvm/tools/llvm-readobj/ObjDumper.h | 49 +- .../llvm/tools/llvm-readobj/WasmDumper.cpp | 16 +- .../llvm/tools/llvm-readobj/Win64EHDumper.cpp | 5 +- .../tools/llvm-readobj/WindowsResourceDumper.cpp | 1 - .../llvm/tools/llvm-readobj/XCOFFDumper.cpp | 15 +- .../llvm/tools/llvm-readobj/llvm-readobj.cpp | 157 +- .../llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp | 2 + .../llvm/tools/llvm-size/llvm-size.cpp | 4 +- .../llvm/tools/llvm-stress/llvm-stress.cpp | 38 +- .../llvm/tools/llvm-symbolizer/Opts.td | 71 + .../llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp | 383 +- .../llvm/tools/llvm-xray/xray-account.cpp | 84 +- .../llvm/tools/llvm-xray/xray-account.h | 31 +- .../llvm/tools/llvm-xray/xray-graph.cpp | 3 +- .../llvm/tools/llvm-xray/xray-stacks.cpp | 23 +- .../llvm-project/llvm/tools/opt/NewPMDriver.cpp | 158 +- contrib/llvm-project/llvm/tools/opt/NewPMDriver.h | 13 +- contrib/llvm-project/llvm/tools/opt/opt.cpp | 233 +- .../llvm/utils/TableGen/AsmMatcherEmitter.cpp | 139 +- .../llvm/utils/TableGen/AsmWriterEmitter.cpp | 113 +- .../llvm/utils/TableGen/AsmWriterInst.cpp | 7 +- .../llvm/utils/TableGen/CallingConvEmitter.cpp | 18 +- .../llvm/utils/TableGen/CodeEmitterGen.cpp | 8 +- .../llvm/utils/TableGen/CodeGenDAGPatterns.cpp | 34 +- .../llvm/utils/TableGen/CodeGenDAGPatterns.h | 8 +- .../llvm/utils/TableGen/CodeGenInstruction.cpp | 2 +- .../llvm/utils/TableGen/CodeGenIntrinsics.h | 10 +- .../llvm/utils/TableGen/CodeGenMapTable.cpp | 26 +- .../llvm/utils/TableGen/CodeGenRegisters.cpp | 19 +- .../llvm/utils/TableGen/CodeGenRegisters.h | 4 +- .../llvm/utils/TableGen/CodeGenSchedule.cpp | 351 +- .../llvm/utils/TableGen/CodeGenSchedule.h | 13 +- .../llvm/utils/TableGen/CodeGenTarget.cpp | 255 +- .../llvm/utils/TableGen/CodeGenTarget.h | 9 +- .../llvm/utils/TableGen/DAGISelEmitter.cpp | 14 +- .../llvm/utils/TableGen/DAGISelMatcher.h | 20 +- .../llvm/utils/TableGen/DAGISelMatcherEmitter.cpp | 226 +- .../llvm/utils/TableGen/DAGISelMatcherGen.cpp | 10 +- .../llvm/utils/TableGen/DFAEmitter.cpp | 5 +- .../llvm/utils/TableGen/DFAPacketizerEmitter.cpp | 2 +- .../llvm/utils/TableGen/DirectiveEmitter.cpp | 760 ++- .../llvm/utils/TableGen/ExegesisEmitter.cpp | 2 +- .../llvm/utils/TableGen/FixedLenDecoderEmitter.cpp | 44 +- .../llvm/utils/TableGen/GICombinerEmitter.cpp | 55 +- .../utils/TableGen/GlobalISel/CodeExpander.cpp | 23 +- .../llvm/utils/TableGen/GlobalISel/GIMatchDag.cpp | 2 +- .../utils/TableGen/GlobalISel/GIMatchDagInstr.cpp | 2 +- .../llvm/utils/TableGen/GlobalISel/GIMatchTree.cpp | 15 +- .../llvm/utils/TableGen/GlobalISel/GIMatchTree.h | 5 +- .../llvm/utils/TableGen/GlobalISelEmitter.cpp | 802 ++- .../llvm/utils/TableGen/InstrInfoEmitter.cpp | 39 +- .../llvm/utils/TableGen/IntrinsicEmitter.cpp | 20 +- .../llvm/utils/TableGen/OptParserEmitter.cpp | 309 +- .../llvm/utils/TableGen/PredicateExpander.cpp | 22 +- .../llvm/utils/TableGen/PredicateExpander.h | 3 + .../llvm/utils/TableGen/PseudoLoweringEmitter.cpp | 114 +- .../utils/TableGen/RISCVCompressInstEmitter.cpp | 234 +- .../llvm/utils/TableGen/RegisterBankEmitter.cpp | 19 +- .../llvm/utils/TableGen/RegisterInfoEmitter.cpp | 47 +- .../llvm/utils/TableGen/SearchableTableEmitter.cpp | 229 +- .../llvm/utils/TableGen/SubtargetEmitter.cpp | 122 +- .../llvm/utils/TableGen/SubtargetFeatureInfo.cpp | 5 +- .../llvm/utils/TableGen/SubtargetFeatureInfo.h | 5 - .../llvm-project/llvm/utils/TableGen/TableGen.cpp | 30 +- .../TableGen/WebAssemblyDisassemblerEmitter.cpp | 15 +- .../llvm/utils/TableGen/X86DisassemblerTables.cpp | 2 +- .../llvm/utils/TableGen/X86FoldTablesEmitter.cpp | 27 +- .../llvm/utils/TableGen/X86RecognizableInstr.cpp | 2 +- 2737 files changed, 249293 insertions(+), 114395 deletions(-) create mode 100644 contrib/llvm-project/llvm/include/llvm-c/LLJIT.h delete mode 100644 contrib/llvm-project/llvm/include/llvm-c/LinkTimeOptimizer.h delete mode 100644 contrib/llvm-project/llvm/include/llvm-c/OrcBindings.h create mode 100644 contrib/llvm-project/llvm/include/llvm-c/OrcEE.h create mode 100644 contrib/llvm-project/llvm/include/llvm/ADT/APFixedPoint.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Analysis/ConstraintSystem.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Analysis/DDGPrinter.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Analysis/Delinearization.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Analysis/FunctionPropertiesAnalysis.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Analysis/IRSimilarityIdentifier.h delete mode 100644 contrib/llvm-project/llvm/include/llvm/Analysis/InlineFeaturesAnalysis.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Analysis/InstCount.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Analysis/MemDerefPrinter.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Analysis/ModuleDebugInfoPrinter.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Analysis/ReplayInlineAdvisor.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Analysis/Utils/ImportedFunctionsInliningStatistics.h create mode 100644 contrib/llvm-project/llvm/include/llvm/BinaryFormat/ELFRelocs/CSKY.def create mode 100644 contrib/llvm-project/llvm/include/llvm/BinaryFormat/WasmTraits.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Bitcode/BitcodeCommon.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Bitcode/BitcodeConvenience.h create mode 100644 contrib/llvm-project/llvm/include/llvm/CodeGen/BasicBlockSectionUtils.h create mode 100644 contrib/llvm-project/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h create mode 100644 contrib/llvm-project/llvm/include/llvm/CodeGen/MachinePassManager.h create mode 100644 contrib/llvm-project/llvm/include/llvm/CodeGen/MachinePassRegistry.def create mode 100644 contrib/llvm-project/llvm/include/llvm/CodeGen/MachineStableHash.h create mode 100644 contrib/llvm-project/llvm/include/llvm/CodeGen/MultiHazardRecognizer.h create mode 100644 contrib/llvm-project/llvm/include/llvm/CodeGen/StableHashing.h create mode 100644 contrib/llvm-project/llvm/include/llvm/CodeGen/TileShapeInfo.h create mode 100644 contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h create mode 100644 contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h create mode 100644 contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/JITLinkDylib.h delete mode 100644 contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h delete mode 100644 contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LambdaResolver.h delete mode 100644 contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h delete mode 100644 contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Legacy.h delete mode 100644 contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/NullResolver.h delete mode 100644 contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcError.h create mode 100644 contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcRPCTargetProcessControl.h delete mode 100644 contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPC/RPCSerialization.h delete mode 100644 contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPC/RPCUtils.h delete mode 100644 contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPC/RawByteChannel.h delete mode 100644 contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h create mode 100644 contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Shared/FDRawByteChannel.h create mode 100644 contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Shared/OrcError.h create mode 100644 contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Shared/RPCUtils.h create mode 100644 contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Shared/RawByteChannel.h create mode 100644 contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Shared/Serialization.h create mode 100644 contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h create mode 100644 contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/TPCDynamicLibrarySearchGenerator.h create mode 100644 contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/TPCEHFrameRegistrar.h create mode 100644 contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/TPCIndirectionUtils.h create mode 100644 contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/OrcRPCTPCServer.h create mode 100644 contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h create mode 100644 contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h create mode 100644 contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/TargetProcessControl.h create mode 100644 contrib/llvm-project/llvm/include/llvm/FileCheck/FileCheck.h create mode 100644 contrib/llvm-project/llvm/include/llvm/IR/Assumptions.h create mode 100644 contrib/llvm-project/llvm/include/llvm/IR/FixedPointBuilder.h create mode 100644 contrib/llvm-project/llvm/include/llvm/IR/IntrinsicsVE.td create mode 100644 contrib/llvm-project/llvm/include/llvm/IR/IntrinsicsVEVL.gen.td create mode 100644 contrib/llvm-project/llvm/include/llvm/IR/PrintPasses.h create mode 100644 contrib/llvm-project/llvm/include/llvm/IR/PseudoProbe.h create mode 100644 contrib/llvm-project/llvm/include/llvm/IR/ReplaceConstant.h create mode 100644 contrib/llvm-project/llvm/include/llvm/IR/StructuralHash.h create mode 100644 contrib/llvm-project/llvm/include/llvm/InterfaceStub/ELFObjHandler.h create mode 100644 contrib/llvm-project/llvm/include/llvm/InterfaceStub/ELFStub.h create mode 100644 contrib/llvm-project/llvm/include/llvm/InterfaceStub/TBEHandler.h create mode 100644 contrib/llvm-project/llvm/include/llvm/MC/MCPseudoProbe.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Object/MachOUniversalWriter.h delete mode 100644 contrib/llvm-project/llvm/include/llvm/Object/WasmTraits.h create mode 100644 contrib/llvm-project/llvm/include/llvm/ObjectYAML/ArchiveYAML.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Remarks/HotnessThresholdParser.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Support/ExitCodes.h delete mode 100644 contrib/llvm-project/llvm/include/llvm/Support/FileCheck.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Support/FileSystem/UniqueID.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Support/InstructionCost.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Support/MemoryBufferRef.h create mode 100644 contrib/llvm-project/llvm/include/llvm/TableGen/DirectiveEmitter.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Target/CGPassBuilderOption.h delete mode 100644 contrib/llvm-project/llvm/include/llvm/TextAPI/ELF/ELFStub.h delete mode 100644 contrib/llvm-project/llvm/include/llvm/TextAPI/ELF/TBEHandler.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/HelloNew/HelloWorld.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/IPO/Annotation2Metadata.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/IPO/BlockExtractor.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/IPO/IROutliner.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/IPO/LoopExtractor.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/IPO/SampleContextTracker.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/IPO/SampleProfileProbe.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/IPO/StripSymbols.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/Instrumentation/DataFlowSanitizer.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/Instrumentation/MemProfiler.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/Scalar/AnnotationRemarks.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/Scalar/ConstraintElimination.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/Scalar/InferAddressSpaces.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/Scalar/LoopFlatten.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/Scalar/LoopInterchange.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/Scalar/LoopReroll.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/Scalar/LoopVersioningLICM.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/Scalar/Reg2Mem.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/Scalar/ScalarizeMaskedMemIntrin.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/Scalar/SeparateConstOffsetFromGEP.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/Scalar/StraightLineStrengthReduce.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/Scalar/StructurizeCFG.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/Utils/FixIrreducible.h delete mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/Utils/ImportedFunctionsInliningStatistics.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/Utils/InstructionNamer.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/Utils/LoopPeel.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/Utils/LowerSwitch.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/Utils/MatrixUtils.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/Utils/MetaRenamer.h delete mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/Utils/MisExpect.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/Utils/SimplifyCFGOptions.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/Utils/StripGCRelocates.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/Utils/StripNonLineTableDebugInfo.h create mode 100644 contrib/llvm-project/llvm/include/llvm/Transforms/Utils/UnifyLoopExits.h create mode 100644 contrib/llvm-project/llvm/lib/Analysis/ConstraintSystem.cpp create mode 100644 contrib/llvm-project/llvm/lib/Analysis/DDGPrinter.cpp create mode 100644 contrib/llvm-project/llvm/lib/Analysis/DevelopmentModeInlineAdvisor.cpp create mode 100644 contrib/llvm-project/llvm/lib/Analysis/FunctionPropertiesAnalysis.cpp create mode 100644 contrib/llvm-project/llvm/lib/Analysis/IRSimilarityIdentifier.cpp create mode 100644 contrib/llvm-project/llvm/lib/Analysis/ImportedFunctionsInliningStatistics.cpp delete mode 100644 contrib/llvm-project/llvm/lib/Analysis/InlineFeaturesAnalysis.cpp create mode 100644 contrib/llvm-project/llvm/lib/Analysis/ReplayInlineAdvisor.cpp create mode 100644 contrib/llvm-project/llvm/lib/Analysis/models/inliner/README.txt create mode 100644 contrib/llvm-project/llvm/lib/Analysis/models/inliner/output_spec.json create mode 100644 contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/AIXException.cpp create mode 100644 contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/PseudoProbePrinter.cpp create mode 100644 contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/PseudoProbePrinter.h delete mode 100644 contrib/llvm-project/llvm/lib/CodeGen/BBSectionsPrepare.cpp create mode 100644 contrib/llvm-project/llvm/lib/CodeGen/BasicBlockSections.cpp create mode 100644 contrib/llvm-project/llvm/lib/CodeGen/CodeGenPassBuilder.cpp delete mode 100644 contrib/llvm-project/llvm/lib/CodeGen/LiveDebugValues.cpp create mode 100644 contrib/llvm-project/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp create mode 100644 contrib/llvm-project/llvm/lib/CodeGen/LiveDebugValues/LiveDebugValues.cpp create mode 100644 contrib/llvm-project/llvm/lib/CodeGen/LiveDebugValues/LiveDebugValues.h create mode 100644 contrib/llvm-project/llvm/lib/CodeGen/LiveDebugValues/VarLocBasedImpl.cpp create mode 100644 contrib/llvm-project/llvm/lib/CodeGen/MachineCheckDebugify.cpp create mode 100644 contrib/llvm-project/llvm/lib/CodeGen/MachineFunctionSplitter.cpp create mode 100644 contrib/llvm-project/llvm/lib/CodeGen/MachinePassManager.cpp create mode 100644 contrib/llvm-project/llvm/lib/CodeGen/MachineStableHash.cpp create mode 100644 contrib/llvm-project/llvm/lib/CodeGen/MultiHazardRecognizer.cpp create mode 100644 contrib/llvm-project/llvm/lib/CodeGen/PseudoProbeInserter.cpp delete mode 100644 contrib/llvm-project/llvm/lib/CodeGen/ScalarizeMaskedMemIntrin.cpp create mode 100644 contrib/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeEnumSymbols.cpp create mode 100644 contrib/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeInlineSiteSymbol.cpp delete mode 100644 contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Legacy.cpp delete mode 100644 contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/NullResolver.cpp delete mode 100644 contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/OrcCBindings.cpp delete mode 100644 contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h delete mode 100644 contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.cpp delete mode 100644 contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h create mode 100644 contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Shared/OrcError.cpp create mode 100644 contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Shared/RPCError.cpp create mode 100644 contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.cpp create mode 100644 contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TPCDynamicLibrarySearchGenerator.cpp create mode 100644 contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TPCEHFrameRegistrar.cpp create mode 100644 contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TPCIndirectionUtils.cpp create mode 100644 contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.cpp create mode 100644 contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.cpp create mode 100644 contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcessControl.cpp delete mode 100644 contrib/llvm-project/llvm/lib/ExecutionEngine/OrcError/OrcError.cpp delete mode 100644 contrib/llvm-project/llvm/lib/ExecutionEngine/OrcError/RPCError.cpp create mode 100644 contrib/llvm-project/llvm/lib/FileCheck/FileCheck.cpp create mode 100644 contrib/llvm-project/llvm/lib/FileCheck/FileCheckImpl.h create mode 100644 contrib/llvm-project/llvm/lib/IR/Assumptions.cpp create mode 100644 contrib/llvm-project/llvm/lib/IR/PrintPasses.cpp create mode 100644 contrib/llvm-project/llvm/lib/IR/PseudoProbe.cpp create mode 100644 contrib/llvm-project/llvm/lib/IR/ReplaceConstant.cpp create mode 100644 contrib/llvm-project/llvm/lib/IR/StructuralHash.cpp create mode 100644 contrib/llvm-project/llvm/lib/InterfaceStub/ELFObjHandler.cpp create mode 100644 contrib/llvm-project/llvm/lib/InterfaceStub/ELFStub.cpp create mode 100644 contrib/llvm-project/llvm/lib/InterfaceStub/TBEHandler.cpp create mode 100644 contrib/llvm-project/llvm/lib/MC/MCPseudoProbe.cpp create mode 100644 contrib/llvm-project/llvm/lib/Object/MachOUniversalWriter.cpp create mode 100644 contrib/llvm-project/llvm/lib/ObjectYAML/ArchiveEmitter.cpp create mode 100644 contrib/llvm-project/llvm/lib/ObjectYAML/ArchiveYAML.cpp delete mode 100644 contrib/llvm-project/llvm/lib/ObjectYAML/DWARFVisitor.cpp delete mode 100644 contrib/llvm-project/llvm/lib/ObjectYAML/DWARFVisitor.h create mode 100644 contrib/llvm-project/llvm/lib/Support/APFixedPoint.cpp delete mode 100644 contrib/llvm-project/llvm/lib/Support/FileCheck.cpp delete mode 100644 contrib/llvm-project/llvm/lib/Support/FileCheckImpl.h create mode 100644 contrib/llvm-project/llvm/lib/Support/InstructionCost.cpp create mode 100644 contrib/llvm-project/llvm/lib/Support/MemoryBufferRef.cpp create mode 100644 contrib/llvm-project/llvm/lib/TableGen/DetailedRecordsBackend.cpp create mode 100644 contrib/llvm-project/llvm/lib/TableGen/TableGenBackendSkeleton.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/AArch64/AArch64SchedA55.td create mode 100644 contrib/llvm-project/llvm/lib/Target/AArch64/AArch64SchedA64FX.td create mode 100644 contrib/llvm-project/llvm/lib/Target/AArch64/AArch64SchedTSV110.td delete mode 100644 contrib/llvm-project/llvm/lib/Target/AArch64/AArch64StackOffset.h create mode 100644 contrib/llvm-project/llvm/lib/Target/AArch64/GISel/AArch64GlobalISelUtils.h create mode 100644 contrib/llvm-project/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerLowering.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/AArch64/GISel/AArch64PostSelectOptimize.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/AArch64/GISel/select-saddo.mir create mode 100644 contrib/llvm-project/llvm/lib/Target/AArch64/GISel/select-ssubo.mir delete mode 100644 contrib/llvm-project/llvm/lib/Target/AMDGPU/AMDGPUInline.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/AMDGPU/AMDGPULateCodeGenPrepare.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/AMDGPU/AMDGPUMIRFormatter.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/AMDGPU/AMDGPUMIRFormatter.h create mode 100644 contrib/llvm-project/llvm/lib/Target/AMDGPU/EXPInstructions.td create mode 100644 contrib/llvm-project/llvm/lib/Target/AMDGPU/GCNSubtarget.h create mode 100644 contrib/llvm-project/llvm/lib/Target/AMDGPU/InstCombineTables.td create mode 100644 contrib/llvm-project/llvm/lib/Target/AMDGPU/R600Subtarget.h delete mode 100644 contrib/llvm-project/llvm/lib/Target/AMDGPU/SIFixupVectorISel.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/AMDGPU/SIProgramInfo.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/ARM/ARMBlockPlacement.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/ARM/ARMSLSHardening.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/ARM/ARMScheduleM7.td create mode 100644 contrib/llvm-project/llvm/lib/Target/ARM/MVETailPredUtils.h create mode 100644 contrib/llvm-project/llvm/lib/Target/BPF/BPFAdjustOpt.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/BPF/BPFCheckAndAdjustIR.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/BPF/BPFTargetTransformInfo.h create mode 100644 contrib/llvm-project/llvm/lib/Target/CSKY/CSKY.td create mode 100644 contrib/llvm-project/llvm/lib/Target/CSKY/CSKYInstrFormats.td create mode 100644 contrib/llvm-project/llvm/lib/Target/CSKY/CSKYInstrInfo.td create mode 100644 contrib/llvm-project/llvm/lib/Target/CSKY/CSKYRegisterInfo.td create mode 100644 contrib/llvm-project/llvm/lib/Target/CSKY/CSKYTargetMachine.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/CSKY/CSKYTargetMachine.h create mode 100644 contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.h create mode 100644 contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYELFObjectWriter.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCAsmInfo.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCAsmInfo.h create mode 100644 contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.h create mode 100644 contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCTargetDesc.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCTargetDesc.h create mode 100644 contrib/llvm-project/llvm/lib/Target/CSKY/TargetInfo/CSKYTargetInfo.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/CSKY/TargetInfo/CSKYTargetInfo.h create mode 100644 contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonLoopIdiomRecognition.h create mode 100644 contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonVectorLoopCarriedReuse.h create mode 100644 contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCCallLowering.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCCallLowering.h create mode 100644 contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCLegalizerInfo.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCLegalizerInfo.h create mode 100644 contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.h create mode 100644 contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCRegisterBanks.td delete mode 100644 contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrQPX.td delete mode 100644 contrib/llvm-project/llvm/lib/Target/PowerPC/PPCQPXLoadSplat.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h create mode 100644 contrib/llvm-project/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.h create mode 100644 contrib/llvm-project/llvm/lib/Target/RISCV/RISCVCleanupVSETVLI.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td create mode 100644 contrib/llvm-project/llvm/lib/Target/RISCV/RISCVInstrInfoVSDPatterns.td create mode 100644 contrib/llvm-project/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td create mode 100644 contrib/llvm-project/llvm/lib/Target/RISCV/RISCVSchedRocket.td delete mode 100644 contrib/llvm-project/llvm/lib/Target/RISCV/RISCVSchedRocket32.td delete mode 100644 contrib/llvm-project/llvm/lib/Target/RISCV/RISCVSchedRocket64.td create mode 100644 contrib/llvm-project/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td delete mode 100644 contrib/llvm-project/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.cpp delete mode 100644 contrib/llvm-project/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h delete mode 100644 contrib/llvm-project/llvm/lib/Target/RISCV/Utils/RISCVMatInt.cpp delete mode 100644 contrib/llvm-project/llvm/lib/Target/RISCV/Utils/RISCVMatInt.h create mode 100644 contrib/llvm-project/llvm/lib/Target/VE/LVLGen.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/VE/VEInstrBuilder.h create mode 100644 contrib/llvm-project/llvm/lib/Target/VE/VEInstrIntrinsicVL.gen.td create mode 100644 contrib/llvm-project/llvm/lib/Target/VE/VEInstrIntrinsicVL.td create mode 100644 contrib/llvm-project/llvm/lib/Target/VE/VEInstrPatternsVec.td create mode 100644 contrib/llvm-project/llvm/lib/Target/VE/VEInstrVec.td create mode 100644 contrib/llvm-project/llvm/lib/Target/VE/VVPInstrInfo.td create mode 100644 contrib/llvm-project/llvm/lib/Target/VE/VVPInstrPatternsVec.td create mode 100644 contrib/llvm-project/llvm/lib/Target/VE/VVPNodes.def create mode 100644 contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrTable.td create mode 100644 contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblySortRegion.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblySortRegion.h delete mode 100644 contrib/llvm-project/llvm/lib/Target/X86/X86CondBrFolding.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/X86/X86InstCombineIntrinsic.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/X86/X86InstrKL.td create mode 100644 contrib/llvm-project/llvm/lib/Target/X86/X86InstrSNP.td create mode 100644 contrib/llvm-project/llvm/lib/Target/X86/X86InstrTDX.td create mode 100644 contrib/llvm-project/llvm/lib/Target/X86/X86LowerAMXType.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/X86/X86PreTileConfig.cpp create mode 100644 contrib/llvm-project/llvm/lib/Target/X86/X86TileConfig.cpp delete mode 100644 contrib/llvm-project/llvm/lib/TextAPI/ELF/ELFStub.cpp delete mode 100644 contrib/llvm-project/llvm/lib/TextAPI/ELF/TBEHandler.cpp create mode 100644 contrib/llvm-project/llvm/lib/Transforms/HelloNew/HelloWorld.cpp create mode 100644 contrib/llvm-project/llvm/lib/Transforms/IPO/Annotation2Metadata.cpp delete mode 100644 contrib/llvm-project/llvm/lib/Transforms/IPO/IPConstantPropagation.cpp create mode 100644 contrib/llvm-project/llvm/lib/Transforms/IPO/IROutliner.cpp create mode 100644 contrib/llvm-project/llvm/lib/Transforms/IPO/SampleContextTracker.cpp create mode 100644 contrib/llvm-project/llvm/lib/Transforms/IPO/SampleProfileProbe.cpp delete mode 100644 contrib/llvm-project/llvm/lib/Transforms/InstCombine/InstCombineTables.td create mode 100644 contrib/llvm-project/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp create mode 100644 contrib/llvm-project/llvm/lib/Transforms/Scalar/AnnotationRemarks.cpp delete mode 100644 contrib/llvm-project/llvm/lib/Transforms/Scalar/ConstantProp.cpp create mode 100644 contrib/llvm-project/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp create mode 100644 contrib/llvm-project/llvm/lib/Transforms/Scalar/LoopFlatten.cpp create mode 100644 contrib/llvm-project/llvm/lib/Transforms/Scalar/ScalarizeMaskedMemIntrin.cpp delete mode 100644 contrib/llvm-project/llvm/lib/Transforms/Utils/ImportedFunctionsInliningStatistics.cpp create mode 100644 contrib/llvm-project/llvm/lib/Transforms/Utils/LoopPeel.cpp delete mode 100644 contrib/llvm-project/llvm/lib/Transforms/Utils/LoopUnrollPeel.cpp create mode 100644 contrib/llvm-project/llvm/lib/Transforms/Utils/MatrixUtils.cpp delete mode 100644 contrib/llvm-project/llvm/lib/Transforms/Utils/MisExpect.cpp create mode 100644 contrib/llvm-project/llvm/tools/llvm-mca/Views/InstructionView.cpp create mode 100644 contrib/llvm-project/llvm/tools/llvm-mca/Views/InstructionView.h create mode 100644 contrib/llvm-project/llvm/tools/llvm-objcopy/BitcodeStripOpts.td delete mode 100644 contrib/llvm-project/llvm/tools/llvm-readobj/Error.cpp delete mode 100644 contrib/llvm-project/llvm/tools/llvm-readobj/Error.h create mode 100644 contrib/llvm-project/llvm/tools/llvm-symbolizer/Opts.td (limited to 'contrib/llvm-project/llvm') diff --git a/contrib/llvm-project/llvm/include/llvm-c/Core.h b/contrib/llvm-project/llvm/include/llvm-c/Core.h index c8a6f970419b..2901ab715810 100644 --- a/contrib/llvm-project/llvm/include/llvm-c/Core.h +++ b/contrib/llvm-project/llvm/include/llvm-c/Core.h @@ -162,7 +162,8 @@ typedef enum { LLVMX86_MMXTypeKind, /**< X86 MMX */ LLVMTokenTypeKind, /**< Tokens */ LLVMScalableVectorTypeKind, /**< Scalable SIMD vector type */ - LLVMBFloatTypeKind /**< 16 bit brain floating point type */ + LLVMBFloatTypeKind, /**< 16 bit brain floating point type */ + LLVMX86_AMXTypeKind /**< X86 AMX */ } LLVMTypeKind; typedef enum { @@ -281,6 +282,7 @@ typedef enum { LLVMInlineAsmValueKind, LLVMInstructionValueKind, + LLVMPoisonValueValueKind } LLVMValueKind; typedef enum { @@ -602,6 +604,17 @@ unsigned LLVMGetEnumAttributeKind(LLVMAttributeRef A); */ uint64_t LLVMGetEnumAttributeValue(LLVMAttributeRef A); +/** + * Create a type attribute + */ +LLVMAttributeRef LLVMCreateTypeAttribute(LLVMContextRef C, unsigned KindID, + LLVMTypeRef type_ref); + +/** + * Get the type attribute's value. + */ +LLVMTypeRef LLVMGetTypeAttributeValue(LLVMAttributeRef A); + /** * Create a string attribute. */ @@ -624,6 +637,12 @@ const char *LLVMGetStringAttributeValue(LLVMAttributeRef A, unsigned *Length); */ LLVMBool LLVMIsEnumAttribute(LLVMAttributeRef A); LLVMBool LLVMIsStringAttribute(LLVMAttributeRef A); +LLVMBool LLVMIsTypeAttribute(LLVMAttributeRef A); + +/** + * Obtain a Type from a context by its registered name. + */ +LLVMTypeRef LLVMGetTypeByName2(LLVMContextRef C, const char *Name); /** * @} @@ -866,9 +885,7 @@ LLVMValueRef LLVMGetInlineAsm(LLVMTypeRef Ty, */ LLVMContextRef LLVMGetModuleContext(LLVMModuleRef M); -/** - * Obtain a Type from a module by its registered name. - */ +/** Deprecated: Use LLVMGetTypeByName2 instead. */ LLVMTypeRef LLVMGetTypeByName(LLVMModuleRef M, const char *Name); /** @@ -1444,9 +1461,21 @@ unsigned LLVMGetPointerAddressSpace(LLVMTypeRef PointerTy); LLVMTypeRef LLVMVectorType(LLVMTypeRef ElementType, unsigned ElementCount); /** - * Obtain the number of elements in a vector type. + * Create a vector type that contains a defined type and has a scalable + * number of elements. * - * This only works on types that represent vectors. + * The created type will exist in the context thats its element type + * exists in. + * + * @see llvm::ScalableVectorType::get() + */ +LLVMTypeRef LLVMScalableVectorType(LLVMTypeRef ElementType, + unsigned ElementCount); + +/** + * Obtain the (possibly scalable) number of elements in a vector type. + * + * This only works on types that represent vectors (fixed or scalable). * * @see llvm::VectorType::getNumElements() */ @@ -1477,6 +1506,11 @@ LLVMTypeRef LLVMLabelTypeInContext(LLVMContextRef C); */ LLVMTypeRef LLVMX86MMXTypeInContext(LLVMContextRef C); +/** + * Create a X86 AMX type in a context. + */ +LLVMTypeRef LLVMX86AMXTypeInContext(LLVMContextRef C); + /** * Create a token type in a context. */ @@ -1494,6 +1528,7 @@ LLVMTypeRef LLVMMetadataTypeInContext(LLVMContextRef C); LLVMTypeRef LLVMVoidType(void); LLVMTypeRef LLVMLabelType(void); LLVMTypeRef LLVMX86MMXType(void); +LLVMTypeRef LLVMX86AMXType(void); /** * @} @@ -1550,6 +1585,7 @@ LLVMTypeRef LLVMX86MMXType(void); macro(Function) \ macro(GlobalVariable) \ macro(UndefValue) \ + macro(PoisonValue) \ macro(Instruction) \ macro(UnaryOperator) \ macro(BinaryOperator) \ @@ -1683,6 +1719,11 @@ LLVMBool LLVMIsConstant(LLVMValueRef Val); */ LLVMBool LLVMIsUndef(LLVMValueRef Val); +/** + * Determine whether a value instance is poisonous. + */ +LLVMBool LLVMIsPoison(LLVMValueRef Val); + /** * Convert value instances between types. * @@ -1841,6 +1882,13 @@ LLVMValueRef LLVMConstAllOnes(LLVMTypeRef Ty); */ LLVMValueRef LLVMGetUndef(LLVMTypeRef Ty); +/** + * Obtain a constant value referring to a poison value of a type. + * + * @see llvm::PoisonValue::get() + */ +LLVMValueRef LLVMGetPoison(LLVMTypeRef Ty); + /** * Determine whether a value instance is null. * diff --git a/contrib/llvm-project/llvm/include/llvm-c/DataTypes.h b/contrib/llvm-project/llvm/include/llvm-c/DataTypes.h index 0f27ba81865e..4eb0ac97d97e 100644 --- a/contrib/llvm-project/llvm/include/llvm-c/DataTypes.h +++ b/contrib/llvm-project/llvm/include/llvm-c/DataTypes.h @@ -77,8 +77,4 @@ typedef signed int ssize_t; # define UINT64_MAX 0xffffffffffffffffULL #endif -#ifndef HUGE_VALF -#define HUGE_VALF (float)HUGE_VAL -#endif - #endif /* LLVM_C_DATATYPES_H */ diff --git a/contrib/llvm-project/llvm/include/llvm-c/DebugInfo.h b/contrib/llvm-project/llvm/include/llvm-c/DebugInfo.h index cdf5f5a0cca8..5a9cd8e2ee63 100644 --- a/contrib/llvm-project/llvm/include/llvm-c/DebugInfo.h +++ b/contrib/llvm-project/llvm/include/llvm-c/DebugInfo.h @@ -159,7 +159,9 @@ enum { LLVMDIImportedEntityMetadataKind, LLVMDIMacroMetadataKind, LLVMDIMacroFileMetadataKind, - LLVMDICommonBlockMetadataKind + LLVMDICommonBlockMetadataKind, + LLVMDIStringTypeMetadataKind, + LLVMDIGenericSubrangeMetadataKind }; typedef unsigned LLVMMetadataKind; diff --git a/contrib/llvm-project/llvm/include/llvm-c/Error.h b/contrib/llvm-project/llvm/include/llvm-c/Error.h index 92f81bf38304..bc702ac7a1bf 100644 --- a/contrib/llvm-project/llvm/include/llvm-c/Error.h +++ b/contrib/llvm-project/llvm/include/llvm-c/Error.h @@ -62,6 +62,11 @@ void LLVMDisposeErrorMessage(char *ErrMsg); */ LLVMErrorTypeId LLVMGetStringErrorTypeId(void); +/** + * Create a StringError. + */ +LLVMErrorRef LLVMCreateStringError(const char *ErrMsg); + LLVM_C_EXTERN_C_END #endif diff --git a/contrib/llvm-project/llvm/include/llvm-c/LLJIT.h b/contrib/llvm-project/llvm/include/llvm-c/LLJIT.h new file mode 100644 index 000000000000..28eb8bbff96b --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm-c/LLJIT.h @@ -0,0 +1,213 @@ +/*===----------- llvm-c/LLJIT.h - OrcV2 LLJIT C bindings --------*- C++ -*-===*\ +|* *| +|* 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 *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to the LLJIT class in *| +|* libLLVMOrcJIT.a, which provides a simple MCJIT-like ORC JIT. *| +|* *| +|* Many exotic languages can interoperate with C code but have a harder time *| +|* with C++ due to name mangling. So in addition to C, this interface enables *| +|* tools written in such languages. *| +|* *| +|* Note: This interface is experimental. It is *NOT* stable, and may be *| +|* changed without warning. Only C API usage documentation is *| +|* provided. See the C++ documentation for all higher level ORC API *| +|* details. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_LLJIT_H +#define LLVM_C_LLJIT_H + +#include "llvm-c/Error.h" +#include "llvm-c/Orc.h" +#include "llvm-c/TargetMachine.h" +#include "llvm-c/Types.h" + +LLVM_C_EXTERN_C_BEGIN + +/** + * A function for constructing an ObjectLinkingLayer instance to be used + * by an LLJIT instance. + * + * Clients can call LLVMOrcLLJITBuilderSetObjectLinkingLayerCreator to + * set the creator function to use when constructing an LLJIT instance. + * This can be used to override the default linking layer implementation + * that would otherwise be chosen by LLJITBuilder. + * + * Object linking layers returned by this function will become owned by the + * LLJIT instance. The client is not responsible for managing their lifetimes + * after the function returns. + */ +typedef LLVMOrcObjectLayerRef ( + *LLVMOrcLLJITBuilderObjectLinkingLayerCreatorFunction)( + void *Ctx, LLVMOrcExecutionSessionRef ES, const char *Triple); + +/** + * A reference to an orc::LLJITBuilder instance. + */ +typedef struct LLVMOrcOpaqueLLJITBuilder *LLVMOrcLLJITBuilderRef; + +/** + * A reference to an orc::LLJIT instance. + */ +typedef struct LLVMOrcOpaqueLLJIT *LLVMOrcLLJITRef; + +/** + * Create an LLVMOrcLLJITBuilder. + * + * The client owns the resulting LLJITBuilder and should dispose of it using + * LLVMOrcDisposeLLJITBuilder once they are done with it. + */ +LLVMOrcLLJITBuilderRef LLVMOrcCreateLLJITBuilder(void); + +/** + * Dispose of an LLVMOrcLLJITBuilderRef. This should only be called if ownership + * has not been passed to LLVMOrcCreateLLJIT (e.g. because some error prevented + * that function from being called). + */ +void LLVMOrcDisposeLLJITBuilder(LLVMOrcLLJITBuilderRef Builder); + +/** + * Set the JITTargetMachineBuilder to be used when constructing the LLJIT + * instance. Calling this function is optional: if it is not called then the + * LLJITBuilder will use JITTargeTMachineBuilder::detectHost to construct a + * JITTargetMachineBuilder. + */ +void LLVMOrcLLJITBuilderSetJITTargetMachineBuilder( + LLVMOrcLLJITBuilderRef Builder, LLVMOrcJITTargetMachineBuilderRef JTMB); + +/** + * Set an ObjectLinkingLayer creator function for this LLJIT instance. + */ +void LLVMOrcLLJITBuilderSetObjectLinkingLayerCreator( + LLVMOrcLLJITBuilderRef Builder, + LLVMOrcLLJITBuilderObjectLinkingLayerCreatorFunction F, void *Ctx); + +/** + * Create an LLJIT instance from an LLJITBuilder. + * + * This operation takes ownership of the Builder argument: clients should not + * dispose of the builder after calling this function (even if the function + * returns an error). If a null Builder argument is provided then a + * default-constructed LLJITBuilder will be used. + * + * On success the resulting LLJIT instance is uniquely owned by the client and + * automatically manages the memory of all JIT'd code and all modules that are + * transferred to it (e.g. via LLVMOrcLLJITAddLLVMIRModule). Disposing of the + * LLJIT instance will free all memory managed by the JIT, including JIT'd code + * and not-yet compiled modules. + */ +LLVMErrorRef LLVMOrcCreateLLJIT(LLVMOrcLLJITRef *Result, + LLVMOrcLLJITBuilderRef Builder); + +/** + * Dispose of an LLJIT instance. + */ +LLVMErrorRef LLVMOrcDisposeLLJIT(LLVMOrcLLJITRef J); + +/** + * Get a reference to the ExecutionSession for this LLJIT instance. + * + * The ExecutionSession is owned by the LLJIT instance. The client is not + * responsible for managing its memory. + */ +LLVMOrcExecutionSessionRef LLVMOrcLLJITGetExecutionSession(LLVMOrcLLJITRef J); + +/** + * Return a reference to the Main JITDylib. + * + * The JITDylib is owned by the LLJIT instance. The client is not responsible + * for managing its memory. + */ +LLVMOrcJITDylibRef LLVMOrcLLJITGetMainJITDylib(LLVMOrcLLJITRef J); + +/** + * Return the target triple for this LLJIT instance. This string is owned by + * the LLJIT instance and should not be freed by the client. + */ +const char *LLVMOrcLLJITGetTripleString(LLVMOrcLLJITRef J); + +/** + * Returns the global prefix character according to the LLJIT's DataLayout. + */ +char LLVMOrcLLJITGetGlobalPrefix(LLVMOrcLLJITRef J); + +/** + * Mangles the given string according to the LLJIT instance's DataLayout, then + * interns the result in the SymbolStringPool and returns a reference to the + * pool entry. Clients should call LLVMOrcReleaseSymbolStringPoolEntry to + * decrement the ref-count on the pool entry once they are finished with this + * value. + */ +LLVMOrcSymbolStringPoolEntryRef +LLVMOrcLLJITMangleAndIntern(LLVMOrcLLJITRef J, const char *UnmangledName); + +/** + * Add a buffer representing an object file to the given JITDylib in the given + * LLJIT instance. This operation transfers ownership of the buffer to the + * LLJIT instance. The buffer should not be disposed of or referenced once this + * function returns. + * + * Resources associated with the given object will be tracked by the given + * JITDylib's default resource tracker. + */ +LLVMErrorRef LLVMOrcLLJITAddObjectFile(LLVMOrcLLJITRef J, LLVMOrcJITDylibRef JD, + LLVMMemoryBufferRef ObjBuffer); + +/** + * Add a buffer representing an object file to the given ResourceTracker's + * JITDylib in the given LLJIT instance. This operation transfers ownership of + * the buffer to the LLJIT instance. The buffer should not be disposed of or + * referenced once this function returns. + * + * Resources associated with the given object will be tracked by ResourceTracker + * RT. + */ +LLVMErrorRef LLVMOrcLLJITAddObjectFileWithRT(LLVMOrcLLJITRef J, + LLVMOrcResourceTrackerRef RT, + LLVMMemoryBufferRef ObjBuffer); + +/** + * Add an IR module to the given JITDylib in the given LLJIT instance. This + * operation transfers ownership of the TSM argument to the LLJIT instance. + * The TSM argument should not be disposed of or referenced once this + * function returns. + * + * Resources associated with the given Module will be tracked by the given + * JITDylib's default resource tracker. + */ +LLVMErrorRef LLVMOrcLLJITAddLLVMIRModule(LLVMOrcLLJITRef J, + LLVMOrcJITDylibRef JD, + LLVMOrcThreadSafeModuleRef TSM); + +/** + * Add an IR module to the given ResourceTracker's JITDylib in the given LLJIT + * instance. This operation transfers ownership of the TSM argument to the LLJIT + * instance. The TSM argument should not be disposed of or referenced once this + * function returns. + * + * Resources associated with the given Module will be tracked by ResourceTracker + * RT. + */ +LLVMErrorRef LLVMOrcLLJITAddLLVMIRModuleWithRT(LLVMOrcLLJITRef J, + LLVMOrcResourceTrackerRef JD, + LLVMOrcThreadSafeModuleRef TSM); + +/** + * Look up the given symbol in the main JITDylib of the given LLJIT instance. + * + * This operation does not take ownership of the Name argument. + */ +LLVMErrorRef LLVMOrcLLJITLookup(LLVMOrcLLJITRef J, + LLVMOrcJITTargetAddress *Result, + const char *Name); + +LLVM_C_EXTERN_C_END + +#endif /* LLVM_C_LLJIT_H */ diff --git a/contrib/llvm-project/llvm/include/llvm-c/LinkTimeOptimizer.h b/contrib/llvm-project/llvm/include/llvm-c/LinkTimeOptimizer.h deleted file mode 100644 index 9ae65b8fe5e0..000000000000 --- a/contrib/llvm-project/llvm/include/llvm-c/LinkTimeOptimizer.h +++ /dev/null @@ -1,66 +0,0 @@ -//===-- llvm/LinkTimeOptimizer.h - LTO Public C Interface -------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// This header provides a C API to use the LLVM link time optimization -// library. This is intended to be used by linkers which are C-only in -// their implementation for performing LTO. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_C_LINKTIMEOPTIMIZER_H -#define LLVM_C_LINKTIMEOPTIMIZER_H - -#include "llvm-c/ExternC.h" - -LLVM_C_EXTERN_C_BEGIN - -/** - * @defgroup LLVMCLinkTimeOptimizer Link Time Optimization - * @ingroup LLVMC - * - * @{ - */ - - /// This provides a dummy type for pointers to the LTO object. - typedef void* llvm_lto_t; - - /// This provides a C-visible enumerator to manage status codes. - /// This should map exactly onto the C++ enumerator LTOStatus. - typedef enum llvm_lto_status { - LLVM_LTO_UNKNOWN, - LLVM_LTO_OPT_SUCCESS, - LLVM_LTO_READ_SUCCESS, - LLVM_LTO_READ_FAILURE, - LLVM_LTO_WRITE_FAILURE, - LLVM_LTO_NO_TARGET, - LLVM_LTO_NO_WORK, - LLVM_LTO_MODULE_MERGE_FAILURE, - LLVM_LTO_ASM_FAILURE, - - // Added C-specific error codes - LLVM_LTO_NULL_OBJECT - } llvm_lto_status_t; - - /// This provides C interface to initialize link time optimizer. This allows - /// linker to use dlopen() interface to dynamically load LinkTimeOptimizer. - /// extern "C" helps, because dlopen() interface uses name to find the symbol. - extern llvm_lto_t llvm_create_optimizer(void); - extern void llvm_destroy_optimizer(llvm_lto_t lto); - - extern llvm_lto_status_t llvm_read_object_file - (llvm_lto_t lto, const char* input_filename); - extern llvm_lto_status_t llvm_optimize_modules - (llvm_lto_t lto, const char* output_filename); - -/** - * @} - */ - - LLVM_C_EXTERN_C_END - -#endif diff --git a/contrib/llvm-project/llvm/include/llvm-c/Orc.h b/contrib/llvm-project/llvm/include/llvm-c/Orc.h index 09a058846108..9beef44c89dd 100644 --- a/contrib/llvm-project/llvm/include/llvm-c/Orc.h +++ b/contrib/llvm-project/llvm/include/llvm-c/Orc.h @@ -38,33 +38,201 @@ LLVM_C_EXTERN_C_BEGIN */ typedef uint64_t LLVMOrcJITTargetAddress; +/** + * Represents generic linkage flags for a symbol definition. + */ +typedef enum { + LLVMJITSymbolGenericFlagsExported = 1U << 0, + LLVMJITSymbolGenericFlagsWeak = 1U << 1 +} LLVMJITSymbolGenericFlags; + +/** + * Represents target specific flags for a symbol definition. + */ +typedef uint8_t LLVMJITTargetSymbolFlags; + +/** + * Represents the linkage flags for a symbol definition. + */ +typedef struct { + uint8_t GenericFlags; + uint8_t TargetFlags; +} LLVMJITSymbolFlags; + +/** + * Represents an evaluated symbol address and flags. + */ +typedef struct { + LLVMOrcJITTargetAddress Address; + LLVMJITSymbolFlags Flags; +} LLVMJITEvaluatedSymbol; + /** * A reference to an orc::ExecutionSession instance. */ typedef struct LLVMOrcOpaqueExecutionSession *LLVMOrcExecutionSessionRef; +/** + * Error reporter function. + */ +typedef void (*LLVMOrcErrorReporterFunction)(void *Ctx, LLVMErrorRef Err); + +/** + * A reference to an orc::SymbolStringPool. + */ +typedef struct LLVMOrcOpaqueSymbolStringPool *LLVMOrcSymbolStringPoolRef; + /** * A reference to an orc::SymbolStringPool table entry. */ -typedef struct LLVMOrcQuaqueSymbolStringPoolEntryPtr +typedef struct LLVMOrcOpaqueSymbolStringPoolEntry *LLVMOrcSymbolStringPoolEntryRef; +/** + * Represents a pair of a symbol name and an evaluated symbol. + */ +typedef struct { + LLVMOrcSymbolStringPoolEntryRef Name; + LLVMJITEvaluatedSymbol Sym; +} LLVMJITCSymbolMapPair; + +/** + * Represents a list of (SymbolStringPtr, JITEvaluatedSymbol) pairs that can be + * used to construct a SymbolMap. + */ +typedef LLVMJITCSymbolMapPair *LLVMOrcCSymbolMapPairs; + +/** + * Lookup kind. This can be used by definition generators when deciding whether + * to produce a definition for a requested symbol. + * + * This enum should be kept in sync with llvm::orc::LookupKind. + */ +typedef enum { + LLVMOrcLookupKindStatic, + LLVMOrcLookupKindDLSym +} LLVMOrcLookupKind; + +/** + * JITDylib lookup flags. This can be used by definition generators when + * deciding whether to produce a definition for a requested symbol. + * + * This enum should be kept in sync with llvm::orc::JITDylibLookupFlags. + */ +typedef enum { + LLVMOrcJITDylibLookupFlagsMatchExportedSymbolsOnly, + LLVMOrcJITDylibLookupFlagsMatchAllSymbols +} LLVMOrcJITDylibLookupFlags; + +/** + * Symbol lookup flags for lookup sets. This should be kept in sync with + * llvm::orc::SymbolLookupFlags. + */ +typedef enum { + LLVMOrcSymbolLookupFlagsRequiredSymbol, + LLVMOrcSymbolLookupFlagsWeaklyReferencedSymbol +} LLVMOrcSymbolLookupFlags; + +/** + * An element type for a symbol lookup set. + */ +typedef struct { + LLVMOrcSymbolStringPoolEntryRef Name; + LLVMOrcSymbolLookupFlags LookupFlags; +} LLVMOrcCLookupSetElement; + +/** + * A set of symbols to look up / generate. + * + * The list is terminated with an element containing a null pointer for the + * Name field. + * + * If a client creates an instance of this type then they are responsible for + * freeing it, and for ensuring that all strings have been retained over the + * course of its life. Clients receiving a copy from a callback are not + * responsible for managing lifetime or retain counts. + */ +typedef LLVMOrcCLookupSetElement *LLVMOrcCLookupSet; + +/** + * A reference to an orc::MaterializationUnit. + */ +typedef struct LLVMOrcOpaqueMaterializationUnit *LLVMOrcMaterializationUnitRef; + /** * A reference to an orc::JITDylib instance. */ typedef struct LLVMOrcOpaqueJITDylib *LLVMOrcJITDylibRef; /** - * A reference to an orc::JITDylib::DefinitionGenerator. + * A reference to an orc::ResourceTracker instance. + */ +typedef struct LLVMOrcOpaqueResourceTracker *LLVMOrcResourceTrackerRef; + +/** + * A reference to an orc::DefinitionGenerator. + */ +typedef struct LLVMOrcOpaqueDefinitionGenerator + *LLVMOrcDefinitionGeneratorRef; + +/** + * An opaque lookup state object. Instances of this type can be captured to + * suspend a lookup while a custom generator function attempts to produce a + * definition. + * + * If a client captures a lookup state object then they must eventually call + * LLVMOrcLookupStateContinueLookup to restart the lookup. This is required + * in order to release memory allocated for the lookup state, even if errors + * have occurred while the lookup was suspended (if these errors have made the + * lookup impossible to complete then it will issue its own error before + * destruction). + */ +typedef struct LLVMOrcOpaqueLookupState *LLVMOrcLookupStateRef; + +/** + * A custom generator function. This can be used to create a custom generator + * object using LLVMOrcCreateCustomCAPIDefinitionGenerator. The resulting + * object can be attached to a JITDylib, via LLVMOrcJITDylibAddGenerator, to + * receive callbacks when lookups fail to match existing definitions. + * + * GeneratorObj will contain the address of the custom generator object. + * + * Ctx will contain the context object passed to + * LLVMOrcCreateCustomCAPIDefinitionGenerator. + * + * LookupState will contain a pointer to an LLVMOrcLookupStateRef object. This + * can optionally be modified to make the definition generation process + * asynchronous: If the LookupStateRef value is copied, and the original + * LLVMOrcLookupStateRef set to null, the lookup will be suspended. Once the + * asynchronous definition process has been completed clients must call + * LLVMOrcLookupStateContinueLookup to continue the lookup (this should be + * done unconditionally, even if errors have occurred in the mean time, to + * free the lookup state memory and notify the query object of the failures. If + * LookupState is captured this function must return LLVMErrorSuccess. + * + * The Kind argument can be inspected to determine the lookup kind (e.g. + * as-if-during-static-link, or as-if-during-dlsym). + * + * The JD argument specifies which JITDylib the definitions should be generated + * into. + * + * The JDLookupFlags argument can be inspected to determine whether the original + * lookup included non-exported symobls. + * + * Finally, the LookupSet argument contains the set of symbols that could not + * be found in JD already (the set of generation candidates). */ -typedef struct LLVMOrcOpaqueJITDylibDefinitionGenerator - *LLVMOrcJITDylibDefinitionGeneratorRef; +typedef LLVMErrorRef (*LLVMOrcCAPIDefinitionGeneratorTryToGenerateFunction)( + LLVMOrcDefinitionGeneratorRef GeneratorObj, void *Ctx, + LLVMOrcLookupStateRef *LookupState, LLVMOrcLookupKind Kind, + LLVMOrcJITDylibRef JD, LLVMOrcJITDylibLookupFlags JDLookupFlags, + LLVMOrcCLookupSet LookupSet, size_t LookupSetSize); /** * Predicate function for SymbolStringPoolEntries. */ -typedef int (*LLVMOrcSymbolPredicate)(LLVMOrcSymbolStringPoolEntryRef Sym, - void *Ctx); +typedef int (*LLVMOrcSymbolPredicate)(void *Ctx, + LLVMOrcSymbolStringPoolEntryRef Sym); /** * A reference to an orc::ThreadSafeContext instance. @@ -83,14 +251,43 @@ typedef struct LLVMOrcOpaqueJITTargetMachineBuilder *LLVMOrcJITTargetMachineBuilderRef; /** - * A reference to an orc::LLJITBuilder instance. + * A reference to an orc::ObjectLayer instance. + */ +typedef struct LLVMOrcOpaqueObjectLayer *LLVMOrcObjectLayerRef; + +/** + * Attach a custom error reporter function to the ExecutionSession. + * + * The error reporter will be called to deliver failure notices that can not be + * directly reported to a caller. For example, failure to resolve symbols in + * the JIT linker is typically reported via the error reporter (callers + * requesting definitions from the JIT will typically be delivered a + * FailureToMaterialize error instead). + */ +void LLVMOrcExecutionSessionSetErrorReporter( + LLVMOrcExecutionSessionRef ES, LLVMOrcErrorReporterFunction ReportError, + void *Ctx); + +/** + * Return a reference to the SymbolStringPool for an ExecutionSession. + * + * Ownership of the pool remains with the ExecutionSession: The caller is + * not required to free the pool. */ -typedef struct LLVMOrcOpaqueLLJITBuilder *LLVMOrcLLJITBuilderRef; +LLVMOrcSymbolStringPoolRef +LLVMOrcExecutionSessionGetSymbolStringPool(LLVMOrcExecutionSessionRef ES); /** - * A reference to an orc::LLJIT instance. + * Clear all unreferenced symbol string pool entries. + * + * This can be called at any time to release unused entries in the + * ExecutionSession's string pool. Since it locks the pool (preventing + * interning of any new strings) it is recommended that it only be called + * infrequently, ideally when the caller has reason to believe that some + * entries will have become unreferenced, e.g. after removing a module or + * closing a JITDylib. */ -typedef struct LLVMOrcOpaqueLLJIT *LLVMOrcLLJITRef; +void LLVMOrcSymbolStringPoolClearDeadEntries(LLVMOrcSymbolStringPoolRef SSP); /** * Intern a string in the ExecutionSession's SymbolStringPool and return a @@ -107,27 +304,139 @@ typedef struct LLVMOrcOpaqueLLJIT *LLVMOrcLLJITRef; LLVMOrcSymbolStringPoolEntryRef LLVMOrcExecutionSessionIntern(LLVMOrcExecutionSessionRef ES, const char *Name); +/** + * Increments the ref-count for a SymbolStringPool entry. + */ +void LLVMOrcRetainSymbolStringPoolEntry(LLVMOrcSymbolStringPoolEntryRef S); + /** * Reduces the ref-count for of a SymbolStringPool entry. */ void LLVMOrcReleaseSymbolStringPoolEntry(LLVMOrcSymbolStringPoolEntryRef S); +const char *LLVMOrcSymbolStringPoolEntryStr(LLVMOrcSymbolStringPoolEntryRef S); + +/** + * Reduces the ref-count of a ResourceTracker. + */ +void LLVMOrcReleaseResourceTracker(LLVMOrcResourceTrackerRef RT); + +/** + * Transfers tracking of all resources associated with resource tracker SrcRT + * to resource tracker DstRT. + */ +void LLVMOrcResourceTrackerTransferTo(LLVMOrcResourceTrackerRef SrcRT, + LLVMOrcResourceTrackerRef DstRT); + +/** + * Remove all resources associated with the given tracker. See + * ResourceTracker::remove(). + */ +LLVMErrorRef LLVMOrcResourceTrackerRemove(LLVMOrcResourceTrackerRef RT); + /** * Dispose of a JITDylib::DefinitionGenerator. This should only be called if * ownership has not been passed to a JITDylib (e.g. because some error * prevented the client from calling LLVMOrcJITDylibAddGenerator). */ -void LLVMOrcDisposeJITDylibDefinitionGenerator( - LLVMOrcJITDylibDefinitionGeneratorRef DG); +void LLVMOrcDisposeDefinitionGenerator(LLVMOrcDefinitionGeneratorRef DG); /** - * Add a JITDylib::DefinitionGenerator to the given JITDylib. + * Dispose of a MaterializationUnit. + */ +void LLVMOrcDisposeMaterializationUnit(LLVMOrcMaterializationUnitRef MU); + +/** + * Create a MaterializationUnit to define the given symbols as pointing to + * the corresponding raw addresses. + */ +LLVMOrcMaterializationUnitRef +LLVMOrcAbsoluteSymbols(LLVMOrcCSymbolMapPairs Syms, size_t NumPairs); + +/** + * Create a "bare" JITDylib. + * + * The client is responsible for ensuring that the JITDylib's name is unique, + * e.g. by calling LLVMOrcExecutionSessionGetJTIDylibByName first. + * + * This call does not install any library code or symbols into the newly + * created JITDylib. The client is responsible for all configuration. + */ +LLVMOrcJITDylibRef +LLVMOrcExecutionSessionCreateBareJITDylib(LLVMOrcExecutionSessionRef ES, + const char *Name); + +/** + * Create a JITDylib. + * + * The client is responsible for ensuring that the JITDylib's name is unique, + * e.g. by calling LLVMOrcExecutionSessionGetJTIDylibByName first. + * + * If a Platform is attached to the ExecutionSession then + * Platform::setupJITDylib will be called to install standard platform symbols + * (e.g. standard library interposes). If no Platform is installed then this + * call is equivalent to LLVMExecutionSessionRefCreateBareJITDylib and will + * always return success. + */ +LLVMErrorRef +LLVMOrcExecutionSessionCreateJITDylib(LLVMOrcExecutionSessionRef ES, + LLVMOrcJITDylibRef *Result, + const char *Name); + +/** + * Returns the JITDylib with the given name, or NULL if no such JITDylib + * exists. + */ +LLVMOrcJITDylibRef +LLVMOrcExecutionSessionGetJITDylibByName(LLVMOrcExecutionSessionRef ES, + const char *Name); + +/** + * Return a reference to a newly created resource tracker associated with JD. + * The tracker is returned with an initial ref-count of 1, and must be released + * with LLVMOrcReleaseResourceTracker when no longer needed. + */ +LLVMOrcResourceTrackerRef +LLVMOrcJITDylibCreateResourceTracker(LLVMOrcJITDylibRef JD); + +/** + * Return a reference to the default resource tracker for the given JITDylib. + * This operation will increase the retain count of the tracker: Clients should + * call LLVMOrcReleaseResourceTracker when the result is no longer needed. + */ +LLVMOrcResourceTrackerRef +LLVMOrcJITDylibGetDefaultResourceTracker(LLVMOrcJITDylibRef JD); + +/** + * Add the given MaterializationUnit to the given JITDylib. + * + * If this operation succeeds then JITDylib JD will take ownership of MU. + * If the operation fails then ownership remains with the caller who should + * call LLVMOrcDisposeMaterializationUnit to destroy it. + */ +LLVMErrorRef LLVMOrcJITDylibDefine(LLVMOrcJITDylibRef JD, + LLVMOrcMaterializationUnitRef MU); + +/** + * Calls remove on all trackers associated with this JITDylib, see + * JITDylib::clear(). + */ +LLVMErrorRef LLVMOrcJITDylibClear(LLVMOrcJITDylibRef JD); + +/** + * Add a DefinitionGenerator to the given JITDylib. * * The JITDylib will take ownership of the given generator: The client is no * longer responsible for managing its memory. */ void LLVMOrcJITDylibAddGenerator(LLVMOrcJITDylibRef JD, - LLVMOrcJITDylibDefinitionGeneratorRef DG); + LLVMOrcDefinitionGeneratorRef DG); + +/** + * Create a custom generator. + */ +LLVMOrcDefinitionGeneratorRef LLVMOrcCreateCustomCAPIDefinitionGenerator( + LLVMOrcCAPIDefinitionGeneratorTryToGenerateFunction F, void *Ctx); /** * Get a DynamicLibrarySearchGenerator that will reflect process symbols into @@ -148,7 +457,7 @@ void LLVMOrcJITDylibAddGenerator(LLVMOrcJITDylibRef JD, * the global prefix if present. */ LLVMErrorRef LLVMOrcCreateDynamicLibrarySearchGeneratorForProcess( - LLVMOrcJITDylibDefinitionGeneratorRef *Result, char GlobalPrefx, + LLVMOrcDefinitionGeneratorRef *Result, char GlobalPrefx, LLVMOrcSymbolPredicate Filter, void *FilterCtx); /** @@ -156,7 +465,7 @@ LLVMErrorRef LLVMOrcCreateDynamicLibrarySearchGeneratorForProcess( * * Ownership of the underlying ThreadSafeContext data is shared: Clients * can and should dispose of their ThreadSafeContext as soon as they no longer - * need to refer to it directly. Other references (e.g. from ThreadSafeModules + * need to refer to it directly. Other references (e.g. from ThreadSafeModules) * will keep the data alive as long as it is needed. */ LLVMOrcThreadSafeContextRef LLVMOrcCreateNewThreadSafeContext(void); @@ -178,7 +487,7 @@ void LLVMOrcDisposeThreadSafeContext(LLVMOrcThreadSafeContextRef TSCtx); * after this function returns. * * Ownership of the ThreadSafeModule is unique: If it is transferred to the JIT - * (e.g. by LLVMOrcLLJITAddLLVMIRModule), in which case the client is no longer + * (e.g. by LLVMOrcLLJITAddLLVMIRModule) then the client is no longer * responsible for it. If it is not transferred to the JIT then the client * should call LLVMOrcDisposeThreadSafeModule to dispose of it. */ @@ -221,114 +530,9 @@ void LLVMOrcDisposeJITTargetMachineBuilder( LLVMOrcJITTargetMachineBuilderRef JTMB); /** - * Create an LLJITTargetMachineBuilder. - * - * The client owns the resulting LLJITBuilder and should dispose of it using - * LLVMOrcDisposeLLJITBuilder once they are done with it. - */ -LLVMOrcLLJITBuilderRef LLVMOrcCreateLLJITBuilder(void); - -/** - * Dispose of an LLVMOrcLLJITBuilderRef. This should only be called if ownership - * has not been passed to LLVMOrcCreateLLJIT (e.g. because some error prevented - * that function from being called). - */ -void LLVMOrcDisposeLLJITBuilder(LLVMOrcLLJITBuilderRef Builder); - -/** - * Set the JITTargetMachineBuilder to be used when constructing the LLJIT - * instance. Calling this function is optional: if it is not called then the - * LLJITBuilder will use JITTargeTMachineBuilder::detectHost to construct a - * JITTargetMachineBuilder. - */ -void LLVMOrcLLJITBuilderSetJITTargetMachineBuilder( - LLVMOrcLLJITBuilderRef Builder, LLVMOrcJITTargetMachineBuilderRef JTMB); - -/** - * Create an LLJIT instance from an LLJITBuilder. - * - * This operation takes ownership of the Builder argument: clients should not - * dispose of the builder after calling this function (even if the function - * returns an error). If a null Builder argument is provided then a - * default-constructed LLJITBuilder will be used. - * - * On success the resulting LLJIT instance is uniquely owned by the client and - * automatically manages the memory of all JIT'd code and all modules that are - * transferred to it (e.g. via LLVMOrcLLJITAddLLVMIRModule). Disposing of the - * LLJIT instance will free all memory managed by the JIT, including JIT'd code - * and not-yet compiled modules. - */ -LLVMErrorRef LLVMOrcCreateLLJIT(LLVMOrcLLJITRef *Result, - LLVMOrcLLJITBuilderRef Builder); - -/** - * Dispose of an LLJIT instance. - */ -LLVMErrorRef LLVMOrcDisposeLLJIT(LLVMOrcLLJITRef J); - -/** - * Get a reference to the ExecutionSession for this LLJIT instance. - * - * The ExecutionSession is owned by the LLJIT instance. The client is not - * responsible for managing its memory. - */ -LLVMOrcExecutionSessionRef LLVMOrcLLJITGetExecutionSession(LLVMOrcLLJITRef J); - -/** - * Return a reference to the Main JITDylib. - * - * The JITDylib is owned by the LLJIT instance. The client is not responsible - * for managing its memory. - */ -LLVMOrcJITDylibRef LLVMOrcLLJITGetMainJITDylib(LLVMOrcLLJITRef J); - -/** - * Return the target triple for this LLJIT instance. This string is owned by - * the LLJIT instance and should not be freed by the client. - */ -const char *LLVMOrcLLJITGetTripleString(LLVMOrcLLJITRef J); - -/** - * Returns the global prefix character according to the LLJIT's DataLayout. - */ -char LLVMOrcLLJITGetGlobalPrefix(LLVMOrcLLJITRef J); - -/** - * Mangles the given string according to the LLJIT instance's DataLayout, then - * interns the result in the SymbolStringPool and returns a reference to the - * pool entry. Clients should call LLVMOrcReleaseSymbolStringPoolEntry to - * decrement the ref-count on the pool entry once they are finished with this - * value. - */ -LLVMOrcSymbolStringPoolEntryRef -LLVMOrcLLJITMangleAndIntern(LLVMOrcLLJITRef J, const char *UnmangledName); - -/** - * Add a buffer representing an object file to the given JITDylib in the given - * LLJIT instance. This operation transfers ownership of the buffer to the - * LLJIT instance. The buffer should not be disposed of or referenced once this - * function returns. - */ -LLVMErrorRef LLVMOrcLLJITAddObjectFile(LLVMOrcLLJITRef J, LLVMOrcJITDylibRef JD, - LLVMMemoryBufferRef ObjBuffer); - -/** - * Add an IR module to the given JITDylib of the given LLJIT instance. This - * operation transfers ownership of the TSM argument to the LLJIT instance. - * The TSM argument should not be 3disposed of or referenced once this - * function returns. - */ -LLVMErrorRef LLVMOrcLLJITAddLLVMIRModule(LLVMOrcLLJITRef J, - LLVMOrcJITDylibRef JD, - LLVMOrcThreadSafeModuleRef TSM); -/** - * Look up the given symbol in the main JITDylib of the given LLJIT instance. - * - * This operation does not take ownership of the Name argument. + * Dispose of an ObjectLayer. */ -LLVMErrorRef LLVMOrcLLJITLookup(LLVMOrcLLJITRef J, - LLVMOrcJITTargetAddress *Result, - const char *Name); +void LLVMOrcDisposeObjectLayer(LLVMOrcObjectLayerRef ObjLayer); LLVM_C_EXTERN_C_END diff --git a/contrib/llvm-project/llvm/include/llvm-c/OrcBindings.h b/contrib/llvm-project/llvm/include/llvm-c/OrcBindings.h deleted file mode 100644 index 11cdade7c26f..000000000000 --- a/contrib/llvm-project/llvm/include/llvm-c/OrcBindings.h +++ /dev/null @@ -1,169 +0,0 @@ -/*===----------- llvm-c/OrcBindings.h - Orc Lib C Iface ---------*- C++ -*-===*\ -|* *| -|* 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 *| -|* *| -|*===----------------------------------------------------------------------===*| -|* *| -|* This header declares the C interface to libLLVMOrcJIT.a, which implements *| -|* JIT compilation of LLVM IR. *| -|* *| -|* Many exotic languages can interoperate with C code but have a harder time *| -|* with C++ due to name mangling. So in addition to C, this interface enables *| -|* tools written in such languages. *| -|* *| -|* Note: This interface is experimental. It is *NOT* stable, and may be *| -|* changed without warning. *| -|* *| -\*===----------------------------------------------------------------------===*/ - -#ifndef LLVM_C_ORCBINDINGS_H -#define LLVM_C_ORCBINDINGS_H - -#include "llvm-c/Error.h" -#include "llvm-c/ExternC.h" -#include "llvm-c/Object.h" -#include "llvm-c/TargetMachine.h" - -LLVM_C_EXTERN_C_BEGIN - -typedef struct LLVMOrcOpaqueJITStack *LLVMOrcJITStackRef; -typedef uint64_t LLVMOrcModuleHandle; -typedef uint64_t LLVMOrcTargetAddress; -typedef uint64_t (*LLVMOrcSymbolResolverFn)(const char *Name, void *LookupCtx); -typedef uint64_t (*LLVMOrcLazyCompileCallbackFn)(LLVMOrcJITStackRef JITStack, - void *CallbackCtx); - -/** - * Create an ORC JIT stack. - * - * The client owns the resulting stack, and must call OrcDisposeInstance(...) - * to destroy it and free its memory. The JIT stack will take ownership of the - * TargetMachine, which will be destroyed when the stack is destroyed. The - * client should not attempt to dispose of the Target Machine, or it will result - * in a double-free. - */ -LLVMOrcJITStackRef LLVMOrcCreateInstance(LLVMTargetMachineRef TM); - -/** - * Get the error message for the most recent error (if any). - * - * This message is owned by the ORC JIT Stack and will be freed when the stack - * is disposed of by LLVMOrcDisposeInstance. - */ -const char *LLVMOrcGetErrorMsg(LLVMOrcJITStackRef JITStack); - -/** - * Mangle the given symbol. - * Memory will be allocated for MangledSymbol to hold the result. The client - */ -void LLVMOrcGetMangledSymbol(LLVMOrcJITStackRef JITStack, char **MangledSymbol, - const char *Symbol); - -/** - * Dispose of a mangled symbol. - */ -void LLVMOrcDisposeMangledSymbol(char *MangledSymbol); - -/** - * Create a lazy compile callback. - */ -LLVMErrorRef LLVMOrcCreateLazyCompileCallback( - LLVMOrcJITStackRef JITStack, LLVMOrcTargetAddress *RetAddr, - LLVMOrcLazyCompileCallbackFn Callback, void *CallbackCtx); - -/** - * Create a named indirect call stub. - */ -LLVMErrorRef LLVMOrcCreateIndirectStub(LLVMOrcJITStackRef JITStack, - const char *StubName, - LLVMOrcTargetAddress InitAddr); - -/** - * Set the pointer for the given indirect stub. - */ -LLVMErrorRef LLVMOrcSetIndirectStubPointer(LLVMOrcJITStackRef JITStack, - const char *StubName, - LLVMOrcTargetAddress NewAddr); - -/** - * Add module to be eagerly compiled. - */ -LLVMErrorRef LLVMOrcAddEagerlyCompiledIR(LLVMOrcJITStackRef JITStack, - LLVMOrcModuleHandle *RetHandle, - LLVMModuleRef Mod, - LLVMOrcSymbolResolverFn SymbolResolver, - void *SymbolResolverCtx); - -/** - * Add module to be lazily compiled one function at a time. - */ -LLVMErrorRef LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack, - LLVMOrcModuleHandle *RetHandle, - LLVMModuleRef Mod, - LLVMOrcSymbolResolverFn SymbolResolver, - void *SymbolResolverCtx); - -/** - * Add an object file. - * - * This method takes ownership of the given memory buffer and attempts to add - * it to the JIT as an object file. - * Clients should *not* dispose of the 'Obj' argument: the JIT will manage it - * from this call onwards. - */ -LLVMErrorRef LLVMOrcAddObjectFile(LLVMOrcJITStackRef JITStack, - LLVMOrcModuleHandle *RetHandle, - LLVMMemoryBufferRef Obj, - LLVMOrcSymbolResolverFn SymbolResolver, - void *SymbolResolverCtx); - -/** - * Remove a module set from the JIT. - * - * This works for all modules that can be added via OrcAdd*, including object - * files. - */ -LLVMErrorRef LLVMOrcRemoveModule(LLVMOrcJITStackRef JITStack, - LLVMOrcModuleHandle H); - -/** - * Get symbol address from JIT instance. - */ -LLVMErrorRef LLVMOrcGetSymbolAddress(LLVMOrcJITStackRef JITStack, - LLVMOrcTargetAddress *RetAddr, - const char *SymbolName); - -/** - * Get symbol address from JIT instance, searching only the specified - * handle. - */ -LLVMErrorRef LLVMOrcGetSymbolAddressIn(LLVMOrcJITStackRef JITStack, - LLVMOrcTargetAddress *RetAddr, - LLVMOrcModuleHandle H, - const char *SymbolName); - -/** - * Dispose of an ORC JIT stack. - */ -LLVMErrorRef LLVMOrcDisposeInstance(LLVMOrcJITStackRef JITStack); - -/** - * Register a JIT Event Listener. - * - * A NULL listener is ignored. - */ -void LLVMOrcRegisterJITEventListener(LLVMOrcJITStackRef JITStack, LLVMJITEventListenerRef L); - -/** - * Unegister a JIT Event Listener. - * - * A NULL listener is ignored. - */ -void LLVMOrcUnregisterJITEventListener(LLVMOrcJITStackRef JITStack, LLVMJITEventListenerRef L); - -LLVM_C_EXTERN_C_END - -#endif /* LLVM_C_ORCBINDINGS_H */ diff --git a/contrib/llvm-project/llvm/include/llvm-c/OrcEE.h b/contrib/llvm-project/llvm/include/llvm-c/OrcEE.h new file mode 100644 index 000000000000..2435e7421a42 --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm-c/OrcEE.h @@ -0,0 +1,55 @@ +/*===-- llvm-c/OrcEE.h - OrcV2 C bindings ExecutionEngine utils -*- C++ -*-===*\ +|* *| +|* 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 *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to ExecutionEngine based utils, e.g. *| +|* RTDyldObjectLinkingLayer (based on RuntimeDyld) in Orc. *| +|* *| +|* Many exotic languages can interoperate with C code but have a harder time *| +|* with C++ due to name mangling. So in addition to C, this interface enables *| +|* tools written in such languages. *| +|* *| +|* Note: This interface is experimental. It is *NOT* stable, and may be *| +|* changed without warning. Only C API usage documentation is *| +|* provided. See the C++ documentation for all higher level ORC API *| +|* details. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_ORCEE_H +#define LLVM_C_ORCEE_H + +#include "llvm-c/Error.h" +#include "llvm-c/ExecutionEngine.h" +#include "llvm-c/Orc.h" +#include "llvm-c/TargetMachine.h" +#include "llvm-c/Types.h" + +LLVM_C_EXTERN_C_BEGIN + +/** + * Create a RTDyldObjectLinkingLayer instance using the standard + * SectionMemoryManager for memory management. + */ +LLVMOrcObjectLayerRef +LLVMOrcCreateRTDyldObjectLinkingLayerWithSectionMemoryManager( + LLVMOrcExecutionSessionRef ES); + +/** + * Add the given listener to the given RTDyldObjectLinkingLayer. + * + * Note: Layer must be an RTDyldObjectLinkingLayer instance or + * behavior is undefined. + */ +void LLVMOrcRTDyldObjectLinkingLayerRegisterJITEventListener( + LLVMOrcObjectLayerRef RTDyldObjLinkingLayer, + LLVMJITEventListenerRef Listener); + +LLVM_C_EXTERN_C_END + +#endif /* LLVM_C_ORCEE_H */ diff --git a/contrib/llvm-project/llvm/include/llvm-c/Transforms/IPO.h b/contrib/llvm-project/llvm/include/llvm-c/Transforms/IPO.h index cde3d2460920..3f2cadf32366 100644 --- a/contrib/llvm-project/llvm/include/llvm-c/Transforms/IPO.h +++ b/contrib/llvm-project/llvm/include/llvm-c/Transforms/IPO.h @@ -57,9 +57,6 @@ void LLVMAddGlobalDCEPass(LLVMPassManagerRef PM); /** See llvm::createGlobalOptimizerPass function. */ void LLVMAddGlobalOptimizerPass(LLVMPassManagerRef PM); -/** See llvm::createIPConstantPropagationPass function. */ -void LLVMAddIPConstantPropagationPass(LLVMPassManagerRef PM); - /** See llvm::createPruneEHPass function. */ void LLVMAddPruneEHPass(LLVMPassManagerRef PM); diff --git a/contrib/llvm-project/llvm/include/llvm-c/Transforms/Scalar.h b/contrib/llvm-project/llvm/include/llvm-c/Transforms/Scalar.h index 93d79a205195..ba142508bbe4 100644 --- a/contrib/llvm-project/llvm/include/llvm-c/Transforms/Scalar.h +++ b/contrib/llvm-project/llvm/include/llvm-c/Transforms/Scalar.h @@ -67,6 +67,9 @@ void LLVMAddIndVarSimplifyPass(LLVMPassManagerRef PM); /** See llvm::createInstructionCombiningPass function. */ void LLVMAddInstructionCombiningPass(LLVMPassManagerRef PM); +/** See llvm::createInstSimplifyLegacyPass function. */ +void LLVMAddInstructionSimplifyPass(LLVMPassManagerRef PM); + /** See llvm::createJumpThreadingPass function. */ void LLVMAddJumpThreadingPass(LLVMPassManagerRef PM); @@ -125,9 +128,6 @@ void LLVMAddSimplifyLibCallsPass(LLVMPassManagerRef PM); /** See llvm::createTailCallEliminationPass function. */ void LLVMAddTailCallEliminationPass(LLVMPassManagerRef PM); -/** See llvm::createConstantPropagationPass function. */ -void LLVMAddConstantPropagationPass(LLVMPassManagerRef PM); - /** See llvm::demotePromoteMemoryToRegisterPass function. */ void LLVMAddDemoteMemoryToRegisterPass(LLVMPassManagerRef PM); diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/APFixedPoint.h b/contrib/llvm-project/llvm/include/llvm/ADT/APFixedPoint.h new file mode 100644 index 000000000000..d6349e6b2a88 --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/ADT/APFixedPoint.h @@ -0,0 +1,237 @@ +//===- APFixedPoint.h - Fixed point constant handling -----------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +/// \file +/// Defines the fixed point number interface. +/// This is a class for abstracting various operations performed on fixed point +/// types. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_APFIXEDPOINT_H +#define LLVM_ADT_APFIXEDPOINT_H + +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +class APFloat; +struct fltSemantics; + +/// The fixed point semantics work similarly to fltSemantics. The width +/// specifies the whole bit width of the underlying scaled integer (with padding +/// if any). The scale represents the number of fractional bits in this type. +/// When HasUnsignedPadding is true and this type is unsigned, the first bit +/// in the value this represents is treated as padding. +class FixedPointSemantics { +public: + FixedPointSemantics(unsigned Width, unsigned Scale, bool IsSigned, + bool IsSaturated, bool HasUnsignedPadding) + : Width(Width), Scale(Scale), IsSigned(IsSigned), + IsSaturated(IsSaturated), HasUnsignedPadding(HasUnsignedPadding) { + assert(Width >= Scale && "Not enough room for the scale"); + assert(!(IsSigned && HasUnsignedPadding) && + "Cannot have unsigned padding on a signed type."); + } + + unsigned getWidth() const { return Width; } + unsigned getScale() const { return Scale; } + bool isSigned() const { return IsSigned; } + bool isSaturated() const { return IsSaturated; } + bool hasUnsignedPadding() const { return HasUnsignedPadding; } + + void setSaturated(bool Saturated) { IsSaturated = Saturated; } + + /// Return the number of integral bits represented by these semantics. These + /// are separate from the fractional bits and do not include the sign or + /// padding bit. + unsigned getIntegralBits() const { + if (IsSigned || (!IsSigned && HasUnsignedPadding)) + return Width - Scale - 1; + else + return Width - Scale; + } + + /// Return the FixedPointSemantics that allows for calculating the full + /// precision semantic that can precisely represent the precision and ranges + /// of both input values. This does not compute the resulting semantics for a + /// given binary operation. + FixedPointSemantics + getCommonSemantics(const FixedPointSemantics &Other) const; + + /// Returns true if this fixed-point semantic with its value bits interpreted + /// as an integer can fit in the given floating point semantic without + /// overflowing to infinity. + /// For example, a signed 8-bit fixed-point semantic has a maximum and + /// minimum integer representation of 127 and -128, respectively. If both of + /// these values can be represented (possibly inexactly) in the floating + /// point semantic without overflowing, this returns true. + bool fitsInFloatSemantics(const fltSemantics &FloatSema) const; + + /// Return the FixedPointSemantics for an integer type. + static FixedPointSemantics GetIntegerSemantics(unsigned Width, + bool IsSigned) { + return FixedPointSemantics(Width, /*Scale=*/0, IsSigned, + /*IsSaturated=*/false, + /*HasUnsignedPadding=*/false); + } + +private: + unsigned Width : 16; + unsigned Scale : 13; + unsigned IsSigned : 1; + unsigned IsSaturated : 1; + unsigned HasUnsignedPadding : 1; +}; + +/// The APFixedPoint class works similarly to APInt/APSInt in that it is a +/// functional replacement for a scaled integer. It is meant to replicate the +/// fixed point types proposed in ISO/IEC JTC1 SC22 WG14 N1169. The class carries +/// info about the fixed point type's width, sign, scale, and saturation, and +/// provides different operations that would normally be performed on fixed point +/// types. +class APFixedPoint { +public: + APFixedPoint(const APInt &Val, const FixedPointSemantics &Sema) + : Val(Val, !Sema.isSigned()), Sema(Sema) { + assert(Val.getBitWidth() == Sema.getWidth() && + "The value should have a bit width that matches the Sema width"); + } + + APFixedPoint(uint64_t Val, const FixedPointSemantics &Sema) + : APFixedPoint(APInt(Sema.getWidth(), Val, Sema.isSigned()), Sema) {} + + // Zero initialization. + APFixedPoint(const FixedPointSemantics &Sema) : APFixedPoint(0, Sema) {} + + APSInt getValue() const { return APSInt(Val, !Sema.isSigned()); } + inline unsigned getWidth() const { return Sema.getWidth(); } + inline unsigned getScale() const { return Sema.getScale(); } + inline bool isSaturated() const { return Sema.isSaturated(); } + inline bool isSigned() const { return Sema.isSigned(); } + inline bool hasPadding() const { return Sema.hasUnsignedPadding(); } + FixedPointSemantics getSemantics() const { return Sema; } + + bool getBoolValue() const { return Val.getBoolValue(); } + + // Convert this number to match the semantics provided. If the overflow + // parameter is provided, set this value to true or false to indicate if this + // operation results in an overflow. + APFixedPoint convert(const FixedPointSemantics &DstSema, + bool *Overflow = nullptr) const; + + // Perform binary operations on a fixed point type. The resulting fixed point + // value will be in the common, full precision semantics that can represent + // the precision and ranges of both input values. See convert() for an + // explanation of the Overflow parameter. + APFixedPoint add(const APFixedPoint &Other, bool *Overflow = nullptr) const; + APFixedPoint sub(const APFixedPoint &Other, bool *Overflow = nullptr) const; + APFixedPoint mul(const APFixedPoint &Other, bool *Overflow = nullptr) const; + APFixedPoint div(const APFixedPoint &Other, bool *Overflow = nullptr) const; + + // Perform shift operations on a fixed point type. Unlike the other binary + // operations, the resulting fixed point value will be in the original + // semantic. + APFixedPoint shl(unsigned Amt, bool *Overflow = nullptr) const; + APFixedPoint shr(unsigned Amt, bool *Overflow = nullptr) const { + // Right shift cannot overflow. + if (Overflow) + *Overflow = false; + return APFixedPoint(Val >> Amt, Sema); + } + + /// Perform a unary negation (-X) on this fixed point type, taking into + /// account saturation if applicable. + APFixedPoint negate(bool *Overflow = nullptr) const; + + /// Return the integral part of this fixed point number, rounded towards + /// zero. (-2.5k -> -2) + APSInt getIntPart() const { + if (Val < 0 && Val != -Val) // Cover the case when we have the min val + return -(-Val >> getScale()); + else + return Val >> getScale(); + } + + /// Return the integral part of this fixed point number, rounded towards + /// zero. The value is stored into an APSInt with the provided width and sign. + /// If the overflow parameter is provided, and the integral value is not able + /// to be fully stored in the provided width and sign, the overflow parameter + /// is set to true. + APSInt convertToInt(unsigned DstWidth, bool DstSign, + bool *Overflow = nullptr) const; + + /// Convert this fixed point number to a floating point value with the + /// provided semantics. + APFloat convertToFloat(const fltSemantics &FloatSema) const; + + void toString(SmallVectorImpl &Str) const; + std::string toString() const { + SmallString<40> S; + toString(S); + return std::string(S.str()); + } + + // If LHS > RHS, return 1. If LHS == RHS, return 0. If LHS < RHS, return -1. + int compare(const APFixedPoint &Other) const; + bool operator==(const APFixedPoint &Other) const { + return compare(Other) == 0; + } + bool operator!=(const APFixedPoint &Other) const { + return compare(Other) != 0; + } + bool operator>(const APFixedPoint &Other) const { return compare(Other) > 0; } + bool operator<(const APFixedPoint &Other) const { return compare(Other) < 0; } + bool operator>=(const APFixedPoint &Other) const { + return compare(Other) >= 0; + } + bool operator<=(const APFixedPoint &Other) const { + return compare(Other) <= 0; + } + + static APFixedPoint getMax(const FixedPointSemantics &Sema); + static APFixedPoint getMin(const FixedPointSemantics &Sema); + + /// Given a floating point semantic, return the next floating point semantic + /// with a larger exponent and larger or equal mantissa. + static const fltSemantics *promoteFloatSemantics(const fltSemantics *S); + + /// Create an APFixedPoint with a value equal to that of the provided integer, + /// and in the same semantics as the provided target semantics. If the value + /// is not able to fit in the specified fixed point semantics, and the + /// overflow parameter is provided, it is set to true. + static APFixedPoint getFromIntValue(const APSInt &Value, + const FixedPointSemantics &DstFXSema, + bool *Overflow = nullptr); + + /// Create an APFixedPoint with a value equal to that of the provided + /// floating point value, in the provided target semantics. If the value is + /// not able to fit in the specified fixed point semantics and the overflow + /// parameter is specified, it is set to true. + /// For NaN, the Overflow flag is always set. For +inf and -inf, if the + /// semantic is saturating, the value saturates. Otherwise, the Overflow flag + /// is set. + static APFixedPoint getFromFloatValue(const APFloat &Value, + const FixedPointSemantics &DstFXSema, + bool *Overflow = nullptr); + +private: + APSInt Val; + FixedPointSemantics Sema; +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const APFixedPoint &FX) { + OS << FX.toString(); + return OS; +} + +} // namespace llvm + +#endif diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/APFloat.h b/contrib/llvm-project/llvm/include/llvm/ADT/APFloat.h index 876e52c150a0..1f9ac22621a6 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/APFloat.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/APFloat.h @@ -249,7 +249,7 @@ public: /// \name Constructors /// @{ - IEEEFloat(const fltSemantics &); // Default construct to 0.0 + IEEEFloat(const fltSemantics &); // Default construct to +0.0 IEEEFloat(const fltSemantics &, integerPart); IEEEFloat(const fltSemantics &, uninitializedTag); IEEEFloat(const fltSemantics &, const APInt &); @@ -539,6 +539,9 @@ private: roundingMode) const; opStatus roundSignificandWithExponent(const integerPart *, unsigned int, int, roundingMode); + ExponentType exponentNaN() const; + ExponentType exponentInf() const; + ExponentType exponentZero() const; /// @} diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/APInt.h b/contrib/llvm-project/llvm/include/llvm/ADT/APInt.h index f7df648d27ed..b97ea2cd9aee 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/APInt.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/APInt.h @@ -31,6 +31,7 @@ class raw_ostream; template class SmallVectorImpl; template class ArrayRef; template class Optional; +template struct DenseMapInfo; class APInt; @@ -96,7 +97,7 @@ private: unsigned BitWidth; ///< The number of bits in this APInt. - friend struct DenseMapAPIntKeyInfo; + friend struct DenseMapInfo; friend class APSInt; @@ -764,8 +765,8 @@ public: /// Move assignment operator. APInt &operator=(APInt &&that) { -#ifdef _MSC_VER - // The MSVC std::shuffle implementation still does self-assignment. +#ifdef EXPENSIVE_CHECKS + // Some std::shuffle implementations still do self-assignment. if (this == &that) return *this; #endif @@ -793,11 +794,10 @@ public: APInt &operator=(uint64_t RHS) { if (isSingleWord()) { U.VAL = RHS; - clearUnusedBits(); - } else { - U.pVal[0] = RHS; - memset(U.pVal+1, 0, (getNumWords() - 1) * APINT_WORD_SIZE); + return clearUnusedBits(); } + U.pVal[0] = RHS; + memset(U.pVal + 1, 0, (getNumWords() - 1) * APINT_WORD_SIZE); return *this; } @@ -854,10 +854,9 @@ public: APInt &operator|=(uint64_t RHS) { if (isSingleWord()) { U.VAL |= RHS; - clearUnusedBits(); - } else { - U.pVal[0] |= RHS; + return clearUnusedBits(); } + U.pVal[0] |= RHS; return *this; } @@ -884,10 +883,9 @@ public: APInt &operator^=(uint64_t RHS) { if (isSingleWord()) { U.VAL ^= RHS; - clearUnusedBits(); - } else { - U.pVal[0] ^= RHS; + return clearUnusedBits(); } + U.pVal[0] ^= RHS; return *this; } @@ -1405,6 +1403,12 @@ public: /// extended, truncated, or left alone to make it that width. APInt zextOrTrunc(unsigned width) const; + /// Truncate to width + /// + /// Make this APInt have the bit width given by \p width. The value is + /// truncated or left alone to make it that width. + APInt truncOrSelf(unsigned width) const; + /// Sign extend or truncate to width /// /// Make this APInt have the bit width given by \p width. The value is sign @@ -1449,6 +1453,14 @@ public: setBit(BitWidth - 1); } + /// Set a given bit to a given value. + void setBitVal(unsigned BitPosition, bool BitValue) { + if (BitValue) + setBit(BitPosition); + else + clearBit(BitPosition); + } + /// Set the bits from loBit (inclusive) to hiBit (exclusive) to 1. /// This function handles "wrap" case when \p loBit >= \p hiBit, and calls /// setBits when \p loBit < \p hiBit. @@ -1609,11 +1621,7 @@ public: /// returns the smallest bit width that will retain the negative value. For /// example, -1 can be written as 0b1 or 0xFFFFFFFFFF. 0b1 is shorter and so /// for -1, this function will always return 1. - unsigned getMinSignedBits() const { - if (isNegative()) - return BitWidth - countLeadingOnes() + 1; - return getActiveBits() + 1; - } + unsigned getMinSignedBits() const { return BitWidth - getNumSignBits() + 1; } /// Get zero extended value /// diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/APSInt.h b/contrib/llvm-project/llvm/include/llvm/ADT/APSInt.h index 0f991826c457..82e9ba81141f 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/APSInt.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/APSInt.h @@ -18,6 +18,7 @@ namespace llvm { +/// An arbitrary precision integer that knows its signedness. class LLVM_NODISCARD APSInt : public APInt { bool IsUnsigned; @@ -25,8 +26,7 @@ public: /// Default constructor that creates an uninitialized APInt. explicit APSInt() : IsUnsigned(false) {} - /// APSInt ctor - Create an APSInt with the specified width, default to - /// unsigned. + /// Create an APSInt with the specified width, default to unsigned. explicit APSInt(uint32_t BitWidth, bool isUnsigned = true) : APInt(BitWidth, 0), IsUnsigned(isUnsigned) {} @@ -78,11 +78,11 @@ public: void setIsUnsigned(bool Val) { IsUnsigned = Val; } void setIsSigned(bool Val) { IsUnsigned = !Val; } - /// toString - Append this APSInt to the specified SmallString. + /// Append this APSInt to the specified SmallString. void toString(SmallVectorImpl &Str, unsigned Radix = 10) const { APInt::toString(Str, Radix, isSigned()); } - /// toString - Converts an APInt to a std::string. This is an inefficient + /// Converts an APInt to a std::string. This is an inefficient /// method; you should prefer passing in a SmallString instead. std::string toString(unsigned Radix) const { return APInt::toString(Radix, isSigned()); @@ -282,15 +282,15 @@ public: return APSInt(~static_cast(*this), IsUnsigned); } - /// getMaxValue - Return the APSInt representing the maximum integer value - /// with the given bit width and signedness. + /// Return the APSInt representing the maximum integer value with the given + /// bit width and signedness. static APSInt getMaxValue(uint32_t numBits, bool Unsigned) { return APSInt(Unsigned ? APInt::getMaxValue(numBits) : APInt::getSignedMaxValue(numBits), Unsigned); } - /// getMinValue - Return the APSInt representing the minimum integer value - /// with the given bit width and signedness. + /// Return the APSInt representing the minimum integer value with the given + /// bit width and signedness. static APSInt getMinValue(uint32_t numBits, bool Unsigned) { return APSInt(Unsigned ? APInt::getMinValue(numBits) : APInt::getSignedMinValue(numBits), Unsigned); @@ -331,8 +331,8 @@ public: static APSInt get(int64_t X) { return APSInt(APInt(64, X), false); } static APSInt getUnsigned(uint64_t X) { return APSInt(APInt(64, X), true); } - /// Profile - Used to insert APSInt objects, or objects that contain APSInt - /// objects, into FoldingSets. + /// Used to insert APSInt objects, or objects that contain APSInt objects, + /// into FoldingSets. void Profile(FoldingSetNodeID& ID) const; }; diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/AllocatorList.h b/contrib/llvm-project/llvm/include/llvm/ADT/AllocatorList.h index 447d7a7538db..404a657f27de 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/AllocatorList.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/AllocatorList.h @@ -118,13 +118,6 @@ private: reference operator*() const { return base_type::wrapped()->V; } pointer operator->() const { return &operator*(); } - - friend bool operator==(const IteratorImpl &L, const IteratorImpl &R) { - return L.wrapped() == R.wrapped(); - } - friend bool operator!=(const IteratorImpl &L, const IteratorImpl &R) { - return !(L == R); - } }; public: diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/Any.h b/contrib/llvm-project/llvm/include/llvm/ADT/Any.h index 0aded628cda4..1e3abca70679 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/Any.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/Any.h @@ -23,7 +23,12 @@ namespace llvm { -class Any { +class LLVM_EXTERNAL_VISIBILITY Any { + + // The `Typeid::Id` static data member below is a globally unique + // identifier for the type `T`. It is explicitly marked with default + // visibility so that when `-fvisibility=hidden` is used, the loader still + // merges duplicate definitions across DSO boundaries. template struct TypeId { static const char Id; }; struct StorageBase { diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/BitVector.h b/contrib/llvm-project/llvm/include/llvm/ADT/BitVector.h index a8d0f07af94a..2a857786f454 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/BitVector.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/BitVector.h @@ -203,9 +203,10 @@ public: return !any(); } - /// find_first_in - Returns the index of the first set bit in the range - /// [Begin, End). Returns -1 if all bits in the range are unset. - int find_first_in(unsigned Begin, unsigned End) const { + /// find_first_in - Returns the index of the first set / unset bit, + /// depending on \p Set, in the range [Begin, End). + /// Returns -1 if all bits in the range are unset / set. + int find_first_in(unsigned Begin, unsigned End, bool Set = true) const { assert(Begin <= End && End <= Size); if (Begin == End) return -1; @@ -214,8 +215,14 @@ public: unsigned LastWord = (End - 1) / BITWORD_SIZE; // Check subsequent words. + // The code below is based on search for the first _set_ bit. If + // we're searching for the first _unset_, we just take the + // complement of each word before we use it and apply + // the same method. for (unsigned i = FirstWord; i <= LastWord; ++i) { BitWord Copy = Bits[i]; + if (!Set) + Copy = ~Copy; if (i == FirstWord) { unsigned FirstBit = Begin % BITWORD_SIZE; @@ -266,32 +273,7 @@ public: /// find_first_unset_in - Returns the index of the first unset bit in the /// range [Begin, End). Returns -1 if all bits in the range are set. int find_first_unset_in(unsigned Begin, unsigned End) const { - assert(Begin <= End && End <= Size); - if (Begin == End) - return -1; - - unsigned FirstWord = Begin / BITWORD_SIZE; - unsigned LastWord = (End - 1) / BITWORD_SIZE; - - // Check subsequent words. - for (unsigned i = FirstWord; i <= LastWord; ++i) { - BitWord Copy = Bits[i]; - - if (i == FirstWord) { - unsigned FirstBit = Begin % BITWORD_SIZE; - Copy |= maskTrailingOnes(FirstBit); - } - - if (i == LastWord) { - unsigned LastBit = (End - 1) % BITWORD_SIZE; - Copy |= maskTrailingZeros(LastBit + 1); - } - if (Copy != ~BitWord(0)) { - unsigned Result = i * BITWORD_SIZE + countTrailingOnes(Copy); - return Result < size() ? Result : -1; - } - } - return -1; + return find_first_in(Begin, End, /* Set = */ false); } /// find_last_unset_in - Returns the index of the last unset bit in the diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/DenseMap.h b/contrib/llvm-project/llvm/include/llvm/ADT/DenseMap.h index 34d397cc9793..ce0b05db840c 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/DenseMap.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/DenseMap.h @@ -426,8 +426,8 @@ protected: setNumEntries(other.getNumEntries()); setNumTombstones(other.getNumTombstones()); - if (is_trivially_copyable::value && - is_trivially_copyable::value) + if (std::is_trivially_copyable::value && + std::is_trivially_copyable::value) memcpy(reinterpret_cast(getBuckets()), other.getBuckets(), getNumBuckets() * sizeof(BucketT)); else @@ -954,7 +954,7 @@ public: std::swap(*LHSB, *RHSB); continue; } - // Swap separately and handle any assymetry. + // Swap separately and handle any asymmetry. std::swap(LHSB->getFirst(), RHSB->getFirst()); if (hasLHSValue) { ::new (&RHSB->getSecond()) ValueT(std::move(LHSB->getSecond())); @@ -1042,7 +1042,7 @@ public: if (Small) { // First move the inline buckets into a temporary storage. AlignedCharArrayUnion TmpStorage; - BucketT *TmpBegin = reinterpret_cast(TmpStorage.buffer); + BucketT *TmpBegin = reinterpret_cast(&TmpStorage); BucketT *TmpEnd = TmpBegin; // Loop over the buckets, moving non-empty, non-tombstones into the @@ -1132,8 +1132,8 @@ private: assert(Small); // Note that this cast does not violate aliasing rules as we assert that // the memory's dynamic type is the small, inline bucket buffer, and the - // 'storage.buffer' static type is 'char *'. - return reinterpret_cast(storage.buffer); + // 'storage' is a POD containing a char buffer. + return reinterpret_cast(&storage); } BucketT *getInlineBuckets() { @@ -1144,7 +1144,7 @@ private: const LargeRep *getLargeRep() const { assert(!Small); // Note, same rule about aliasing as with getInlineBuckets. - return reinterpret_cast(storage.buffer); + return reinterpret_cast(&storage); } LargeRep *getLargeRep() { @@ -1190,8 +1190,6 @@ class DenseMapIterator : DebugEpochBase::HandleBase { friend class DenseMapIterator; friend class DenseMapIterator; - using ConstIterator = DenseMapIterator; - public: using difference_type = ptrdiff_t; using value_type = @@ -1244,19 +1242,18 @@ public: return Ptr; } - bool operator==(const ConstIterator &RHS) const { - assert((!Ptr || isHandleInSync()) && "handle not in sync!"); + friend bool operator==(const DenseMapIterator &LHS, + const DenseMapIterator &RHS) { + assert((!LHS.Ptr || LHS.isHandleInSync()) && "handle not in sync!"); assert((!RHS.Ptr || RHS.isHandleInSync()) && "handle not in sync!"); - assert(getEpochAddress() == RHS.getEpochAddress() && + assert(LHS.getEpochAddress() == RHS.getEpochAddress() && "comparing incomparable iterators!"); - return Ptr == RHS.Ptr; + return LHS.Ptr == RHS.Ptr; } - bool operator!=(const ConstIterator &RHS) const { - assert((!Ptr || isHandleInSync()) && "handle not in sync!"); - assert((!RHS.Ptr || RHS.isHandleInSync()) && "handle not in sync!"); - assert(getEpochAddress() == RHS.getEpochAddress() && - "comparing incomparable iterators!"); - return Ptr != RHS.Ptr; + + friend bool operator!=(const DenseMapIterator &LHS, + const DenseMapIterator &RHS) { + return !(LHS == RHS); } inline DenseMapIterator& operator++() { // Preincrement diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/DenseMapInfo.h b/contrib/llvm-project/llvm/include/llvm/ADT/DenseMapInfo.h index e465331ac6f7..8271b9334b86 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/DenseMapInfo.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/DenseMapInfo.h @@ -13,6 +13,8 @@ #ifndef LLVM_ADT_DENSEMAPINFO_H #define LLVM_ADT_DENSEMAPINFO_H +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/StringRef.h" @@ -347,6 +349,49 @@ template <> struct DenseMapInfo { static bool isEqual(hash_code LHS, hash_code RHS) { return LHS == RHS; } }; +/// Provide DenseMapInfo for APInt. +template <> struct DenseMapInfo { + static inline APInt getEmptyKey() { + APInt V(nullptr, 0); + V.U.VAL = 0; + return V; + } + + static inline APInt getTombstoneKey() { + APInt V(nullptr, 0); + V.U.VAL = 1; + return V; + } + + static unsigned getHashValue(const APInt &Key) { + return static_cast(hash_value(Key)); + } + + static bool isEqual(const APInt &LHS, const APInt &RHS) { + return LHS.getBitWidth() == RHS.getBitWidth() && LHS == RHS; + } +}; + +/// Provide DenseMapInfo for APSInt, using the DenseMapInfo for APInt. +template <> struct DenseMapInfo { + static inline APSInt getEmptyKey() { + return APSInt(DenseMapInfo::getEmptyKey()); + } + + static inline APSInt getTombstoneKey() { + return APSInt(DenseMapInfo::getTombstoneKey()); + } + + static unsigned getHashValue(const APSInt &Key) { + return static_cast(hash_value(Key)); + } + + static bool isEqual(const APSInt &LHS, const APSInt &RHS) { + return LHS.getBitWidth() == RHS.getBitWidth() && + LHS.isUnsigned() == RHS.isUnsigned() && LHS == RHS; + } +}; + } // end namespace llvm #endif // LLVM_ADT_DENSEMAPINFO_H diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/DenseSet.h b/contrib/llvm-project/llvm/include/llvm/ADT/DenseSet.h index 07edc3d8e4ec..edce7c43773c 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/DenseSet.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/DenseSet.h @@ -130,8 +130,12 @@ public: Iterator& operator++() { ++I; return *this; } Iterator operator++(int) { auto T = *this; ++I; return T; } - bool operator==(const ConstIterator& X) const { return I == X.I; } - bool operator!=(const ConstIterator& X) const { return I != X.I; } + friend bool operator==(const Iterator &X, const Iterator &Y) { + return X.I == Y.I; + } + friend bool operator!=(const Iterator &X, const Iterator &Y) { + return X.I != Y.I; + } }; class ConstIterator { @@ -155,8 +159,12 @@ public: ConstIterator& operator++() { ++I; return *this; } ConstIterator operator++(int) { auto T = *this; ++I; return T; } - bool operator==(const ConstIterator& X) const { return I == X.I; } - bool operator!=(const ConstIterator& X) const { return I != X.I; } + friend bool operator==(const ConstIterator &X, const ConstIterator &Y) { + return X.I == Y.I; + } + friend bool operator!=(const ConstIterator &X, const ConstIterator &Y) { + return X.I != Y.I; + } }; using iterator = Iterator; @@ -173,6 +181,11 @@ public: return ConstIterator(TheMap.find(V)); } + /// Check if the set contains the given element. + bool contains(const_arg_type_t V) const { + return TheMap.find(V) != TheMap.end(); + } + /// Alternative version of find() which allows a different, and possibly less /// expensive, key type. /// The DenseMapInfo is responsible for supplying methods diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/DepthFirstIterator.h b/contrib/llvm-project/llvm/include/llvm/ADT/DepthFirstIterator.h index 11967f5eefcc..5bfea28332b2 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/DepthFirstIterator.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/DepthFirstIterator.h @@ -198,7 +198,7 @@ public: // nodes that a depth first iteration did not find: ie unreachable nodes. // bool nodeVisited(NodeRef Node) const { - return this->Visited.count(Node) != 0; + return this->Visited.contains(Node); } /// getPathLength - Return the length of the path from the entry node to the diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/DirectedGraph.h b/contrib/llvm-project/llvm/include/llvm/ADT/DirectedGraph.h index cfe98e178a91..e8bb9e6b2292 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/DirectedGraph.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/DirectedGraph.h @@ -38,8 +38,10 @@ public: /// Static polymorphism: delegate implementation (via isEqualTo) to the /// derived class. - bool operator==(const EdgeType &E) const { return getDerived().isEqualTo(E); } - bool operator!=(const EdgeType &E) const { return !operator==(E); } + bool operator==(const DGEdge &E) const { + return getDerived().isEqualTo(E.getDerived()); + } + bool operator!=(const DGEdge &E) const { return !operator==(E); } /// Retrieve the target node this edge connects to. const NodeType &getTargetNode() const { return TargetNode; } @@ -91,8 +93,12 @@ public: /// Static polymorphism: delegate implementation (via isEqualTo) to the /// derived class. - bool operator==(const NodeType &N) const { return getDerived().isEqualTo(N); } - bool operator!=(const NodeType &N) const { return !operator==(N); } + friend bool operator==(const NodeType &M, const NodeType &N) { + return M.isEqualTo(N); + } + friend bool operator!=(const NodeType &M, const NodeType &N) { + return !(M == N); + } const_iterator begin() const { return Edges.begin(); } const_iterator end() const { return Edges.end(); } @@ -223,7 +229,7 @@ public: if (*Node == N) continue; Node->findEdgesTo(N, TempList); - EL.insert(EL.end(), TempList.begin(), TempList.end()); + llvm::append_range(EL, TempList); TempList.clear(); } return !EL.empty(); diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/FloatingPointMode.h b/contrib/llvm-project/llvm/include/llvm/ADT/FloatingPointMode.h index 3ba8ae1b2855..698830937870 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/FloatingPointMode.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/FloatingPointMode.h @@ -44,6 +44,24 @@ enum class RoundingMode : int8_t { Invalid = -1 ///< Denotes invalid value. }; +/// Returns text representation of the given rounding mode. +inline StringRef spell(RoundingMode RM) { + switch (RM) { + case RoundingMode::TowardZero: return "towardzero"; + case RoundingMode::NearestTiesToEven: return "tonearest"; + case RoundingMode::TowardPositive: return "upward"; + case RoundingMode::TowardNegative: return "downward"; + case RoundingMode::NearestTiesToAway: return "tonearestaway"; + case RoundingMode::Dynamic: return "dynamic"; + default: return "invalid"; + } +} + +inline raw_ostream &operator << (raw_ostream &OS, RoundingMode RM) { + OS << spell(RM); + return OS; +} + /// Represent subnormal handling kind for floating point instruction inputs and /// outputs. struct DenormalMode { diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/FunctionExtras.h b/contrib/llvm-project/llvm/include/llvm/ADT/FunctionExtras.h index 4c75e4d2547b..7f8fb103f148 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/FunctionExtras.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/FunctionExtras.h @@ -64,12 +64,12 @@ template class UniqueFunctionBase { protected: static constexpr size_t InlineStorageSize = sizeof(void *) * 3; - // MSVC has a bug and ICEs if we give it a particular dependent value - // expression as part of the `std::conditional` below. To work around this, - // we build that into a template struct's constexpr bool. - template struct IsSizeLessThanThresholdT { - static constexpr bool value = sizeof(T) <= (2 * sizeof(void *)); - }; + template + struct IsSizeLessThanThresholdT : std::false_type {}; + + template + struct IsSizeLessThanThresholdT< + T, std::enable_if_t> : std::true_type {}; // Provide a type function to map parameters that won't observe extra copies // or moves and which are small enough to likely pass in register to values diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/Hashing.h b/contrib/llvm-project/llvm/include/llvm/ADT/Hashing.h index 9ee310c879fd..cb53b7fa7469 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/Hashing.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/Hashing.h @@ -52,6 +52,7 @@ #include #include #include +#include #include namespace llvm { @@ -112,6 +113,10 @@ template hash_code hash_value(const T *ptr); template hash_code hash_value(const std::pair &arg); +/// Compute a hash_code for a tuple. +template +hash_code hash_value(const std::tuple &arg); + /// Compute a hash_code for a standard string. template hash_code hash_value(const std::basic_string &arg); @@ -645,6 +650,26 @@ hash_code hash_value(const std::pair &arg) { return hash_combine(arg.first, arg.second); } +// Implementation details for the hash_value overload for std::tuple<...>(...). +namespace hashing { +namespace detail { + +template +hash_code hash_value_tuple_helper(const std::tuple &arg, + std::index_sequence indices) { + return hash_combine(std::get(arg)...); +} + +} // namespace detail +} // namespace hashing + +template +hash_code hash_value(const std::tuple &arg) { + // TODO: Use std::apply when LLVM starts using C++17. + return ::llvm::hashing::detail::hash_value_tuple_helper( + arg, typename std::index_sequence_for()); +} + // Declared and documented above, but defined here so that any of the hashing // infrastructure is available. template diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/IntervalMap.h b/contrib/llvm-project/llvm/include/llvm/ADT/IntervalMap.h index db7804d0a551..0b6c7d667807 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/IntervalMap.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/IntervalMap.h @@ -963,8 +963,7 @@ public: private: // The root data is either a RootLeaf or a RootBranchData instance. - alignas(RootLeaf) alignas(RootBranchData) - AlignedCharArrayUnion data; + AlignedCharArrayUnion data; // Tree height. // 0: Leaves in root. @@ -979,10 +978,7 @@ private: Allocator &allocator; /// Represent data as a node type without breaking aliasing rules. - template - T &dataAs() const { - return *bit_cast(const_cast(data.buffer)); - } + template T &dataAs() const { return *bit_cast(&data); } const RootLeaf &rootLeaf() const { assert(!branched() && "Cannot acces leaf data in branched root"); @@ -1040,7 +1036,7 @@ private: public: explicit IntervalMap(Allocator &a) : height(0), rootSize(0), allocator(a) { - assert((uintptr_t(data.buffer) & (alignof(RootLeaf) - 1)) == 0 && + assert((uintptr_t(&data) & (alignof(RootLeaf) - 1)) == 0 && "Insufficient alignment"); new(&rootLeaf()) RootLeaf(); } diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/IntrusiveRefCntPtr.h b/contrib/llvm-project/llvm/include/llvm/ADT/IntrusiveRefCntPtr.h index 6d97fe15db8b..ca4c40db48b9 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/IntrusiveRefCntPtr.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/IntrusiveRefCntPtr.h @@ -58,6 +58,7 @@ #include #include #include +#include namespace llvm { @@ -70,10 +71,23 @@ namespace llvm { template class RefCountedBase { mutable unsigned RefCount = 0; -public: +protected: RefCountedBase() = default; RefCountedBase(const RefCountedBase &) {} + RefCountedBase &operator=(const RefCountedBase &) = delete; + +#ifndef NDEBUG + ~RefCountedBase() { + assert(RefCount == 0 && + "Destruction occured when there are still references to this."); + } +#else + // Default the destructor in release builds, A trivial destructor may enable + // better codegen. + ~RefCountedBase() = default; +#endif +public: void Retain() const { ++RefCount; } void Release() const { @@ -85,10 +99,24 @@ public: /// A thread-safe version of \c RefCountedBase. template class ThreadSafeRefCountedBase { - mutable std::atomic RefCount; + mutable std::atomic RefCount{0}; protected: - ThreadSafeRefCountedBase() : RefCount(0) {} + ThreadSafeRefCountedBase() = default; + ThreadSafeRefCountedBase(const ThreadSafeRefCountedBase &) {} + ThreadSafeRefCountedBase & + operator=(const ThreadSafeRefCountedBase &) = delete; + +#ifndef NDEBUG + ~ThreadSafeRefCountedBase() { + assert(RefCount == 0 && + "Destruction occured when there are still references to this."); + } +#else + // Default the destructor in release builds, A trivial destructor may enable + // better codegen. + ~ThreadSafeRefCountedBase() = default; +#endif public: void Retain() const { RefCount.fetch_add(1, std::memory_order_relaxed); } @@ -148,6 +176,11 @@ public: S.Obj = nullptr; } + template + IntrusiveRefCntPtr(std::unique_ptr S) : Obj(S.release()) { + retain(); + } + template IntrusiveRefCntPtr(const IntrusiveRefCntPtr &S) : Obj(S.get()) { retain(); @@ -264,6 +297,12 @@ template struct simplify_type> { } }; +/// Factory function for creating intrusive ref counted pointers. +template +IntrusiveRefCntPtr makeIntrusiveRefCnt(Args &&...A) { + return IntrusiveRefCntPtr(new T(std::forward(A)...)); +} + } // end namespace llvm #endif // LLVM_ADT_INTRUSIVEREFCNTPTR_H diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/Optional.h b/contrib/llvm-project/llvm/include/llvm/ADT/Optional.h index c64b82352397..a285c81d1be8 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/Optional.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/Optional.h @@ -15,6 +15,7 @@ #ifndef LLVM_ADT_OPTIONAL_H #define LLVM_ADT_OPTIONAL_H +#include "llvm/ADT/Hashing.h" #include "llvm/ADT/None.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/type_traits.h" @@ -32,7 +33,30 @@ namespace optional_detail { struct in_place_t {}; /// Storage for any type. -template ::value> +// +// The specialization condition intentionally uses +// llvm::is_trivially_copy_constructible instead of +// std::is_trivially_copy_constructible. GCC versions prior to 7.4 may +// instantiate the copy constructor of `T` when +// std::is_trivially_copy_constructible is instantiated. This causes +// compilation to fail if we query the trivially copy constructible property of +// a class which is not copy constructible. +// +// The current implementation of OptionalStorage insists that in order to use +// the trivial specialization, the value_type must be trivially copy +// constructible and trivially copy assignable due to =default implementations +// of the copy/move constructor/assignment. It does not follow that this is +// necessarily the case std::is_trivially_copyable is true (hence the expanded +// specialization condition). +// +// The move constructible / assignable conditions emulate the remaining behavior +// of std::is_trivially_copyable. +template ::value && + std::is_trivially_copy_assignable::value && + (std::is_trivially_move_constructible::value || + !std::is_move_constructible::value) && + (std::is_trivially_move_assignable::value || + !std::is_move_assignable::value))> class OptionalStorage { union { char empty; @@ -43,21 +67,21 @@ class OptionalStorage { public: ~OptionalStorage() { reset(); } - OptionalStorage() noexcept : empty(), hasVal(false) {} + constexpr OptionalStorage() noexcept : empty(), hasVal(false) {} - OptionalStorage(OptionalStorage const &other) : OptionalStorage() { + constexpr OptionalStorage(OptionalStorage const &other) : OptionalStorage() { if (other.hasValue()) { emplace(other.value); } } - OptionalStorage(OptionalStorage &&other) : OptionalStorage() { + constexpr OptionalStorage(OptionalStorage &&other) : OptionalStorage() { if (other.hasValue()) { emplace(std::move(other.value)); } } template - explicit OptionalStorage(in_place_t, Args &&... args) + constexpr explicit OptionalStorage(in_place_t, Args &&... args) : value(std::forward(args)...), hasVal(true) {} void reset() noexcept { @@ -67,13 +91,13 @@ public: } } - bool hasValue() const noexcept { return hasVal; } + constexpr bool hasValue() const noexcept { return hasVal; } T &getValue() LLVM_LVALUE_FUNCTION noexcept { assert(hasVal); return value; } - T const &getValue() const LLVM_LVALUE_FUNCTION noexcept { + constexpr T const &getValue() const LLVM_LVALUE_FUNCTION noexcept { assert(hasVal); return value; } @@ -148,16 +172,16 @@ template class OptionalStorage { public: ~OptionalStorage() = default; - OptionalStorage() noexcept : empty{} {} + constexpr OptionalStorage() noexcept : empty{} {} - OptionalStorage(OptionalStorage const &other) = default; - OptionalStorage(OptionalStorage &&other) = default; + constexpr OptionalStorage(OptionalStorage const &other) = default; + constexpr OptionalStorage(OptionalStorage &&other) = default; OptionalStorage &operator=(OptionalStorage const &other) = default; OptionalStorage &operator=(OptionalStorage &&other) = default; template - explicit OptionalStorage(in_place_t, Args &&... args) + constexpr explicit OptionalStorage(in_place_t, Args &&... args) : value(std::forward(args)...), hasVal(true) {} void reset() noexcept { @@ -167,13 +191,13 @@ public: } } - bool hasValue() const noexcept { return hasVal; } + constexpr bool hasValue() const noexcept { return hasVal; } T &getValue() LLVM_LVALUE_FUNCTION noexcept { assert(hasVal); return value; } - T const &getValue() const LLVM_LVALUE_FUNCTION noexcept { + constexpr T const &getValue() const LLVM_LVALUE_FUNCTION noexcept { assert(hasVal); return value; } @@ -221,11 +245,12 @@ public: constexpr Optional() {} constexpr Optional(NoneType) {} - Optional(const T &y) : Storage(optional_detail::in_place_t{}, y) {} - Optional(const Optional &O) = default; + constexpr Optional(const T &y) : Storage(optional_detail::in_place_t{}, y) {} + constexpr Optional(const Optional &O) = default; - Optional(T &&y) : Storage(optional_detail::in_place_t{}, std::move(y)) {} - Optional(Optional &&O) = default; + constexpr Optional(T &&y) + : Storage(optional_detail::in_place_t{}, std::move(y)) {} + constexpr Optional(Optional &&O) = default; Optional &operator=(T &&y) { Storage = std::move(y); @@ -238,7 +263,7 @@ public: Storage.emplace(std::forward(Args)...); } - static inline Optional create(const T *y) { + static constexpr Optional create(const T *y) { return y ? Optional(*y) : Optional(); } @@ -250,16 +275,20 @@ public: void reset() { Storage.reset(); } - const T *getPointer() const { return &Storage.getValue(); } + constexpr const T *getPointer() const { return &Storage.getValue(); } T *getPointer() { return &Storage.getValue(); } - const T &getValue() const LLVM_LVALUE_FUNCTION { return Storage.getValue(); } + constexpr const T &getValue() const LLVM_LVALUE_FUNCTION { + return Storage.getValue(); + } T &getValue() LLVM_LVALUE_FUNCTION { return Storage.getValue(); } - explicit operator bool() const { return hasValue(); } - bool hasValue() const { return Storage.hasValue(); } - const T *operator->() const { return getPointer(); } + constexpr explicit operator bool() const { return hasValue(); } + constexpr bool hasValue() const { return Storage.hasValue(); } + constexpr const T *operator->() const { return getPointer(); } T *operator->() { return getPointer(); } - const T &operator*() const LLVM_LVALUE_FUNCTION { return getValue(); } + constexpr const T &operator*() const LLVM_LVALUE_FUNCTION { + return getValue(); + } T &operator*() LLVM_LVALUE_FUNCTION { return getValue(); } template @@ -294,137 +323,157 @@ public: #endif }; +template llvm::hash_code hash_value(const Optional &O) { + return O ? hash_combine(true, *O) : hash_value(false); +} + template -bool operator==(const Optional &X, const Optional &Y) { +constexpr bool operator==(const Optional &X, const Optional &Y) { if (X && Y) return *X == *Y; return X.hasValue() == Y.hasValue(); } template -bool operator!=(const Optional &X, const Optional &Y) { +constexpr bool operator!=(const Optional &X, const Optional &Y) { return !(X == Y); } template -bool operator<(const Optional &X, const Optional &Y) { +constexpr bool operator<(const Optional &X, const Optional &Y) { if (X && Y) return *X < *Y; return X.hasValue() < Y.hasValue(); } template -bool operator<=(const Optional &X, const Optional &Y) { +constexpr bool operator<=(const Optional &X, const Optional &Y) { return !(Y < X); } template -bool operator>(const Optional &X, const Optional &Y) { +constexpr bool operator>(const Optional &X, const Optional &Y) { return Y < X; } template -bool operator>=(const Optional &X, const Optional &Y) { +constexpr bool operator>=(const Optional &X, const Optional &Y) { return !(X < Y); } -template -bool operator==(const Optional &X, NoneType) { +template +constexpr bool operator==(const Optional &X, NoneType) { return !X; } -template -bool operator==(NoneType, const Optional &X) { +template +constexpr bool operator==(NoneType, const Optional &X) { return X == None; } -template -bool operator!=(const Optional &X, NoneType) { +template +constexpr bool operator!=(const Optional &X, NoneType) { return !(X == None); } -template -bool operator!=(NoneType, const Optional &X) { +template +constexpr bool operator!=(NoneType, const Optional &X) { return X != None; } -template bool operator<(const Optional &X, NoneType) { +template constexpr bool operator<(const Optional &X, NoneType) { return false; } -template bool operator<(NoneType, const Optional &X) { +template constexpr bool operator<(NoneType, const Optional &X) { return X.hasValue(); } -template bool operator<=(const Optional &X, NoneType) { +template +constexpr bool operator<=(const Optional &X, NoneType) { return !(None < X); } -template bool operator<=(NoneType, const Optional &X) { +template +constexpr bool operator<=(NoneType, const Optional &X) { return !(X < None); } -template bool operator>(const Optional &X, NoneType) { +template constexpr bool operator>(const Optional &X, NoneType) { return None < X; } -template bool operator>(NoneType, const Optional &X) { +template constexpr bool operator>(NoneType, const Optional &X) { return X < None; } -template bool operator>=(const Optional &X, NoneType) { +template +constexpr bool operator>=(const Optional &X, NoneType) { return None <= X; } -template bool operator>=(NoneType, const Optional &X) { +template +constexpr bool operator>=(NoneType, const Optional &X) { return X <= None; } -template bool operator==(const Optional &X, const T &Y) { +template +constexpr bool operator==(const Optional &X, const T &Y) { return X && *X == Y; } -template bool operator==(const T &X, const Optional &Y) { +template +constexpr bool operator==(const T &X, const Optional &Y) { return Y && X == *Y; } -template bool operator!=(const Optional &X, const T &Y) { +template +constexpr bool operator!=(const Optional &X, const T &Y) { return !(X == Y); } -template bool operator!=(const T &X, const Optional &Y) { +template +constexpr bool operator!=(const T &X, const Optional &Y) { return !(X == Y); } -template bool operator<(const Optional &X, const T &Y) { +template +constexpr bool operator<(const Optional &X, const T &Y) { return !X || *X < Y; } -template bool operator<(const T &X, const Optional &Y) { +template +constexpr bool operator<(const T &X, const Optional &Y) { return Y && X < *Y; } -template bool operator<=(const Optional &X, const T &Y) { +template +constexpr bool operator<=(const Optional &X, const T &Y) { return !(Y < X); } -template bool operator<=(const T &X, const Optional &Y) { +template +constexpr bool operator<=(const T &X, const Optional &Y) { return !(Y < X); } -template bool operator>(const Optional &X, const T &Y) { +template +constexpr bool operator>(const Optional &X, const T &Y) { return Y < X; } -template bool operator>(const T &X, const Optional &Y) { +template +constexpr bool operator>(const T &X, const Optional &Y) { return Y < X; } -template bool operator>=(const Optional &X, const T &Y) { +template +constexpr bool operator>=(const Optional &X, const T &Y) { return !(X < Y); } -template bool operator>=(const T &X, const Optional &Y) { +template +constexpr bool operator>=(const T &X, const Optional &Y) { return !(X < Y); } diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/PointerUnion.h b/contrib/llvm-project/llvm/include/llvm/ADT/PointerUnion.h index 6fecff8d756f..c39691061b72 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/PointerUnion.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/PointerUnion.h @@ -93,13 +93,6 @@ namespace pointer_union_detail { static constexpr int NumLowBitsAvailable = lowBitsAvailable(); }; - /// Implement assignment in terms of construction. - template struct AssignableFrom { - Derived &operator=(T t) { - return static_cast(*this) = Derived(t); - } - }; - template class PointerUnionMembers; diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/STLExtras.h b/contrib/llvm-project/llvm/include/llvm/ADT/STLExtras.h index 50b688b36648..63c7f48a5bd2 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/STLExtras.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/STLExtras.h @@ -193,9 +193,15 @@ public: template function_ref( Callable &&callable, + // This is not the copy-constructor. std::enable_if_t< !std::is_same>, - function_ref>::value> * = nullptr) + function_ref>::value> * = nullptr, + // Functor must be callable and return a suitable type. + std::enable_if_t::value || + std::is_convertible()( + std::declval()...)), + Ret>::value> * = nullptr) : callback(callback_fn::type>), callable(reinterpret_cast(&callable)) {} @@ -206,15 +212,6 @@ public: explicit operator bool() const { return callback; } }; -// deleter - Very very very simple method that is used to invoke operator -// delete on something. It is used like this: -// -// for_each(V.begin(), B.end(), deleter); -template -inline void deleter(T *Ptr) { - delete Ptr; -} - //===----------------------------------------------------------------------===// // Extra additions to //===----------------------------------------------------------------------===// @@ -275,7 +272,7 @@ template bool hasSingleElement(ContainerTy &&C) { /// Return a range covering \p RangeOrContainer with the first N elements /// excluded. -template auto drop_begin(T &&RangeOrContainer, size_t N) { +template auto drop_begin(T &&RangeOrContainer, size_t N = 1) { return make_range(std::next(adl_begin(RangeOrContainer), N), adl_end(RangeOrContainer)); } @@ -541,7 +538,7 @@ public: early_inc_iterator_impl(WrappedIteratorT I) : BaseT(I) {} using BaseT::operator*; - typename BaseT::reference operator*() { + decltype(*std::declval()) operator*() { #if LLVM_ENABLE_ABI_BREAKING_CHECKS assert(!IsEarlyIncremented && "Cannot dereference twice!"); IsEarlyIncremented = true; @@ -558,12 +555,12 @@ public: return *this; } - using BaseT::operator==; - bool operator==(const early_inc_iterator_impl &RHS) const { + friend bool operator==(const early_inc_iterator_impl &LHS, + const early_inc_iterator_impl &RHS) { #if LLVM_ENABLE_ABI_BREAKING_CHECKS - assert(!IsEarlyIncremented && "Cannot compare after dereferencing!"); + assert(!LHS.IsEarlyIncremented && "Cannot compare after dereferencing!"); #endif - return BaseT::operator==(RHS); + return (const BaseT &)LHS == (const BaseT &)RHS; } }; @@ -1246,6 +1243,15 @@ public: } }; +/// Given a container of pairs, return a range over the first elements. +template auto make_first_range(ContainerTy &&c) { + return llvm::map_range( + std::forward(c), + [](decltype((*std::begin(c))) elt) -> decltype((elt.first)) { + return elt.first; + }); +} + /// Given a container of pairs, return a range over the second elements. template auto make_second_range(ContainerTy &&c) { return llvm::map_range( @@ -1422,7 +1428,7 @@ template // is trivially copyable. using sort_trivially_copyable = conjunction< std::is_pointer, - is_trivially_copyable::value_type>>; + std::is_trivially_copyable::value_type>>; } // namespace detail // Provide wrappers to std::sort which shuffle the elements before sorting @@ -1471,18 +1477,19 @@ inline void sort(Container &&C, Compare Comp) { /// which is only enabled when the operation is O(1). template auto size(R &&Range, - std::enable_if_t::iterator_category, - std::random_access_iterator_tag>::value, - void> * = nullptr) { + std::enable_if_t< + std::is_base_of::iterator_category>::value, + void> * = nullptr) { return std::distance(Range.begin(), Range.end()); } /// Provide wrappers to std::for_each which take ranges instead of having to /// pass begin/end explicitly. -template -UnaryPredicate for_each(R &&Range, UnaryPredicate P) { - return std::for_each(adl_begin(Range), adl_end(Range), P); +template +UnaryFunction for_each(R &&Range, UnaryFunction F) { + return std::for_each(adl_begin(Range), adl_end(Range), F); } /// Provide wrappers to std::all_of which take ranges instead of having to pass @@ -1543,6 +1550,13 @@ OutputIt copy(R &&Range, OutputIt Out) { return std::copy(adl_begin(Range), adl_end(Range), Out); } +/// Provide wrappers to std::move which take ranges instead of having to +/// pass begin/end explicitly. +template +OutputIt move(R &&Range, OutputIt Out) { + return std::move(adl_begin(Range), adl_end(Range), Out); +} + /// Wrapper function around std::find to detect if an element exists /// in a container. template @@ -1577,9 +1591,9 @@ auto count_if(R &&Range, UnaryPredicate P) { /// Wrapper function around std::transform to apply a function to a range and /// store the result elsewhere. -template -OutputIt transform(R &&Range, OutputIt d_first, UnaryPredicate P) { - return std::transform(adl_begin(Range), adl_end(Range), d_first, P); +template +OutputIt transform(R &&Range, OutputIt d_first, UnaryFunction F) { + return std::transform(adl_begin(Range), adl_end(Range), d_first, F); } /// Provide wrappers to std::partition which take ranges instead of having to @@ -1654,6 +1668,22 @@ void erase_if(Container &C, UnaryPredicate P) { C.erase(remove_if(C, P), C.end()); } +/// Wrapper function to remove a value from a container: +/// +/// C.erase(remove(C.begin(), C.end(), V), C.end()); +template +void erase_value(Container &C, ValueType V) { + C.erase(std::remove(C.begin(), C.end(), V), C.end()); +} + +/// Wrapper function to append a range to a container. +/// +/// C.insert(C.end(), R.begin(), R.end()); +template +inline void append_range(Container &C, Range &&R) { + C.insert(C.end(), R.begin(), R.end()); +} + /// Given a sequence container Cont, replace the range [ContIt, ContEnd) with /// the range [ValIt, ValEnd) (which is not from the same container). template @@ -1911,16 +1941,16 @@ decltype(auto) apply_tuple(F &&f, Tuple &&t) { /// Return true if the sequence [Begin, End) has exactly N items. Runs in O(N) /// time. Not meant for use with random-access iterators. /// Can optionally take a predicate to filter lazily some items. -template()) &)> +template ()) &)> bool hasNItems( IterTy &&Begin, IterTy &&End, unsigned N, Pred &&ShouldBeCounted = [](const decltype(*std::declval()) &) { return true; }, std::enable_if_t< - !std::is_same>::iterator_category, - std::random_access_iterator_tag>::value, + !std::is_base_of>::iterator_category>::value, void> * = nullptr) { for (; N; ++Begin) { if (Begin == End) @@ -1936,16 +1966,16 @@ bool hasNItems( /// Return true if the sequence [Begin, End) has N or more items. Runs in O(N) /// time. Not meant for use with random-access iterators. /// Can optionally take a predicate to lazily filter some items. -template()) &)> +template ()) &)> bool hasNItemsOrMore( IterTy &&Begin, IterTy &&End, unsigned N, Pred &&ShouldBeCounted = [](const decltype(*std::declval()) &) { return true; }, std::enable_if_t< - !std::is_same>::iterator_category, - std::random_access_iterator_tag>::value, + !std::is_base_of>::iterator_category>::value, void> * = nullptr) { for (; N; ++Begin) { if (Begin == End) diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/Sequence.h b/contrib/llvm-project/llvm/include/llvm/ADT/Sequence.h index 8c505f2010dd..8a695d75f77a 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/Sequence.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/Sequence.h @@ -42,6 +42,10 @@ public: value_sequence_iterator(const value_sequence_iterator &) = default; value_sequence_iterator(value_sequence_iterator &&Arg) : Value(std::move(Arg.Value)) {} + value_sequence_iterator &operator=(const value_sequence_iterator &Arg) { + Value = Arg.Value; + return *this; + } template ()))> value_sequence_iterator(U &&Value) : Value(std::forward(Value)) {} diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/SetVector.h b/contrib/llvm-project/llvm/include/llvm/ADT/SetVector.h index 91ad72143ed3..32bcd50966cc 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/SetVector.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/SetVector.h @@ -205,6 +205,11 @@ public: return true; } + /// Check if the SetVector contains the given key. + bool contains(const key_type &key) const { + return set_.find(key) != set_.end(); + } + /// Count the number of elements of a given key in the SetVector. /// \returns 0 if the element is not in the SetVector, 1 if it is. size_type count(const key_type &key) const { diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/SmallSet.h b/contrib/llvm-project/llvm/include/llvm/ADT/SmallSet.h index a03fa7dd8423..0600e528ee69 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/SmallSet.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/SmallSet.h @@ -232,6 +232,13 @@ public: return {Set.end()}; } + /// Check if the SmallSet contains the given element. + bool contains(const T &V) const { + if (isSmall()) + return vfind(V) != Vector.end(); + return Set.find(V) != Set.end(); + } + private: bool isSmall() const { return Set.empty(); } diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/SmallString.h b/contrib/llvm-project/llvm/include/llvm/ADT/SmallString.h index cd6f2173d04f..5a56321ae492 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/SmallString.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/SmallString.h @@ -30,63 +30,56 @@ public: /// Initialize from a StringRef. SmallString(StringRef S) : SmallVector(S.begin(), S.end()) {} + /// Initialize by concatenating a list of StringRefs. + SmallString(std::initializer_list Refs) + : SmallVector() { + this->append(Refs); + } + /// Initialize with a range. template SmallString(ItTy S, ItTy E) : SmallVector(S, E) {} - // Note that in order to add new overloads for append & assign, we have to - // duplicate the inherited versions so as not to inadvertently hide them. - /// @} /// @name String Assignment /// @{ - /// Assign from a repeated element. - void assign(size_t NumElts, char Elt) { - this->SmallVectorImpl::assign(NumElts, Elt); - } - - /// Assign from an iterator pair. - template - void assign(in_iter S, in_iter E) { - this->clear(); - SmallVectorImpl::append(S, E); - } + using SmallVector::assign; /// Assign from a StringRef. void assign(StringRef RHS) { - this->clear(); - SmallVectorImpl::append(RHS.begin(), RHS.end()); + SmallVectorImpl::assign(RHS.begin(), RHS.end()); } - /// Assign from a SmallVector. - void assign(const SmallVectorImpl &RHS) { + /// Assign from a list of StringRefs. + void assign(std::initializer_list Refs) { this->clear(); - SmallVectorImpl::append(RHS.begin(), RHS.end()); + append(Refs); } /// @} /// @name String Concatenation /// @{ - /// Append from an iterator pair. - template - void append(in_iter S, in_iter E) { - SmallVectorImpl::append(S, E); - } - - void append(size_t NumInputs, char Elt) { - SmallVectorImpl::append(NumInputs, Elt); - } + using SmallVector::append; /// Append from a StringRef. void append(StringRef RHS) { SmallVectorImpl::append(RHS.begin(), RHS.end()); } - /// Append from a SmallVector. - void append(const SmallVectorImpl &RHS) { - SmallVectorImpl::append(RHS.begin(), RHS.end()); + /// Append from a list of StringRefs. + void append(std::initializer_list Refs) { + size_t SizeNeeded = this->size(); + for (const StringRef &Ref : Refs) + SizeNeeded += Ref.size(); + this->reserve(SizeNeeded); + auto CurEnd = this->end(); + for (const StringRef &Ref : Refs) { + this->uninitialized_copy(Ref.begin(), Ref.end(), CurEnd); + CurEnd += Ref.size(); + } + this->set_size(SizeNeeded); } /// @} @@ -280,9 +273,9 @@ public: } // Extra operators. - const SmallString &operator=(StringRef RHS) { - this->clear(); - return *this += RHS; + SmallString &operator=(StringRef RHS) { + this->assign(RHS); + return *this; } SmallString &operator+=(StringRef RHS) { diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/SmallVector.h b/contrib/llvm-project/llvm/include/llvm/ADT/SmallVector.h index 3ccee3d21d48..e960b272db04 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/SmallVector.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/SmallVector.h @@ -14,7 +14,6 @@ #define LLVM_ADT_SMALLVECTOR_H #include "llvm/ADT/iterator_range.h" -#include "llvm/Support/AlignOf.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" @@ -57,10 +56,15 @@ protected: SmallVectorBase(void *FirstEl, size_t TotalCapacity) : BeginX(FirstEl), Capacity(TotalCapacity) {} + /// This is a helper for \a grow() that's out of line to reduce code + /// duplication. This function will report a fatal error if it can't grow at + /// least to \p MinSize. + void *mallocForGrow(size_t MinSize, size_t TSize, size_t &NewCapacity); + /// This is an implementation of the grow() method which only works /// on POD-like data types and is out of line to reduce code duplication. /// This function will report a fatal error if it cannot increase capacity. - void grow_pod(void *FirstEl, size_t MinCapacity, size_t TSize); + void grow_pod(void *FirstEl, size_t MinSize, size_t TSize); public: size_t size() const { return Size; } @@ -90,8 +94,9 @@ using SmallVectorSizeType = /// Figure out the offset of the first element. template struct SmallVectorAlignmentAndSize { - AlignedCharArrayUnion>> Base; - AlignedCharArrayUnion FirstEl; + alignas(SmallVectorBase>) char Base[sizeof( + SmallVectorBase>)]; + alignas(T) char FirstEl[sizeof(T)]; }; /// This is the part of SmallVectorTemplateBase which does not depend on whether @@ -115,8 +120,8 @@ class SmallVectorTemplateCommon protected: SmallVectorTemplateCommon(size_t Size) : Base(getFirstEl(), Size) {} - void grow_pod(size_t MinCapacity, size_t TSize) { - Base::grow_pod(getFirstEl(), MinCapacity, TSize); + void grow_pod(size_t MinSize, size_t TSize) { + Base::grow_pod(getFirstEl(), MinSize, TSize); } /// Return true if this is a smallvector which has not had dynamic @@ -129,6 +134,102 @@ protected: this->Size = this->Capacity = 0; // FIXME: Setting Capacity to 0 is suspect. } + /// Return true if V is an internal reference to the given range. + bool isReferenceToRange(const void *V, const void *First, const void *Last) const { + // Use std::less to avoid UB. + std::less<> LessThan; + return !LessThan(V, First) && LessThan(V, Last); + } + + /// Return true if V is an internal reference to this vector. + bool isReferenceToStorage(const void *V) const { + return isReferenceToRange(V, this->begin(), this->end()); + } + + /// Return true if First and Last form a valid (possibly empty) range in this + /// vector's storage. + bool isRangeInStorage(const void *First, const void *Last) const { + // Use std::less to avoid UB. + std::less<> LessThan; + return !LessThan(First, this->begin()) && !LessThan(Last, First) && + !LessThan(this->end(), Last); + } + + /// Return true unless Elt will be invalidated by resizing the vector to + /// NewSize. + bool isSafeToReferenceAfterResize(const void *Elt, size_t NewSize) { + // Past the end. + if (LLVM_LIKELY(!isReferenceToStorage(Elt))) + return true; + + // Return false if Elt will be destroyed by shrinking. + if (NewSize <= this->size()) + return Elt < this->begin() + NewSize; + + // Return false if we need to grow. + return NewSize <= this->capacity(); + } + + /// Check whether Elt will be invalidated by resizing the vector to NewSize. + void assertSafeToReferenceAfterResize(const void *Elt, size_t NewSize) { + assert(isSafeToReferenceAfterResize(Elt, NewSize) && + "Attempting to reference an element of the vector in an operation " + "that invalidates it"); + } + + /// Check whether Elt will be invalidated by increasing the size of the + /// vector by N. + void assertSafeToAdd(const void *Elt, size_t N = 1) { + this->assertSafeToReferenceAfterResize(Elt, this->size() + N); + } + + /// Check whether any part of the range will be invalidated by clearing. + void assertSafeToReferenceAfterClear(const T *From, const T *To) { + if (From == To) + return; + this->assertSafeToReferenceAfterResize(From, 0); + this->assertSafeToReferenceAfterResize(To - 1, 0); + } + template < + class ItTy, + std::enable_if_t, T *>::value, + bool> = false> + void assertSafeToReferenceAfterClear(ItTy, ItTy) {} + + /// Check whether any part of the range will be invalidated by growing. + void assertSafeToAddRange(const T *From, const T *To) { + if (From == To) + return; + this->assertSafeToAdd(From, To - From); + this->assertSafeToAdd(To - 1, To - From); + } + template < + class ItTy, + std::enable_if_t, T *>::value, + bool> = false> + void assertSafeToAddRange(ItTy, ItTy) {} + + /// Reserve enough space to add one element, and return the updated element + /// pointer in case it was a reference to the storage. + template + static const T *reserveForParamAndGetAddressImpl(U *This, const T &Elt, + size_t N) { + size_t NewSize = This->size() + N; + if (LLVM_LIKELY(NewSize <= This->capacity())) + return &Elt; + + bool ReferencesStorage = false; + int64_t Index = -1; + if (!U::TakesParamByValue) { + if (LLVM_UNLIKELY(This->isReferenceToStorage(&Elt))) { + ReferencesStorage = true; + Index = &Elt - This->begin(); + } + } + This->grow(NewSize); + return ReferencesStorage ? This->begin() + Index : &Elt; + } + public: using size_type = size_t; using difference_type = ptrdiff_t; @@ -212,7 +313,12 @@ template ::value) && (is_trivially_move_constructible::value) && std::is_trivially_destructible::value> class SmallVectorTemplateBase : public SmallVectorTemplateCommon { + friend class SmallVectorTemplateCommon; + protected: + static constexpr bool TakesParamByValue = false; + using ValueParamT = const T &; + SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon(Size) {} static void destroy_range(T *S, T *E) { @@ -242,18 +348,68 @@ protected: /// element, or MinSize more elements if specified. void grow(size_t MinSize = 0); + /// Create a new allocation big enough for \p MinSize and pass back its size + /// in \p NewCapacity. This is the first section of \a grow(). + T *mallocForGrow(size_t MinSize, size_t &NewCapacity) { + return static_cast( + SmallVectorBase>::mallocForGrow( + MinSize, sizeof(T), NewCapacity)); + } + + /// Move existing elements over to the new allocation \p NewElts, the middle + /// section of \a grow(). + void moveElementsForGrow(T *NewElts); + + /// Transfer ownership of the allocation, finishing up \a grow(). + void takeAllocationForGrow(T *NewElts, size_t NewCapacity); + + /// Reserve enough space to add one element, and return the updated element + /// pointer in case it was a reference to the storage. + const T *reserveForParamAndGetAddress(const T &Elt, size_t N = 1) { + return this->reserveForParamAndGetAddressImpl(this, Elt, N); + } + + /// Reserve enough space to add one element, and return the updated element + /// pointer in case it was a reference to the storage. + T *reserveForParamAndGetAddress(T &Elt, size_t N = 1) { + return const_cast( + this->reserveForParamAndGetAddressImpl(this, Elt, N)); + } + + static T &&forward_value_param(T &&V) { return std::move(V); } + static const T &forward_value_param(const T &V) { return V; } + + void growAndAssign(size_t NumElts, const T &Elt) { + // Grow manually in case Elt is an internal reference. + size_t NewCapacity; + T *NewElts = mallocForGrow(NumElts, NewCapacity); + std::uninitialized_fill_n(NewElts, NumElts, Elt); + this->destroy_range(this->begin(), this->end()); + takeAllocationForGrow(NewElts, NewCapacity); + this->set_size(NumElts); + } + + template T &growAndEmplaceBack(ArgTypes &&... Args) { + // Grow manually in case one of Args is an internal reference. + size_t NewCapacity; + T *NewElts = mallocForGrow(0, NewCapacity); + ::new ((void *)(NewElts + this->size())) T(std::forward(Args)...); + moveElementsForGrow(NewElts); + takeAllocationForGrow(NewElts, NewCapacity); + this->set_size(this->size() + 1); + return this->back(); + } + public: void push_back(const T &Elt) { - if (LLVM_UNLIKELY(this->size() >= this->capacity())) - this->grow(); - ::new ((void*) this->end()) T(Elt); + const T *EltPtr = reserveForParamAndGetAddress(Elt); + ::new ((void *)this->end()) T(*EltPtr); this->set_size(this->size() + 1); } void push_back(T &&Elt) { - if (LLVM_UNLIKELY(this->size() >= this->capacity())) - this->grow(); - ::new ((void*) this->end()) T(::std::move(Elt)); + T *EltPtr = reserveForParamAndGetAddress(Elt); + ::new ((void *)this->end()) T(::std::move(*EltPtr)); this->set_size(this->size() + 1); } @@ -266,29 +422,27 @@ public: // Define this out-of-line to dissuade the C++ compiler from inlining it. template void SmallVectorTemplateBase::grow(size_t MinSize) { - // Ensure we can fit the new capacity. - // This is only going to be applicable when the capacity is 32 bit. - if (MinSize > this->SizeTypeMax()) - report_bad_alloc_error("SmallVector capacity overflow during allocation"); - - // Ensure we can meet the guarantee of space for at least one more element. - // The above check alone will not catch the case where grow is called with a - // default MinCapacity of 0, but the current capacity cannot be increased. - // This is only going to be applicable when the capacity is 32 bit. - if (this->capacity() == this->SizeTypeMax()) - report_bad_alloc_error("SmallVector capacity unable to grow"); - - // Always grow, even from zero. - size_t NewCapacity = size_t(NextPowerOf2(this->capacity() + 2)); - NewCapacity = std::min(std::max(NewCapacity, MinSize), this->SizeTypeMax()); - T *NewElts = static_cast(llvm::safe_malloc(NewCapacity*sizeof(T))); + size_t NewCapacity; + T *NewElts = mallocForGrow(MinSize, NewCapacity); + moveElementsForGrow(NewElts); + takeAllocationForGrow(NewElts, NewCapacity); +} +// Define this out-of-line to dissuade the C++ compiler from inlining it. +template +void SmallVectorTemplateBase::moveElementsForGrow( + T *NewElts) { // Move the elements over. this->uninitialized_move(this->begin(), this->end(), NewElts); // Destroy the original elements. destroy_range(this->begin(), this->end()); +} +// Define this out-of-line to dissuade the C++ compiler from inlining it. +template +void SmallVectorTemplateBase::takeAllocationForGrow( + T *NewElts, size_t NewCapacity) { // If this wasn't grown from the inline copy, deallocate the old space. if (!this->isSmall()) free(this->begin()); @@ -303,7 +457,18 @@ void SmallVectorTemplateBase::grow(size_t MinSize) { /// skipping destruction. template class SmallVectorTemplateBase : public SmallVectorTemplateCommon { + friend class SmallVectorTemplateCommon; + protected: + /// True if it's cheap enough to take parameters by value. Doing so avoids + /// overhead related to mitigations for reference invalidation. + static constexpr bool TakesParamByValue = sizeof(T) <= 2 * sizeof(void *); + + /// Either const T& or T, depending on whether it's cheap enough to take + /// parameters by value. + using ValueParamT = + typename std::conditional::type; + SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon(Size) {} // No need to do a destroy loop for POD's. @@ -344,11 +509,43 @@ protected: /// least one more element or MinSize if specified. void grow(size_t MinSize = 0) { this->grow_pod(MinSize, sizeof(T)); } + /// Reserve enough space to add one element, and return the updated element + /// pointer in case it was a reference to the storage. + const T *reserveForParamAndGetAddress(const T &Elt, size_t N = 1) { + return this->reserveForParamAndGetAddressImpl(this, Elt, N); + } + + /// Reserve enough space to add one element, and return the updated element + /// pointer in case it was a reference to the storage. + T *reserveForParamAndGetAddress(T &Elt, size_t N = 1) { + return const_cast( + this->reserveForParamAndGetAddressImpl(this, Elt, N)); + } + + /// Copy \p V or return a reference, depending on \a ValueParamT. + static ValueParamT forward_value_param(ValueParamT V) { return V; } + + void growAndAssign(size_t NumElts, T Elt) { + // Elt has been copied in case it's an internal reference, side-stepping + // reference invalidation problems without losing the realloc optimization. + this->set_size(0); + this->grow(NumElts); + std::uninitialized_fill_n(this->begin(), NumElts, Elt); + this->set_size(NumElts); + } + + template T &growAndEmplaceBack(ArgTypes &&... Args) { + // Use push_back with a copy in case Args has an internal reference, + // side-stepping reference invalidation problems without losing the realloc + // optimization. + push_back(T(std::forward(Args)...)); + return this->back(); + } + public: - void push_back(const T &Elt) { - if (LLVM_UNLIKELY(this->size() >= this->capacity())) - this->grow(); - memcpy(reinterpret_cast(this->end()), &Elt, sizeof(T)); + void push_back(ValueParamT Elt) { + const T *EltPtr = reserveForParamAndGetAddress(Elt); + memcpy(reinterpret_cast(this->end()), EltPtr, sizeof(T)); this->set_size(this->size() + 1); } @@ -368,6 +565,9 @@ public: using size_type = typename SuperClass::size_type; protected: + using SmallVectorTemplateBase::TakesParamByValue; + using ValueParamT = typename SuperClass::ValueParamT; + // Default ctor - Initialize to empty. explicit SmallVectorImpl(unsigned N) : SmallVectorTemplateBase(N) {} @@ -387,29 +587,38 @@ public: this->Size = 0; } - void resize(size_type N) { +private: + template void resizeImpl(size_type N) { if (N < this->size()) { - this->destroy_range(this->begin()+N, this->end()); - this->set_size(N); + this->pop_back_n(this->size() - N); } else if (N > this->size()) { - if (this->capacity() < N) - this->grow(N); + this->reserve(N); for (auto I = this->end(), E = this->begin() + N; I != E; ++I) - new (&*I) T(); + if (ForOverwrite) + new (&*I) T; + else + new (&*I) T(); this->set_size(N); } } - void resize(size_type N, const T &NV) { +public: + void resize(size_type N) { resizeImpl(N); } + + /// Like resize, but \ref T is POD, the new values won't be initialized. + void resize_for_overwrite(size_type N) { resizeImpl(N); } + + void resize(size_type N, ValueParamT NV) { + if (N == this->size()) + return; + if (N < this->size()) { - this->destroy_range(this->begin()+N, this->end()); - this->set_size(N); - } else if (N > this->size()) { - if (this->capacity() < N) - this->grow(N); - std::uninitialized_fill(this->end(), this->begin()+N, NV); - this->set_size(N); + this->pop_back_n(this->size() - N); + return; } + + // N > this->size(). Defer to append. + this->append(N - this->size(), NV); } void reserve(size_type N) { @@ -417,6 +626,12 @@ public: this->grow(N); } + void pop_back_n(size_type NumItems) { + assert(this->size() >= NumItems); + this->destroy_range(this->end() - NumItems, this->end()); + this->set_size(this->size() - NumItems); + } + LLVM_NODISCARD T pop_back_val() { T Result = ::std::move(this->back()); this->pop_back(); @@ -431,20 +646,17 @@ public: typename std::iterator_traits::iterator_category, std::input_iterator_tag>::value>> void append(in_iter in_start, in_iter in_end) { + this->assertSafeToAddRange(in_start, in_end); size_type NumInputs = std::distance(in_start, in_end); - if (NumInputs > this->capacity() - this->size()) - this->grow(this->size()+NumInputs); - + this->reserve(this->size() + NumInputs); this->uninitialized_copy(in_start, in_end, this->end()); this->set_size(this->size() + NumInputs); } /// Append \p NumInputs copies of \p Elt to the end. - void append(size_type NumInputs, const T &Elt) { - if (NumInputs > this->capacity() - this->size()) - this->grow(this->size()+NumInputs); - - std::uninitialized_fill_n(this->end(), NumInputs, Elt); + void append(size_type NumInputs, ValueParamT Elt) { + const T *EltPtr = this->reserveForParamAndGetAddress(Elt, NumInputs); + std::uninitialized_fill_n(this->end(), NumInputs, *EltPtr); this->set_size(this->size() + NumInputs); } @@ -452,22 +664,33 @@ public: append(IL.begin(), IL.end()); } - // FIXME: Consider assigning over existing elements, rather than clearing & - // re-initializing them - for all assign(...) variants. + void append(const SmallVectorImpl &RHS) { append(RHS.begin(), RHS.end()); } - void assign(size_type NumElts, const T &Elt) { - clear(); - if (this->capacity() < NumElts) - this->grow(NumElts); + void assign(size_type NumElts, ValueParamT Elt) { + // Note that Elt could be an internal reference. + if (NumElts > this->capacity()) { + this->growAndAssign(NumElts, Elt); + return; + } + + // Assign over existing elements. + std::fill_n(this->begin(), std::min(NumElts, this->size()), Elt); + if (NumElts > this->size()) + std::uninitialized_fill_n(this->end(), NumElts - this->size(), Elt); + else if (NumElts < this->size()) + this->destroy_range(this->begin() + NumElts, this->end()); this->set_size(NumElts); - std::uninitialized_fill(this->begin(), this->end(), Elt); } + // FIXME: Consider assigning over existing elements, rather than clearing & + // re-initializing them - for all assign(...) variants. + template ::iterator_category, std::input_iterator_tag>::value>> void assign(in_iter in_start, in_iter in_end) { + this->assertSafeToReferenceAfterClear(in_start, in_end); clear(); append(in_start, in_end); } @@ -477,12 +700,13 @@ public: append(IL); } + void assign(const SmallVectorImpl &RHS) { assign(RHS.begin(), RHS.end()); } + iterator erase(const_iterator CI) { // Just cast away constness because this is a non-const member function. iterator I = const_cast(CI); - assert(I >= this->begin() && "Iterator to erase is out of bounds."); - assert(I < this->end() && "Erasing at past-the-end iterator."); + assert(this->isReferenceToStorage(CI) && "Iterator to erase is out of bounds."); iterator N = I; // Shift all elts down one. @@ -497,9 +721,7 @@ public: iterator S = const_cast(CS); iterator E = const_cast(CE); - assert(S >= this->begin() && "Range to erase is out of bounds."); - assert(S <= E && "Trying to erase invalid range."); - assert(E <= this->end() && "Trying to erase past the end."); + assert(this->isRangeInStorage(S, E) && "Range to erase is out of bounds."); iterator N = S; // Shift all elts down. @@ -510,20 +732,26 @@ public: return(N); } - iterator insert(iterator I, T &&Elt) { +private: + template iterator insert_one_impl(iterator I, ArgType &&Elt) { + // Callers ensure that ArgType is derived from T. + static_assert( + std::is_same>, + T>::value, + "ArgType must be derived from T!"); + if (I == this->end()) { // Important special case for empty vector. - this->push_back(::std::move(Elt)); + this->push_back(::std::forward(Elt)); return this->end()-1; } - assert(I >= this->begin() && "Insertion iterator is out of bounds."); - assert(I <= this->end() && "Inserting past the end of the vector."); + assert(this->isReferenceToStorage(I) && "Insertion iterator is out of bounds."); - if (this->size() >= this->capacity()) { - size_t EltNo = I-this->begin(); - this->grow(); - I = this->begin()+EltNo; - } + // Grow if necessary. + size_t Index = I - this->begin(); + std::remove_reference_t *EltPtr = + this->reserveForParamAndGetAddress(Elt); + I = this->begin() + Index; ::new ((void*) this->end()) T(::std::move(this->back())); // Push everything else over. @@ -531,45 +759,26 @@ public: this->set_size(this->size() + 1); // If we just moved the element we're inserting, be sure to update - // the reference. - T *EltPtr = &Elt; - if (I <= EltPtr && EltPtr < this->end()) + // the reference (never happens if TakesParamByValue). + static_assert(!TakesParamByValue || std::is_same::value, + "ArgType must be 'T' when taking by value!"); + if (!TakesParamByValue && this->isReferenceToRange(EltPtr, I, this->end())) ++EltPtr; - *I = ::std::move(*EltPtr); + *I = ::std::forward(*EltPtr); return I; } - iterator insert(iterator I, const T &Elt) { - if (I == this->end()) { // Important special case for empty vector. - this->push_back(Elt); - return this->end()-1; - } - - assert(I >= this->begin() && "Insertion iterator is out of bounds."); - assert(I <= this->end() && "Inserting past the end of the vector."); - - if (this->size() >= this->capacity()) { - size_t EltNo = I-this->begin(); - this->grow(); - I = this->begin()+EltNo; - } - ::new ((void*) this->end()) T(std::move(this->back())); - // Push everything else over. - std::move_backward(I, this->end()-1, this->end()); - this->set_size(this->size() + 1); - - // If we just moved the element we're inserting, be sure to update - // the reference. - const T *EltPtr = &Elt; - if (I <= EltPtr && EltPtr < this->end()) - ++EltPtr; +public: + iterator insert(iterator I, T &&Elt) { + return insert_one_impl(I, this->forward_value_param(std::move(Elt))); + } - *I = *EltPtr; - return I; + iterator insert(iterator I, const T &Elt) { + return insert_one_impl(I, this->forward_value_param(Elt)); } - iterator insert(iterator I, size_type NumToInsert, const T &Elt) { + iterator insert(iterator I, size_type NumToInsert, ValueParamT Elt) { // Convert iterator to elt# to avoid invalidating iterator when we reserve() size_t InsertElt = I - this->begin(); @@ -578,11 +787,11 @@ public: return this->begin()+InsertElt; } - assert(I >= this->begin() && "Insertion iterator is out of bounds."); - assert(I <= this->end() && "Inserting past the end of the vector."); + assert(this->isReferenceToStorage(I) && "Insertion iterator is out of bounds."); - // Ensure there is enough space. - reserve(this->size() + NumToInsert); + // Ensure there is enough space, and get the (maybe updated) address of + // Elt. + const T *EltPtr = this->reserveForParamAndGetAddress(Elt, NumToInsert); // Uninvalidate the iterator. I = this->begin()+InsertElt; @@ -599,7 +808,12 @@ public: // Copy the existing elements that get replaced. std::move_backward(I, OldEnd-NumToInsert, OldEnd); - std::fill_n(I, NumToInsert, Elt); + // If we just moved the element we're inserting, be sure to update + // the reference (never happens if TakesParamByValue). + if (!TakesParamByValue && I <= EltPtr && EltPtr < this->end()) + EltPtr += NumToInsert; + + std::fill_n(I, NumToInsert, *EltPtr); return I; } @@ -612,11 +826,16 @@ public: size_t NumOverwritten = OldEnd-I; this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten); + // If we just moved the element we're inserting, be sure to update + // the reference (never happens if TakesParamByValue). + if (!TakesParamByValue && I <= EltPtr && EltPtr < this->end()) + EltPtr += NumToInsert; + // Replace the overwritten part. - std::fill_n(I, NumOverwritten, Elt); + std::fill_n(I, NumOverwritten, *EltPtr); // Insert the non-overwritten middle part. - std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt); + std::uninitialized_fill_n(OldEnd, NumToInsert - NumOverwritten, *EltPtr); return I; } @@ -633,8 +852,10 @@ public: return this->begin()+InsertElt; } - assert(I >= this->begin() && "Insertion iterator is out of bounds."); - assert(I <= this->end() && "Inserting past the end of the vector."); + assert(this->isReferenceToStorage(I) && "Insertion iterator is out of bounds."); + + // Check that the reserve that follows doesn't invalidate the iterators. + this->assertSafeToAddRange(From, To); size_t NumToInsert = std::distance(From, To); @@ -686,7 +907,8 @@ public: template reference emplace_back(ArgTypes &&... Args) { if (LLVM_UNLIKELY(this->size() >= this->capacity())) - this->grow(); + return this->growAndEmplaceBack(std::forward(Args)...); + ::new ((void *)this->end()) T(std::forward(Args)...); this->set_size(this->size() + 1); return this->back(); @@ -721,10 +943,8 @@ void SmallVectorImpl::swap(SmallVectorImpl &RHS) { std::swap(this->Capacity, RHS.Capacity); return; } - if (RHS.size() > this->capacity()) - this->grow(RHS.size()); - if (this->size() > RHS.capacity()) - RHS.grow(this->size()); + this->reserve(RHS.size()); + RHS.reserve(this->size()); // Swap the shared elements. size_t NumShared = this->size(); @@ -779,8 +999,7 @@ SmallVectorImpl &SmallVectorImpl:: // FIXME: don't do this if they're efficiently moveable. if (this->capacity() < RHSSize) { // Destroy current elements. - this->destroy_range(this->begin(), this->end()); - this->set_size(0); + this->clear(); CurSize = 0; this->grow(RHSSize); } else if (CurSize) { @@ -839,8 +1058,7 @@ SmallVectorImpl &SmallVectorImpl::operator=(SmallVectorImpl &&RHS) { // elements. if (this->capacity() < RHSSize) { // Destroy current elements. - this->destroy_range(this->begin(), this->end()); - this->set_size(0); + this->clear(); CurSize = 0; this->grow(RHSSize); } else if (CurSize) { @@ -863,13 +1081,71 @@ SmallVectorImpl &SmallVectorImpl::operator=(SmallVectorImpl &&RHS) { /// to avoid allocating unnecessary storage. template struct SmallVectorStorage { - AlignedCharArrayUnion InlineElts[N]; + alignas(T) char InlineElts[N * sizeof(T)]; }; /// We need the storage to be properly aligned even for small-size of 0 so that /// the pointer math in \a SmallVectorTemplateCommon::getFirstEl() is /// well-defined. -template struct alignas(alignof(T)) SmallVectorStorage {}; +template struct alignas(T) SmallVectorStorage {}; + +/// Forward declaration of SmallVector so that +/// calculateSmallVectorDefaultInlinedElements can reference +/// `sizeof(SmallVector)`. +template class LLVM_GSL_OWNER SmallVector; + +/// Helper class for calculating the default number of inline elements for +/// `SmallVector`. +/// +/// This should be migrated to a constexpr function when our minimum +/// compiler support is enough for multi-statement constexpr functions. +template struct CalculateSmallVectorDefaultInlinedElements { + // Parameter controlling the default number of inlined elements + // for `SmallVector`. + // + // The default number of inlined elements ensures that + // 1. There is at least one inlined element. + // 2. `sizeof(SmallVector) <= kPreferredSmallVectorSizeof` unless + // it contradicts 1. + static constexpr size_t kPreferredSmallVectorSizeof = 64; + + // static_assert that sizeof(T) is not "too big". + // + // Because our policy guarantees at least one inlined element, it is possible + // for an arbitrarily large inlined element to allocate an arbitrarily large + // amount of inline storage. We generally consider it an antipattern for a + // SmallVector to allocate an excessive amount of inline storage, so we want + // to call attention to these cases and make sure that users are making an + // intentional decision if they request a lot of inline storage. + // + // We want this assertion to trigger in pathological cases, but otherwise + // not be too easy to hit. To accomplish that, the cutoff is actually somewhat + // larger than kPreferredSmallVectorSizeof (otherwise, + // `SmallVector>` would be one easy way to trip it, and that + // pattern seems useful in practice). + // + // One wrinkle is that this assertion is in theory non-portable, since + // sizeof(T) is in general platform-dependent. However, we don't expect this + // to be much of an issue, because most LLVM development happens on 64-bit + // hosts, and therefore sizeof(T) is expected to *decrease* when compiled for + // 32-bit hosts, dodging the issue. The reverse situation, where development + // happens on a 32-bit host and then fails due to sizeof(T) *increasing* on a + // 64-bit host, is expected to be very rare. + static_assert( + sizeof(T) <= 256, + "You are trying to use a default number of inlined elements for " + "`SmallVector` but `sizeof(T)` is really big! Please use an " + "explicit number of inlined elements with `SmallVector` to make " + "sure you really want that much inline storage."); + + // Discount the size of the header itself when calculating the maximum inline + // bytes. + static constexpr size_t PreferredInlineBytes = + kPreferredSmallVectorSizeof - sizeof(SmallVector); + static constexpr size_t NumElementsThatFit = PreferredInlineBytes / sizeof(T); + static constexpr size_t value = + NumElementsThatFit == 0 ? 1 : NumElementsThatFit; +}; /// This is a 'vector' (really, a variable-sized array), optimized /// for the case when the array is small. It contains some number of elements @@ -877,9 +1153,18 @@ template struct alignas(alignof(T)) SmallVectorStorage {}; /// elements is below that threshold. This allows normal "small" cases to be /// fast without losing generality for large inputs. /// -/// Note that this does not attempt to be exception safe. +/// \note +/// In the absence of a well-motivated choice for the number of inlined +/// elements \p N, it is recommended to use \c SmallVector (that is, +/// omitting the \p N). This will choose a default number of inlined elements +/// reasonable for allocation on the stack (for example, trying to keep \c +/// sizeof(SmallVector) around 64 bytes). /// -template +/// \warning This does not attempt to be exception safe. +/// +/// \see https://llvm.org/docs/ProgrammersManual.html#llvm-adt-smallvector-h +template ::value> class LLVM_GSL_OWNER SmallVector : public SmallVectorImpl, SmallVectorStorage { public: @@ -918,7 +1203,7 @@ public: SmallVectorImpl::operator=(RHS); } - const SmallVector &operator=(const SmallVector &RHS) { + SmallVector &operator=(const SmallVector &RHS) { SmallVectorImpl::operator=(RHS); return *this; } @@ -933,17 +1218,17 @@ public: SmallVectorImpl::operator=(::std::move(RHS)); } - const SmallVector &operator=(SmallVector &&RHS) { + SmallVector &operator=(SmallVector &&RHS) { SmallVectorImpl::operator=(::std::move(RHS)); return *this; } - const SmallVector &operator=(SmallVectorImpl &&RHS) { + SmallVector &operator=(SmallVectorImpl &&RHS) { SmallVectorImpl::operator=(::std::move(RHS)); return *this; } - const SmallVector &operator=(std::initializer_list IL) { + SmallVector &operator=(std::initializer_list IL) { this->assign(IL); return *this; } diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/SparseSet.h b/contrib/llvm-project/llvm/include/llvm/ADT/SparseSet.h index 74457d5fd679..d8acf1ee2f3a 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/SparseSet.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/SparseSet.h @@ -229,12 +229,15 @@ public: return const_cast(this)->findIndex(KeyIndexOf(Key)); } + /// Check if the set contains the given \c Key. + /// + /// @param Key A valid key to find. + bool contains(const KeyT &Key) const { return find(Key) == end() ? 0 : 1; } + /// count - Returns 1 if this set contains an element identified by Key, /// 0 otherwise. /// - size_type count(const KeyT &Key) const { - return find(Key) == end() ? 0 : 1; - } + size_type count(const KeyT &Key) const { return contains(Key) ? 1 : 0; } /// insert - Attempts to insert a new element. /// diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/Statistic.h b/contrib/llvm-project/llvm/include/llvm/ADT/Statistic.h index d7aff6c5939a..aa338ccff19a 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/Statistic.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/Statistic.h @@ -36,6 +36,8 @@ // configure time. #if !defined(NDEBUG) || LLVM_FORCE_ENABLE_STATS #define LLVM_ENABLE_STATS 1 +#else +#define LLVM_ENABLE_STATS 0 #endif namespace llvm { diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/StringExtras.h b/contrib/llvm-project/llvm/include/llvm/ADT/StringExtras.h index 990a3054a9d2..68e89508cba9 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/StringExtras.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/StringExtras.h @@ -66,17 +66,29 @@ inline ArrayRef arrayRefFromStringRef(StringRef Input) { /// /// If \p C is not a valid hex digit, -1U is returned. inline unsigned hexDigitValue(char C) { - if (C >= '0' && C <= '9') return C-'0'; - if (C >= 'a' && C <= 'f') return C-'a'+10U; - if (C >= 'A' && C <= 'F') return C-'A'+10U; - return -1U; + struct HexTable { + unsigned LUT[255] = {}; + constexpr HexTable() { + // Default initialize everything to invalid. + for (int i = 0; i < 255; ++i) + LUT[i] = ~0U; + // Initialize `0`-`9`. + for (int i = 0; i < 10; ++i) + LUT['0' + i] = i; + // Initialize `A`-`F` and `a`-`f`. + for (int i = 0; i < 6; ++i) + LUT['A' + i] = LUT['a' + i] = 10 + i; + } + }; + constexpr HexTable Table; + return Table.LUT[static_cast(C)]; } /// Checks if character \p C is one of the 10 decimal digits. inline bool isDigit(char C) { return C >= '0' && C <= '9'; } /// Checks if character \p C is a hexadecimal numeric character. -inline bool isHexDigit(char C) { return hexDigitValue(C) != -1U; } +inline bool isHexDigit(char C) { return hexDigitValue(C) != ~0U; } /// Checks if character \p C is a valid letter as classified by "C" locale. inline bool isAlpha(char C) { @@ -165,34 +177,68 @@ inline std::string toHex(ArrayRef Input, bool LowerCase = false) { return toHex(toStringRef(Input), LowerCase); } -inline uint8_t hexFromNibbles(char MSB, char LSB) { +/// Store the binary representation of the two provided values, \p MSB and +/// \p LSB, that make up the nibbles of a hexadecimal digit. If \p MSB or \p LSB +/// do not correspond to proper nibbles of a hexadecimal digit, this method +/// returns false. Otherwise, returns true. +inline bool tryGetHexFromNibbles(char MSB, char LSB, uint8_t &Hex) { unsigned U1 = hexDigitValue(MSB); unsigned U2 = hexDigitValue(LSB); - assert(U1 != -1U && U2 != -1U); + if (U1 == ~0U || U2 == ~0U) + return false; - return static_cast((U1 << 4) | U2); + Hex = static_cast((U1 << 4) | U2); + return true; } -/// Convert hexadecimal string \p Input to its binary representation. -/// The return string is half the size of \p Input. -inline std::string fromHex(StringRef Input) { +/// Return the binary representation of the two provided values, \p MSB and +/// \p LSB, that make up the nibbles of a hexadecimal digit. +inline uint8_t hexFromNibbles(char MSB, char LSB) { + uint8_t Hex = 0; + bool GotHex = tryGetHexFromNibbles(MSB, LSB, Hex); + (void)GotHex; + assert(GotHex && "MSB and/or LSB do not correspond to hex digits"); + return Hex; +} + +/// Convert hexadecimal string \p Input to its binary representation and store +/// the result in \p Output. Returns true if the binary representation could be +/// converted from the hexadecimal string. Returns false if \p Input contains +/// non-hexadecimal digits. The output string is half the size of \p Input. +inline bool tryGetFromHex(StringRef Input, std::string &Output) { if (Input.empty()) - return std::string(); + return true; - std::string Output; Output.reserve((Input.size() + 1) / 2); if (Input.size() % 2 == 1) { - Output.push_back(hexFromNibbles('0', Input.front())); + uint8_t Hex = 0; + if (!tryGetHexFromNibbles('0', Input.front(), Hex)) + return false; + + Output.push_back(Hex); Input = Input.drop_front(); } assert(Input.size() % 2 == 0); while (!Input.empty()) { - uint8_t Hex = hexFromNibbles(Input[0], Input[1]); + uint8_t Hex = 0; + if (!tryGetHexFromNibbles(Input[0], Input[1], Hex)) + return false; + Output.push_back(Hex); Input = Input.drop_front(2); } - return Output; + return true; +} + +/// Convert hexadecimal string \p Input to its binary representation. +/// The return string is half the size of \p Input. +inline std::string fromHex(StringRef Input) { + std::string Hex; + bool GotHex = tryGetFromHex(Input, Hex); + (void)GotHex; + assert(GotHex && "Input contains non hex digits"); + return Hex; } /// Convert the string \p S to an integer of the specified type using @@ -245,7 +291,7 @@ inline std::string utostr(uint64_t X, bool isNeg = false) { inline std::string itostr(int64_t X) { if (X < 0) - return utostr(-static_cast(X), true); + return utostr(static_cast(1) + ~static_cast(X), true); else return utostr(static_cast(X)); } @@ -338,13 +384,16 @@ inline std::string join_impl(IteratorT Begin, IteratorT End, size_t Len = (std::distance(Begin, End) - 1) * Separator.size(); for (IteratorT I = Begin; I != End; ++I) - Len += (*Begin).size(); + Len += (*I).size(); S.reserve(Len); + size_t PrevCapacity = S.capacity(); + (void)PrevCapacity; S += (*Begin); while (++Begin != End) { S += Separator; S += (*Begin); } + assert(PrevCapacity == S.capacity() && "String grew during building"); return S; } @@ -416,6 +465,30 @@ inline std::string join_items(Sep Separator, Args &&... Items) { return Result; } +/// A helper class to return the specified delimiter string after the first +/// invocation of operator StringRef(). Used to generate a comma-separated +/// list from a loop like so: +/// +/// \code +/// ListSeparator LS; +/// for (auto &I : C) +/// OS << LS << I.getName(); +/// \end +class ListSeparator { + bool First = true; + StringRef Separator; + +public: + ListSeparator(StringRef Separator = ", ") : Separator(Separator) {} + operator StringRef() { + if (First) { + First = false; + return {}; + } + return Separator; + } +}; + } // end namespace llvm #endif // LLVM_ADT_STRINGEXTRAS_H diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/StringMap.h b/contrib/llvm-project/llvm/include/llvm/ADT/StringMap.h index 840f328db796..a82afc9a817c 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/StringMap.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/StringMap.h @@ -78,10 +78,12 @@ protected: void init(unsigned Size); public: + static constexpr uintptr_t TombstoneIntVal = + static_cast(-1) + << PointerLikeTypeTraits::NumLowBitsAvailable; + static StringMapEntryBase *getTombstoneVal() { - uintptr_t Val = static_cast(-1); - Val <<= PointerLikeTypeTraits::NumLowBitsAvailable; - return reinterpret_cast(Val); + return reinterpret_cast(TombstoneIntVal); } unsigned getNumBuckets() const { return NumBuckets; } @@ -387,7 +389,9 @@ public: return static_cast(*this); } - bool operator==(const DerivedTy &RHS) const { return Ptr == RHS.Ptr; } + friend bool operator==(const DerivedTy &LHS, const DerivedTy &RHS) { + return LHS.Ptr == RHS.Ptr; + } DerivedTy &operator++() { // Preincrement ++Ptr; diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/StringSet.h b/contrib/llvm-project/llvm/include/llvm/ADT/StringSet.h index 63d929399a4e..c4245175544b 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/StringSet.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/StringSet.h @@ -45,6 +45,9 @@ public: insert(const StringMapEntry &mapEntry) { return insert(mapEntry.getKey()); } + + /// Check if the set contains the given \c key. + bool contains(StringRef key) const { return Base::FindKey(key) != -1; } }; } // end namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/Triple.h b/contrib/llvm-project/llvm/include/llvm/ADT/Triple.h index 6bad18f19244..eed315c929ad 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/Triple.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/Triple.h @@ -56,6 +56,7 @@ public: avr, // AVR: Atmel AVR microcontroller bpfel, // eBPF or extended BPF or 64-bit BPF (little endian) bpfeb, // eBPF or extended BPF or 64-bit BPF (big endian) + csky, // CSKY: csky hexagon, // Hexagon: hexagon mips, // MIPS: mips, mipsallegrex, mipsr6 mipsel, // MIPSEL: mipsel, mipsallegrexe, mipsr6el @@ -63,6 +64,7 @@ public: mips64el, // MIPS64EL: mips64el, mips64r6el, mipsn32el, mipsn32r6el msp430, // MSP430: msp430 ppc, // PPC: powerpc + ppcle, // PPCLE: powerpc (little endian) ppc64, // PPC64: powerpc64, ppu ppc64le, // PPC64LE: powerpc64le r600, // R600: AMD GPUs HD2XXX - HD6XXX @@ -103,6 +105,7 @@ public: enum SubArchType { NoSubArch, + ARMSubArch_v8_7a, ARMSubArch_v8_6a, ARMSubArch_v8_5a, ARMSubArch_v8_4a, @@ -128,6 +131,8 @@ public: ARMSubArch_v5te, ARMSubArch_v4t, + AArch64SubArch_arm64e, + KalimbaSubArch_v3, KalimbaSubArch_v4, KalimbaSubArch_v5, @@ -142,8 +147,6 @@ public: Apple, PC, SCEI, - BGP, - BGQ, Freescale, IBM, ImaginationTechnologies, @@ -175,11 +178,11 @@ public: OpenBSD, Solaris, Win32, + ZOS, Haiku, Minix, RTEMS, NaCl, // Native Client - CNK, // BG/P Compute-Node Kernel AIX, CUDA, // NVIDIA CUDA NVCL, // NVIDIA OpenCL @@ -206,6 +209,7 @@ public: GNUEABI, GNUEABIHF, GNUX32, + GNUILP32, CODE16, EABI, EABIHF, @@ -227,6 +231,7 @@ public: COFF, ELF, + GOFF, MachO, Wasm, XCOFF, @@ -471,6 +476,8 @@ public: return getSubArch() == Triple::ARMSubArch_v7k; } + bool isOSzOS() const { return getOS() == Triple::ZOS; } + /// isOSDarwin - Is this a "Darwin" OS (macOS, iOS, tvOS or watchOS). bool isOSDarwin() const { return isMacOSX() || isiOS() || isWatchOS(); @@ -484,6 +491,12 @@ public: return getEnvironment() == Triple::MacABI; } + /// Returns true for targets that run on a macOS machine. + bool isTargetMachineMac() const { + return isMacOSX() || (isOSDarwin() && (isSimulatorEnvironment() || + isMacCatalystEnvironment())); + } + bool isOSNetBSD() const { return getOS() == Triple::NetBSD; } @@ -623,6 +636,9 @@ public: return getObjectFormat() == Triple::COFF; } + /// Tests whether the OS uses the GOFF binary format. + bool isOSBinFormatGOFF() const { return getObjectFormat() == Triple::GOFF; } + /// Tests whether the environment is MachO. bool isOSBinFormatMachO() const { return getObjectFormat() == Triple::MachO; @@ -703,7 +719,20 @@ public: /// Tests whether the target is AArch64 (little and big endian). bool isAArch64() const { - return getArch() == Triple::aarch64 || getArch() == Triple::aarch64_be; + return getArch() == Triple::aarch64 || getArch() == Triple::aarch64_be || + getArch() == Triple::aarch64_32; + } + + /// Tests whether the target is AArch64 and pointers are the size specified by + /// \p PointerWidth. + bool isAArch64(int PointerWidth) const { + assert(PointerWidth == 64 || PointerWidth == 32); + if (!isAArch64()) + return false; + return getArch() == Triple::aarch64_32 || + getEnvironment() == Triple::GNUILP32 + ? PointerWidth == 32 + : PointerWidth == 64; } /// Tests whether the target is MIPS 32-bit (little and big endian). @@ -721,6 +750,17 @@ public: return isMIPS32() || isMIPS64(); } + /// Tests whether the target is PowerPC (32- or 64-bit LE or BE). + bool isPPC() const { + return getArch() == Triple::ppc || getArch() == Triple::ppc64 || + getArch() == Triple::ppcle || getArch() == Triple::ppc64le; + } + + /// Tests whether the target is 32-bit PowerPC (little and big endian). + bool isPPC32() const { + return getArch() == Triple::ppc || getArch() == Triple::ppcle; + } + /// Tests whether the target is 64-bit PowerPC (little and big endian). bool isPPC64() const { return getArch() == Triple::ppc64 || getArch() == Triple::ppc64le; @@ -751,6 +791,17 @@ public: return getArch() == Triple::wasm32 || getArch() == Triple::wasm64; } + // Tests whether the target is CSKY + bool isCSKY() const { + return getArch() == Triple::csky; + } + + /// Tests whether the target is the Apple "arm64e" AArch64 subarch. + bool isArm64e() const { + return getArch() == Triple::aarch64 && + getSubArch() == Triple::AArch64SubArch_arm64e; + } + /// Tests whether the target supports comdat bool supportsCOMDAT() const { return !(isOSBinFormatMachO() || isOSBinFormatXCOFF()); @@ -761,6 +812,14 @@ public: return isAndroid() || isOSOpenBSD() || isWindowsCygwinEnvironment(); } + /// Tests whether the target uses -data-sections as default. + bool hasDefaultDataSections() const { + return isOSBinFormatXCOFF() || isWasm(); + } + + /// Tests if the environment supports dllimport/export annotations. + bool hasDLLImportExport() const { return isOSWindows() || isPS4CPU(); } + /// @} /// @name Mutators /// @{ diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/iterator.h b/contrib/llvm-project/llvm/include/llvm/ADT/iterator.h index 9a1f6e1511e7..6625a3f6179e 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/iterator.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/iterator.h @@ -142,28 +142,30 @@ public: return tmp; } +#ifndef __cpp_impl_three_way_comparison bool operator!=(const DerivedT &RHS) const { - return !static_cast(this)->operator==(RHS); + return !(static_cast(*this) == RHS); } +#endif bool operator>(const DerivedT &RHS) const { static_assert( IsRandomAccess, "Relational operators are only defined for random access iterators."); - return !static_cast(this)->operator<(RHS) && - !static_cast(this)->operator==(RHS); + return !(static_cast(*this) < RHS) && + !(static_cast(*this) == RHS); } bool operator<=(const DerivedT &RHS) const { static_assert( IsRandomAccess, "Relational operators are only defined for random access iterators."); - return !static_cast(this)->operator>(RHS); + return !(static_cast(*this) > RHS); } bool operator>=(const DerivedT &RHS) const { static_assert( IsRandomAccess, "Relational operators are only defined for random access iterators."); - return !static_cast(this)->operator<(RHS); + return !(static_cast(*this) < RHS); } PointerT operator->() { return &static_cast(this)->operator*(); } @@ -260,12 +262,16 @@ public: return *static_cast(this); } - bool operator==(const DerivedT &RHS) const { return I == RHS.I; } - bool operator<(const DerivedT &RHS) const { + friend bool operator==(const iterator_adaptor_base &LHS, + const iterator_adaptor_base &RHS) { + return LHS.I == RHS.I; + } + friend bool operator<(const iterator_adaptor_base &LHS, + const iterator_adaptor_base &RHS) { static_assert( BaseT::IsRandomAccess, "Relational operators are only defined for random access iterators."); - return I < RHS.I; + return LHS.I < RHS.I; } ReferenceT operator*() const { return *I; } diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/iterator_range.h b/contrib/llvm-project/llvm/include/llvm/ADT/iterator_range.h index f038f6bf2128..a9b46a3aa45b 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/iterator_range.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/iterator_range.h @@ -18,7 +18,6 @@ #ifndef LLVM_ADT_ITERATOR_RANGE_H #define LLVM_ADT_ITERATOR_RANGE_H -#include #include namespace llvm { diff --git a/contrib/llvm-project/llvm/include/llvm/ADT/simple_ilist.h b/contrib/llvm-project/llvm/include/llvm/ADT/simple_ilist.h index 9257b47b9cf8..d4b6be347219 100644 --- a/contrib/llvm-project/llvm/include/llvm/ADT/simple_ilist.h +++ b/contrib/llvm-project/llvm/include/llvm/ADT/simple_ilist.h @@ -28,8 +28,8 @@ namespace llvm { /// This is a simple intrusive list for a \c T that inherits from \c /// ilist_node. The list never takes ownership of anything inserted in it. /// -/// Unlike \a iplist and \a ilist, \a simple_ilist never allocates or -/// deletes values, and has no callback traits. +/// Unlike \a iplist and \a ilist, \a simple_ilist never deletes +/// values, and has no callback traits. /// /// The API for adding nodes include \a push_front(), \a push_back(), and \a /// insert(). These all take values by reference (not by pointer), except for @@ -52,7 +52,7 @@ namespace llvm { /// to calling \a std::for_each() on the range to be discarded. /// /// The currently available \p Options customize the nodes in the list. The -/// same options must be specified in the \a ilist_node instantation for +/// same options must be specified in the \a ilist_node instantiation for /// compatibility (although the order is irrelevant). /// \li Use \a ilist_tag to designate which ilist_node for a given \p T this /// list should use. This is useful if a type \p T is part of multiple, diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/AliasAnalysis.h b/contrib/llvm-project/llvm/include/llvm/Analysis/AliasAnalysis.h index c35ee2f499de..9f7461243f35 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/AliasAnalysis.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/AliasAnalysis.h @@ -42,10 +42,6 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/MemoryLocation.h" -#include "llvm/Analysis/TargetLibraryInfo.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/Instruction.h" -#include "llvm/IR/Instructions.h" #include "llvm/IR/PassManager.h" #include "llvm/Pass.h" #include @@ -56,9 +52,17 @@ namespace llvm { class AnalysisUsage; +class AtomicCmpXchgInst; class BasicAAResult; class BasicBlock; +class CatchPadInst; +class CatchReturnInst; class DominatorTree; +class FenceInst; +class Function; +class InvokeInst; +class PreservedAnalyses; +class TargetLibraryInfo; class Value; /// The possible results of an alias query. @@ -342,12 +346,28 @@ createModRefInfo(const FunctionModRefBehavior FMRB) { class AAQueryInfo { public: using LocPair = std::pair; - using AliasCacheT = SmallDenseMap; + struct CacheEntry { + AliasResult Result; + /// Number of times a NoAlias assumption has been used. + /// 0 for assumptions that have not been used, -1 for definitive results. + int NumAssumptionUses; + /// Whether this is a definitive (non-assumption) result. + bool isDefinitive() const { return NumAssumptionUses < 0; } + }; + using AliasCacheT = SmallDenseMap; AliasCacheT AliasCache; using IsCapturedCacheT = SmallDenseMap; IsCapturedCacheT IsCapturedCache; + /// How many active NoAlias assumption uses there are. + int NumAssumptionUses = 0; + + /// Location pairs for which an assumption based result is currently stored. + /// Used to remove all potentially incorrect results from the cache if an + /// assumption is disproven. + SmallVector AssumptionBasedResults; + AAQueryInfo() : AliasCache(), IsCapturedCache() {} }; @@ -401,7 +421,8 @@ public: /// A convenience wrapper around the primary \c alias interface. AliasResult alias(const Value *V1, const Value *V2) { - return alias(V1, LocationSize::unknown(), V2, LocationSize::unknown()); + return alias(MemoryLocation::getBeforeOrAfter(V1), + MemoryLocation::getBeforeOrAfter(V2)); } /// A trivial helper function to check to see if the specified pointers are @@ -418,7 +439,8 @@ public: /// A convenience wrapper around the \c isNoAlias helper interface. bool isNoAlias(const Value *V1, const Value *V2) { - return isNoAlias(MemoryLocation(V1), MemoryLocation(V2)); + return isNoAlias(MemoryLocation::getBeforeOrAfter(V1), + MemoryLocation::getBeforeOrAfter(V2)); } /// A trivial helper function to check to see if the specified pointers are @@ -440,7 +462,7 @@ public: /// A convenience wrapper around the primary \c pointsToConstantMemory /// interface. bool pointsToConstantMemory(const Value *P, bool OrLocal = false) { - return pointsToConstantMemory(MemoryLocation(P), OrLocal); + return pointsToConstantMemory(MemoryLocation::getBeforeOrAfter(P), OrLocal); } /// @} @@ -533,7 +555,7 @@ public: /// write at most from objects pointed to by their pointer-typed arguments /// (with arbitrary offsets). static bool onlyAccessesArgPointees(FunctionModRefBehavior MRB) { - return !(MRB & FMRL_Anywhere & ~FMRL_ArgumentPointees); + return !((unsigned)MRB & FMRL_Anywhere & ~FMRL_ArgumentPointees); } /// Checks if functions with the specified behavior are known to potentially @@ -541,26 +563,27 @@ public: /// (with arbitrary offsets). static bool doesAccessArgPointees(FunctionModRefBehavior MRB) { return isModOrRefSet(createModRefInfo(MRB)) && - (MRB & FMRL_ArgumentPointees); + ((unsigned)MRB & FMRL_ArgumentPointees); } /// Checks if functions with the specified behavior are known to read and /// write at most from memory that is inaccessible from LLVM IR. static bool onlyAccessesInaccessibleMem(FunctionModRefBehavior MRB) { - return !(MRB & FMRL_Anywhere & ~FMRL_InaccessibleMem); + return !((unsigned)MRB & FMRL_Anywhere & ~FMRL_InaccessibleMem); } /// Checks if functions with the specified behavior are known to potentially /// read or write from memory that is inaccessible from LLVM IR. static bool doesAccessInaccessibleMem(FunctionModRefBehavior MRB) { - return isModOrRefSet(createModRefInfo(MRB)) && (MRB & FMRL_InaccessibleMem); + return isModOrRefSet(createModRefInfo(MRB)) && + ((unsigned)MRB & FMRL_InaccessibleMem); } /// Checks if functions with the specified behavior are known to read and /// write at most from memory that is inaccessible from LLVM IR or objects /// pointed to by their pointer-typed arguments (with arbitrary offsets). static bool onlyAccessesInaccessibleOrArgMem(FunctionModRefBehavior MRB) { - return !(MRB & FMRL_Anywhere & + return !((unsigned)MRB & FMRL_Anywhere & ~(FMRL_InaccessibleMem | FMRL_ArgumentPointees)); } @@ -760,40 +783,7 @@ private: AAQueryInfo &AAQI); ModRefInfo getModRefInfo(const Instruction *I, const Optional &OptLoc, - AAQueryInfo &AAQIP) { - if (OptLoc == None) { - if (const auto *Call = dyn_cast(I)) { - return createModRefInfo(getModRefBehavior(Call)); - } - } - - const MemoryLocation &Loc = OptLoc.getValueOr(MemoryLocation()); - - switch (I->getOpcode()) { - case Instruction::VAArg: - return getModRefInfo((const VAArgInst *)I, Loc, AAQIP); - case Instruction::Load: - return getModRefInfo((const LoadInst *)I, Loc, AAQIP); - case Instruction::Store: - return getModRefInfo((const StoreInst *)I, Loc, AAQIP); - case Instruction::Fence: - return getModRefInfo((const FenceInst *)I, Loc, AAQIP); - case Instruction::AtomicCmpXchg: - return getModRefInfo((const AtomicCmpXchgInst *)I, Loc, AAQIP); - case Instruction::AtomicRMW: - return getModRefInfo((const AtomicRMWInst *)I, Loc, AAQIP); - case Instruction::Call: - return getModRefInfo((const CallInst *)I, Loc, AAQIP); - case Instruction::Invoke: - return getModRefInfo((const InvokeInst *)I, Loc, AAQIP); - case Instruction::CatchPad: - return getModRefInfo((const CatchPadInst *)I, Loc, AAQIP); - case Instruction::CatchRet: - return getModRefInfo((const CatchReturnInst *)I, Loc, AAQIP); - default: - return ModRefInfo::NoModRef; - } - } + AAQueryInfo &AAQIP); class Concept; @@ -807,6 +797,9 @@ private: std::vector AADeps; + /// Query depth used to distinguish recursive queries. + unsigned Depth = 0; + friend class BatchAAResults; }; @@ -847,6 +840,13 @@ public: FunctionModRefBehavior getModRefBehavior(const CallBase *Call) { return AA.getModRefBehavior(Call); } + bool isMustAlias(const MemoryLocation &LocA, const MemoryLocation &LocB) { + return alias(LocA, LocB) == MustAlias; + } + bool isMustAlias(const Value *V1, const Value *V2) { + return alias(MemoryLocation(V1, LocationSize::precise(1)), + MemoryLocation(V2, LocationSize::precise(1))) == MustAlias; + } }; /// Temporary typedef for legacy code that uses a generic \c AliasAnalysis @@ -1107,9 +1107,6 @@ public: /// Return true if this pointer is returned by a noalias function. bool isNoAliasCall(const Value *V); -/// Return true if this is an argument with the noalias attribute. -bool isNoAliasArgument(const Value *V); - /// Return true if this pointer refers to a distinct and identifiable object. /// This returns true for: /// Global Variables and Functions (but not Global Aliases) @@ -1157,12 +1154,7 @@ public: ResultGetters.push_back(&getModuleAAResultImpl); } - Result run(Function &F, FunctionAnalysisManager &AM) { - Result R(AM.getResult(F)); - for (auto &Getter : ResultGetters) - (*Getter)(F, AM, R); - return R; - } + Result run(Function &F, FunctionAnalysisManager &AM); private: friend AnalysisInfoMixin; diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/AliasSetTracker.h b/contrib/llvm-project/llvm/include/llvm/Analysis/AliasSetTracker.h index 690a94d9cf2c..b27fd5aa92a7 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/AliasSetTracker.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/AliasSetTracker.h @@ -20,9 +20,10 @@ #include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" -#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/MemoryLocation.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Metadata.h" +#include "llvm/IR/PassManager.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Support/Casting.h" #include @@ -33,6 +34,7 @@ namespace llvm { +class AAResults; class AliasSetTracker; class BasicBlock; class LoadInst; @@ -45,6 +47,8 @@ class StoreInst; class VAArgInst; class Value; +enum AliasResult : uint8_t; + class AliasSet : public ilist_node { friend class AliasSetTracker; @@ -293,7 +297,7 @@ private: void addPointer(AliasSetTracker &AST, PointerRec &Entry, LocationSize Size, const AAMDNodes &AAInfo, bool KnownMustAlias = false, bool SkipSizeUpdate = false); - void addUnknownInst(Instruction *I, AliasAnalysis &AA); + void addUnknownInst(Instruction *I, AAResults &AA); void removeUnknownInst(AliasSetTracker &AST, Instruction *I) { bool WasEmpty = UnknownInsts.empty(); @@ -311,8 +315,8 @@ public: /// If the specified pointer "may" (or must) alias one of the members in the /// set return the appropriate AliasResult. Otherwise return NoAlias. AliasResult aliasesPointer(const Value *Ptr, LocationSize Size, - const AAMDNodes &AAInfo, AliasAnalysis &AA) const; - bool aliasesUnknownInst(const Instruction *Inst, AliasAnalysis &AA) const; + const AAMDNodes &AAInfo, AAResults &AA) const; + bool aliasesUnknownInst(const Instruction *Inst, AAResults &AA) const; }; inline raw_ostream& operator<<(raw_ostream &OS, const AliasSet &AS) { @@ -338,7 +342,7 @@ class AliasSetTracker { /// handle. struct ASTCallbackVHDenseMapInfo : public DenseMapInfo {}; - AliasAnalysis &AA; + AAResults &AA; MemorySSA *MSSA = nullptr; Loop *L = nullptr; ilist AliasSets; @@ -352,9 +356,9 @@ class AliasSetTracker { public: /// Create an empty collection of AliasSets, and use the specified alias /// analysis object to disambiguate load and store addresses. - explicit AliasSetTracker(AliasAnalysis &aa) : AA(aa) {} - explicit AliasSetTracker(AliasAnalysis &aa, MemorySSA *mssa, Loop *l) - : AA(aa), MSSA(mssa), L(l) {} + explicit AliasSetTracker(AAResults &AA) : AA(AA) {} + explicit AliasSetTracker(AAResults &AA, MemorySSA *MSSA, Loop *L) + : AA(AA), MSSA(MSSA), L(L) {} ~AliasSetTracker() { clear(); } /// These methods are used to add different types of instructions to the alias @@ -393,7 +397,7 @@ public: AliasSet &getAliasSetFor(const MemoryLocation &MemLoc); /// Return the underlying alias analysis object used by this tracker. - AliasAnalysis &getAliasAnalysis() const { return AA; } + AAResults &getAliasAnalysis() const { return AA; } /// This method is used to remove a pointer value from the AliasSetTracker /// entirely. It should be used when an instruction is deleted from the @@ -457,6 +461,14 @@ inline raw_ostream& operator<<(raw_ostream &OS, const AliasSetTracker &AST) { return OS; } +class AliasSetsPrinterPass : public PassInfoMixin { + raw_ostream &OS; + +public: + explicit AliasSetsPrinterPass(raw_ostream &OS); + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + } // end namespace llvm #endif // LLVM_ANALYSIS_ALIASSETTRACKER_H diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/AssumptionCache.h b/contrib/llvm-project/llvm/include/llvm/Analysis/AssumptionCache.h index 0ef63dc68e1c..c4602d3449c0 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/AssumptionCache.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/AssumptionCache.h @@ -45,7 +45,7 @@ public: enum : unsigned { ExprResultIdx = std::numeric_limits::max() }; struct ResultElem { - WeakTrackingVH Assume; + WeakVH Assume; /// contains either ExprResultIdx or the index of the operand bundle /// containing the knowledge. diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/BasicAliasAnalysis.h b/contrib/llvm-project/llvm/include/llvm/Analysis/BasicAliasAnalysis.h index 9214bfcd7a24..46b8cd1f3a88 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/BasicAliasAnalysis.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/BasicAliasAnalysis.h @@ -18,9 +18,6 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/AliasAnalysis.h" -#include "llvm/Analysis/AssumptionCache.h" -#include "llvm/Analysis/MemoryLocation.h" -#include "llvm/IR/InstrTypes.h" #include "llvm/IR/PassManager.h" #include "llvm/Pass.h" #include @@ -120,6 +117,9 @@ private: APInt Scale; + // Context instruction to use when querying information about this index. + const Instruction *CxtI; + bool operator==(const VariableGEPIndex &Other) const { return V == Other.V && ZExtBits == Other.ZExtBits && SExtBits == Other.SExtBits && Scale == Other.Scale; @@ -128,6 +128,17 @@ private: bool operator!=(const VariableGEPIndex &Other) const { return !operator==(Other); } + + void dump() const { + print(dbgs()); + dbgs() << "\n"; + } + void print(raw_ostream &OS) const { + OS << "(V=" << V->getName() + << ", zextbits=" << ZExtBits + << ", sextbits=" << SExtBits + << ", scale=" << Scale << ")"; + } }; // Represents the internal structure of a GEP, decomposed into a base pointer, @@ -135,15 +146,29 @@ private: struct DecomposedGEP { // Base pointer of the GEP const Value *Base; - // Total constant offset w.r.t the base from indexing into structs - APInt StructOffset; - // Total constant offset w.r.t the base from indexing through - // pointers/arrays/vectors - APInt OtherOffset; + // Total constant offset from base. + APInt Offset; // Scaled variable (non-constant) indices. SmallVector VarIndices; // Is GEP index scale compile-time constant. bool HasCompileTimeConstantScale; + + void dump() const { + print(dbgs()); + dbgs() << "\n"; + } + void print(raw_ostream &OS) const { + OS << "(DecomposedGEP Base=" << Base->getName() + << ", Offset=" << Offset + << ", VarIndices=["; + for (size_t i = 0; i < VarIndices.size(); i++) { + if (i != 0) + OS << ", "; + VarIndices[i].print(OS); + } + OS << "], HasCompileTimeConstantScale=" << HasCompileTimeConstantScale + << ")"; + } }; /// Tracks phi nodes we have visited. @@ -171,8 +196,9 @@ private: const DataLayout &DL, unsigned Depth, AssumptionCache *AC, DominatorTree *DT, bool &NSW, bool &NUW); - static bool DecomposeGEPExpression(const Value *V, DecomposedGEP &Decomposed, - const DataLayout &DL, AssumptionCache *AC, DominatorTree *DT); + static DecomposedGEP + DecomposeGEPExpression(const Value *V, const DataLayout &DL, + AssumptionCache *AC, DominatorTree *DT); static bool isGEPBaseAtNegativeOffset(const GEPOperator *GEPOp, const DecomposedGEP &DecompGEP, const DecomposedGEP &DecompObject, @@ -206,18 +232,23 @@ private: AliasResult aliasPHI(const PHINode *PN, LocationSize PNSize, const AAMDNodes &PNAAInfo, const Value *V2, LocationSize V2Size, const AAMDNodes &V2AAInfo, - const Value *UnderV2, AAQueryInfo &AAQI); + AAQueryInfo &AAQI); AliasResult aliasSelect(const SelectInst *SI, LocationSize SISize, const AAMDNodes &SIAAInfo, const Value *V2, LocationSize V2Size, const AAMDNodes &V2AAInfo, - const Value *UnderV2, AAQueryInfo &AAQI); + AAQueryInfo &AAQI); AliasResult aliasCheck(const Value *V1, LocationSize V1Size, - AAMDNodes V1AATag, const Value *V2, - LocationSize V2Size, AAMDNodes V2AATag, - AAQueryInfo &AAQI, const Value *O1 = nullptr, - const Value *O2 = nullptr); + const AAMDNodes &V1AATag, const Value *V2, + LocationSize V2Size, const AAMDNodes &V2AATag, + AAQueryInfo &AAQI); + + AliasResult aliasCheckRecursive(const Value *V1, LocationSize V1Size, + const AAMDNodes &V1AATag, const Value *V2, + LocationSize V2Size, const AAMDNodes &V2AATag, + AAQueryInfo &AAQI, const Value *O1, + const Value *O2); }; /// Analysis pass providing a never-invalidated alias analysis result. diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h b/contrib/llvm-project/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h index 868da7a64f68..c22787531117 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h @@ -169,7 +169,7 @@ inline raw_ostream &operator<<(raw_ostream &OS, BlockMass X) { /// algorithms for BlockFrequencyInfoImplBase. Only algorithms that depend on /// the block type (or that call such algorithms) are skipped here. /// -/// Nevertheless, the majority of the overall algorithm documention lives with +/// Nevertheless, the majority of the overall algorithm documentation lives with /// BlockFrequencyInfoImpl. See there for details. class BlockFrequencyInfoImplBase { public: @@ -458,7 +458,7 @@ public: /// Analyze irreducible SCCs. /// - /// Separate irreducible SCCs from \c G, which is an explict graph of \c + /// Separate irreducible SCCs from \c G, which is an explicit graph of \c /// OuterLoop (or the top-level function, if \c OuterLoop is \c nullptr). /// Insert them into \a Loops before \c Insert. /// @@ -706,7 +706,7 @@ void IrreducibleGraph::addEdges(const BlockNode &Node, /// /// In addition to loops, this algorithm has limited support for irreducible /// SCCs, which are SCCs with multiple entry blocks. Irreducible SCCs are -/// discovered on they fly, and modelled as loops with multiple headers. +/// discovered on the fly, and modelled as loops with multiple headers. /// /// The headers of irreducible sub-SCCs consist of its entry blocks and all /// nodes that are targets of a backedge within it (excluding backedges within @@ -1246,7 +1246,7 @@ bool BlockFrequencyInfoImpl::computeMassInLoop(LoopData &Loop) { } } // As a heuristic, if some headers don't have a weight, give them the - // minimium weight seen (not to disrupt the existing trends too much by + // minimum weight seen (not to disrupt the existing trends too much by // using a weight that's in the general range of the other headers' weights, // and the minimum seems to perform better than the average.) // FIXME: better update in the passes that drop the header weight. @@ -1449,8 +1449,8 @@ void BlockFrequencyInfoImpl::verifyMatch( BlockNode Node = Entry.second; if (OtherValidNodes.count(BB)) { BlockNode OtherNode = OtherValidNodes[BB]; - auto Freq = Freqs[Node.Index]; - auto OtherFreq = Other.Freqs[OtherNode.Index]; + const auto &Freq = Freqs[Node.Index]; + const auto &OtherFreq = Other.Freqs[OtherNode.Index]; if (Freq.Integer != OtherFreq.Integer) { Match = false; dbgs() << "Freq mismatch: " << bfi_detail::getBlockName(BB) << " " diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/BranchProbabilityInfo.h b/contrib/llvm-project/llvm/include/llvm/Analysis/BranchProbabilityInfo.h index 3e72afba36c3..6a286236a80e 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/BranchProbabilityInfo.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/BranchProbabilityInfo.h @@ -27,13 +27,16 @@ #include #include #include +#include #include namespace llvm { class Function; +class Loop; class LoopInfo; class raw_ostream; +class DominatorTree; class PostDominatorTree; class TargetLibraryInfo; class Value; @@ -50,20 +53,79 @@ class Value; /// identify an edge, since we can have multiple edges from Src to Dst. /// As an example, we can have a switch which jumps to Dst with value 0 and /// value 10. +/// +/// Process of computing branch probabilities can be logically viewed as three +/// step process: +/// +/// First, if there is a profile information associated with the branch then +/// it is trivially translated to branch probabilities. There is one exception +/// from this rule though. Probabilities for edges leading to "unreachable" +/// blocks (blocks with the estimated weight not greater than +/// UNREACHABLE_WEIGHT) are evaluated according to static estimation and +/// override profile information. If no branch probabilities were calculated +/// on this step then take the next one. +/// +/// Second, estimate absolute execution weights for each block based on +/// statically known information. Roots of such information are "cold", +/// "unreachable", "noreturn" and "unwind" blocks. Those blocks get their +/// weights set to BlockExecWeight::COLD, BlockExecWeight::UNREACHABLE, +/// BlockExecWeight::NORETURN and BlockExecWeight::UNWIND respectively. Then the +/// weights are propagated to the other blocks up the domination line. In +/// addition, if all successors have estimated weights set then maximum of these +/// weights assigned to the block itself (while this is not ideal heuristic in +/// theory it's simple and works reasonably well in most cases) and the process +/// repeats. Once the process of weights propagation converges branch +/// probabilities are set for all such branches that have at least one successor +/// with the weight set. Default execution weight (BlockExecWeight::DEFAULT) is +/// used for any successors which doesn't have its weight set. For loop back +/// branches we use their weights scaled by loop trip count equal to +/// 'LBH_TAKEN_WEIGHT/LBH_NOTTAKEN_WEIGHT'. +/// +/// Here is a simple example demonstrating how the described algorithm works. +/// +/// BB1 +/// / \ +/// v v +/// BB2 BB3 +/// / \ +/// v v +/// ColdBB UnreachBB +/// +/// Initially, ColdBB is associated with COLD_WEIGHT and UnreachBB with +/// UNREACHABLE_WEIGHT. COLD_WEIGHT is set to BB2 as maximum between its +/// successors. BB1 and BB3 has no explicit estimated weights and assumed to +/// have DEFAULT_WEIGHT. Based on assigned weights branches will have the +/// following probabilities: +/// P(BB1->BB2) = COLD_WEIGHT/(COLD_WEIGHT + DEFAULT_WEIGHT) = +/// 0xffff / (0xffff + 0xfffff) = 0.0588(5.9%) +/// P(BB1->BB3) = DEFAULT_WEIGHT_WEIGHT/(COLD_WEIGHT + DEFAULT_WEIGHT) = +/// 0xfffff / (0xffff + 0xfffff) = 0.941(94.1%) +/// P(BB2->ColdBB) = COLD_WEIGHT/(COLD_WEIGHT + UNREACHABLE_WEIGHT) = 1(100%) +/// P(BB2->UnreachBB) = +/// UNREACHABLE_WEIGHT/(COLD_WEIGHT+UNREACHABLE_WEIGHT) = 0(0%) +/// +/// If no branch probabilities were calculated on this step then take the next +/// one. +/// +/// Third, apply different kinds of local heuristics for each individual +/// branch until first match. For example probability of a pointer to be null is +/// estimated as PH_TAKEN_WEIGHT/(PH_TAKEN_WEIGHT + PH_NONTAKEN_WEIGHT). If +/// no local heuristic has been matched then branch is left with no explicit +/// probability set and assumed to have default probability. class BranchProbabilityInfo { public: BranchProbabilityInfo() = default; BranchProbabilityInfo(const Function &F, const LoopInfo &LI, const TargetLibraryInfo *TLI = nullptr, + DominatorTree *DT = nullptr, PostDominatorTree *PDT = nullptr) { - calculate(F, LI, TLI, PDT); + calculate(F, LI, TLI, DT, PDT); } BranchProbabilityInfo(BranchProbabilityInfo &&Arg) : Probs(std::move(Arg.Probs)), LastF(Arg.LastF), - PostDominatedByUnreachable(std::move(Arg.PostDominatedByUnreachable)), - PostDominatedByColdCall(std::move(Arg.PostDominatedByColdCall)) {} + EstimatedBlockWeight(std::move(Arg.EstimatedBlockWeight)) {} BranchProbabilityInfo(const BranchProbabilityInfo &) = delete; BranchProbabilityInfo &operator=(const BranchProbabilityInfo &) = delete; @@ -71,8 +133,7 @@ public: BranchProbabilityInfo &operator=(BranchProbabilityInfo &&RHS) { releaseMemory(); Probs = std::move(RHS.Probs); - PostDominatedByColdCall = std::move(RHS.PostDominatedByColdCall); - PostDominatedByUnreachable = std::move(RHS.PostDominatedByUnreachable); + EstimatedBlockWeight = std::move(RHS.EstimatedBlockWeight); return *this; } @@ -121,16 +182,6 @@ public: raw_ostream &printEdgeProbability(raw_ostream &OS, const BasicBlock *Src, const BasicBlock *Dst) const; -protected: - /// Set the raw edge probability for the given edge. - /// - /// This allows a pass to explicitly set the edge probability for an edge. It - /// can be used when updating the CFG to update and preserve the branch - /// probability information. Read the implementation of how these edge - /// probabilities are calculated carefully before using! - void setEdgeProbability(const BasicBlock *Src, unsigned IndexInSuccessors, - BranchProbability Prob); - public: /// Set the raw probabilities for all edges from the given block. /// @@ -140,24 +191,85 @@ public: void setEdgeProbability(const BasicBlock *Src, const SmallVectorImpl &Probs); + /// Copy outgoing edge probabilities from \p Src to \p Dst. + /// + /// This allows to keep probabilities unset for the destination if they were + /// unset for source. + void copyEdgeProbabilities(BasicBlock *Src, BasicBlock *Dst); + static BranchProbability getBranchProbStackProtector(bool IsLikely) { static const BranchProbability LikelyProb((1u << 20) - 1, 1u << 20); return IsLikely ? LikelyProb : LikelyProb.getCompl(); } void calculate(const Function &F, const LoopInfo &LI, - const TargetLibraryInfo *TLI, PostDominatorTree *PDT); + const TargetLibraryInfo *TLI, DominatorTree *DT, + PostDominatorTree *PDT); /// Forget analysis results for the given basic block. void eraseBlock(const BasicBlock *BB); - // Use to track SCCs for handling irreducible loops. - using SccMap = DenseMap; - using SccHeaderMap = DenseMap; - using SccHeaderMaps = std::vector; - struct SccInfo { + // Data structure to track SCCs for handling irreducible loops. + class SccInfo { + // Enum of types to classify basic blocks in SCC. Basic block belonging to + // SCC is 'Inner' until it is either 'Header' or 'Exiting'. Note that a + // basic block can be 'Header' and 'Exiting' at the same time. + enum SccBlockType { + Inner = 0x0, + Header = 0x1, + Exiting = 0x2, + }; + // Map of basic blocks to SCC IDs they belong to. If basic block doesn't + // belong to any SCC it is not in the map. + using SccMap = DenseMap; + // Each basic block in SCC is attributed with one or several types from + // SccBlockType. Map value has uint32_t type (instead of SccBlockType) + // since basic block may be for example "Header" and "Exiting" at the same + // time and we need to be able to keep more than one value from + // SccBlockType. + using SccBlockTypeMap = DenseMap; + // Vector containing classification of basic blocks for all SCCs where i'th + // vector element corresponds to SCC with ID equal to i. + using SccBlockTypeMaps = std::vector; + SccMap SccNums; - SccHeaderMaps SccHeaders; + SccBlockTypeMaps SccBlocks; + + public: + explicit SccInfo(const Function &F); + + /// If \p BB belongs to some SCC then ID of that SCC is returned, otherwise + /// -1 is returned. If \p BB belongs to more than one SCC at the same time + /// result is undefined. + int getSCCNum(const BasicBlock *BB) const; + /// Returns true if \p BB is a 'header' block in SCC with \p SccNum ID, + /// false otherwise. + bool isSCCHeader(const BasicBlock *BB, int SccNum) const { + return getSccBlockType(BB, SccNum) & Header; + } + /// Returns true if \p BB is an 'exiting' block in SCC with \p SccNum ID, + /// false otherwise. + bool isSCCExitingBlock(const BasicBlock *BB, int SccNum) const { + return getSccBlockType(BB, SccNum) & Exiting; + } + /// Fills in \p Enters vector with all such blocks that don't belong to + /// SCC with \p SccNum ID but there is an edge to a block belonging to the + /// SCC. + void getSccEnterBlocks(int SccNum, + SmallVectorImpl &Enters) const; + /// Fills in \p Exits vector with all such blocks that don't belong to + /// SCC with \p SccNum ID but there is an edge from a block belonging to the + /// SCC. + void getSccExitBlocks(int SccNum, + SmallVectorImpl &Exits) const; + + private: + /// Returns \p BB's type according to classification given by SccBlockType + /// enum. Please note that \p BB must belong to SSC with \p SccNum ID. + uint32_t getSccBlockType(const BasicBlock *BB, int SccNum) const; + /// Calculates \p BB's type and stores it in internal data structures for + /// future use. Please note that \p BB must belong to SSC with \p SccNum ID. + void calculateSccBlockType(const BasicBlock *BB, int SccNum); }; private: @@ -169,7 +281,6 @@ private: void deleted() override { assert(BPI != nullptr); BPI->eraseBlock(cast(getValPtr())); - BPI->Handles.erase(*this); } public: @@ -177,44 +288,132 @@ private: : CallbackVH(const_cast(V)), BPI(BPI) {} }; + /// Pair of Loop and SCC ID number. Used to unify handling of normal and + /// SCC based loop representations. + using LoopData = std::pair; + /// Helper class to keep basic block along with its loop data information. + class LoopBlock { + public: + explicit LoopBlock(const BasicBlock *BB, const LoopInfo &LI, + const SccInfo &SccI); + + const BasicBlock *getBlock() const { return BB; } + BasicBlock *getBlock() { return const_cast(BB); } + LoopData getLoopData() const { return LD; } + Loop *getLoop() const { return LD.first; } + int getSccNum() const { return LD.second; } + + bool belongsToLoop() const { return getLoop() || getSccNum() != -1; } + bool belongsToSameLoop(const LoopBlock &LB) const { + return (LB.getLoop() && getLoop() == LB.getLoop()) || + (LB.getSccNum() != -1 && getSccNum() == LB.getSccNum()); + } + + private: + const BasicBlock *const BB = nullptr; + LoopData LD = {nullptr, -1}; + }; + + // Pair of LoopBlocks representing an edge from first to second block. + using LoopEdge = std::pair; + DenseSet> Handles; // Since we allow duplicate edges from one basic block to another, we use // a pair (PredBlock and an index in the successors) to specify an edge. using Edge = std::pair; - // Default weight value. Used when we don't have information about the edge. - // TODO: DEFAULT_WEIGHT makes sense during static predication, when none of - // the successors have a weight yet. But it doesn't make sense when providing - // weight to an edge that may have siblings with non-zero weights. This can - // be handled various ways, but it's probably fine for an edge with unknown - // weight to just "inherit" the non-zero weight of an adjacent successor. - static const uint32_t DEFAULT_WEIGHT = 16; - DenseMap Probs; /// Track the last function we run over for printing. const Function *LastF = nullptr; - /// Track the set of blocks directly succeeded by a returning block. - SmallPtrSet PostDominatedByUnreachable; + const LoopInfo *LI = nullptr; + + /// Keeps information about all SCCs in a function. + std::unique_ptr SccI; - /// Track the set of blocks that always lead to a cold call. - SmallPtrSet PostDominatedByColdCall; + /// Keeps mapping of a basic block to its estimated weight. + SmallDenseMap EstimatedBlockWeight; + + /// Keeps mapping of a loop to estimated weight to enter the loop. + SmallDenseMap EstimatedLoopWeight; + + /// Helper to construct LoopBlock for \p BB. + LoopBlock getLoopBlock(const BasicBlock *BB) const { + return LoopBlock(BB, *LI, *SccI.get()); + } - void computePostDominatedByUnreachable(const Function &F, - PostDominatorTree *PDT); - void computePostDominatedByColdCall(const Function &F, - PostDominatorTree *PDT); - bool calcUnreachableHeuristics(const BasicBlock *BB); + /// Returns true if destination block belongs to some loop and source block is + /// either doesn't belong to any loop or belongs to a loop which is not inner + /// relative to the destination block. + bool isLoopEnteringEdge(const LoopEdge &Edge) const; + /// Returns true if source block belongs to some loop and destination block is + /// either doesn't belong to any loop or belongs to a loop which is not inner + /// relative to the source block. + bool isLoopExitingEdge(const LoopEdge &Edge) const; + /// Returns true if \p Edge is either enters to or exits from some loop, false + /// in all other cases. + bool isLoopEnteringExitingEdge(const LoopEdge &Edge) const; + /// Returns true if source and destination blocks belongs to the same loop and + /// destination block is loop header. + bool isLoopBackEdge(const LoopEdge &Edge) const; + // Fills in \p Enters vector with all "enter" blocks to a loop \LB belongs to. + void getLoopEnterBlocks(const LoopBlock &LB, + SmallVectorImpl &Enters) const; + // Fills in \p Exits vector with all "exit" blocks from a loop \LB belongs to. + void getLoopExitBlocks(const LoopBlock &LB, + SmallVectorImpl &Exits) const; + + /// Returns estimated weight for \p BB. None if \p BB has no estimated weight. + Optional getEstimatedBlockWeight(const BasicBlock *BB) const; + + /// Returns estimated weight to enter \p L. In other words it is weight of + /// loop's header block not scaled by trip count. Returns None if \p L has no + /// no estimated weight. + Optional getEstimatedLoopWeight(const LoopData &L) const; + + /// Return estimated weight for \p Edge. Returns None if estimated weight is + /// unknown. + Optional getEstimatedEdgeWeight(const LoopEdge &Edge) const; + + /// Iterates over all edges leading from \p SrcBB to \p Successors and + /// returns maximum of all estimated weights. If at least one edge has unknown + /// estimated weight None is returned. + template + Optional + getMaxEstimatedEdgeWeight(const LoopBlock &SrcBB, + iterator_range Successors) const; + + /// If \p LoopBB has no estimated weight then set it to \p BBWeight and + /// return true. Otherwise \p BB's weight remains unchanged and false is + /// returned. In addition all blocks/loops that might need their weight to be + /// re-estimated are put into BlockWorkList/LoopWorkList. + bool updateEstimatedBlockWeight(LoopBlock &LoopBB, uint32_t BBWeight, + SmallVectorImpl &BlockWorkList, + SmallVectorImpl &LoopWorkList); + + /// Starting from \p LoopBB (including \p LoopBB itself) propagate \p BBWeight + /// up the domination tree. + void propagateEstimatedBlockWeight(const LoopBlock &LoopBB, DominatorTree *DT, + PostDominatorTree *PDT, uint32_t BBWeight, + SmallVectorImpl &WorkList, + SmallVectorImpl &LoopWorkList); + + /// Returns block's weight encoded in the IR. + Optional getInitialEstimatedBlockWeight(const BasicBlock *BB); + + // Computes estimated weights for all blocks in \p F. + void computeEestimateBlockWeight(const Function &F, DominatorTree *DT, + PostDominatorTree *PDT); + + /// Based on computed weights by \p computeEstimatedBlockWeight set + /// probabilities on branches. + bool calcEstimatedHeuristics(const BasicBlock *BB); bool calcMetadataWeights(const BasicBlock *BB); - bool calcColdCallHeuristics(const BasicBlock *BB); bool calcPointerHeuristics(const BasicBlock *BB); - bool calcLoopBranchHeuristics(const BasicBlock *BB, const LoopInfo &LI, - SccInfo &SccI); bool calcZeroHeuristics(const BasicBlock *BB, const TargetLibraryInfo *TLI); bool calcFloatingPointHeuristics(const BasicBlock *BB); - bool calcInvokeHeuristics(const BasicBlock *BB); }; /// Analysis pass which computes \c BranchProbabilityInfo. diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/CFGPrinter.h b/contrib/llvm-project/llvm/include/llvm/Analysis/CFGPrinter.h index c4e49ce493ea..53700798b6b3 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/CFGPrinter.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/CFGPrinter.h @@ -18,6 +18,7 @@ #ifndef LLVM_ANALYSIS_CFGPRINTER_H #define LLVM_ANALYSIS_CFGPRINTER_H +#include "llvm/ADT/STLExtras.h" #include "llvm/Analysis/BlockFrequencyInfo.h" #include "llvm/Analysis/BranchProbabilityInfo.h" #include "llvm/Analysis/HeatUtils.h" @@ -141,8 +142,18 @@ struct DOTGraphTraits : public DefaultDOTGraphTraits { return OS.str(); } - static std::string getCompleteNodeLabel(const BasicBlock *Node, - DOTFuncInfo *) { + static void eraseComment(std::string &OutStr, unsigned &I, unsigned Idx) { + OutStr.erase(OutStr.begin() + I, OutStr.begin() + Idx); + --I; + } + + static std::string getCompleteNodeLabel( + const BasicBlock *Node, DOTFuncInfo *, + llvm::function_ref + HandleBasicBlock = [](raw_string_ostream &OS, + const BasicBlock &Node) -> void { OS << Node; }, + llvm::function_ref + HandleComment = eraseComment) { enum { MaxColumns = 80 }; std::string Str; raw_string_ostream OS(Str); @@ -152,7 +163,7 @@ struct DOTGraphTraits : public DefaultDOTGraphTraits { OS << ":"; } - OS << *Node; + HandleBasicBlock(OS, *Node); std::string OutStr = OS.str(); if (OutStr[0] == '\n') OutStr.erase(OutStr.begin()); @@ -168,8 +179,7 @@ struct DOTGraphTraits : public DefaultDOTGraphTraits { LastSpace = 0; } else if (OutStr[i] == ';') { // Delete comments! unsigned Idx = OutStr.find('\n', i + 1); // Find end of line - OutStr.erase(OutStr.begin() + i, OutStr.begin() + Idx); - --i; + HandleComment(OutStr, i, Idx); } else if (ColNum == MaxColumns) { // Wrap lines. // Wrap very long names even though we can't find a space. if (!LastSpace) @@ -285,7 +295,7 @@ struct DOTGraphTraits : public DefaultDOTGraphTraits { " fillcolor=\"" + Color + "70\""; return Attrs; } - bool isNodeHidden(const BasicBlock *Node); + bool isNodeHidden(const BasicBlock *Node, const DOTFuncInfo *CFGInfo); void computeHiddenNodes(const Function *F); }; } // End llvm namespace diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/CGSCCPassManager.h b/contrib/llvm-project/llvm/include/llvm/Analysis/CGSCCPassManager.h index eb0d3ae8fedf..985424a74054 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/CGSCCPassManager.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/CGSCCPassManager.h @@ -90,6 +90,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/PriorityWorklist.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" @@ -314,6 +315,16 @@ struct CGSCCUpdateResult { /// for a better technique. SmallDenseSet, 4> &InlinedInternalEdges; + + /// Weak VHs to keep track of indirect calls for the purposes of detecting + /// devirtualization. + /// + /// This is a map to avoid having duplicate entries. If a Value is + /// deallocated, its corresponding WeakTrackingVH will be nulled out. When + /// checking if a Value is in the map or not, also check if the corresponding + /// WeakTrackingVH is null to avoid issues with a new Value sharing the same + /// address as a deallocated one. + SmallMapVector IndirectVHs; }; /// The core module pass which does a post-order walk of the SCCs and @@ -325,18 +336,15 @@ struct CGSCCUpdateResult { /// \c CGSCCAnalysisManagerModuleProxy analysis prior to running the CGSCC /// pass over the module to enable a \c FunctionAnalysisManager to be used /// within this run safely. -template class ModuleToPostOrderCGSCCPassAdaptor - : public PassInfoMixin> { + : public PassInfoMixin { public: - explicit ModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass) - : Pass(std::move(Pass)) {} + using PassConceptT = + detail::PassConcept; - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - ModuleToPostOrderCGSCCPassAdaptor( - const ModuleToPostOrderCGSCCPassAdaptor &Arg) - : Pass(Arg.Pass) {} + explicit ModuleToPostOrderCGSCCPassAdaptor(std::unique_ptr Pass) + : Pass(std::move(Pass)) {} ModuleToPostOrderCGSCCPassAdaptor(ModuleToPostOrderCGSCCPassAdaptor &&Arg) : Pass(std::move(Arg.Pass)) {} @@ -355,16 +363,22 @@ public: /// Runs the CGSCC pass across every SCC in the module. PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); + static bool isRequired() { return true; } + private: - CGSCCPassT Pass; + std::unique_ptr Pass; }; /// A function to deduce a function pass type and wrap it in the /// templated adaptor. template -ModuleToPostOrderCGSCCPassAdaptor +ModuleToPostOrderCGSCCPassAdaptor createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass) { - return ModuleToPostOrderCGSCCPassAdaptor(std::move(Pass)); + using PassModelT = detail::PassModel; + return ModuleToPostOrderCGSCCPassAdaptor( + std::make_unique(std::move(Pass))); } /// A proxy from a \c FunctionAnalysisManager to an \c SCC. @@ -442,17 +456,13 @@ LazyCallGraph::SCC &updateCGAndAnalysisManagerForCGSCCPass( /// \c FunctionAnalysisManagerCGSCCProxy analysis prior to running the function /// pass over the SCC to enable a \c FunctionAnalysisManager to be used /// within this run safely. -template class CGSCCToFunctionPassAdaptor - : public PassInfoMixin> { + : public PassInfoMixin { public: - explicit CGSCCToFunctionPassAdaptor(FunctionPassT Pass) - : Pass(std::move(Pass)) {} + using PassConceptT = detail::PassConcept; - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - CGSCCToFunctionPassAdaptor(const CGSCCToFunctionPassAdaptor &Arg) - : Pass(Arg.Pass) {} + explicit CGSCCToFunctionPassAdaptor(std::unique_ptr Pass) + : Pass(std::move(Pass)) {} CGSCCToFunctionPassAdaptor(CGSCCToFunctionPassAdaptor &&Arg) : Pass(std::move(Arg.Pass)) {} @@ -469,90 +479,24 @@ public: /// Runs the function pass across every function in the module. PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, - LazyCallGraph &CG, CGSCCUpdateResult &UR) { - // Setup the function analysis manager from its proxy. - FunctionAnalysisManager &FAM = - AM.getResult(C, CG).getManager(); - - SmallVector Nodes; - for (LazyCallGraph::Node &N : C) - Nodes.push_back(&N); - - // The SCC may get split while we are optimizing functions due to deleting - // edges. If this happens, the current SCC can shift, so keep track of - // a pointer we can overwrite. - LazyCallGraph::SCC *CurrentC = &C; - - LLVM_DEBUG(dbgs() << "Running function passes across an SCC: " << C - << "\n"); - - PreservedAnalyses PA = PreservedAnalyses::all(); - for (LazyCallGraph::Node *N : Nodes) { - // Skip nodes from other SCCs. These may have been split out during - // processing. We'll eventually visit those SCCs and pick up the nodes - // there. - if (CG.lookupSCC(*N) != CurrentC) - continue; - - Function &F = N->getFunction(); - - PassInstrumentation PI = FAM.getResult(F); - if (!PI.runBeforePass(Pass, F)) - continue; - - PreservedAnalyses PassPA; - { - TimeTraceScope TimeScope(Pass.name()); - PassPA = Pass.run(F, FAM); - } - - PI.runAfterPass(Pass, F); - - // We know that the function pass couldn't have invalidated any other - // function's analyses (that's the contract of a function pass), so - // directly handle the function analysis manager's invalidation here. - FAM.invalidate(F, PassPA); - - // Then intersect the preserved set so that invalidation of module - // analyses will eventually occur when the module pass completes. - PA.intersect(std::move(PassPA)); - - // If the call graph hasn't been preserved, update it based on this - // function pass. This may also update the current SCC to point to - // a smaller, more refined SCC. - auto PAC = PA.getChecker(); - if (!PAC.preserved() && !PAC.preservedSet>()) { - CurrentC = &updateCGAndAnalysisManagerForFunctionPass(CG, *CurrentC, *N, - AM, UR, FAM); - assert( - CG.lookupSCC(*N) == CurrentC && - "Current SCC not updated to the SCC containing the current node!"); - } - } + LazyCallGraph &CG, CGSCCUpdateResult &UR); - // By definition we preserve the proxy. And we preserve all analyses on - // Functions. This precludes *any* invalidation of function analyses by the - // proxy, but that's OK because we've taken care to invalidate analyses in - // the function analysis manager incrementally above. - PA.preserveSet>(); - PA.preserve(); - - // We've also ensured that we updated the call graph along the way. - PA.preserve(); - - return PA; - } + static bool isRequired() { return true; } private: - FunctionPassT Pass; + std::unique_ptr Pass; }; /// A function to deduce a function pass type and wrap it in the /// templated adaptor. template -CGSCCToFunctionPassAdaptor +CGSCCToFunctionPassAdaptor createCGSCCToFunctionPassAdaptor(FunctionPassT Pass) { - return CGSCCToFunctionPassAdaptor(std::move(Pass)); + using PassModelT = + detail::PassModel; + return CGSCCToFunctionPassAdaptor( + std::make_unique(std::move(Pass))); } /// A helper that repeats an SCC pass each time an indirect call is refined to @@ -569,410 +513,36 @@ createCGSCCToFunctionPassAdaptor(FunctionPassT Pass) { /// This repetition has the potential to be very large however, as each one /// might refine a single call site. As a consequence, in practice we use an /// upper bound on the number of repetitions to limit things. -template -class DevirtSCCRepeatedPass - : public PassInfoMixin> { +class DevirtSCCRepeatedPass : public PassInfoMixin { public: - explicit DevirtSCCRepeatedPass(PassT Pass, int MaxIterations) + using PassConceptT = + detail::PassConcept; + + explicit DevirtSCCRepeatedPass(std::unique_ptr Pass, + int MaxIterations) : Pass(std::move(Pass)), MaxIterations(MaxIterations) {} /// Runs the wrapped pass up to \c MaxIterations on the SCC, iterating /// whenever an indirect call is refined. PreservedAnalyses run(LazyCallGraph::SCC &InitialC, CGSCCAnalysisManager &AM, - LazyCallGraph &CG, CGSCCUpdateResult &UR) { - PreservedAnalyses PA = PreservedAnalyses::all(); - PassInstrumentation PI = - AM.getResult(InitialC, CG); - - // The SCC may be refined while we are running passes over it, so set up - // a pointer that we can update. - LazyCallGraph::SCC *C = &InitialC; - - // Collect value handles for all of the indirect call sites. - SmallVector CallHandles; - - // Struct to track the counts of direct and indirect calls in each function - // of the SCC. - struct CallCount { - int Direct; - int Indirect; - }; - - // Put value handles on all of the indirect calls and return the number of - // direct calls for each function in the SCC. - auto ScanSCC = [](LazyCallGraph::SCC &C, - SmallVectorImpl &CallHandles) { - assert(CallHandles.empty() && "Must start with a clear set of handles."); - - SmallDenseMap CallCounts; - CallCount CountLocal = {0, 0}; - for (LazyCallGraph::Node &N : C) { - CallCount &Count = - CallCounts.insert(std::make_pair(&N.getFunction(), CountLocal)) - .first->second; - for (Instruction &I : instructions(N.getFunction())) - if (auto *CB = dyn_cast(&I)) { - if (CB->getCalledFunction()) { - ++Count.Direct; - } else { - ++Count.Indirect; - CallHandles.push_back(WeakTrackingVH(&I)); - } - } - } - - return CallCounts; - }; - - // Populate the initial call handles and get the initial call counts. - auto CallCounts = ScanSCC(*C, CallHandles); - - for (int Iteration = 0;; ++Iteration) { - - if (!PI.runBeforePass(Pass, *C)) - continue; - - PreservedAnalyses PassPA = Pass.run(*C, AM, CG, UR); - - if (UR.InvalidatedSCCs.count(C)) - PI.runAfterPassInvalidated(Pass); - else - PI.runAfterPass(Pass, *C); - - // If the SCC structure has changed, bail immediately and let the outer - // CGSCC layer handle any iteration to reflect the refined structure. - if (UR.UpdatedC && UR.UpdatedC != C) { - PA.intersect(std::move(PassPA)); - break; - } - - // Check that we didn't miss any update scenario. - assert(!UR.InvalidatedSCCs.count(C) && "Processing an invalid SCC!"); - assert(C->begin() != C->end() && "Cannot have an empty SCC!"); - - // Check whether any of the handles were devirtualized. - auto IsDevirtualizedHandle = [&](WeakTrackingVH &CallH) { - if (!CallH) - return false; - auto *CB = dyn_cast(CallH); - if (!CB) - return false; - - // If the call is still indirect, leave it alone. - Function *F = CB->getCalledFunction(); - if (!F) - return false; - - LLVM_DEBUG(dbgs() << "Found devirtualized call from " - << CB->getParent()->getParent()->getName() << " to " - << F->getName() << "\n"); - - // We now have a direct call where previously we had an indirect call, - // so iterate to process this devirtualization site. - return true; - }; - bool Devirt = llvm::any_of(CallHandles, IsDevirtualizedHandle); - - // Rescan to build up a new set of handles and count how many direct - // calls remain. If we decide to iterate, this also sets up the input to - // the next iteration. - CallHandles.clear(); - auto NewCallCounts = ScanSCC(*C, CallHandles); - - // If we haven't found an explicit devirtualization already see if we - // have decreased the number of indirect calls and increased the number - // of direct calls for any function in the SCC. This can be fooled by all - // manner of transformations such as DCE and other things, but seems to - // work well in practice. - if (!Devirt) - // Iterate over the keys in NewCallCounts, if Function also exists in - // CallCounts, make the check below. - for (auto &Pair : NewCallCounts) { - auto &CallCountNew = Pair.second; - auto CountIt = CallCounts.find(Pair.first); - if (CountIt != CallCounts.end()) { - const auto &CallCountOld = CountIt->second; - if (CallCountOld.Indirect > CallCountNew.Indirect && - CallCountOld.Direct < CallCountNew.Direct) { - Devirt = true; - break; - } - } - } - - if (!Devirt) { - PA.intersect(std::move(PassPA)); - break; - } - - // Otherwise, if we've already hit our max, we're done. - if (Iteration >= MaxIterations) { - LLVM_DEBUG( - dbgs() << "Found another devirtualization after hitting the max " - "number of repetitions (" - << MaxIterations << ") on SCC: " << *C << "\n"); - PA.intersect(std::move(PassPA)); - break; - } - - LLVM_DEBUG( - dbgs() - << "Repeating an SCC pass after finding a devirtualization in: " << *C - << "\n"); - - // Move over the new call counts in preparation for iterating. - CallCounts = std::move(NewCallCounts); - - // Update the analysis manager with each run and intersect the total set - // of preserved analyses so we're ready to iterate. - AM.invalidate(*C, PassPA); - - PA.intersect(std::move(PassPA)); - } - - // Note that we don't add any preserved entries here unlike a more normal - // "pass manager" because we only handle invalidation *between* iterations, - // not after the last iteration. - return PA; - } + LazyCallGraph &CG, CGSCCUpdateResult &UR); private: - PassT Pass; + std::unique_ptr Pass; int MaxIterations; }; /// A function to deduce a function pass type and wrap it in the /// templated adaptor. -template -DevirtSCCRepeatedPass createDevirtSCCRepeatedPass(PassT Pass, - int MaxIterations) { - return DevirtSCCRepeatedPass(std::move(Pass), MaxIterations); -} - -// Out-of-line implementation details for templates below this point. - template -PreservedAnalyses -ModuleToPostOrderCGSCCPassAdaptor::run(Module &M, - ModuleAnalysisManager &AM) { - // Setup the CGSCC analysis manager from its proxy. - CGSCCAnalysisManager &CGAM = - AM.getResult(M).getManager(); - - // Get the call graph for this module. - LazyCallGraph &CG = AM.getResult(M); - - // Get Function analysis manager from its proxy. - FunctionAnalysisManager &FAM = - AM.getCachedResult(M)->getManager(); - - // We keep worklists to allow us to push more work onto the pass manager as - // the passes are run. - SmallPriorityWorklist RCWorklist; - SmallPriorityWorklist CWorklist; - - // Keep sets for invalidated SCCs and RefSCCs that should be skipped when - // iterating off the worklists. - SmallPtrSet InvalidRefSCCSet; - SmallPtrSet InvalidSCCSet; - - SmallDenseSet, 4> - InlinedInternalEdges; - - CGSCCUpdateResult UR = { - RCWorklist, CWorklist, InvalidRefSCCSet, InvalidSCCSet, - nullptr, nullptr, PreservedAnalyses::all(), InlinedInternalEdges}; - - // Request PassInstrumentation from analysis manager, will use it to run - // instrumenting callbacks for the passes later. - PassInstrumentation PI = AM.getResult(M); - - PreservedAnalyses PA = PreservedAnalyses::all(); - CG.buildRefSCCs(); - for (auto RCI = CG.postorder_ref_scc_begin(), - RCE = CG.postorder_ref_scc_end(); - RCI != RCE;) { - assert(RCWorklist.empty() && - "Should always start with an empty RefSCC worklist"); - // The postorder_ref_sccs range we are walking is lazily constructed, so - // we only push the first one onto the worklist. The worklist allows us - // to capture *new* RefSCCs created during transformations. - // - // We really want to form RefSCCs lazily because that makes them cheaper - // to update as the program is simplified and allows us to have greater - // cache locality as forming a RefSCC touches all the parts of all the - // functions within that RefSCC. - // - // We also eagerly increment the iterator to the next position because - // the CGSCC passes below may delete the current RefSCC. - RCWorklist.insert(&*RCI++); - - do { - LazyCallGraph::RefSCC *RC = RCWorklist.pop_back_val(); - if (InvalidRefSCCSet.count(RC)) { - LLVM_DEBUG(dbgs() << "Skipping an invalid RefSCC...\n"); - continue; - } - - assert(CWorklist.empty() && - "Should always start with an empty SCC worklist"); - - LLVM_DEBUG(dbgs() << "Running an SCC pass across the RefSCC: " << *RC - << "\n"); - - // The top of the worklist may *also* be the same SCC we just ran over - // (and invalidated for). Keep track of that last SCC we processed due - // to SCC update to avoid redundant processing when an SCC is both just - // updated itself and at the top of the worklist. - LazyCallGraph::SCC *LastUpdatedC = nullptr; - - // Push the initial SCCs in reverse post-order as we'll pop off the - // back and so see this in post-order. - for (LazyCallGraph::SCC &C : llvm::reverse(*RC)) - CWorklist.insert(&C); - - do { - LazyCallGraph::SCC *C = CWorklist.pop_back_val(); - // Due to call graph mutations, we may have invalid SCCs or SCCs from - // other RefSCCs in the worklist. The invalid ones are dead and the - // other RefSCCs should be queued above, so we just need to skip both - // scenarios here. - if (InvalidSCCSet.count(C)) { - LLVM_DEBUG(dbgs() << "Skipping an invalid SCC...\n"); - continue; - } - if (LastUpdatedC == C) { - LLVM_DEBUG(dbgs() << "Skipping redundant run on SCC: " << *C << "\n"); - continue; - } - if (&C->getOuterRefSCC() != RC) { - LLVM_DEBUG(dbgs() << "Skipping an SCC that is now part of some other " - "RefSCC...\n"); - continue; - } - - // Ensure we can proxy analysis updates from the CGSCC analysis manager - // into the the Function analysis manager by getting a proxy here. - // This also needs to update the FunctionAnalysisManager, as this may be - // the first time we see this SCC. - CGAM.getResult(*C, CG).updateFAM( - FAM); - - // Each time we visit a new SCC pulled off the worklist, - // a transformation of a child SCC may have also modified this parent - // and invalidated analyses. So we invalidate using the update record's - // cross-SCC preserved set. This preserved set is intersected by any - // CGSCC pass that handles invalidation (primarily pass managers) prior - // to marking its SCC as preserved. That lets us track everything that - // might need invalidation across SCCs without excessive invalidations - // on a single SCC. - // - // This essentially allows SCC passes to freely invalidate analyses - // of any ancestor SCC. If this becomes detrimental to successfully - // caching analyses, we could force each SCC pass to manually - // invalidate the analyses for any SCCs other than themselves which - // are mutated. However, that seems to lose the robustness of the - // pass-manager driven invalidation scheme. - CGAM.invalidate(*C, UR.CrossSCCPA); - - do { - // Check that we didn't miss any update scenario. - assert(!InvalidSCCSet.count(C) && "Processing an invalid SCC!"); - assert(C->begin() != C->end() && "Cannot have an empty SCC!"); - assert(&C->getOuterRefSCC() == RC && - "Processing an SCC in a different RefSCC!"); - - LastUpdatedC = UR.UpdatedC; - UR.UpdatedRC = nullptr; - UR.UpdatedC = nullptr; - - // Check the PassInstrumentation's BeforePass callbacks before - // running the pass, skip its execution completely if asked to - // (callback returns false). - if (!PI.runBeforePass(Pass, *C)) - continue; - - PreservedAnalyses PassPA; - { - TimeTraceScope TimeScope(Pass.name()); - PassPA = Pass.run(*C, CGAM, CG, UR); - } - - if (UR.InvalidatedSCCs.count(C)) - PI.runAfterPassInvalidated(Pass); - else - PI.runAfterPass(Pass, *C); - - // Update the SCC and RefSCC if necessary. - C = UR.UpdatedC ? UR.UpdatedC : C; - RC = UR.UpdatedRC ? UR.UpdatedRC : RC; - - if (UR.UpdatedC) { - // If we're updating the SCC, also update the FAM inside the proxy's - // result. - CGAM.getResult(*C, CG).updateFAM( - FAM); - } - - // If the CGSCC pass wasn't able to provide a valid updated SCC, - // the current SCC may simply need to be skipped if invalid. - if (UR.InvalidatedSCCs.count(C)) { - LLVM_DEBUG(dbgs() << "Skipping invalidated root or island SCC!\n"); - break; - } - // Check that we didn't miss any update scenario. - assert(C->begin() != C->end() && "Cannot have an empty SCC!"); - - // We handle invalidating the CGSCC analysis manager's information - // for the (potentially updated) SCC here. Note that any other SCCs - // whose structure has changed should have been invalidated by - // whatever was updating the call graph. This SCC gets invalidated - // late as it contains the nodes that were actively being - // processed. - CGAM.invalidate(*C, PassPA); - - // Then intersect the preserved set so that invalidation of module - // analyses will eventually occur when the module pass completes. - // Also intersect with the cross-SCC preserved set to capture any - // cross-SCC invalidation. - UR.CrossSCCPA.intersect(PassPA); - PA.intersect(std::move(PassPA)); - - // The pass may have restructured the call graph and refined the - // current SCC and/or RefSCC. We need to update our current SCC and - // RefSCC pointers to follow these. Also, when the current SCC is - // refined, re-run the SCC pass over the newly refined SCC in order - // to observe the most precise SCC model available. This inherently - // cannot cycle excessively as it only happens when we split SCCs - // apart, at most converging on a DAG of single nodes. - // FIXME: If we ever start having RefSCC passes, we'll want to - // iterate there too. - if (UR.UpdatedC) - LLVM_DEBUG(dbgs() - << "Re-running SCC passes after a refinement of the " - "current SCC: " - << *UR.UpdatedC << "\n"); - - // Note that both `C` and `RC` may at this point refer to deleted, - // invalid SCC and RefSCCs respectively. But we will short circuit - // the processing when we check them in the loop above. - } while (UR.UpdatedC); - } while (!CWorklist.empty()); - - // We only need to keep internal inlined edge information within - // a RefSCC, clear it to save on space and let the next time we visit - // any of these functions have a fresh start. - InlinedInternalEdges.clear(); - } while (!RCWorklist.empty()); - } - - // By definition we preserve the call garph, all SCC analyses, and the - // analysis proxies by handling them above and in any nested pass managers. - PA.preserveSet>(); - PA.preserve(); - PA.preserve(); - PA.preserve(); - return PA; +DevirtSCCRepeatedPass createDevirtSCCRepeatedPass(CGSCCPassT Pass, + int MaxIterations) { + using PassModelT = detail::PassModel; + return DevirtSCCRepeatedPass(std::make_unique(std::move(Pass)), + MaxIterations); } // Clear out the debug logging macro. diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/CallGraph.h b/contrib/llvm-project/llvm/include/llvm/Analysis/CallGraph.h index 98f9b0683fd4..4da448c9900b 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/CallGraph.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/CallGraph.h @@ -87,13 +87,6 @@ class CallGraph { /// or calling an external function. std::unique_ptr CallsExternalNode; - /// Replace the function represented by this node by another. - /// - /// This does not rescan the body of the function, so it is suitable when - /// splicing the body of one function to another while also updating all - /// callers from the old function to the new. - void spliceFunction(const Function *From, const Function *To); - public: explicit CallGraph(Module &M); CallGraph(CallGraph &&Arg); diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/CaptureTracking.h b/contrib/llvm-project/llvm/include/llvm/Analysis/CaptureTracking.h index e68675b278f1..9da5f18e944b 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/CaptureTracking.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/CaptureTracking.h @@ -13,6 +13,8 @@ #ifndef LLVM_ANALYSIS_CAPTURETRACKING_H #define LLVM_ANALYSIS_CAPTURETRACKING_H +#include "llvm/ADT/DenseMap.h" + namespace llvm { class Value; @@ -94,6 +96,12 @@ namespace llvm { /// is zero, a default value is assumed. void PointerMayBeCaptured(const Value *V, CaptureTracker *Tracker, unsigned MaxUsesToExplore = 0); + + /// Returns true if the pointer is to a function-local object that never + /// escapes from the function. + bool isNonEscapingLocalObject( + const Value *V, + SmallDenseMap *IsCapturedCache = nullptr); } // end namespace llvm #endif diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/CodeMetrics.h b/contrib/llvm-project/llvm/include/llvm/Analysis/CodeMetrics.h index eab24c8ab179..615591aa83ad 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/CodeMetrics.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/CodeMetrics.h @@ -75,7 +75,8 @@ struct CodeMetrics { /// Add information about a block to the current state. void analyzeBasicBlock(const BasicBlock *BB, const TargetTransformInfo &TTI, - const SmallPtrSetImpl &EphValues); + const SmallPtrSetImpl &EphValues, + bool PrepareForLTO = false); /// Collect a loop's ephemeral values (those used only by an assume /// or similar intrinsics in the loop). diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/ConstantFolding.h b/contrib/llvm-project/llvm/include/llvm/Analysis/ConstantFolding.h index 0ccc782ad6f5..ef6e66b2b88e 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/ConstantFolding.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/ConstantFolding.h @@ -25,6 +25,7 @@ template class ArrayRef; class CallBase; class Constant; class ConstantExpr; +class DSOLocalEquivalent; class DataLayout; class Function; class GlobalValue; @@ -34,8 +35,11 @@ class Type; /// If this constant is a constant offset from a global, return the global and /// the constant. Because of constantexprs, this function is recursive. +/// If the global is part of a dso_local_equivalent constant, return it through +/// `Equiv` if it is provided. bool IsConstantOffsetFromGlobal(Constant *C, GlobalValue *&GV, APInt &Offset, - const DataLayout &DL); + const DataLayout &DL, + DSOLocalEquivalent **DSOEquiv = nullptr); /// ConstantFoldInstruction - Try to constant fold the specified instruction. /// If successful, the constant result is returned, if not, null is returned. diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/ConstraintSystem.h b/contrib/llvm-project/llvm/include/llvm/Analysis/ConstraintSystem.h new file mode 100644 index 000000000000..83c1fb4485fd --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/ConstraintSystem.h @@ -0,0 +1,88 @@ +//===- ConstraintSystem.h - A system of linear constraints. --------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CONSTRAINTSYSTEM_H +#define LLVM_ANALYSIS_CONSTRAINTSYSTEM_H + +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" + +#include + +namespace llvm { + +class ConstraintSystem { + /// Current linear constraints in the system. + /// An entry of the form c0, c1, ... cn represents the following constraint: + /// c0 >= v0 * c1 + .... + v{n-1} * cn + SmallVector, 4> Constraints; + + /// Current greatest common divisor for all coefficients in the system. + uint32_t GCD = 1; + + // Eliminate constraints from the system using Fourier–Motzkin elimination. + bool eliminateUsingFM(); + + /// Print the constraints in the system, using \p Names as variable names. + void dump(ArrayRef Names) const; + + /// Print the constraints in the system, using x0...xn as variable names. + void dump() const; + + /// Returns true if there may be a solution for the constraints in the system. + bool mayHaveSolutionImpl(); + +public: + bool addVariableRow(const SmallVector &R) { + assert(Constraints.empty() || R.size() == Constraints.back().size()); + // If all variable coefficients are 0, the constraint does not provide any + // usable information. + if (all_of(makeArrayRef(R).drop_front(1), [](int64_t C) { return C == 0; })) + return false; + + for (const auto &C : R) { + auto A = std::abs(C); + GCD = APIntOps::GreatestCommonDivisor({32, (uint32_t)A}, {32, GCD}) + .getZExtValue(); + } + Constraints.push_back(R); + return true; + } + + bool addVariableRowFill(const SmallVector &R) { + for (auto &CR : Constraints) { + while (CR.size() != R.size()) + CR.push_back(0); + } + return addVariableRow(R); + } + + /// Returns true if there may be a solution for the constraints in the system. + bool mayHaveSolution(); + + static SmallVector negate(SmallVector R) { + // The negated constraint R is obtained by multiplying by -1 and adding 1 to + // the constant. + R[0] += 1; + for (auto &C : R) + C *= -1; + return R; + } + + bool isConditionImplied(SmallVector R); + + void popLastConstraint() { Constraints.pop_back(); } + + /// Returns the number of rows in the constraint system. + unsigned size() const { return Constraints.size(); } +}; +} // namespace llvm + +#endif // LLVM_ANALYSIS_CONSTRAINTSYSTEM_H diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/DDG.h b/contrib/llvm-project/llvm/include/llvm/Analysis/DDG.h index 9e2b7907eaec..e3bef33e55c3 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/DDG.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/DDG.h @@ -152,7 +152,7 @@ private: setKind((InstList.size() == 0 && Input.size() == 1) ? NodeKind::SingleInstruction : NodeKind::MultiInstruction); - InstList.insert(InstList.end(), Input.begin(), Input.end()); + llvm::append_range(InstList, Input); } void appendInstructions(const SimpleDDGNode &Input) { appendInstructions(Input.getInstructions()); @@ -290,6 +290,12 @@ public: bool getDependencies(const NodeType &Src, const NodeType &Dst, DependenceList &Deps) const; + /// Return a string representing the type of dependence that the dependence + /// analysis identified between the two given nodes. This function assumes + /// that there is a memory dependence between the given two nodes. + const std::string getDependenceString(const NodeType &Src, + const NodeType &Dst) const; + protected: // Name of the graph. std::string Name; @@ -463,6 +469,26 @@ bool DependenceGraphInfo::getDependencies( return !Deps.empty(); } +template +const std::string +DependenceGraphInfo::getDependenceString(const NodeType &Src, + const NodeType &Dst) const { + std::string Str; + raw_string_ostream OS(Str); + DependenceList Deps; + if (!getDependencies(Src, Dst, Deps)) + return OS.str(); + interleaveComma(Deps, OS, [&](const std::unique_ptr &D) { + D->dump(OS); + // Remove the extra new-line character printed by the dump + // method + if (OS.str().back() == '\n') + OS.str().pop_back(); + }); + + return OS.str(); +} + //===--------------------------------------------------------------------===// // GraphTraits specializations for the DDG //===--------------------------------------------------------------------===// diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/DDGPrinter.h b/contrib/llvm-project/llvm/include/llvm/Analysis/DDGPrinter.h new file mode 100644 index 000000000000..4477b387fe50 --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/DDGPrinter.h @@ -0,0 +1,91 @@ +//===- llvm/Analysis/DDGPrinter.h -------------------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// +// This file defines the DOT printer for the Data-Dependence Graph (DDG). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_DDGPRINTER_H +#define LLVM_ANALYSIS_DDGPRINTER_H + +#include "llvm/Analysis/DDG.h" +#include "llvm/Pass.h" +#include "llvm/Support/DOTGraphTraits.h" + +namespace llvm { + +//===--------------------------------------------------------------------===// +// Implementation of DDG DOT Printer for a loop. +//===--------------------------------------------------------------------===// +class DDGDotPrinterPass : public PassInfoMixin { +public: + PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, + LoopStandardAnalysisResults &AR, LPMUpdater &U); +}; + +//===--------------------------------------------------------------------===// +// Specialization of DOTGraphTraits. +//===--------------------------------------------------------------------===// +template <> +struct DOTGraphTraits + : public DefaultDOTGraphTraits { + + DOTGraphTraits(bool IsSimple = false) : DefaultDOTGraphTraits(IsSimple) {} + + /// Generate a title for the graph in DOT format + std::string getGraphName(const DataDependenceGraph *G) { + assert(G && "expected a valid pointer to the graph."); + return "DDG for '" + std::string(G->getName()) + "'"; + } + + /// Print a DDG node either in concise form (-ddg-dot-only) or + /// verbose mode (-ddg-dot). + std::string getNodeLabel(const DDGNode *Node, + const DataDependenceGraph *Graph); + + /// Print attributes of an edge in the DDG graph. If the edge + /// is a MemoryDependence edge, then detailed dependence info + /// available from DependenceAnalysis is displayed. + std::string + getEdgeAttributes(const DDGNode *Node, + GraphTraits::ChildIteratorType I, + const DataDependenceGraph *G); + + /// Do not print nodes that are part of a pi-block separately. They + /// will be printed when their containing pi-block is being printed. + bool isNodeHidden(const DDGNode *Node, const DataDependenceGraph *G); + +private: + /// Print a DDG node in concise form. + static std::string getSimpleNodeLabel(const DDGNode *Node, + const DataDependenceGraph *G); + + /// Print a DDG node with more information including containing instructions + /// and detailed information about the dependence edges. + static std::string getVerboseNodeLabel(const DDGNode *Node, + const DataDependenceGraph *G); + + /// Print a DDG edge in concise form. + static std::string getSimpleEdgeAttributes(const DDGNode *Src, + const DDGEdge *Edge, + const DataDependenceGraph *G); + + /// Print a DDG edge with more information including detailed information + /// about the dependence edges. + static std::string getVerboseEdgeAttributes(const DDGNode *Src, + const DDGEdge *Edge, + const DataDependenceGraph *G); +}; + +using DDGDotGraphTraits = DOTGraphTraits; + +} // namespace llvm + +#endif // LLVM_ANALYSIS_DDGPRINTER_H diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/Delinearization.h b/contrib/llvm-project/llvm/include/llvm/Analysis/Delinearization.h new file mode 100644 index 000000000000..2658b6bbc80c --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/Delinearization.h @@ -0,0 +1,33 @@ +//===---- Delinearization.h - MultiDimensional Index Delinearization ------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This implements an analysis pass that tries to delinearize all GEP +// instructions in all loops using the SCEV analysis functionality. This pass is +// only used for testing purposes: if your pass needs delinearization, please +// use the on-demand SCEVAddRecExpr::delinearize() function. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_DELINEARIZATION_H +#define LLVM_ANALYSIS_DELINEARIZATION_H + +#include "llvm/IR/PassManager.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { +struct DelinearizationPrinterPass + : public PassInfoMixin { + explicit DelinearizationPrinterPass(raw_ostream &OS); + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); + +private: + raw_ostream &OS; +}; +} // namespace llvm + +#endif // LLVM_ANALYSIS_DELINEARIZATION_H diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/DemandedBits.h b/contrib/llvm-project/llvm/include/llvm/Analysis/DemandedBits.h index 04db3eb57c18..7a8618a27ce7 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/DemandedBits.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/DemandedBits.h @@ -61,6 +61,20 @@ public: void print(raw_ostream &OS); + /// Compute alive bits of one addition operand from alive output and known + /// operand bits + static APInt determineLiveOperandBitsAdd(unsigned OperandNo, + const APInt &AOut, + const KnownBits &LHS, + const KnownBits &RHS); + + /// Compute alive bits of one subtraction operand from alive output and known + /// operand bits + static APInt determineLiveOperandBitsSub(unsigned OperandNo, + const APInt &AOut, + const KnownBits &LHS, + const KnownBits &RHS); + private: void performAnalysis(); void determineLiveOperandBits(const Instruction *UserI, diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/DivergenceAnalysis.h b/contrib/llvm-project/llvm/include/llvm/Analysis/DivergenceAnalysis.h index a2da97bb9059..2e4ae65d0981 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/DivergenceAnalysis.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/DivergenceAnalysis.h @@ -59,8 +59,10 @@ public: /// \brief Mark \p UniVal as a value that is always uniform. void addUniformOverride(const Value &UniVal); - /// \brief Mark \p DivVal as a value that is always divergent. - void markDivergent(const Value &DivVal); + /// \brief Mark \p DivVal as a value that is always divergent. Will not do so + /// if `isAlwaysUniform(DivVal)`. + /// \returns Whether the tracked divergence state of \p DivVal changed. + bool markDivergent(const Value &DivVal); /// \brief Propagate divergence to all instructions in the region. /// Divergence is seeded by calls to \p markDivergent. @@ -76,45 +78,38 @@ public: /// \brief Whether \p Val is divergent at its definition. bool isDivergent(const Value &Val) const; - /// \brief Whether \p U is divergent. Uses of a uniform value can be divergent. + /// \brief Whether \p U is divergent. Uses of a uniform value can be + /// divergent. bool isDivergentUse(const Use &U) const; void print(raw_ostream &OS, const Module *) const; private: - bool updateTerminator(const Instruction &Term) const; - bool updatePHINode(const PHINode &Phi) const; - - /// \brief Computes whether \p Inst is divergent based on the - /// divergence of its operands. - /// - /// \returns Whether \p Inst is divergent. - /// - /// This should only be called for non-phi, non-terminator instructions. - bool updateNormalInstruction(const Instruction &Inst) const; - - /// \brief Mark users of live-out users as divergent. - /// - /// \param LoopHeader the header of the divergent loop. - /// - /// Marks all users of live-out values of the loop headed by \p LoopHeader - /// as divergent and puts them on the worklist. - void taintLoopLiveOuts(const BasicBlock &LoopHeader); - - /// \brief Push all users of \p Val (in the region) to the worklist + /// \brief Mark \p Term as divergent and push all Instructions that become + /// divergent as a result on the worklist. + void analyzeControlDivergence(const Instruction &Term); + /// \brief Mark all phi nodes in \p JoinBlock as divergent and push them on + /// the worklist. + void taintAndPushPhiNodes(const BasicBlock &JoinBlock); + + /// \brief Identify all Instructions that become divergent because \p DivExit + /// is a divergent loop exit of \p DivLoop. Mark those instructions as + /// divergent and push them on the worklist. + void propagateLoopExitDivergence(const BasicBlock &DivExit, + const Loop &DivLoop); + + /// \brief Internal implementation function for propagateLoopExitDivergence. + void analyzeLoopExitDivergence(const BasicBlock &DivExit, + const Loop &OuterDivLoop); + + /// \brief Mark all instruction as divergent that use a value defined in \p + /// OuterDivLoop. Push their users on the worklist. + void analyzeTemporalDivergence(const Instruction &I, + const Loop &OuterDivLoop); + + /// \brief Push all users of \p Val (in the region) to the worklist. void pushUsers(const Value &I); - /// \brief Push all phi nodes in @block to the worklist - void pushPHINodes(const BasicBlock &Block); - - /// \brief Mark \p Block as join divergent - /// - /// A block is join divergent if two threads may reach it from different - /// incoming blocks at the same time. - void markBlockJoinDivergent(const BasicBlock &Block) { - DivergentJoinBlocks.insert(&Block); - } - /// \brief Whether \p Val is divergent when read in \p ObservingBlock. bool isTemporalDivergent(const BasicBlock &ObservingBlock, const Value &Val) const; @@ -123,27 +118,9 @@ private: /// /// (see markBlockJoinDivergent). bool isJoinDivergent(const BasicBlock &Block) const { - return DivergentJoinBlocks.find(&Block) != DivergentJoinBlocks.end(); + return DivergentJoinBlocks.contains(&Block); } - /// \brief Propagate control-induced divergence to users (phi nodes and - /// instructions). - // - // \param JoinBlock is a divergent loop exit or join point of two disjoint - // paths. - // \returns Whether \p JoinBlock is a divergent loop exit of \p TermLoop. - bool propagateJoinDivergence(const BasicBlock &JoinBlock, - const Loop *TermLoop); - - /// \brief Propagate induced value divergence due to control divergence in \p - /// Term. - void propagateBranchDivergence(const Instruction &Term); - - /// \brief Propagate divergent caused by a divergent loop exit. - /// - /// \param ExitingLoop is a divergent loop. - void propagateLoopDivergence(const Loop &ExitingLoop); - private: const Function &F; // If regionLoop != nullptr, analysis is only performed within \p RegionLoop. @@ -166,7 +143,7 @@ private: DenseSet UniformOverrides; // Blocks with joining divergent control from different predecessors. - DenseSet DivergentJoinBlocks; + DenseSet DivergentJoinBlocks; // FIXME Deprecated // Detected/marked divergent values. DenseSet DivergentValues; diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/DominanceFrontier.h b/contrib/llvm-project/llvm/include/llvm/Analysis/DominanceFrontier.h index f67929c997f9..cef5e03b3b7a 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/DominanceFrontier.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/DominanceFrontier.h @@ -26,7 +26,6 @@ #include #include #include -#include namespace llvm { diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/EHPersonalities.h b/contrib/llvm-project/llvm/include/llvm/Analysis/EHPersonalities.h index c17b0b4a90d3..eaada6627494 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/EHPersonalities.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/EHPersonalities.h @@ -28,11 +28,12 @@ enum class EHPersonality { GNU_CXX_SjLj, GNU_ObjC, MSVC_X86SEH, - MSVC_Win64SEH, + MSVC_TableSEH, MSVC_CXX, CoreCLR, Rust, - Wasm_CXX + Wasm_CXX, + XL_CXX }; /// See if the given exception handling personality function is one @@ -51,7 +52,7 @@ inline bool isAsynchronousEHPersonality(EHPersonality Pers) { // unknown personalities don't catch asynch exceptions. switch (Pers) { case EHPersonality::MSVC_X86SEH: - case EHPersonality::MSVC_Win64SEH: + case EHPersonality::MSVC_TableSEH: return true; default: return false; @@ -65,7 +66,7 @@ inline bool isFuncletEHPersonality(EHPersonality Pers) { switch (Pers) { case EHPersonality::MSVC_CXX: case EHPersonality::MSVC_X86SEH: - case EHPersonality::MSVC_Win64SEH: + case EHPersonality::MSVC_TableSEH: case EHPersonality::CoreCLR: return true; default: @@ -80,7 +81,7 @@ inline bool isScopedEHPersonality(EHPersonality Pers) { switch (Pers) { case EHPersonality::MSVC_CXX: case EHPersonality::MSVC_X86SEH: - case EHPersonality::MSVC_Win64SEH: + case EHPersonality::MSVC_TableSEH: case EHPersonality::CoreCLR: case EHPersonality::Wasm_CXX: return true; diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/FunctionPropertiesAnalysis.h b/contrib/llvm-project/llvm/include/llvm/Analysis/FunctionPropertiesAnalysis.h new file mode 100644 index 000000000000..a5f96e72ce97 --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/FunctionPropertiesAnalysis.h @@ -0,0 +1,86 @@ +//=- FunctionPropertiesAnalysis.h - Function Properties Analysis --*- C++ -*-=// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file defines the FunctionPropertiesInfo and FunctionPropertiesAnalysis +// classes used to extract function properties. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUNCTIONPROPERTIESANALYSIS_H_ +#define LLVM_FUNCTIONPROPERTIESANALYSIS_H_ + +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/IR/PassManager.h" + +namespace llvm { +class Function; + +class FunctionPropertiesInfo { +public: + static FunctionPropertiesInfo getFunctionPropertiesInfo(const Function &F, + const LoopInfo &LI); + + void print(raw_ostream &OS) const; + + /// Number of basic blocks + int64_t BasicBlockCount = 0; + + /// Number of blocks reached from a conditional instruction, or that are + /// 'cases' of a SwitchInstr. + // FIXME: We may want to replace this with a more meaningful metric, like + // number of conditionally executed blocks: + // 'if (a) s();' would be counted here as 2 blocks, just like + // 'if (a) s(); else s2(); s3();' would. + int64_t BlocksReachedFromConditionalInstruction = 0; + + /// Number of uses of this function, plus 1 if the function is callable + /// outside the module. + int64_t Uses = 0; + + /// Number of direct calls made from this function to other functions + /// defined in this module. + int64_t DirectCallsToDefinedFunctions = 0; + + // Load Instruction Count + int64_t LoadInstCount = 0; + + // Store Instruction Count + int64_t StoreInstCount = 0; + + // Maximum Loop Depth in the Function + int64_t MaxLoopDepth = 0; + + // Number of Top Level Loops in the Function + int64_t TopLevelLoopCount = 0; +}; + +// Analysis pass +class FunctionPropertiesAnalysis + : public AnalysisInfoMixin { + +public: + static AnalysisKey Key; + + using Result = FunctionPropertiesInfo; + + Result run(Function &F, FunctionAnalysisManager &FAM); +}; + +/// Printer pass for the FunctionPropertiesAnalysis results. +class FunctionPropertiesPrinterPass + : public PassInfoMixin { + raw_ostream &OS; + +public: + explicit FunctionPropertiesPrinterPass(raw_ostream &OS) : OS(OS) {} + + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + +} // namespace llvm +#endif // LLVM_FUNCTIONPROPERTIESANALYSIS_H_ diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/IRSimilarityIdentifier.h b/contrib/llvm-project/llvm/include/llvm/Analysis/IRSimilarityIdentifier.h new file mode 100644 index 000000000000..9e97541e542b --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/IRSimilarityIdentifier.h @@ -0,0 +1,789 @@ +//===- IRSimilarityIdentifier.h - Find similarity in a module --------------==// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// \file +// Interface file for the IRSimilarityIdentifier for identifying similarities in +// IR including the IRInstructionMapper, which maps an Instruction to unsigned +// integers. +// +// Two sequences of instructions are called "similar" if they perform the same +// series of operations for all inputs. +// +// \code +// %1 = add i32 %a, 10 +// %2 = add i32 %a, %1 +// %3 = icmp slt icmp %1, %2 +// \endcode +// +// and +// +// \code +// %1 = add i32 11, %a +// %2 = sub i32 %a, %1 +// %3 = icmp sgt icmp %2, %1 +// \endcode +// +// ultimately have the same result, even if the inputs, and structure are +// slightly different. +// +// For instructions, we do not worry about operands that do not have fixed +// semantic meaning to the program. We consider the opcode that the instruction +// has, the types, parameters, and extra information such as the function name, +// or comparison predicate. These are used to create a hash to map instructions +// to integers to be used in similarity matching in sequences of instructions +// +// Terminology: +// An IRSimilarityCandidate is a region of IRInstructionData (wrapped +// Instructions), usually used to denote a region of similarity has been found. +// +// A SimilarityGroup is a set of IRSimilarityCandidates that are structurally +// similar to one another. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_IRSIMILARITYIDENTIFIER_H +#define LLVM_ANALYSIS_IRSIMILARITYIDENTIFIER_H + +#include "llvm/IR/InstVisitor.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Pass.h" +#include "llvm/Support/Allocator.h" + +namespace llvm { +namespace IRSimilarity { + +struct IRInstructionDataList; + +/// This represents what is and is not supported when finding similarity in +/// Instructions. +/// +/// Legal Instructions are considered when looking at similarity between +/// Instructions. +/// +/// Illegal Instructions cannot be considered when looking for similarity +/// between Instructions. They act as boundaries between similarity regions. +/// +/// Invisible Instructions are skipped over during analysis. +// TODO: Shared with MachineOutliner +enum InstrType { Legal, Illegal, Invisible }; + +/// This provides the utilities for hashing an Instruction to an unsigned +/// integer. Two IRInstructionDatas produce the same hash value when their +/// underlying Instructions perform the same operation (even if they don't have +/// the same input operands.) +/// As a more concrete example, consider the following: +/// +/// \code +/// %add1 = add i32 %a, %b +/// %add2 = add i32 %c, %d +/// %add3 = add i64 %e, %f +/// \endcode +/// +// Then the IRInstructionData wrappers for these Instructions may be hashed like +/// so: +/// +/// \code +/// ; These two adds have the same types and operand types, so they hash to the +/// ; same number. +/// %add1 = add i32 %a, %b ; Hash: 1 +/// %add2 = add i32 %c, %d ; Hash: 1 +/// ; This add produces an i64. This differentiates it from %add1 and %add2. So, +/// ; it hashes to a different number. +/// %add3 = add i64 %e, %f; Hash: 2 +/// \endcode +/// +/// +/// This hashing scheme will be used to represent the program as a very long +/// string. This string can then be placed in a data structure which can be used +/// for similarity queries. +/// +/// TODO: Handle types of Instructions which can be equal even with different +/// operands. (E.g. comparisons with swapped predicates.) +/// TODO: Handle CallInsts, which are only checked for function type +/// by \ref isSameOperationAs. +/// TODO: Handle GetElementPtrInsts, as some of the operands have to be the +/// exact same, and some do not. +struct IRInstructionData : ilist_node { + + /// The source Instruction that is being wrapped. + Instruction *Inst = nullptr; + /// The values of the operands in the Instruction. + SmallVector OperVals; + /// The legality of the wrapped instruction. This is informed by InstrType, + /// and is used when checking when two instructions are considered similar. + /// If either instruction is not legal, the instructions are automatically not + /// considered similar. + bool Legal; + + /// This is only relevant if we are wrapping a CmpInst where we needed to + /// change the predicate of a compare instruction from a greater than form + /// to a less than form. It is None otherwise. + Optional RevisedPredicate; + + /// Gather the information that is difficult to gather for an Instruction, or + /// is changed. i.e. the operands of an Instruction and the Types of those + /// operands. This extra information allows for similarity matching to make + /// assertions that allow for more flexibility when checking for whether an + /// Instruction performs the same operation. + IRInstructionData(Instruction &I, bool Legality, IRInstructionDataList &IDL); + + /// Get the predicate that the compare instruction is using for hashing the + /// instruction. the IRInstructionData must be wrapping a CmpInst. + CmpInst::Predicate getPredicate() const; + + /// A function that swaps the predicates to their less than form if they are + /// in a greater than form. Otherwise, the predicate is unchanged. + /// + /// \param CI - The comparison operation to find a consistent preidcate for. + /// \return the consistent comparison predicate. + static CmpInst::Predicate predicateForConsistency(CmpInst *CI); + + /// Hashes \p Value based on its opcode, types, and operand types. + /// Two IRInstructionData instances produce the same hash when they perform + /// the same operation. + /// + /// As a simple example, consider the following instructions. + /// + /// \code + /// %add1 = add i32 %x1, %y1 + /// %add2 = add i32 %x2, %y2 + /// + /// %sub = sub i32 %x1, %y1 + /// + /// %add_i64 = add i64 %x2, %y2 + /// \endcode + /// + /// Because the first two adds operate the same types, and are performing the + /// same action, they will be hashed to the same value. + /// + /// However, the subtraction instruction is not the same as an addition, and + /// will be hashed to a different value. + /// + /// Finally, the last add has a different type compared to the first two add + /// instructions, so it will also be hashed to a different value that any of + /// the previous instructions. + /// + /// \param [in] ID - The IRInstructionData instance to be hashed. + /// \returns A hash_value of the IRInstructionData. + friend hash_code hash_value(const IRInstructionData &ID) { + SmallVector OperTypes; + for (Value *V : ID.OperVals) + OperTypes.push_back(V->getType()); + + if (isa(ID.Inst)) + return llvm::hash_combine( + llvm::hash_value(ID.Inst->getOpcode()), + llvm::hash_value(ID.Inst->getType()), + llvm::hash_value(ID.getPredicate()), + llvm::hash_combine_range(OperTypes.begin(), OperTypes.end())); + else if (CallInst *CI = dyn_cast(ID.Inst)) + return llvm::hash_combine( + llvm::hash_value(ID.Inst->getOpcode()), + llvm::hash_value(ID.Inst->getType()), + llvm::hash_value(CI->getCalledFunction()->getName().str()), + llvm::hash_combine_range(OperTypes.begin(), OperTypes.end())); + return llvm::hash_combine( + llvm::hash_value(ID.Inst->getOpcode()), + llvm::hash_value(ID.Inst->getType()), + llvm::hash_combine_range(OperTypes.begin(), OperTypes.end())); + } + + IRInstructionDataList *IDL = nullptr; +}; + +struct IRInstructionDataList : simple_ilist {}; + +/// Compare one IRInstructionData class to another IRInstructionData class for +/// whether they are performing a the same operation, and can mapped to the +/// same value. For regular instructions if the hash value is the same, then +/// they will also be close. +/// +/// \param A - The first IRInstructionData class to compare +/// \param B - The second IRInstructionData class to compare +/// \returns true if \p A and \p B are similar enough to be mapped to the same +/// value. +bool isClose(const IRInstructionData &A, const IRInstructionData &B); + +struct IRInstructionDataTraits : DenseMapInfo { + static inline IRInstructionData *getEmptyKey() { return nullptr; } + static inline IRInstructionData *getTombstoneKey() { + return reinterpret_cast(-1); + } + + static unsigned getHashValue(const IRInstructionData *E) { + using llvm::hash_value; + assert(E && "IRInstructionData is a nullptr?"); + return hash_value(*E); + } + + static bool isEqual(const IRInstructionData *LHS, + const IRInstructionData *RHS) { + if (RHS == getEmptyKey() || RHS == getTombstoneKey() || + LHS == getEmptyKey() || LHS == getTombstoneKey()) + return LHS == RHS; + + assert(LHS && RHS && "nullptr should have been caught by getEmptyKey?"); + return isClose(*LHS, *RHS); + } +}; + +/// Helper struct for converting the Instructions in a Module into a vector of +/// unsigned integers. This vector of unsigned integers can be thought of as a +/// "numeric string". This numeric string can then be queried by, for example, +/// data structures that find repeated substrings. +/// +/// This hashing is done per BasicBlock in the module. To hash Instructions +/// based off of their operations, each Instruction is wrapped in an +/// IRInstructionData struct. The unsigned integer for an IRInstructionData +/// depends on: +/// - The hash provided by the IRInstructionData. +/// - Which member of InstrType the IRInstructionData is classified as. +// See InstrType for more details on the possible classifications, and how they +// manifest in the numeric string. +/// +/// The numeric string for an individual BasicBlock is terminated by an unique +/// unsigned integer. This prevents data structures which rely on repetition +/// from matching across BasicBlocks. (For example, the SuffixTree.) +/// As a concrete example, if we have the following two BasicBlocks: +/// \code +/// bb0: +/// %add1 = add i32 %a, %b +/// %add2 = add i32 %c, %d +/// %add3 = add i64 %e, %f +/// bb1: +/// %sub = sub i32 %c, %d +/// \endcode +/// We may hash the Instructions like this (via IRInstructionData): +/// \code +/// bb0: +/// %add1 = add i32 %a, %b ; Hash: 1 +/// %add2 = add i32 %c, %d; Hash: 1 +/// %add3 = add i64 %e, %f; Hash: 2 +/// bb1: +/// %sub = sub i32 %c, %d; Hash: 3 +/// %add4 = add i32 %c, %d ; Hash: 1 +/// \endcode +/// And produce a "numeric string representation" like so: +/// 1, 1, 2, unique_integer_1, 3, 1, unique_integer_2 +/// +/// TODO: This is very similar to the MachineOutliner, and should be +/// consolidated into the same interface. +struct IRInstructionMapper { + /// The starting illegal instruction number to map to. + /// + /// Set to -3 for compatibility with DenseMapInfo. + unsigned IllegalInstrNumber = static_cast(-3); + + /// The next available integer to assign to a legal Instruction to. + unsigned LegalInstrNumber = 0; + + /// Correspondence from IRInstructionData to unsigned integers. + DenseMap + InstructionIntegerMap; + + /// Set if we added an illegal number in the previous step. + /// Since each illegal number is unique, we only need one of them between + /// each range of legal numbers. This lets us make sure we don't add more + /// than one illegal number per range. + bool AddedIllegalLastTime = false; + + /// Marks whether we found a illegal instruction in the previous step. + bool CanCombineWithPrevInstr = false; + + /// Marks whether we have found a set of instructions that is long enough + /// to be considered for similarity. + bool HaveLegalRange = false; + + /// This allocator pointer is in charge of holding on to the IRInstructionData + /// so it is not deallocated until whatever external tool is using it is done + /// with the information. + SpecificBumpPtrAllocator *InstDataAllocator = nullptr; + + /// This allocator pointer is in charge of creating the IRInstructionDataList + /// so it is not deallocated until whatever external tool is using it is done + /// with the information. + SpecificBumpPtrAllocator *IDLAllocator = nullptr; + + /// Get an allocated IRInstructionData struct using the InstDataAllocator. + /// + /// \param I - The Instruction to wrap with IRInstructionData. + /// \param Legality - A boolean value that is true if the instruction is to + /// be considered for similarity, and false if not. + /// \param IDL - The InstructionDataList that the IRInstructionData is + /// inserted into. + /// \returns An allocated IRInstructionData struct. + IRInstructionData *allocateIRInstructionData(Instruction &I, bool Legality, + IRInstructionDataList &IDL); + + /// Get an allocated IRInstructionDataList object using the IDLAllocator. + /// + /// \returns An allocated IRInstructionDataList object. + IRInstructionDataList *allocateIRInstructionDataList(); + + IRInstructionDataList *IDL = nullptr; + + /// Maps the Instructions in a BasicBlock \p BB to legal or illegal integers + /// determined by \p InstrType. Two Instructions are mapped to the same value + /// if they are close as defined by the InstructionData class above. + /// + /// \param [in] BB - The BasicBlock to be mapped to integers. + /// \param [in,out] InstrList - Vector of IRInstructionData to append to. + /// \param [in,out] IntegerMapping - Vector of unsigned integers to append to. + void convertToUnsignedVec(BasicBlock &BB, + std::vector &InstrList, + std::vector &IntegerMapping); + + /// Maps an Instruction to a legal integer. + /// + /// \param [in] It - The Instruction to be mapped to an integer. + /// \param [in,out] IntegerMappingForBB - Vector of unsigned integers to + /// append to. + /// \param [in,out] InstrListForBB - Vector of InstructionData to append to. + /// \returns The integer \p It was mapped to. + unsigned mapToLegalUnsigned(BasicBlock::iterator &It, + std::vector &IntegerMappingForBB, + std::vector &InstrListForBB); + + /// Maps an Instruction to an illegal integer. + /// + /// \param [in] It - The \p Instruction to be mapped to an integer. + /// \param [in,out] IntegerMappingForBB - Vector of unsigned integers to + /// append to. + /// \param [in,out] InstrListForBB - Vector of IRInstructionData to append to. + /// \param End - true if creating a dummy IRInstructionData at the end of a + /// basic block. + /// \returns The integer \p It was mapped to. + unsigned mapToIllegalUnsigned( + BasicBlock::iterator &It, std::vector &IntegerMappingForBB, + std::vector &InstrListForBB, bool End = false); + + IRInstructionMapper(SpecificBumpPtrAllocator *IDA, + SpecificBumpPtrAllocator *IDLA) + : InstDataAllocator(IDA), IDLAllocator(IDLA) { + // Make sure that the implementation of DenseMapInfo hasn't + // changed. + assert(DenseMapInfo::getEmptyKey() == static_cast(-1) && + "DenseMapInfo's empty key isn't -1!"); + assert(DenseMapInfo::getTombstoneKey() == + static_cast(-2) && + "DenseMapInfo's tombstone key isn't -2!"); + + IDL = new (IDLAllocator->Allocate()) + IRInstructionDataList(); + } + + /// Custom InstVisitor to classify different instructions for whether it can + /// be analyzed for similarity. + struct InstructionClassification + : public InstVisitor { + InstructionClassification() {} + + // TODO: Determine a scheme to resolve when the label is similar enough. + InstrType visitBranchInst(BranchInst &BI) { return Illegal; } + // TODO: Determine a scheme to resolve when the labels are similar enough. + InstrType visitPHINode(PHINode &PN) { return Illegal; } + // TODO: Handle allocas. + InstrType visitAllocaInst(AllocaInst &AI) { return Illegal; } + // We exclude variable argument instructions since variable arguments + // requires extra checking of the argument list. + InstrType visitVAArgInst(VAArgInst &VI) { return Illegal; } + // We exclude all exception handling cases since they are so context + // dependent. + InstrType visitLandingPadInst(LandingPadInst &LPI) { return Illegal; } + InstrType visitFuncletPadInst(FuncletPadInst &FPI) { return Illegal; } + // DebugInfo should be included in the regions, but should not be + // analyzed for similarity as it has no bearing on the outcome of the + // program. + InstrType visitDbgInfoIntrinsic(DbgInfoIntrinsic &DII) { return Invisible; } + // TODO: Handle specific intrinsics. + InstrType visitIntrinsicInst(IntrinsicInst &II) { return Illegal; } + // We only allow call instructions where the function has a name and + // is not an indirect call. + InstrType visitCallInst(CallInst &CI) { + Function *F = CI.getCalledFunction(); + if (!F || CI.isIndirectCall() || !F->hasName()) + return Illegal; + return Legal; + } + // TODO: We do not current handle similarity that changes the control flow. + InstrType visitInvokeInst(InvokeInst &II) { return Illegal; } + // TODO: We do not current handle similarity that changes the control flow. + InstrType visitCallBrInst(CallBrInst &CBI) { return Illegal; } + // TODO: Handle interblock similarity. + InstrType visitTerminator(Instruction &I) { return Illegal; } + InstrType visitInstruction(Instruction &I) { return Legal; } + }; + + /// Maps an Instruction to a member of InstrType. + InstructionClassification InstClassifier; +}; + +/// This is a class that wraps a range of IRInstructionData from one point to +/// another in the vector of IRInstructionData, which is a region of the +/// program. It is also responsible for defining the structure within this +/// region of instructions. +/// +/// The structure of a region is defined through a value numbering system +/// assigned to each unique value in a region at the creation of the +/// IRSimilarityCandidate. +/// +/// For example, for each Instruction we add a mapping for each new +/// value seen in that Instruction. +/// IR: Mapping Added: +/// %add1 = add i32 %a, c1 %add1 -> 3, %a -> 1, c1 -> 2 +/// %add2 = add i32 %a, %1 %add2 -> 4 +/// %add3 = add i32 c2, c1 %add3 -> 6, c2 -> 5 +/// +/// We can compare IRSimilarityCandidates against one another. +/// The \ref isSimilar function compares each IRInstructionData against one +/// another and if we have the same sequences of IRInstructionData that would +/// create the same hash, we have similar IRSimilarityCandidates. +/// +/// We can also compare the structure of IRSimilarityCandidates. If we can +/// create a mapping of registers in the region contained by one +/// IRSimilarityCandidate to the region contained by different +/// IRSimilarityCandidate, they can be considered structurally similar. +/// +/// IRSimilarityCandidate1: IRSimilarityCandidate2: +/// %add1 = add i32 %a, %b %add1 = add i32 %d, %e +/// %add2 = add i32 %a, %c %add2 = add i32 %d, %f +/// %add3 = add i32 c1, c2 %add3 = add i32 c3, c4 +/// +/// Can have the following mapping from candidate to candidate of: +/// %a -> %d, %b -> %e, %c -> %f, c1 -> c3, c2 -> c4 +/// and can be considered similar. +/// +/// IRSimilarityCandidate1: IRSimilarityCandidate2: +/// %add1 = add i32 %a, %b %add1 = add i32 %d, c4 +/// %add2 = add i32 %a, %c %add2 = add i32 %d, %f +/// %add3 = add i32 c1, c2 %add3 = add i32 c3, c4 +/// +/// We cannot create the same mapping since the use of c4 is not used in the +/// same way as %b or c2. +class IRSimilarityCandidate { +private: + /// The start index of this IRSimilarityCandidate in the instruction list. + unsigned StartIdx = 0; + + /// The number of instructions in this IRSimilarityCandidate. + unsigned Len = 0; + + /// The first instruction in this IRSimilarityCandidate. + IRInstructionData *FirstInst = nullptr; + + /// The last instruction in this IRSimilarityCandidate. + IRInstructionData *LastInst = nullptr; + + /// Global Value Numbering structures + /// @{ + /// Stores the mapping of the value to the number assigned to it in the + /// IRSimilarityCandidate. + DenseMap ValueToNumber; + /// Stores the mapping of the number to the value assigned this number. + DenseMap NumberToValue; + /// @} + +public: + /// \param StartIdx - The starting location of the region. + /// \param Len - The length of the region. + /// \param FirstInstIt - The starting IRInstructionData of the region. + /// \param LastInstIt - The ending IRInstructionData of the region. + IRSimilarityCandidate(unsigned StartIdx, unsigned Len, + IRInstructionData *FirstInstIt, + IRInstructionData *LastInstIt); + + /// \param A - The first IRInstructionCandidate to compare. + /// \param B - The second IRInstructionCandidate to compare. + /// \returns True when every IRInstructionData in \p A is similar to every + /// IRInstructionData in \p B. + static bool isSimilar(const IRSimilarityCandidate &A, + const IRSimilarityCandidate &B); + + /// \param A - The first IRInstructionCandidate to compare. + /// \param B - The second IRInstructionCandidate to compare. + /// \returns True when every IRInstructionData in \p A is structurally similar + /// to \p B. + static bool compareStructure(const IRSimilarityCandidate &A, + const IRSimilarityCandidate &B); + + struct OperandMapping { + /// The IRSimilarityCandidate that holds the instruction the OperVals were + /// pulled from. + const IRSimilarityCandidate &IRSC; + + /// The operand values to be analyzed. + ArrayRef &OperVals; + + /// The current mapping of global value numbers from one IRSimilarityCandidate + /// to another IRSimilarityCandidate. + DenseMap> &ValueNumberMapping; + }; + + /// Compare the operands in \p A and \p B and check that the current mapping + /// of global value numbers from \p A to \p B and \p B to \A is consistent. + /// + /// \param A - The first IRInstructionCandidate, operand values, and current + /// operand mappings to compare. + /// \param B - The second IRInstructionCandidate, operand values, and current + /// operand mappings to compare. + /// \returns true if the IRSimilarityCandidates operands are compatible. + static bool compareNonCommutativeOperandMapping(OperandMapping A, + OperandMapping B); + + /// Compare the operands in \p A and \p B and check that the current mapping + /// of global value numbers from \p A to \p B and \p B to \A is consistent + /// given that the operands are commutative. + /// + /// \param A - The first IRInstructionCandidate, operand values, and current + /// operand mappings to compare. + /// \param B - The second IRInstructionCandidate, operand values, and current + /// operand mappings to compare. + /// \returns true if the IRSimilarityCandidates operands are compatible. + static bool compareCommutativeOperandMapping(OperandMapping A, + OperandMapping B); + + /// Compare the start and end indices of the two IRSimilarityCandidates for + /// whether they overlap. If the start instruction of one + /// IRSimilarityCandidate is less than the end instruction of the other, and + /// the start instruction of one is greater than the start instruction of the + /// other, they overlap. + /// + /// \returns true if the IRSimilarityCandidates do not have overlapping + /// instructions. + static bool overlap(const IRSimilarityCandidate &A, + const IRSimilarityCandidate &B); + + /// \returns the number of instructions in this Candidate. + unsigned getLength() const { return Len; } + + /// \returns the start index of this IRSimilarityCandidate. + unsigned getStartIdx() const { return StartIdx; } + + /// \returns the end index of this IRSimilarityCandidate. + unsigned getEndIdx() const { return StartIdx + Len - 1; } + + /// \returns The first IRInstructionData. + IRInstructionData *front() const { return FirstInst; } + /// \returns The last IRInstructionData. + IRInstructionData *back() const { return LastInst; } + + /// \returns The first Instruction. + Instruction *frontInstruction() { return FirstInst->Inst; } + /// \returns The last Instruction + Instruction *backInstruction() { return LastInst->Inst; } + + /// \returns The BasicBlock the IRSimilarityCandidate starts in. + BasicBlock *getStartBB() { return FirstInst->Inst->getParent(); } + /// \returns The BasicBlock the IRSimilarityCandidate ends in. + BasicBlock *getEndBB() { return LastInst->Inst->getParent(); } + + /// \returns The Function that the IRSimilarityCandidate is located in. + Function *getFunction() { return getStartBB()->getParent(); } + + /// Finds the positive number associated with \p V if it has been mapped. + /// \param [in] V - the Value to find. + /// \returns The positive number corresponding to the value. + /// \returns None if not present. + Optional getGVN(Value *V) { + assert(V != nullptr && "Value is a nullptr?"); + DenseMap::iterator VNIt = ValueToNumber.find(V); + if (VNIt == ValueToNumber.end()) + return None; + return VNIt->second; + } + + /// Finds the Value associate with \p Num if it exists. + /// \param [in] Num - the number to find. + /// \returns The Value associated with the number. + /// \returns None if not present. + Optional fromGVN(unsigned Num) { + DenseMap::iterator VNIt = NumberToValue.find(Num); + if (VNIt == NumberToValue.end()) + return None; + assert(VNIt->second != nullptr && "Found value is a nullptr!"); + return VNIt->second; + } + + /// \param RHS -The IRSimilarityCandidate to compare against + /// \returns true if the IRSimilarityCandidate is occurs after the + /// IRSimilarityCandidate in the program. + bool operator<(const IRSimilarityCandidate &RHS) const { + return getStartIdx() > RHS.getStartIdx(); + } + + using iterator = IRInstructionDataList::iterator; + iterator begin() const { return iterator(front()); } + iterator end() const { return std::next(iterator(back())); } +}; + +typedef std::vector SimilarityGroup; +typedef std::vector SimilarityGroupList; + +/// This class puts all the pieces of the IRInstructionData, +/// IRInstructionMapper, IRSimilarityCandidate together. +/// +/// It first feeds the Module or vector of Modules into the IRInstructionMapper, +/// and puts all the mapped instructions into a single long list of +/// IRInstructionData. +/// +/// The list of unsigned integers is given to the Suffix Tree or similar data +/// structure to find repeated subsequences. We construct an +/// IRSimilarityCandidate for each instance of the subsequence. We compare them +/// against one another since These repeated subsequences can have different +/// structure. For each different kind of structure found, we create a +/// similarity group. +/// +/// If we had four IRSimilarityCandidates A, B, C, and D where A, B and D are +/// structurally similar to one another, while C is different we would have two +/// SimilarityGroups: +/// +/// SimilarityGroup 1: SimilarityGroup 2 +/// A, B, D C +/// +/// A list of the different similarity groups is then returned after +/// analyzing the module. +class IRSimilarityIdentifier { +public: + IRSimilarityIdentifier() + : Mapper(&InstDataAllocator, &InstDataListAllocator) {} + + /// \param M the module to find similarity in. + explicit IRSimilarityIdentifier(Module &M) + : Mapper(&InstDataAllocator, &InstDataListAllocator) { + findSimilarity(M); + } + +private: + /// Map the instructions in the module to unsigned integers, using mapping + /// already present in the Mapper if possible. + /// + /// \param [in] M Module - To map to integers. + /// \param [in,out] InstrList - The vector to append IRInstructionData to. + /// \param [in,out] IntegerMapping - The vector to append integers to. + void populateMapper(Module &M, std::vector &InstrList, + std::vector &IntegerMapping); + + /// Map the instructions in the modules vector to unsigned integers, using + /// mapping already present in the mapper if possible. + /// + /// \param [in] Modules - The list of modules to use to populate the mapper + /// \param [in,out] InstrList - The vector to append IRInstructionData to. + /// \param [in,out] IntegerMapping - The vector to append integers to. + void populateMapper(ArrayRef> &Modules, + std::vector &InstrList, + std::vector &IntegerMapping); + + /// Find the similarity candidates in \p InstrList and corresponding + /// \p UnsignedVec + /// + /// \param [in,out] InstrList - The vector to append IRInstructionData to. + /// \param [in,out] IntegerMapping - The vector to append integers to. + /// candidates found in the program. + void findCandidates(std::vector &InstrList, + std::vector &IntegerMapping); + +public: + // Find the IRSimilarityCandidates in the \p Modules and group by structural + // similarity in a SimilarityGroup, each group is returned in a + // SimilarityGroupList. + // + // \param [in] Modules - the modules to analyze. + // \returns The groups of similarity ranges found in the modules. + SimilarityGroupList & + findSimilarity(ArrayRef> Modules); + + // Find the IRSimilarityCandidates in the given Module grouped by structural + // similarity in a SimilarityGroup, contained inside a SimilarityGroupList. + // + // \param [in] M - the module to analyze. + // \returns The groups of similarity ranges found in the module. + SimilarityGroupList &findSimilarity(Module &M); + + // Clears \ref SimilarityCandidates if it is already filled by a previous run. + void resetSimilarityCandidates() { + // If we've already analyzed a Module or set of Modules, so we must clear + // the SimilarityCandidates to make sure we do not have only old values + // hanging around. + if (SimilarityCandidates.hasValue()) + SimilarityCandidates->clear(); + else + SimilarityCandidates = SimilarityGroupList(); + } + + // \returns The groups of similarity ranges found in the most recently passed + // set of modules. + Optional &getSimilarity() { + return SimilarityCandidates; + } + +private: + /// The allocator for IRInstructionData. + SpecificBumpPtrAllocator InstDataAllocator; + + /// The allocator for IRInstructionDataLists. + SpecificBumpPtrAllocator InstDataListAllocator; + + /// Map Instructions to unsigned integers and wraps the Instruction in an + /// instance of IRInstructionData. + IRInstructionMapper Mapper; + + /// The SimilarityGroups found with the most recent run of \ref + /// findSimilarity. None if there is no recent run. + Optional SimilarityCandidates; +}; + +} // end namespace IRSimilarity + +/// An analysis pass based on legacy pass manager that runs and returns +/// IRSimilarityIdentifier run on the Module. +class IRSimilarityIdentifierWrapperPass : public ModulePass { + std::unique_ptr IRSI; + +public: + static char ID; + IRSimilarityIdentifierWrapperPass(); + + IRSimilarity::IRSimilarityIdentifier &getIRSI() { return *IRSI; } + const IRSimilarity::IRSimilarityIdentifier &getIRSI() const { return *IRSI; } + + bool doInitialization(Module &M) override; + bool doFinalization(Module &M) override; + bool runOnModule(Module &M) override; + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + } +}; + +/// An analysis pass that runs and returns the IRSimilarityIdentifier run on the +/// Module. +class IRSimilarityAnalysis : public AnalysisInfoMixin { +public: + typedef IRSimilarity::IRSimilarityIdentifier Result; + + Result run(Module &M, ModuleAnalysisManager &); + +private: + friend AnalysisInfoMixin; + static AnalysisKey Key; +}; + +/// Printer pass that uses \c IRSimilarityAnalysis. +class IRSimilarityAnalysisPrinterPass + : public PassInfoMixin { + raw_ostream &OS; + +public: + explicit IRSimilarityAnalysisPrinterPass(raw_ostream &OS) : OS(OS) {} + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); +}; + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_IRSIMILARITYIDENTIFIER_H diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/IVDescriptors.h b/contrib/llvm-project/llvm/include/llvm/Analysis/IVDescriptors.h index 1bae83d13c7a..28546110ba04 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/IVDescriptors.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/IVDescriptors.h @@ -32,7 +32,24 @@ class PredicatedScalarEvolution; class ScalarEvolution; class SCEV; class DominatorTree; -class ICFLoopSafetyInfo; + +/// These are the kinds of recurrences that we support. +enum class RecurKind { + None, ///< Not a recurrence. + Add, ///< Sum of integers. + Mul, ///< Product of integers. + Or, ///< Bitwise or logical OR of integers. + And, ///< Bitwise or logical AND of integers. + Xor, ///< Bitwise or logical XOR of integers. + SMin, ///< Signed integer min implemented in terms of select(cmp()). + SMax, ///< Signed integer max implemented in terms of select(cmp()). + UMin, ///< Unisgned integer min implemented in terms of select(cmp()). + UMax, ///< Unsigned integer max implemented in terms of select(cmp()). + FAdd, ///< Sum of floats. + FMul, ///< Product of floats. + FMin, ///< FP min implemented in terms of select(cmp()). + FMax ///< FP max implemented in terms of select(cmp()). +}; /// The RecurrenceDescriptor is used to identify recurrences variables in a /// loop. Reduction is a special case of recurrence that has uses of the @@ -48,40 +65,13 @@ class ICFLoopSafetyInfo; /// This struct holds information about recurrence variables. class RecurrenceDescriptor { public: - /// This enum represents the kinds of recurrences that we support. - enum RecurrenceKind { - RK_NoRecurrence, ///< Not a recurrence. - RK_IntegerAdd, ///< Sum of integers. - RK_IntegerMult, ///< Product of integers. - RK_IntegerOr, ///< Bitwise or logical OR of numbers. - RK_IntegerAnd, ///< Bitwise or logical AND of numbers. - RK_IntegerXor, ///< Bitwise or logical XOR of numbers. - RK_IntegerMinMax, ///< Min/max implemented in terms of select(cmp()). - RK_FloatAdd, ///< Sum of floats. - RK_FloatMult, ///< Product of floats. - RK_FloatMinMax ///< Min/max implemented in terms of select(cmp()). - }; - - // This enum represents the kind of minmax recurrence. - enum MinMaxRecurrenceKind { - MRK_Invalid, - MRK_UIntMin, - MRK_UIntMax, - MRK_SIntMin, - MRK_SIntMax, - MRK_FloatMin, - MRK_FloatMax - }; - RecurrenceDescriptor() = default; - RecurrenceDescriptor(Value *Start, Instruction *Exit, RecurrenceKind K, - FastMathFlags FMF, MinMaxRecurrenceKind MK, - Instruction *UAI, Type *RT, bool Signed, - SmallPtrSetImpl &CI) + RecurrenceDescriptor(Value *Start, Instruction *Exit, RecurKind K, + FastMathFlags FMF, Instruction *UAI, Type *RT, + bool Signed, SmallPtrSetImpl &CI) : StartValue(Start), LoopExitInstr(Exit), Kind(K), FMF(FMF), - MinMaxKind(MK), UnsafeAlgebraInst(UAI), RecurrenceType(RT), - IsSigned(Signed) { + UnsafeAlgebraInst(UAI), RecurrenceType(RT), IsSigned(Signed) { CastInsts.insert(CI.begin(), CI.end()); } @@ -89,22 +79,22 @@ public: class InstDesc { public: InstDesc(bool IsRecur, Instruction *I, Instruction *UAI = nullptr) - : IsRecurrence(IsRecur), PatternLastInst(I), MinMaxKind(MRK_Invalid), - UnsafeAlgebraInst(UAI) {} + : IsRecurrence(IsRecur), PatternLastInst(I), + RecKind(RecurKind::None), UnsafeAlgebraInst(UAI) {} - InstDesc(Instruction *I, MinMaxRecurrenceKind K, Instruction *UAI = nullptr) - : IsRecurrence(true), PatternLastInst(I), MinMaxKind(K), + InstDesc(Instruction *I, RecurKind K, Instruction *UAI = nullptr) + : IsRecurrence(true), PatternLastInst(I), RecKind(K), UnsafeAlgebraInst(UAI) {} - bool isRecurrence() { return IsRecurrence; } + bool isRecurrence() const { return IsRecurrence; } - bool hasUnsafeAlgebra() { return UnsafeAlgebraInst != nullptr; } + bool hasUnsafeAlgebra() const { return UnsafeAlgebraInst != nullptr; } - Instruction *getUnsafeAlgebraInst() { return UnsafeAlgebraInst; } + Instruction *getUnsafeAlgebraInst() const { return UnsafeAlgebraInst; } - MinMaxRecurrenceKind getMinMaxKind() { return MinMaxKind; } + RecurKind getRecKind() const { return RecKind; } - Instruction *getPatternInst() { return PatternLastInst; } + Instruction *getPatternInst() const { return PatternLastInst; } private: // Is this instruction a recurrence candidate. @@ -112,8 +102,8 @@ public: // The last instruction in a min/max pattern (select of the select(icmp()) // pattern), or the current recurrence instruction otherwise. Instruction *PatternLastInst; - // If this is a min/max pattern the comparison predicate. - MinMaxRecurrenceKind MinMaxKind; + // If this is a min/max pattern. + RecurKind RecKind; // Recurrence has unsafe algebra. Instruction *UnsafeAlgebraInst; }; @@ -123,7 +113,7 @@ public: /// select(icmp()) this function advances the instruction pointer 'I' from the /// compare instruction to the select instruction and stores this pointer in /// 'PatternLastInst' member of the returned struct. - static InstDesc isRecurrenceInstr(Instruction *I, RecurrenceKind Kind, + static InstDesc isRecurrenceInstr(Instruction *I, RecurKind Kind, InstDesc &Prev, bool HasFunNoNaNAttr); /// Returns true if instruction I has multiple uses in Insts @@ -134,27 +124,28 @@ public: /// Returns true if all uses of the instruction I is within the Set. static bool areAllUsesIn(Instruction *I, SmallPtrSetImpl &Set); - /// Returns a struct describing if the instruction if the instruction is a + /// Returns a struct describing if the instruction is a /// Select(ICmp(X, Y), X, Y) instruction pattern corresponding to a min(X, Y) - /// or max(X, Y). - static InstDesc isMinMaxSelectCmpPattern(Instruction *I, InstDesc &Prev); + /// or max(X, Y). \p Prev specifies the description of an already processed + /// select instruction, so its corresponding cmp can be matched to it. + static InstDesc isMinMaxSelectCmpPattern(Instruction *I, + const InstDesc &Prev); /// Returns a struct describing if the instruction is a /// Select(FCmp(X, Y), (Z = X op PHINode), PHINode) instruction pattern. - static InstDesc isConditionalRdxPattern(RecurrenceKind Kind, Instruction *I); + static InstDesc isConditionalRdxPattern(RecurKind Kind, Instruction *I); /// Returns identity corresponding to the RecurrenceKind. - static Constant *getRecurrenceIdentity(RecurrenceKind K, Type *Tp); + static Constant *getRecurrenceIdentity(RecurKind K, Type *Tp); - /// Returns the opcode of binary operation corresponding to the - /// RecurrenceKind. - static unsigned getRecurrenceBinOp(RecurrenceKind Kind); + /// Returns the opcode corresponding to the RecurrenceKind. + static unsigned getOpcode(RecurKind Kind); /// Returns true if Phi is a reduction of type Kind and adds it to the /// RecurrenceDescriptor. If either \p DB is non-null or \p AC and \p DT are /// non-null, the minimal bit width needed to compute the reduction will be /// computed. - static bool AddReductionVar(PHINode *Phi, RecurrenceKind Kind, Loop *TheLoop, + static bool AddReductionVar(PHINode *Phi, RecurKind Kind, Loop *TheLoop, bool HasFunNoNaNAttr, RecurrenceDescriptor &RedDes, DemandedBits *DB = nullptr, @@ -183,42 +174,63 @@ public: DenseMap &SinkAfter, DominatorTree *DT); - RecurrenceKind getRecurrenceKind() { return Kind; } + RecurKind getRecurrenceKind() const { return Kind; } - MinMaxRecurrenceKind getMinMaxRecurrenceKind() { return MinMaxKind; } + unsigned getOpcode() const { return getOpcode(getRecurrenceKind()); } - FastMathFlags getFastMathFlags() { return FMF; } + FastMathFlags getFastMathFlags() const { return FMF; } - TrackingVH getRecurrenceStartValue() { return StartValue; } + TrackingVH getRecurrenceStartValue() const { return StartValue; } - Instruction *getLoopExitInstr() { return LoopExitInstr; } + Instruction *getLoopExitInstr() const { return LoopExitInstr; } /// Returns true if the recurrence has unsafe algebra which requires a relaxed /// floating-point model. - bool hasUnsafeAlgebra() { return UnsafeAlgebraInst != nullptr; } + bool hasUnsafeAlgebra() const { return UnsafeAlgebraInst != nullptr; } /// Returns first unsafe algebra instruction in the PHI node's use-chain. - Instruction *getUnsafeAlgebraInst() { return UnsafeAlgebraInst; } + Instruction *getUnsafeAlgebraInst() const { return UnsafeAlgebraInst; } /// Returns true if the recurrence kind is an integer kind. - static bool isIntegerRecurrenceKind(RecurrenceKind Kind); + static bool isIntegerRecurrenceKind(RecurKind Kind); /// Returns true if the recurrence kind is a floating point kind. - static bool isFloatingPointRecurrenceKind(RecurrenceKind Kind); + static bool isFloatingPointRecurrenceKind(RecurKind Kind); /// Returns true if the recurrence kind is an arithmetic kind. - static bool isArithmeticRecurrenceKind(RecurrenceKind Kind); + static bool isArithmeticRecurrenceKind(RecurKind Kind); + + /// Returns true if the recurrence kind is an integer min/max kind. + static bool isIntMinMaxRecurrenceKind(RecurKind Kind) { + return Kind == RecurKind::UMin || Kind == RecurKind::UMax || + Kind == RecurKind::SMin || Kind == RecurKind::SMax; + } + + /// Returns true if the recurrence kind is a floating-point min/max kind. + static bool isFPMinMaxRecurrenceKind(RecurKind Kind) { + return Kind == RecurKind::FMin || Kind == RecurKind::FMax; + } + + /// Returns true if the recurrence kind is any min/max kind. + static bool isMinMaxRecurrenceKind(RecurKind Kind) { + return isIntMinMaxRecurrenceKind(Kind) || isFPMinMaxRecurrenceKind(Kind); + } /// Returns the type of the recurrence. This type can be narrower than the /// actual type of the Phi if the recurrence has been type-promoted. - Type *getRecurrenceType() { return RecurrenceType; } + Type *getRecurrenceType() const { return RecurrenceType; } /// Returns a reference to the instructions used for type-promoting the /// recurrence. - SmallPtrSet &getCastInsts() { return CastInsts; } + const SmallPtrSet &getCastInsts() const { return CastInsts; } /// Returns true if all source operands of the recurrence are SExtInsts. - bool isSigned() { return IsSigned; } + bool isSigned() const { return IsSigned; } + + /// Attempts to find a chain of operations from Phi to LoopExitInst that can + /// be treated as a set of reductions instructions for in-loop reductions. + SmallVector getReductionOpChain(PHINode *Phi, + Loop *L) const; private: // The starting value of the recurrence. @@ -227,12 +239,10 @@ private: // The instruction who's value is used outside the loop. Instruction *LoopExitInstr = nullptr; // The kind of the recurrence. - RecurrenceKind Kind = RK_NoRecurrence; + RecurKind Kind = RecurKind::None; // The fast-math flags on the recurrent instructions. We propagate these // fast-math flags into the vectorized FP instructions we generate. FastMathFlags FMF; - // If this a min/max recurrence the kind of recurrence. - MinMaxRecurrenceKind MinMaxKind = MRK_Invalid; // First occurrence of unasfe algebra in the PHI's use-chain. Instruction *UnsafeAlgebraInst = nullptr; // The type of the recurrence. @@ -258,12 +268,6 @@ public: /// Default constructor - creates an invalid induction. InductionDescriptor() = default; - /// Get the consecutive direction. Returns: - /// 0 - unknown or non-consecutive. - /// 1 - consecutive and increasing. - /// -1 - consecutive and decreasing. - int getConsecutiveDirection() const; - Value *getStartValue() const { return StartValue; } InductionKind getKind() const { return IK; } const SCEV *getStep() const { return Step; } diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/InlineAdvisor.h b/contrib/llvm-project/llvm/include/llvm/Analysis/InlineAdvisor.h index 3480d93385a8..c39fae13d3b8 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/InlineAdvisor.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/InlineAdvisor.h @@ -9,12 +9,12 @@ #ifndef LLVM_INLINEADVISOR_H_ #define LLVM_INLINEADVISOR_H_ -#include -#include -#include - #include "llvm/Analysis/InlineCost.h" +#include "llvm/Config/llvm-config.h" #include "llvm/IR/PassManager.h" +#include "llvm/Analysis/Utils/ImportedFunctionsInliningStatistics.h" +#include +#include namespace llvm { class BasicBlock; @@ -36,7 +36,11 @@ class OptimizationRemarkEmitter; /// requires the full C Tensorflow API library, and evaluates models /// dynamically. This mode also permits generating training logs, for offline /// training. -enum class InliningAdvisorMode : int { Default, Release, Development }; +enum class InliningAdvisorMode : int { + Default, + Release, + Development +}; class InlineAdvisor; /// Capture state between an inlining decision having had been made, and @@ -62,10 +66,7 @@ public: /// behavior by implementing the corresponding record*Impl. /// /// Call after inlining succeeded, and did not result in deleting the callee. - void recordInlining() { - markRecorded(); - recordInliningImpl(); - } + void recordInlining(); /// Call after inlining succeeded, and resulted in deleting the callee. void recordInliningWithCalleeDeleted(); @@ -111,21 +112,44 @@ private: assert(!Recorded && "Recording should happen exactly once"); Recorded = true; } + void recordInlineStatsIfNeeded(); bool Recorded = false; }; +class DefaultInlineAdvice : public InlineAdvice { +public: + DefaultInlineAdvice(InlineAdvisor *Advisor, CallBase &CB, + Optional OIC, OptimizationRemarkEmitter &ORE, + bool EmitRemarks = true) + : InlineAdvice(Advisor, CB, ORE, OIC.hasValue()), OriginalCB(&CB), + OIC(OIC), EmitRemarks(EmitRemarks) {} + +private: + void recordUnsuccessfulInliningImpl(const InlineResult &Result) override; + void recordInliningWithCalleeDeletedImpl() override; + void recordInliningImpl() override; + +private: + CallBase *const OriginalCB; + Optional OIC; + bool EmitRemarks; +}; + /// Interface for deciding whether to inline a call site or not. class InlineAdvisor { public: InlineAdvisor(InlineAdvisor &&) = delete; - virtual ~InlineAdvisor() { freeDeletedFunctions(); } + virtual ~InlineAdvisor(); /// Get an InlineAdvice containing a recommendation on whether to /// inline or not. \p CB is assumed to be a direct call. \p FAM is assumed to - /// be up-to-date wrt previous inlining decisions. + /// be up-to-date wrt previous inlining decisions. \p MandatoryOnly indicates + /// only mandatory (always-inline) call sites should be recommended - this + /// allows the InlineAdvisor track such inlininings. /// Returns an InlineAdvice with the inlining recommendation. - virtual std::unique_ptr getAdvice(CallBase &CB) = 0; + std::unique_ptr getAdvice(CallBase &CB, + bool MandatoryOnly = false); /// This must be called when the Inliner pass is entered, to allow the /// InlineAdvisor update internal state, as result of function passes run @@ -138,9 +162,14 @@ public: virtual void onPassExit() {} protected: - InlineAdvisor(FunctionAnalysisManager &FAM) : FAM(FAM) {} + InlineAdvisor(Module &M, FunctionAnalysisManager &FAM); + virtual std::unique_ptr getAdviceImpl(CallBase &CB) = 0; + virtual std::unique_ptr getMandatoryAdvice(CallBase &CB, + bool Advice); + Module &M; FunctionAnalysisManager &FAM; + std::unique_ptr ImportedFunctionsStats; /// We may want to defer deleting functions to after the inlining for a whole /// module has finished. This allows us to reliably use function pointers as @@ -155,6 +184,14 @@ protected: return DeletedFunctions.count(F); } + enum class MandatoryInliningKind { NotMandatory, Always, Never }; + + static MandatoryInliningKind getMandatoryKind(CallBase &CB, + FunctionAnalysisManager &FAM, + OptimizationRemarkEmitter &ORE); + + OptimizationRemarkEmitter &getCallerORE(CallBase &CB); + private: friend class InlineAdvice; void markFunctionAsDeleted(Function *F); @@ -166,11 +203,12 @@ private: /// reusable as-is for inliner pass test scenarios, as well as for regular use. class DefaultInlineAdvisor : public InlineAdvisor { public: - DefaultInlineAdvisor(FunctionAnalysisManager &FAM, InlineParams Params) - : InlineAdvisor(FAM), Params(Params) {} + DefaultInlineAdvisor(Module &M, FunctionAnalysisManager &FAM, + InlineParams Params) + : InlineAdvisor(M, FAM), Params(Params) {} private: - std::unique_ptr getAdvice(CallBase &CB) override; + std::unique_ptr getAdviceImpl(CallBase &CB) override; void onPassExit() override { freeDeletedFunctions(); } @@ -190,7 +228,8 @@ public: // InlineAdvisor must be preserved across analysis invalidations. return false; } - bool tryCreate(InlineParams Params, InliningAdvisorMode Mode); + bool tryCreate(InlineParams Params, InliningAdvisorMode Mode, + StringRef ReplayFile); InlineAdvisor *getAdvisor() const { return Advisor.get(); } void clear() { Advisor.reset(); } @@ -208,6 +247,12 @@ std::unique_ptr getReleaseModeAdvisor(Module &M, ModuleAnalysisManager &MAM); #endif +#ifdef LLVM_HAVE_TF_API +std::unique_ptr +getDevelopmentModeAdvisor(Module &M, ModuleAnalysisManager &MAM, + std::function GetDefaultAdvice); +#endif + // Default (manual policy) decision making helper APIs. Shared with the legacy // pass manager inliner. @@ -226,6 +271,9 @@ void emitInlinedInto(OptimizationRemarkEmitter &ORE, DebugLoc DLoc, bool ForProfileContext = false, const char *PassName = nullptr); +/// get call site location as string +std::string getCallSiteLocation(DebugLoc DLoc); + /// Add location info to ORE message. void addLocationToRemarks(OptimizationRemark &Remark, DebugLoc DLoc); diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/InlineFeaturesAnalysis.h b/contrib/llvm-project/llvm/include/llvm/Analysis/InlineFeaturesAnalysis.h deleted file mode 100644 index cc3f96c424e9..000000000000 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/InlineFeaturesAnalysis.h +++ /dev/null @@ -1,45 +0,0 @@ -//===- InlineFeaturesAnalysis.h - ML Policy Feature extraction -*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_INLINEFEATURESANALYSIS_H_ -#define LLVM_INLINEFEATURESANALYSIS_H_ - -#include "llvm/IR/PassManager.h" - -namespace llvm { -class Function; - -class InlineFeaturesAnalysis - : public AnalysisInfoMixin { -public: - static AnalysisKey Key; - struct Result { - /// Number of basic blocks - int64_t BasicBlockCount = 0; - - /// Number of blocks reached from a conditional instruction, or that are - /// 'cases' of a SwitchInstr. - // FIXME: We may want to replace this with a more meaningful metric, like - // number of conditionally executed blocks: - // 'if (a) s();' would be counted here as 2 blocks, just like - // 'if (a) s(); else s2(); s3();' would. - int64_t BlocksReachedFromConditionalInstruction = 0; - - /// Number of uses of this function, plus 1 if the function is callable - /// outside the module. - int64_t Uses = 0; - - /// Number of direct calls made from this function to other functions - /// defined in this module. - int64_t DirectCallsToDefinedFunctions = 0; - }; - Result run(const Function &F, FunctionAnalysisManager &FAM); -}; - -} // namespace llvm -#endif // LLVM_INLINEFEATURESANALYSIS_H_ \ No newline at end of file diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/InlineSizeEstimatorAnalysis.h b/contrib/llvm-project/llvm/include/llvm/Analysis/InlineSizeEstimatorAnalysis.h index 29a6f5914674..ab2cf52494c0 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/InlineSizeEstimatorAnalysis.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/InlineSizeEstimatorAnalysis.h @@ -31,5 +31,15 @@ public: private: std::unique_ptr Evaluator; }; + +class InlineSizeEstimatorAnalysisPrinterPass + : public PassInfoMixin { + raw_ostream &OS; + +public: + explicit InlineSizeEstimatorAnalysisPrinterPass(raw_ostream &OS) : OS(OS) {} + + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; } // namespace llvm -#endif // LLVM_ANALYSIS_INLINESIZEESTIMATORANALYSIS_H \ No newline at end of file +#endif // LLVM_ANALYSIS_INLINESIZEESTIMATORANALYSIS_H diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/InstCount.h b/contrib/llvm-project/llvm/include/llvm/Analysis/InstCount.h new file mode 100644 index 000000000000..e5ce822caf6e --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/InstCount.h @@ -0,0 +1,28 @@ +//===- InstCount.h - Collects the count of all instructions -----*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This pass collects the count of all instructions and reports them +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_INSTCOUNT_H +#define LLVM_ANALYSIS_INSTCOUNT_H + +#include "llvm/IR/PassManager.h" + +namespace llvm { + +class Function; + +struct InstCountPass : PassInfoMixin { + PreservedAnalyses run(Function &F, FunctionAnalysisManager &); +}; + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_INSTCOUNT_H diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/InstructionSimplify.h b/contrib/llvm-project/llvm/include/llvm/Analysis/InstructionSimplify.h index b5ae54fb98bc..17d6f30a35cb 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/InstructionSimplify.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/InstructionSimplify.h @@ -26,6 +26,10 @@ // same call context of that function (and not split between caller and callee // contexts of a directly recursive call, for example). // +// Additionally, these routines can't simplify to the instructions that are not +// def-reachable, meaning we can't just scan the basic block for instructions +// to simplify to. +// //===----------------------------------------------------------------------===// #ifndef LLVM_ANALYSIS_INSTRUCTIONSIMPLIFY_H @@ -98,19 +102,39 @@ struct SimplifyQuery { // be safely used. const InstrInfoQuery IIQ; + /// Controls whether simplifications are allowed to constrain the range of + /// possible values for uses of undef. If it is false, simplifications are not + /// allowed to assume a particular value for a use of undef for example. + bool CanUseUndef = true; + SimplifyQuery(const DataLayout &DL, const Instruction *CXTI = nullptr) : DL(DL), CxtI(CXTI) {} SimplifyQuery(const DataLayout &DL, const TargetLibraryInfo *TLI, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, - const Instruction *CXTI = nullptr, bool UseInstrInfo = true) - : DL(DL), TLI(TLI), DT(DT), AC(AC), CxtI(CXTI), IIQ(UseInstrInfo) {} + const Instruction *CXTI = nullptr, bool UseInstrInfo = true, + bool CanUseUndef = true) + : DL(DL), TLI(TLI), DT(DT), AC(AC), CxtI(CXTI), IIQ(UseInstrInfo), + CanUseUndef(CanUseUndef) {} SimplifyQuery getWithInstruction(Instruction *I) const { SimplifyQuery Copy(*this); Copy.CxtI = I; return Copy; } + SimplifyQuery getWithoutUndef() const { + SimplifyQuery Copy(*this); + Copy.CanUseUndef = false; + return Copy; + } + + /// If CanUseUndef is true, returns whether \p V is undef. + /// Otherwise always return false. + bool isUndefValue(Value *V) const { + if (!CanUseUndef) + return false; + return isa(V); + } }; // NOTE: the explicit multiple argument versions of these functions are @@ -268,7 +292,8 @@ Value *SimplifyFreezeInst(Value *Op, const SimplifyQuery &Q); Value *SimplifyInstruction(Instruction *I, const SimplifyQuery &Q, OptimizationRemarkEmitter *ORE = nullptr); -/// See if V simplifies when its operand Op is replaced with RepOp. +/// See if V simplifies when its operand Op is replaced with RepOp. If not, +/// return null. /// AllowRefinement specifies whether the simplification can be a refinement, /// or whether it needs to be strictly identical. Value *SimplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp, @@ -288,17 +313,6 @@ bool replaceAndRecursivelySimplify( const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, SmallSetVector *UnsimplifiedUsers = nullptr); -/// Recursively attempt to simplify an instruction. -/// -/// This routine uses SimplifyInstruction to simplify 'I', and if successful -/// replaces uses of 'I' with the simplified value. It then recurses on each -/// of the users impacted. It returns true if any simplifications were -/// performed. -bool recursivelySimplifyInstruction(Instruction *I, - const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr, - AssumptionCache *AC = nullptr); - // These helper functions return a SimplifyQuery structure that contains as // many of the optional analysis we use as are currently valid. This is the // strongly preferred way of constructing SimplifyQuery in passes. diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/Interval.h b/contrib/llvm-project/llvm/include/llvm/Analysis/Interval.h index 5c9a4535bc7f..9afe659d00dd 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/Interval.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/Interval.h @@ -89,9 +89,6 @@ public: return HeaderNode == I.HeaderNode; } - /// isLoop - Find out if there is a back edge in this interval... - bool isLoop() const; - /// print - Show contents in human readable format... void print(raw_ostream &O) const; }; diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/IntervalIterator.h b/contrib/llvm-project/llvm/include/llvm/Analysis/IntervalIterator.h index efaaf9715b3d..8e2273618a66 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/IntervalIterator.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/IntervalIterator.h @@ -81,7 +81,7 @@ inline void addNodeToInterval(Interval *Int, BasicBlock *BB) { // BasicBlocks are added to the interval. inline void addNodeToInterval(Interval *Int, Interval *I) { // Add all of the nodes in I as new nodes in Int. - Int->Nodes.insert(Int->Nodes.end(), I->Nodes.begin(), I->Nodes.end()); + llvm::append_range(Int->Nodes, I->Nodes); } template, @@ -227,9 +227,7 @@ private: if (Int->isSuccessor(NodeHeader)) { // If we were in the successor list from before... remove from succ list - Int->Successors.erase(std::remove(Int->Successors.begin(), - Int->Successors.end(), NodeHeader), - Int->Successors.end()); + llvm::erase_value(Int->Successors, NodeHeader); } // Now that we have discovered that Node is in the interval, perhaps some diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/IteratedDominanceFrontier.h b/contrib/llvm-project/llvm/include/llvm/Analysis/IteratedDominanceFrontier.h index fb6605285156..8166b52aa226 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/IteratedDominanceFrontier.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/IteratedDominanceFrontier.h @@ -73,13 +73,7 @@ ChildrenGetterTy::get(const NodeRef &N) { return {Children.begin(), Children.end()}; } - using SnapShotBBPairTy = - std::pair *, OrderedNodeTy>; - - ChildrenTy Ret; - for (const auto &SnapShotBBPair : children({GD, N})) - Ret.emplace_back(SnapShotBBPair.second); - return Ret; + return GD->template getChildren(N); } } // end of namespace IDFCalculatorDetail diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/LazyBranchProbabilityInfo.h b/contrib/llvm-project/llvm/include/llvm/Analysis/LazyBranchProbabilityInfo.h index f4249f74104c..3c632f02905a 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/LazyBranchProbabilityInfo.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/LazyBranchProbabilityInfo.h @@ -63,7 +63,7 @@ class LazyBranchProbabilityInfoPass : public FunctionPass { BranchProbabilityInfo &getCalculated() { if (!Calculated) { assert(F && LI && "call setAnalysis"); - BPI.calculate(*F, *LI, TLI, nullptr); + BPI.calculate(*F, *LI, TLI, nullptr, nullptr); Calculated = true; } return BPI; diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/LazyCallGraph.h b/contrib/llvm-project/llvm/include/llvm/Analysis/LazyCallGraph.h index ea63b837ba70..f7a5adac2b43 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/LazyCallGraph.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/LazyCallGraph.h @@ -258,7 +258,6 @@ public: iterator begin() { return iterator(Edges.begin(), Edges.end()); } iterator end() { return iterator(Edges.end(), Edges.end()); } - Edge &operator[](int i) { return Edges[i]; } Edge &operator[](Node &N) { assert(EdgeIndexMap.find(&N) != EdgeIndexMap.end() && "No such edge!"); auto &E = Edges[EdgeIndexMap.find(&N)->second]; @@ -305,13 +304,6 @@ public: /// Internal helper to remove the edge to the given function. bool removeEdgeInternal(Node &ChildN); - - /// Internal helper to replace an edge key with a new one. - /// - /// This should be used when the function for a particular node in the - /// graph gets replaced and we are updating all of the edges to that node - /// to use the new function as the key. - void replaceEdgeKey(Function &OldTarget, Function &NewTarget); }; /// A node in the call graph. @@ -606,10 +598,6 @@ public: void verify(); #endif - /// Handle any necessary parent set updates after inserting a trivial ref - /// or call edge. - void handleTrivialEdgeInsertion(Node &SourceN, Node &TargetN); - public: using iterator = pointee_iterator::const_iterator>; using range = iterator_range; @@ -1058,12 +1046,29 @@ public: /// fully visited by the DFS prior to calling this routine. void removeDeadFunction(Function &F); - /// Introduce a node for the function \p NewF in the SCC \p C. - void addNewFunctionIntoSCC(Function &NewF, SCC &C); + /// Add a new function split/outlined from an existing function. + /// + /// The new function may only reference other functions that the original + /// function did. + /// + /// The original function must reference (either directly or indirectly) the + /// new function. + /// + /// The new function may also reference the original function. + /// It may end up in a parent SCC in the case that the original function's + /// edge to the new function is a ref edge, and the edge back is a call edge. + void addSplitFunction(Function &OriginalFunction, Function &NewFunction); - /// Introduce a node for the function \p NewF, as a single node in a - /// new SCC, in the RefSCC \p RC. - void addNewFunctionIntoRefSCC(Function &NewF, RefSCC &RC); + /// Add new ref-recursive functions split/outlined from an existing function. + /// + /// The new functions may only reference other functions that the original + /// function did. The new functions may reference (not call) the original + /// function. + /// + /// The original function must reference (not call) all new functions. + /// All new functions must reference (not call) each other. + void addSplitRefRecursiveFunctions(Function &OriginalFunction, + ArrayRef NewFunctions); ///@} @@ -1168,16 +1173,14 @@ private: /// the NodeMap. Node &insertInto(Function &F, Node *&MappedN); + /// Helper to initialize a new node created outside of creating SCCs and add + /// it to the NodeMap if necessary. For example, useful when a function is + /// split. + Node &initNode(Function &F); + /// Helper to update pointers back to the graph object during moves. void updateGraphPtrs(); - /// Helper to insert a new function, add it to the NodeMap, and populate its - /// node. - Node &createNode(Function &F); - - /// Helper to add the given Node \p N to the SCCMap, mapped to the SCC \p C. - void addNodeToSCC(SCC &C, Node &N); - /// Allocates an SCC and constructs it using the graph allocator. /// /// The arguments are forwarded to the constructor. diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/LazyValueInfo.h b/contrib/llvm-project/llvm/include/llvm/Analysis/LazyValueInfo.h index 1bc88235273e..363cb49af382 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/LazyValueInfo.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/LazyValueInfo.h @@ -71,20 +71,20 @@ public: Instruction *CxtI = nullptr); /// Determine whether the specified value comparison with a constant is known - /// to be true or false at the specified instruction - /// (from an assume intrinsic). Pred is a CmpInst predicate. + /// to be true or false at the specified instruction. + /// \p Pred is a CmpInst predicate. If \p UseBlockValue is true, the block + /// value is also taken into account. Tristate getPredicateAt(unsigned Pred, Value *V, Constant *C, - Instruction *CxtI); + Instruction *CxtI, bool UseBlockValue = false); - /// Determine whether the specified value is known to be a - /// constant at the end of the specified block. Return null if not. - Constant *getConstant(Value *V, BasicBlock *BB, Instruction *CxtI = nullptr); + /// Determine whether the specified value is known to be a constant at the + /// specified instruction. Return null if not. + Constant *getConstant(Value *V, Instruction *CxtI); /// Return the ConstantRange constraint that is known to hold for the - /// specified value at the end of the specified block. This may only be called + /// specified value at the specified instruction. This may only be called /// on integer-typed Values. - ConstantRange getConstantRange(Value *V, BasicBlock *BB, - Instruction *CxtI = nullptr, + ConstantRange getConstantRange(Value *V, Instruction *CxtI, bool UndefAllowed = true); /// Determine whether the specified value is known to be a diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/Lint.h b/contrib/llvm-project/llvm/include/llvm/Analysis/Lint.h index 0fea81e215c9..6eb637e72782 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/Lint.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/Lint.h @@ -19,30 +19,30 @@ #ifndef LLVM_ANALYSIS_LINT_H #define LLVM_ANALYSIS_LINT_H +#include "llvm/IR/PassManager.h" + namespace llvm { class FunctionPass; class Module; class Function; -/// Create a lint pass. -/// -/// Check a module or function. -FunctionPass *createLintPass(); +FunctionPass *createLintLegacyPassPass(); -/// Check a module. +/// Lint a module. /// /// This should only be used for debugging, because it plays games with /// PassManagers and stuff. -void lintModule( - const Module &M ///< The module to be checked -); +void lintModule(const Module &M); + +// Lint a function. +void lintFunction(const Function &F); -// lintFunction - Check a function. -void lintFunction( - const Function &F ///< The function to be checked -); +class LintPass : public PassInfoMixin { +public: + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; -} // End llvm namespace +} // namespace llvm -#endif +#endif // LLVM_ANALYSIS_LINT_H diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/Loads.h b/contrib/llvm-project/llvm/include/llvm/Analysis/Loads.h index 5665a802942d..24a05610e68d 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/Loads.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/Loads.h @@ -155,6 +155,15 @@ Value *FindAvailablePtrLoadStore(Value *Ptr, Type *AccessTy, bool AtLeastAtomic, BasicBlock::iterator &ScanFrom, unsigned MaxInstsToScan, AAResults *AA, bool *IsLoadCSE, unsigned *NumScanedInst); + +/// Returns true if a pointer value \p A can be replace with another pointer +/// value \B if they are deemed equal through some means (e.g. information from +/// conditions). +/// NOTE: the current implementations is incomplete and unsound. It does not +/// reject all invalid cases yet, but will be made stricter in the future. In +/// particular this means returning true means unknown if replacement is safe. +bool canReplacePointersIfEqual(Value *A, Value *B, const DataLayout &DL, + Instruction *CtxI); } #endif diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/LoopAccessAnalysis.h b/contrib/llvm-project/llvm/include/llvm/Analysis/LoopAccessAnalysis.h index a5237e9ba59e..13fbe884eddf 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/LoopAccessAnalysis.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/LoopAccessAnalysis.h @@ -171,7 +171,8 @@ public: MemoryDepChecker(PredicatedScalarEvolution &PSE, const Loop *L) : PSE(PSE), InnermostLoop(L), AccessIdx(0), MaxSafeDepDistBytes(0), - MaxSafeRegisterWidth(-1U), FoundNonConstantDistanceDependence(false), + MaxSafeVectorWidthInBits(-1U), + FoundNonConstantDistanceDependence(false), Status(VectorizationSafetyStatus::Safe), RecordDependences(true) {} /// Register the location (instructions are given increasing numbers) @@ -204,13 +205,21 @@ public: return Status == VectorizationSafetyStatus::Safe; } + /// Return true if the number of elements that are safe to operate on + /// simultaneously is not bounded. + bool isSafeForAnyVectorWidth() const { + return MaxSafeVectorWidthInBits == UINT_MAX; + } + /// The maximum number of bytes of a vector register we can vectorize /// the accesses safely with. uint64_t getMaxSafeDepDistBytes() { return MaxSafeDepDistBytes; } /// Return the number of elements that are safe to operate on /// simultaneously, multiplied by the size of the element in bits. - uint64_t getMaxSafeRegisterWidth() const { return MaxSafeRegisterWidth; } + uint64_t getMaxSafeVectorWidthInBits() const { + return MaxSafeVectorWidthInBits; + } /// In same cases when the dependency check fails we can still /// vectorize the loop with a dynamic array access check. @@ -275,7 +284,7 @@ private: /// operate on simultaneously, multiplied by the size of the element in bits. /// The size of the element is taken from the memory access that is most /// restrictive. - uint64_t MaxSafeRegisterWidth; + uint64_t MaxSafeVectorWidthInBits; /// If we see a non-constant dependence distance we can still try to /// vectorize this loop with runtime checks. @@ -418,7 +427,7 @@ public: bool UseDependencies); /// Returns the checks that generateChecks created. - const SmallVector &getChecks() const { + const SmallVectorImpl &getChecks() const { return Checks; } diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/LoopAnalysisManager.h b/contrib/llvm-project/llvm/include/llvm/Analysis/LoopAnalysisManager.h index 0e162e03bde1..11dbd15c8678 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/LoopAnalysisManager.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/LoopAnalysisManager.h @@ -57,6 +57,7 @@ struct LoopStandardAnalysisResults { ScalarEvolution &SE; TargetLibraryInfo &TLI; TargetTransformInfo &TTI; + BlockFrequencyInfo *BFI; MemorySSA *MSSA; }; diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/LoopCacheAnalysis.h b/contrib/llvm-project/llvm/include/llvm/Analysis/LoopCacheAnalysis.h index ffec78b6db2c..e8f2205545eb 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/LoopCacheAnalysis.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/LoopCacheAnalysis.h @@ -14,19 +14,20 @@ #ifndef LLVM_ANALYSIS_LOOPCACHEANALYSIS_H #define LLVM_ANALYSIS_LOOPCACHEANALYSIS_H -#include "llvm/Analysis/AliasAnalysis.h" -#include "llvm/Analysis/DependenceAnalysis.h" #include "llvm/Analysis/LoopAnalysisManager.h" -#include "llvm/Analysis/LoopInfo.h" -#include "llvm/Analysis/ScalarEvolution.h" -#include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/IR/Instructions.h" -#include "llvm/Pass.h" +#include "llvm/IR/PassManager.h" #include "llvm/Support/raw_ostream.h" namespace llvm { +class AAResults; +class DependenceInfo; class LPMUpdater; +class ScalarEvolution; +class SCEV; +class TargetTransformInfo; + using CacheCostTy = int64_t; using LoopVectorTy = SmallVector; @@ -70,7 +71,7 @@ public: /// the same chace line iff the distance between them in the innermost /// dimension is less than the cache line size. Return None if unsure. Optional hasSpacialReuse(const IndexedReference &Other, unsigned CLS, - AliasAnalysis &AA) const; + AAResults &AA) const; /// Return true if the current object and the indexed reference \p Other /// have distance smaller than \p MaxDistance in the dimension associated with @@ -78,7 +79,7 @@ public: /// MaxDistance and None if unsure. Optional hasTemporalReuse(const IndexedReference &Other, unsigned MaxDistance, const Loop &L, - DependenceInfo &DI, AliasAnalysis &AA) const; + DependenceInfo &DI, AAResults &AA) const; /// Compute the cost of the reference w.r.t. the given loop \p L when it is /// considered in the innermost position in the loop nest. @@ -118,7 +119,7 @@ private: /// Return true if the given reference \p Other is definetely aliased with /// the indexed reference represented by this class. - bool isAliased(const IndexedReference &Other, AliasAnalysis &AA) const; + bool isAliased(const IndexedReference &Other, AAResults &AA) const; private: /// True if the reference can be delinearized, false otherwise. @@ -183,7 +184,7 @@ public: /// between array elements accessed in a loop so that the elements are /// classified to have temporal reuse. CacheCost(const LoopVectorTy &Loops, const LoopInfo &LI, ScalarEvolution &SE, - TargetTransformInfo &TTI, AliasAnalysis &AA, DependenceInfo &DI, + TargetTransformInfo &TTI, AAResults &AA, DependenceInfo &DI, Optional TRT = None); /// Create a CacheCost for the loop nest rooted by \p Root. @@ -197,9 +198,9 @@ public: /// Return the estimated cost of loop \p L if the given loop is part of the /// loop nest associated with this object. Return -1 otherwise. CacheCostTy getLoopCost(const Loop &L) const { - auto IT = std::find_if( - LoopCosts.begin(), LoopCosts.end(), - [&L](const LoopCacheCostTy &LCC) { return LCC.first == &L; }); + auto IT = llvm::find_if(LoopCosts, [&L](const LoopCacheCostTy &LCC) { + return LCC.first == &L; + }); return (IT != LoopCosts.end()) ? (*IT).second : -1; } @@ -258,7 +259,7 @@ private: const LoopInfo &LI; ScalarEvolution &SE; TargetTransformInfo &TTI; - AliasAnalysis &AA; + AAResults &AA; DependenceInfo &DI; }; diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/LoopInfo.h b/contrib/llvm-project/llvm/include/llvm/Analysis/LoopInfo.h index 35fe2a03a2a2..a5717bae12c3 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/LoopInfo.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/LoopInfo.h @@ -155,7 +155,17 @@ public: iterator end() const { return getSubLoops().end(); } reverse_iterator rbegin() const { return getSubLoops().rbegin(); } reverse_iterator rend() const { return getSubLoops().rend(); } - bool empty() const { return getSubLoops().empty(); } + + // LoopInfo does not detect irreducible control flow, just natural + // loops. That is, it is possible that there is cyclic control + // flow within the "innermost loop" or around the "outermost + // loop". + + /// Return true if the loop does not contain any (natural) loops. + bool isInnermost() const { return getSubLoops().empty(); } + /// Return true if the loop does not have a parent (natural) loop + // (i.e. it is outermost, which is the same as top-level). + bool isOutermost() const { return getParentLoop() == nullptr; } /// Get a list of the basic blocks which make up this loop. ArrayRef getBlocks() const { @@ -292,6 +302,9 @@ public: /// Otherwise return null. BlockT *getUniqueExitBlock() const; + /// Return true if this loop does not have any exit blocks. + bool hasNoExitBlocks() const; + /// Edge type. typedef std::pair Edge; @@ -830,6 +843,9 @@ public: /// unrolling pass is run more than once (which it generally is). void setLoopAlreadyUnrolled(); + /// Add llvm.loop.mustprogress to this loop's loop id metadata. + void setLoopMustProgress(); + void dump() const; void dumpVerbose() const; @@ -974,7 +990,7 @@ public: LoopT *removeLoop(iterator I) { assert(I != end() && "Cannot remove end iterator!"); LoopT *L = *I; - assert(!L->getParentLoop() && "Not a top-level loop!"); + assert(L->isOutermost() && "Not a top-level loop!"); TopLevelLoops.erase(TopLevelLoops.begin() + (I - begin())); return L; } @@ -1002,7 +1018,7 @@ public: /// This adds the specified loop to the collection of top-level loops. void addTopLevelLoop(LoopT *New) { - assert(!New->getParentLoop() && "Loop already in subloop!"); + assert(New->isOutermost() && "Loop already in subloop!"); TopLevelLoops.push_back(New); } diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/LoopInfoImpl.h b/contrib/llvm-project/llvm/include/llvm/Analysis/LoopInfoImpl.h index 58a4abafcc85..426b349c6b8a 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/LoopInfoImpl.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/LoopInfoImpl.h @@ -68,6 +68,13 @@ void LoopBase::getExitBlocks( ExitBlocks.push_back(Succ); } +template +bool LoopBase::hasNoExitBlocks() const { + SmallVector ExitBlocks; + getExitBlocks(ExitBlocks); + return ExitBlocks.empty(); +} + /// getExitBlock - If getExitBlocks would return exactly one block, /// return that block. Otherwise return null. template @@ -502,7 +509,7 @@ void PopulateLoopsDFS::insertIntoLoop(BlockT *Block) { if (Subloop && Block == Subloop->getHeader()) { // We reach this point once per subloop after processing all the blocks in // the subloop. - if (Subloop->getParentLoop()) + if (!Subloop->isOutermost()) Subloop->getParentLoop()->getSubLoopsVector().push_back(Subloop); else LI->addTopLevelLoop(Subloop); @@ -666,12 +673,13 @@ static void compareLoops(const LoopT *L, const LoopT *OtherL, "Mismatched basic blocks in the loops!"); const SmallPtrSetImpl &BlocksSet = L->getBlocksSet(); - const SmallPtrSetImpl &OtherBlocksSet = L->getBlocksSet(); + const SmallPtrSetImpl &OtherBlocksSet = + OtherL->getBlocksSet(); assert(BlocksSet.size() == OtherBlocksSet.size() && - std::all_of(BlocksSet.begin(), BlocksSet.end(), - [&OtherBlocksSet](const BlockT *BB) { - return OtherBlocksSet.count(BB); - }) && + llvm::all_of(BlocksSet, + [&OtherBlocksSet](const BlockT *BB) { + return OtherBlocksSet.count(BB); + }) && "Mismatched basic blocks in BlocksSets!"); } #endif @@ -681,7 +689,7 @@ void LoopInfoBase::verify( const DomTreeBase &DomTree) const { DenseSet Loops; for (iterator I = begin(), E = end(); I != E; ++I) { - assert(!(*I)->getParentLoop() && "Top-level loop has a parent!"); + assert((*I)->isOutermost() && "Top-level loop has a parent!"); (*I)->verifyLoopNest(&Loops); } diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/LoopNestAnalysis.h b/contrib/llvm-project/llvm/include/llvm/Analysis/LoopNestAnalysis.h index 792958a312ce..9c4fb4dbc29b 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/LoopNestAnalysis.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/LoopNestAnalysis.h @@ -14,6 +14,7 @@ #ifndef LLVM_ANALYSIS_LOOPNESTANALYSIS_H #define LLVM_ANALYSIS_LOOPNESTANALYSIS_H +#include "llvm/ADT/STLExtras.h" #include "llvm/Analysis/LoopAnalysisManager.h" #include "llvm/Analysis/LoopInfo.h" @@ -59,6 +60,12 @@ public: /// getMaxPerfectDepth(Loop_i) would return 2. static unsigned getMaxPerfectDepth(const Loop &Root, ScalarEvolution &SE); + /// Recursivelly traverse all empty 'single successor' basic blocks of \p From + /// (if there are any). Return the last basic block found or \p End if it was + /// reached during the search. + static const BasicBlock &skipEmptyBlockUntil(const BasicBlock *From, + const BasicBlock *End); + /// Return the outermost loop in the loop nest. Loop &getOutermostLoop() const { return *Loops.front(); } @@ -124,10 +131,16 @@ public: /// Return true if all loops in the loop nest are in simplify form. bool areAllLoopsSimplifyForm() const { - return llvm::all_of(Loops, - [](const Loop *L) { return L->isLoopSimplifyForm(); }); + return all_of(Loops, [](const Loop *L) { return L->isLoopSimplifyForm(); }); + } + + /// Return true if all loops in the loop nest are in rotated form. + bool areAllLoopsRotatedForm() const { + return all_of(Loops, [](const Loop *L) { return L->isRotatedForm(); }); } + StringRef getName() const { return Loops.front()->getName(); } + protected: const unsigned MaxPerfectDepth; // maximum perfect nesting depth level. LoopVectorTy Loops; // the loops in the nest (in breadth first order). diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/MLInlineAdvisor.h b/contrib/llvm-project/llvm/include/llvm/Analysis/MLInlineAdvisor.h index cbe3b1f1f4e6..54edbb823263 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/MLInlineAdvisor.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/MLInlineAdvisor.h @@ -31,8 +31,6 @@ public: void onPassEntry() override; - std::unique_ptr getAdvice(CallBase &CB) override; - int64_t getIRSize(const Function &F) const { return F.getInstructionCount(); } void onSuccessfulInlining(const MLInlineAdvice &Advice, bool CalleeWasDeleted); @@ -42,13 +40,16 @@ public: const MLModelRunner &getModelRunner() const { return *ModelRunner.get(); } protected: - virtual std::unique_ptr - getMandatoryAdvice(CallBase &CB, OptimizationRemarkEmitter &ORE); + std::unique_ptr getAdviceImpl(CallBase &CB) override; + + std::unique_ptr getMandatoryAdvice(CallBase &CB, + bool Advice) override; + + virtual std::unique_ptr getMandatoryAdviceImpl(CallBase &CB); virtual std::unique_ptr getAdviceFromModel(CallBase &CB, OptimizationRemarkEmitter &ORE); - Module &M; std::unique_ptr ModelRunner; private: @@ -104,4 +105,4 @@ private: } // namespace llvm -#endif // LLVM_ANALYSIS_MLINLINEADVISOR_H \ No newline at end of file +#endif // LLVM_ANALYSIS_MLINLINEADVISOR_H diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/MemDerefPrinter.h b/contrib/llvm-project/llvm/include/llvm/Analysis/MemDerefPrinter.h new file mode 100644 index 000000000000..bafdc543eeaf --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/MemDerefPrinter.h @@ -0,0 +1,24 @@ +//===- MemDerefPrinter.h - Printer for isDereferenceablePointer -----------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_MEMDEREFPRINTER_H +#define LLVM_ANALYSIS_MEMDEREFPRINTER_H + +#include "llvm/IR/PassManager.h" + +namespace llvm { +class MemDerefPrinterPass : public PassInfoMixin { + raw_ostream &OS; + +public: + MemDerefPrinterPass(raw_ostream &OS) : OS(OS) {} + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; +} // namespace llvm + +#endif // LLVM_ANALYSIS_MEMDEREFPRINTER_H diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h b/contrib/llvm-project/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h index 0777dc7d7862..efde00f82d57 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h @@ -302,7 +302,7 @@ private: /// The maximum size of the dereferences of the pointer. /// /// May be UnknownSize if the sizes are unknown. - LocationSize Size = LocationSize::unknown(); + LocationSize Size = LocationSize::afterPointer(); /// The AA tags associated with dereferences of the pointer. /// /// The members may be null if there are no tags or conflicting tags. diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/MemoryLocation.h b/contrib/llvm-project/llvm/include/llvm/Analysis/MemoryLocation.h index d01ac7da85cd..3b188d763ef2 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/MemoryLocation.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/MemoryLocation.h @@ -64,10 +64,11 @@ class VAArgInst; // None. class LocationSize { enum : uint64_t { - Unknown = ~uint64_t(0), + BeforeOrAfterPointer = ~uint64_t(0), + AfterPointer = BeforeOrAfterPointer - 1, + MapEmpty = BeforeOrAfterPointer - 2, + MapTombstone = BeforeOrAfterPointer - 3, ImpreciseBit = uint64_t(1) << 63, - MapEmpty = Unknown - 1, - MapTombstone = Unknown - 2, // The maximum value we can represent without falling back to 'unknown'. MaxValue = (MapTombstone - 1) & ~ImpreciseBit, @@ -81,7 +82,11 @@ class LocationSize { constexpr LocationSize(uint64_t Raw, DirectConstruction): Value(Raw) {} - static_assert(Unknown & ImpreciseBit, "Unknown is imprecise by definition."); + static_assert(AfterPointer & ImpreciseBit, + "AfterPointer is imprecise by definition."); + static_assert(BeforeOrAfterPointer & ImpreciseBit, + "BeforeOrAfterPointer is imprecise by definition."); + public: // FIXME: Migrate all users to construct via either `precise` or `upperBound`, // to make it more obvious at the callsite the kind of size that they're @@ -90,12 +95,12 @@ public: // Since the overwhelming majority of users of this provide precise values, // this assumes the provided value is precise. constexpr LocationSize(uint64_t Raw) - : Value(Raw > MaxValue ? Unknown : Raw) {} + : Value(Raw > MaxValue ? AfterPointer : Raw) {} static LocationSize precise(uint64_t Value) { return LocationSize(Value); } static LocationSize precise(TypeSize Value) { if (Value.isScalable()) - return unknown(); + return afterPointer(); return precise(Value.getFixedSize()); } @@ -104,17 +109,25 @@ public: if (LLVM_UNLIKELY(Value == 0)) return precise(0); if (LLVM_UNLIKELY(Value > MaxValue)) - return unknown(); + return afterPointer(); return LocationSize(Value | ImpreciseBit, Direct); } static LocationSize upperBound(TypeSize Value) { if (Value.isScalable()) - return unknown(); + return afterPointer(); return upperBound(Value.getFixedSize()); } - constexpr static LocationSize unknown() { - return LocationSize(Unknown, Direct); + /// Any location after the base pointer (but still within the underlying + /// object). + constexpr static LocationSize afterPointer() { + return LocationSize(AfterPointer, Direct); + } + + /// Any location before or after the base pointer (but still within the + /// underlying object). + constexpr static LocationSize beforeOrAfterPointer() { + return LocationSize(BeforeOrAfterPointer, Direct); } // Sentinel values, generally used for maps. @@ -131,20 +144,24 @@ public: if (Other == *this) return *this; - if (!hasValue() || !Other.hasValue()) - return unknown(); + if (Value == BeforeOrAfterPointer || Other.Value == BeforeOrAfterPointer) + return beforeOrAfterPointer(); + if (Value == AfterPointer || Other.Value == AfterPointer) + return afterPointer(); return upperBound(std::max(getValue(), Other.getValue())); } - bool hasValue() const { return Value != Unknown; } + bool hasValue() const { + return Value != AfterPointer && Value != BeforeOrAfterPointer; + } uint64_t getValue() const { assert(hasValue() && "Getting value from an unknown LocationSize!"); return Value & ~ImpreciseBit; } // Returns whether or not this value is precise. Note that if a value is - // precise, it's guaranteed to not be `unknown()`. + // precise, it's guaranteed to not be unknown. bool isPrecise() const { return (Value & ImpreciseBit) == 0; } @@ -152,6 +169,9 @@ public: // Convenience method to check if this LocationSize's value is 0. bool isZero() const { return hasValue() && getValue() == 0; } + /// Whether accesses before the base pointer are possible. + bool mayBeBeforePointer() const { return Value == BeforeOrAfterPointer; } + bool operator==(const LocationSize &Other) const { return Value == Other.Value; } @@ -242,14 +262,30 @@ public: return getForArgument(Call, ArgIdx, &TLI); } + /// Return a location that may access any location after Ptr, while remaining + /// within the underlying object. + static MemoryLocation getAfter(const Value *Ptr, + const AAMDNodes &AATags = AAMDNodes()) { + return MemoryLocation(Ptr, LocationSize::afterPointer(), AATags); + } + + /// Return a location that may access any location before or after Ptr, while + /// remaining within the underlying object. + static MemoryLocation + getBeforeOrAfter(const Value *Ptr, const AAMDNodes &AATags = AAMDNodes()) { + return MemoryLocation(Ptr, LocationSize::beforeOrAfterPointer(), AATags); + } + // Return the exact size if the exact size is known at compiletime, // otherwise return MemoryLocation::UnknownSize. static uint64_t getSizeOrUnknown(const TypeSize &T) { return T.isScalable() ? UnknownSize : T.getFixedSize(); } - explicit MemoryLocation(const Value *Ptr = nullptr, - LocationSize Size = LocationSize::unknown(), + MemoryLocation() + : Ptr(nullptr), Size(LocationSize::beforeOrAfterPointer()), AATags() {} + + explicit MemoryLocation(const Value *Ptr, LocationSize Size, const AAMDNodes &AATags = AAMDNodes()) : Ptr(Ptr), Size(Size), AATags(AATags) {} diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/MemorySSA.h b/contrib/llvm-project/llvm/include/llvm/Analysis/MemorySSA.h index 5ce2b3fd047f..63c031b1921f 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/MemorySSA.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/MemorySSA.h @@ -88,6 +88,7 @@ #include "llvm/IR/DerivedUser.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Module.h" +#include "llvm/IR/Operator.h" #include "llvm/IR/Type.h" #include "llvm/IR/Use.h" #include "llvm/IR/User.h" @@ -108,6 +109,7 @@ namespace llvm { /// Enables memory ssa as a dependency for loop passes. extern cl::opt EnableMSSALoopDependency; +class AllocaInst; class Function; class Instruction; class MemoryAccess; @@ -270,7 +272,7 @@ public: // Retrieve AliasResult type of the optimized access. Ideally this would be // returned by the caching walker and may go away in the future. Optional getOptimizedAccessType() const { - return OptimizedAccessAlias; + return isOptimized() ? OptimizedAccessAlias : None; } /// Reset the ID of what this MemoryUse was optimized to, causing it to @@ -840,7 +842,6 @@ private: CachingWalker *getWalkerImpl(); void buildMemorySSA(BatchAAResults &BAA); - void optimizeUses(); void prepareForMoveTo(MemoryAccess *, BasicBlock *); void verifyUseInDefs(MemoryAccess *, MemoryAccess *) const; @@ -848,15 +849,11 @@ private: using AccessMap = DenseMap>; using DefsMap = DenseMap>; - void - determineInsertionPoint(const SmallPtrSetImpl &DefiningBlocks); void markUnreachableAsLiveOnEntry(BasicBlock *BB); - bool dominatesUse(const MemoryAccess *, const MemoryAccess *) const; MemoryPhi *createMemoryPhi(BasicBlock *BB); template MemoryUseOrDef *createNewAccess(Instruction *, AliasAnalysisType *, const MemoryUseOrDef *Template = nullptr); - MemoryAccess *findDominatingDef(BasicBlock *, enum InsertionPlace); void placePHINodes(const SmallPtrSetImpl &); MemoryAccess *renameBlock(BasicBlock *, MemoryAccess *, bool); void renameSuccessorPhis(BasicBlock *, MemoryAccess *, bool); @@ -1181,9 +1178,11 @@ class upward_defs_iterator using BaseT = upward_defs_iterator::iterator_facade_base; public: - upward_defs_iterator(const MemoryAccessPair &Info, DominatorTree *DT) + upward_defs_iterator(const MemoryAccessPair &Info, DominatorTree *DT, + bool *PerformedPhiTranslation = nullptr) : DefIterator(Info.first), Location(Info.second), - OriginalAccess(Info.first), DT(DT) { + OriginalAccess(Info.first), DT(DT), + PerformedPhiTranslation(PerformedPhiTranslation) { CurrentPair.first = nullptr; WalkingPhi = Info.first && isa(Info.first); @@ -1215,38 +1214,60 @@ public: BasicBlock *getPhiArgBlock() const { return DefIterator.getPhiArgBlock(); } private: + /// Returns true if \p Ptr is guaranteed to be loop invariant for any possible + /// loop. In particular, this guarantees that it only references a single + /// MemoryLocation during execution of the containing function. + bool IsGuaranteedLoopInvariant(Value *Ptr) const; + void fillInCurrentPair() { CurrentPair.first = *DefIterator; + CurrentPair.second = Location; if (WalkingPhi && Location.Ptr) { + // Mark size as unknown, if the location is not guaranteed to be + // loop-invariant for any possible loop in the function. Setting the size + // to unknown guarantees that any memory accesses that access locations + // after the pointer are considered as clobbers, which is important to + // catch loop carried dependences. + if (Location.Ptr && + !IsGuaranteedLoopInvariant(const_cast(Location.Ptr))) + CurrentPair.second = + Location.getWithNewSize(LocationSize::beforeOrAfterPointer()); PHITransAddr Translator( const_cast(Location.Ptr), OriginalAccess->getBlock()->getModule()->getDataLayout(), nullptr); + if (!Translator.PHITranslateValue(OriginalAccess->getBlock(), DefIterator.getPhiArgBlock(), DT, - false)) { - if (Translator.getAddr() != Location.Ptr) { - CurrentPair.second = Location.getWithNewPtr(Translator.getAddr()); - return; + true)) { + Value *TransAddr = Translator.getAddr(); + if (TransAddr != Location.Ptr) { + CurrentPair.second = CurrentPair.second.getWithNewPtr(TransAddr); + + if (TransAddr && + !IsGuaranteedLoopInvariant(const_cast(TransAddr))) + CurrentPair.second = CurrentPair.second.getWithNewSize( + LocationSize::beforeOrAfterPointer()); + + if (PerformedPhiTranslation) + *PerformedPhiTranslation = true; } - } else { - CurrentPair.second = Location.getWithNewSize(LocationSize::unknown()); - return; } } - CurrentPair.second = Location; } MemoryAccessPair CurrentPair; memoryaccess_def_iterator DefIterator; MemoryLocation Location; MemoryAccess *OriginalAccess = nullptr; - bool WalkingPhi = false; DominatorTree *DT = nullptr; + bool WalkingPhi = false; + bool *PerformedPhiTranslation = nullptr; }; -inline upward_defs_iterator upward_defs_begin(const MemoryAccessPair &Pair, - DominatorTree &DT) { - return upward_defs_iterator(Pair, &DT); +inline upward_defs_iterator +upward_defs_begin(const MemoryAccessPair &Pair, DominatorTree &DT, + bool *PerformedPhiTranslation = nullptr) { + return upward_defs_iterator(Pair, &DT, PerformedPhiTranslation); } inline upward_defs_iterator upward_defs_end() { return upward_defs_iterator(); } diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/MemorySSAUpdater.h b/contrib/llvm-project/llvm/include/llvm/Analysis/MemorySSAUpdater.h index 20588ef083c5..b0bf2e5ead62 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/MemorySSAUpdater.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/MemorySSAUpdater.h @@ -52,8 +52,6 @@ class LoopBlocksRPO; using ValueToValueMapTy = ValueMap; using PhiToDefMap = SmallDenseMap; using CFGUpdate = cfg::Update; -using GraphDiffInvBBPair = - std::pair *, Inverse>; class MemorySSAUpdater { private: @@ -121,8 +119,11 @@ public: ArrayRef ExitBlocks, ArrayRef> VMaps, DominatorTree &DT); - /// Apply CFG updates, analogous with the DT edge updates. - void applyUpdates(ArrayRef Updates, DominatorTree &DT); + /// Apply CFG updates, analogous with the DT edge updates. By default, the + /// DT is assumed to be already up to date. If UpdateDTFirst is true, first + /// update the DT with the same updates. + void applyUpdates(ArrayRef Updates, DominatorTree &DT, + bool UpdateDTFirst = false); /// Apply CFG insert updates, analogous with the DT edge updates. void applyInsertUpdates(ArrayRef Updates, DominatorTree &DT); diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/ModuleDebugInfoPrinter.h b/contrib/llvm-project/llvm/include/llvm/Analysis/ModuleDebugInfoPrinter.h new file mode 100644 index 000000000000..99aa315319b8 --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/ModuleDebugInfoPrinter.h @@ -0,0 +1,29 @@ +//===- ModuleDebugInfoPrinter.h - -----------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_MODULEDEBUGINFOPRINTER_H +#define LLVM_ANALYSIS_MODULEDEBUGINFOPRINTER_H + +#include "llvm/IR/DebugInfo.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +class ModuleDebugInfoPrinterPass + : public PassInfoMixin { + DebugInfoFinder Finder; + raw_ostream &OS; + +public: + explicit ModuleDebugInfoPrinterPass(raw_ostream &OS); + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); +}; +} // end namespace llvm + +#endif // LLVM_ANALYSIS_MODULEDEBUGINFOPRINTER_H diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/MustExecute.h b/contrib/llvm-project/llvm/include/llvm/Analysis/MustExecute.h index a3b7bee97808..df489aaa534d 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/MustExecute.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/MustExecute.h @@ -27,6 +27,8 @@ #include "llvm/ADT/DenseSet.h" #include "llvm/Analysis/EHPersonalities.h" #include "llvm/Analysis/InstructionPrecedenceTracking.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Support/raw_ostream.h" namespace llvm { @@ -541,6 +543,23 @@ private: MustBeExecutedIterator EndIterator; }; +class MustExecutePrinterPass : public PassInfoMixin { + raw_ostream &OS; + +public: + MustExecutePrinterPass(raw_ostream &OS) : OS(OS) {} + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + +class MustBeExecutedContextPrinterPass + : public PassInfoMixin { + raw_ostream &OS; + +public: + MustBeExecutedContextPrinterPass(raw_ostream &OS) : OS(OS) {} + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); +}; + } // namespace llvm #endif diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h b/contrib/llvm-project/llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h index cad1c52f7f87..16c5f6701da0 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h @@ -23,7 +23,6 @@ #define LLVM_LIB_ANALYSIS_OBJCARCANALYSISUTILS_H #include "llvm/ADT/Optional.h" -#include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/ObjCARCInstKind.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/Constants.h" @@ -31,6 +30,9 @@ #include "llvm/IR/ValueHandle.h" namespace llvm { + +class AAResults; + namespace objcarc { /// A handy option to enable/disable all ARC Optimizations. @@ -64,10 +66,9 @@ inline bool ModuleHasARC(const Module &M) { /// This is a wrapper around getUnderlyingObject which also knows how to /// look through objc_retain and objc_autorelease calls, which we know to return /// their argument verbatim. -inline const Value *GetUnderlyingObjCPtr(const Value *V, - const DataLayout &DL) { +inline const Value *GetUnderlyingObjCPtr(const Value *V) { for (;;) { - V = GetUnderlyingObject(V, DL); + V = getUnderlyingObject(V); if (!IsForwarding(GetBasicARCInstKind(V))) break; V = cast(V)->getArgOperand(0); @@ -78,12 +79,12 @@ inline const Value *GetUnderlyingObjCPtr(const Value *V, /// A wrapper for GetUnderlyingObjCPtr used for results memoization. inline const Value * -GetUnderlyingObjCPtrCached(const Value *V, const DataLayout &DL, +GetUnderlyingObjCPtrCached(const Value *V, DenseMap &Cache) { if (auto InCache = Cache.lookup(V)) return InCache; - const Value *Computed = GetUnderlyingObjCPtr(V, DL); + const Value *Computed = GetUnderlyingObjCPtr(V); Cache[V] = const_cast(Computed); return Computed; } @@ -146,7 +147,7 @@ inline bool IsPotentialRetainableObjPtr(const Value *Op) { return false; // Special arguments can not be a valid retainable object pointer. if (const Argument *Arg = dyn_cast(Op)) - if (Arg->hasPassPointeeByValueAttr() || Arg->hasNestAttr() || + if (Arg->hasPassPointeeByValueCopyAttr() || Arg->hasNestAttr() || Arg->hasStructRetAttr()) return false; // Only consider values with pointer types. @@ -162,24 +163,7 @@ inline bool IsPotentialRetainableObjPtr(const Value *Op) { return true; } -inline bool IsPotentialRetainableObjPtr(const Value *Op, - AliasAnalysis &AA) { - // First make the rudimentary check. - if (!IsPotentialRetainableObjPtr(Op)) - return false; - - // Objects in constant memory are not reference-counted. - if (AA.pointsToConstantMemory(Op)) - return false; - - // Pointers in constant memory are not pointing to reference-counted objects. - if (const LoadInst *LI = dyn_cast(Op)) - if (AA.pointsToConstantMemory(LI->getPointerOperand())) - return false; - - // Otherwise assume the worst. - return true; -} +bool IsPotentialRetainableObjPtr(const Value *Op, AAResults &AA); /// Helper for GetARCInstKind. Determines what kind of construct CS /// is. diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/OptimizationRemarkEmitter.h b/contrib/llvm-project/llvm/include/llvm/Analysis/OptimizationRemarkEmitter.h index ab97d5b8504e..9815dd05cd1c 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/OptimizationRemarkEmitter.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/OptimizationRemarkEmitter.h @@ -88,8 +88,14 @@ public: /// provide more context so that non-trivial false positives can be quickly /// detected by the user. bool allowExtraAnalysis(StringRef PassName) const { - return (F->getContext().getLLVMRemarkStreamer() || - F->getContext().getDiagHandlerPtr()->isAnyRemarkEnabled(PassName)); + return OptimizationRemarkEmitter::allowExtraAnalysis(*F, PassName); + } + static bool allowExtraAnalysis(const Function &F, StringRef PassName) { + return allowExtraAnalysis(F.getContext(), PassName); + } + static bool allowExtraAnalysis(LLVMContext &Ctx, StringRef PassName) { + return Ctx.getLLVMRemarkStreamer() || + Ctx.getDiagHandlerPtr()->isAnyRemarkEnabled(PassName); } private: diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/PhiValues.h b/contrib/llvm-project/llvm/include/llvm/Analysis/PhiValues.h index ea879d727282..c0e91c8b0bdf 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/PhiValues.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/PhiValues.h @@ -21,7 +21,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/IR/PassManager.h" #include "llvm/IR/ValueHandle.h" @@ -40,7 +40,7 @@ class Function; /// it is queried. class PhiValues { public: - using ValueSet = SmallPtrSet; + using ValueSet = SmallSetVector; /// Construct an empty PhiValues. PhiValues(const Function &F) : F(F) {} @@ -70,8 +70,7 @@ public: FunctionAnalysisManager::Invalidator &); private: - using PhiSet = SmallPtrSet; - using ConstValueSet = SmallPtrSet; + using ConstValueSet = SmallSetVector; /// The next depth number to be used by processPhi. unsigned int NextDepthNumber = 1; diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/ProfileSummaryInfo.h b/contrib/llvm-project/llvm/include/llvm/Analysis/ProfileSummaryInfo.h index a1fea9fefc9a..a4e6ffc3dd58 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/ProfileSummaryInfo.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/ProfileSummaryInfo.h @@ -25,7 +25,6 @@ class BasicBlock; class BlockFrequencyInfo; class CallBase; class Function; -class ProfileSummary; /// Analysis providing profile information. /// @@ -39,7 +38,7 @@ class ProfileSummary; // units. This would require making this depend on BFI. class ProfileSummaryInfo { private: - Module &M; + const Module &M; std::unique_ptr Summary; void computeThresholds(); // Count thresholds to answer isHotCount and isColdCount queries. @@ -59,7 +58,8 @@ private: mutable DenseMap ThresholdCache; public: - ProfileSummaryInfo(Module &M) : M(M) { refresh(); } + ProfileSummaryInfo(const Module &M) : M(M) { refresh(); } + ProfileSummaryInfo(ProfileSummaryInfo &&Arg) = default; /// If no summary is present, attempt to refresh. diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/RegionInfo.h b/contrib/llvm-project/llvm/include/llvm/Analysis/RegionInfo.h index b0336c559774..f93081d6f51d 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/RegionInfo.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/RegionInfo.h @@ -59,7 +59,6 @@ namespace llvm { class DominanceFrontier; -class DominatorTree; class Loop; class LoopInfo; class PostDominatorTree; @@ -877,8 +876,6 @@ public: void verifyAnalysis() const; }; -class Region; - class RegionNode : public RegionNodeBase> { public: inline RegionNode(Region *Parent, BasicBlock *Entry, bool isSubRegion = false) diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/RegionInfoImpl.h b/contrib/llvm-project/llvm/include/llvm/Analysis/RegionInfoImpl.h index 8d9ec646f519..b694effb2229 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/RegionInfoImpl.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/RegionInfoImpl.h @@ -585,10 +585,8 @@ bool RegionInfoBase::isRegion(BlockT *entry, BlockT *exit) const { // Exit is the header of a loop that contains the entry. In this case, // the dominance frontier must only contain the exit. if (!DT->dominates(entry, exit)) { - for (typename DST::iterator SI = entrySuccs->begin(), - SE = entrySuccs->end(); - SI != SE; ++SI) { - if (*SI != exit && *SI != entry) + for (BlockT *successor : *entrySuccs) { + if (successor != exit && successor != entry) return false; } @@ -817,8 +815,7 @@ void RegionInfoBase::verifyAnalysis() const { // Region pass manager support. template typename Tr::RegionT *RegionInfoBase::getRegionFor(BlockT *BB) const { - typename BBtoRegionMap::const_iterator I = BBtoRegion.find(BB); - return I != BBtoRegion.end() ? I->second : nullptr; + return BBtoRegion.lookup(BB); } template @@ -889,8 +886,7 @@ typename Tr::RegionT *RegionInfoBase::getCommonRegion(RegionT *A, template typename Tr::RegionT * RegionInfoBase::getCommonRegion(SmallVectorImpl &Regions) const { - RegionT *ret = Regions.back(); - Regions.pop_back(); + RegionT *ret = Regions.pop_back_val(); for (RegionT *R : Regions) ret = getCommonRegion(ret, R); diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/RegionPass.h b/contrib/llvm-project/llvm/include/llvm/Analysis/RegionPass.h index 995c5dca3de3..5c7fa5f56693 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/RegionPass.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/RegionPass.h @@ -85,8 +85,6 @@ protected: /// The pass manager to schedule RegionPasses. class RGPassManager : public FunctionPass, public PMDataManager { std::deque RQ; - bool skipThisRegion; - bool redoThisRegion; RegionInfo *RI; Region *CurrentRegion; diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/ReplayInlineAdvisor.h b/contrib/llvm-project/llvm/include/llvm/Analysis/ReplayInlineAdvisor.h new file mode 100644 index 000000000000..3018bcc241d8 --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/ReplayInlineAdvisor.h @@ -0,0 +1,41 @@ +//===- ReplayInlineAdvisor.h - Replay Inline Advisor interface -*- C++ --*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +#ifndef LLVM_ANALYSIS_REPLAYINLINEADVISOR_H +#define LLVM_ANALYSIS_REPLAYINLINEADVISOR_H + +#include "llvm/ADT/StringSet.h" +#include "llvm/Analysis/InlineAdvisor.h" +#include "llvm/IR/LLVMContext.h" + +namespace llvm { +class BasicBlock; +class CallBase; +class Function; +class Module; +class OptimizationRemarkEmitter; + +/// Replay inline advisor that uses optimization remarks from inlining of +/// previous build to guide current inlining. This is useful for inliner tuning. +class ReplayInlineAdvisor : public InlineAdvisor { +public: + ReplayInlineAdvisor(Module &M, FunctionAnalysisManager &FAM, + LLVMContext &Context, + std::unique_ptr OriginalAdvisor, + StringRef RemarksFile, bool EmitRemarks); + std::unique_ptr getAdviceImpl(CallBase &CB) override; + bool areReplayRemarksLoaded() const { return HasReplayRemarks; } + +private: + StringSet<> InlineSitesFromRemarks; + std::unique_ptr OriginalAdvisor; + bool HasReplayRemarks = false; + bool EmitRemarks = false; +}; +} // namespace llvm +#endif // LLVM_ANALYSIS_REPLAYINLINEADVISOR_H diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/ScalarEvolution.h b/contrib/llvm-project/llvm/include/llvm/Analysis/ScalarEvolution.h index 81c5fc932588..b3f199de2cfa 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/ScalarEvolution.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/ScalarEvolution.h @@ -70,6 +70,7 @@ class StructType; class TargetLibraryInfo; class Type; class Value; +enum SCEVTypes : unsigned short; /// This class represents an analyzed expression in the program. These are /// opaque objects that the client is not allowed to do much with directly. @@ -82,7 +83,7 @@ class SCEV : public FoldingSetNode { FoldingSetNodeIDRef FastID; // The SCEV baseclass this node corresponds to - const unsigned short SCEVType; + const SCEVTypes SCEVType; protected: // Estimated complexity of this node's expression tree size. @@ -119,13 +120,13 @@ public: NoWrapMask = (1 << 3) - 1 }; - explicit SCEV(const FoldingSetNodeIDRef ID, unsigned SCEVTy, + explicit SCEV(const FoldingSetNodeIDRef ID, SCEVTypes SCEVTy, unsigned short ExpressionSize) : FastID(ID), SCEVType(SCEVTy), ExpressionSize(ExpressionSize) {} SCEV(const SCEV &) = delete; SCEV &operator=(const SCEV &) = delete; - unsigned getSCEVType() const { return SCEVType; } + SCEVTypes getSCEVType() const { return SCEVType; } /// Return the LLVM type of this SCEV expression. Type *getType() const; @@ -511,6 +512,7 @@ public: const SCEV *getConstant(ConstantInt *V); const SCEV *getConstant(const APInt &Val); const SCEV *getConstant(Type *Ty, uint64_t V, bool isSigned = false); + const SCEV *getPtrToIntExpr(const SCEV *Op, Type *Ty, unsigned Depth = 0); const SCEV *getTruncateExpr(const SCEV *Op, Type *Ty, unsigned Depth = 0); const SCEV *getZeroExtendExpr(const SCEV *Op, Type *Ty, unsigned Depth = 0); const SCEV *getSignExtendExpr(const SCEV *Op, Type *Ty, unsigned Depth = 0); @@ -572,7 +574,9 @@ public: /// \p IndexExprs The expressions for the indices. const SCEV *getGEPExpr(GEPOperator *GEP, const SmallVectorImpl &IndexExprs); - const SCEV *getMinMaxExpr(unsigned Kind, + const SCEV *getAbsExpr(const SCEV *Op, bool IsNSW); + const SCEV *getSignumExpr(const SCEV *Op); + const SCEV *getMinMaxExpr(SCEVTypes Kind, SmallVectorImpl &Operands); const SCEV *getSMaxExpr(const SCEV *LHS, const SCEV *RHS); const SCEV *getSMaxExpr(SmallVectorImpl &Operands); @@ -591,9 +595,22 @@ public: /// Return a SCEV for the constant 1 of a specific type. const SCEV *getOne(Type *Ty) { return getConstant(Ty, 1); } - /// Return an expression for sizeof AllocTy that is type IntTy + /// Return a SCEV for the constant -1 of a specific type. + const SCEV *getMinusOne(Type *Ty) { + return getConstant(Ty, -1, /*isSigned=*/true); + } + + /// Return an expression for sizeof ScalableTy that is type IntTy, where + /// ScalableTy is a scalable vector type. + const SCEV *getSizeOfScalableVectorExpr(Type *IntTy, + ScalableVectorType *ScalableTy); + + /// Return an expression for the alloc size of AllocTy that is type IntTy const SCEV *getSizeOfExpr(Type *IntTy, Type *AllocTy); + /// Return an expression for the store size of StoreTy that is type IntTy + const SCEV *getStoreSizeOfExpr(Type *IntTy, Type *StoreTy); + /// Return an expression for offsetof on the given field with type IntTy const SCEV *getOffsetOfExpr(Type *IntTy, StructType *STy, unsigned FieldNo); @@ -677,6 +694,12 @@ public: bool isLoopEntryGuardedByCond(const Loop *L, ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS); + /// Test whether entry to the basic block is protected by a conditional + /// between LHS and RHS. + bool isBasicBlockEntryGuardedByCond(const BasicBlock *BB, + ICmpInst::Predicate Pred, const SCEV *LHS, + const SCEV *RHS); + /// Test whether the backedge of the loop is protected by a conditional /// between LHS and RHS. This is used to eliminate casts. bool isLoopBackedgeGuardedByCond(const Loop *L, ICmpInst::Predicate Pred, @@ -696,7 +719,8 @@ public: /// before taking the branch. For loops with multiple exits, it may not be /// the number times that the loop header executes if the loop exits /// prematurely via another branch. - unsigned getSmallConstantTripCount(const Loop *L, BasicBlock *ExitingBlock); + unsigned getSmallConstantTripCount(const Loop *L, + const BasicBlock *ExitingBlock); /// Returns the upper bound of the loop trip count as a normal unsigned /// value. @@ -718,8 +742,7 @@ public: /// for getSmallConstantTripCount, this assumes that control exits the loop /// via ExitingBlock. unsigned getSmallConstantTripMultiple(const Loop *L, - BasicBlock *ExitingBlock); - + const BasicBlock *ExitingBlock); /// The terms "backedge taken count" and "exit count" are used /// interchangeably to refer to the number of times the backedge of a loop @@ -730,6 +753,8 @@ public: Exact, /// A constant which provides an upper bound on the exact trip count. ConstantMaximum, + /// An expression which provides an upper bound on the exact trip count. + SymbolicMaximum, }; /// Return the number of times the backedge executes before the given exit @@ -737,8 +762,8 @@ public: /// For a single exit loop, this value is equivelent to the result of /// getBackedgeTakenCount. The loop is guaranteed to exit (via *some* exit) /// before the backedge is executed (ExitCount + 1) times. Note that there - /// is no guarantee about *which* exit is taken on the exiting iteration. - const SCEV *getExitCount(const Loop *L, BasicBlock *ExitingBlock, + /// is no guarantee about *which* exit is taken on the exiting iteration. + const SCEV *getExitCount(const Loop *L, const BasicBlock *ExitingBlock, ExitCountKind Kind = Exact); /// If the specified loop has a predictable backedge-taken count, return it, @@ -766,7 +791,15 @@ public: /// SCEVCouldNotCompute object. const SCEV *getConstantMaxBackedgeTakenCount(const Loop *L) { return getBackedgeTakenCount(L, ConstantMaximum); - } + } + + /// When successful, this returns a SCEV that is greater than or equal + /// to (i.e. a "conservative over-approximation") of the value returend by + /// getBackedgeTakenCount. If such a value cannot be computed, it returns the + /// SCEVCouldNotCompute object. + const SCEV *getSymbolicMaxBackedgeTakenCount(const Loop *L) { + return getBackedgeTakenCount(L, SymbolicMaximum); + } /// Return true if the backedge taken count is either the value returned by /// getConstantMaxBackedgeTakenCount or zero. @@ -905,32 +938,61 @@ public: bool isKnownPredicate(ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS); + /// Test if the given expression is known to satisfy the condition described + /// by Pred, LHS, and RHS in the given Context. + bool isKnownPredicateAt(ICmpInst::Predicate Pred, const SCEV *LHS, + const SCEV *RHS, const Instruction *Context); + /// Test if the condition described by Pred, LHS, RHS is known to be true on /// every iteration of the loop of the recurrency LHS. bool isKnownOnEveryIteration(ICmpInst::Predicate Pred, const SCEVAddRecExpr *LHS, const SCEV *RHS); - /// Return true if, for all loop invariant X, the predicate "LHS `Pred` X" - /// is monotonically increasing or decreasing. In the former case set - /// `Increasing` to true and in the latter case set `Increasing` to false. - /// /// A predicate is said to be monotonically increasing if may go from being /// false to being true as the loop iterates, but never the other way /// around. A predicate is said to be monotonically decreasing if may go /// from being true to being false as the loop iterates, but never the other /// way around. - bool isMonotonicPredicate(const SCEVAddRecExpr *LHS, ICmpInst::Predicate Pred, - bool &Increasing); - - /// Return true if the result of the predicate LHS `Pred` RHS is loop - /// invariant with respect to L. Set InvariantPred, InvariantLHS and - /// InvariantLHS so that InvariantLHS `InvariantPred` InvariantRHS is the - /// loop invariant form of LHS `Pred` RHS. - bool isLoopInvariantPredicate(ICmpInst::Predicate Pred, const SCEV *LHS, - const SCEV *RHS, const Loop *L, - ICmpInst::Predicate &InvariantPred, - const SCEV *&InvariantLHS, - const SCEV *&InvariantRHS); + enum MonotonicPredicateType { + MonotonicallyIncreasing, + MonotonicallyDecreasing + }; + + /// If, for all loop invariant X, the predicate "LHS `Pred` X" is + /// monotonically increasing or decreasing, returns + /// Some(MonotonicallyIncreasing) and Some(MonotonicallyDecreasing) + /// respectively. If we could not prove either of these facts, returns None. + Optional + getMonotonicPredicateType(const SCEVAddRecExpr *LHS, + ICmpInst::Predicate Pred); + + struct LoopInvariantPredicate { + ICmpInst::Predicate Pred; + const SCEV *LHS; + const SCEV *RHS; + + LoopInvariantPredicate(ICmpInst::Predicate Pred, const SCEV *LHS, + const SCEV *RHS) + : Pred(Pred), LHS(LHS), RHS(RHS) {} + }; + /// If the result of the predicate LHS `Pred` RHS is loop invariant with + /// respect to L, return a LoopInvariantPredicate with LHS and RHS being + /// invariants, available at L's entry. Otherwise, return None. + Optional + getLoopInvariantPredicate(ICmpInst::Predicate Pred, const SCEV *LHS, + const SCEV *RHS, const Loop *L); + + /// If the result of the predicate LHS `Pred` RHS is loop invariant with + /// respect to L at given Context during at least first MaxIter iterations, + /// return a LoopInvariantPredicate with LHS and RHS being invariants, + /// available at L's entry. Otherwise, return None. The predicate should be + /// the loop's exit condition. + Optional + getLoopInvariantExitCondDuringFirstIterations(ICmpInst::Predicate Pred, + const SCEV *LHS, + const SCEV *RHS, const Loop *L, + const Instruction *Context, + const SCEV *MaxIter); /// Simplify LHS and RHS in a comparison with predicate Pred. Return true /// iff any changes were made. If the operands are provably equal or @@ -1101,6 +1163,20 @@ public: const SCEV *S, const Loop *L, SmallPtrSetImpl &Preds); + /// Compute \p LHS - \p RHS and returns the result as an APInt if it is a + /// constant, and None if it isn't. + /// + /// This is intended to be a cheaper version of getMinusSCEV. We can be + /// frugal here since we just bail out of actually constructing and + /// canonicalizing an expression in the cases where the result isn't going + /// to be a constant. + Optional computeConstantDifference(const SCEV *LHS, const SCEV *RHS); + + /// Update no-wrap flags of an AddRec. This may drop the cached info about + /// this AddRec (such as range info) in case if new flags may potentially + /// sharpen it. + void setNoWrapFlags(SCEVAddRecExpr *AddRec, SCEV::NoWrapFlags Flags); + private: /// A CallbackVH to arrange for ScalarEvolution to be notified whenever a /// Value is deleted. @@ -1181,7 +1257,7 @@ private: ValueExprMapType ValueExprMap; /// Mark predicate values currently being processed by isImpliedCond. - SmallPtrSet PendingLoopPredicates; + SmallPtrSet PendingLoopPredicates; /// Mark SCEVUnknown Phis currently being processed by getRangeRef. SmallPtrSet PendingPhiRanges; @@ -1284,39 +1360,41 @@ private: /// never have more than one computable exit. SmallVector ExitNotTaken; - /// The pointer part of \c MaxAndComplete is an expression indicating the - /// least maximum backedge-taken count of the loop that is known, or a - /// SCEVCouldNotCompute. This expression is only valid if the predicates - /// associated with all loop exits are true. - /// - /// The integer part of \c MaxAndComplete is a boolean indicating if \c - /// ExitNotTaken has an element for every exiting block in the loop. - PointerIntPair MaxAndComplete; + /// Expression indicating the least constant maximum backedge-taken count of + /// the loop that is known, or a SCEVCouldNotCompute. This expression is + /// only valid if the redicates associated with all loop exits are true. + const SCEV *ConstantMax; + + /// Indicating if \c ExitNotTaken has an element for every exiting block in + /// the loop. + bool IsComplete; + + /// Expression indicating the least maximum backedge-taken count of the loop + /// that is known, or a SCEVCouldNotCompute. Lazily computed on first query. + const SCEV *SymbolicMax = nullptr; /// True iff the backedge is taken either exactly Max or zero times. bool MaxOrZero = false; - /// \name Helper projection functions on \c MaxAndComplete. - /// @{ - bool isComplete() const { return MaxAndComplete.getInt(); } - const SCEV *getMax() const { return MaxAndComplete.getPointer(); } - /// @} + bool isComplete() const { return IsComplete; } + const SCEV *getConstantMax() const { return ConstantMax; } public: - BackedgeTakenInfo() : MaxAndComplete(nullptr, 0) {} + BackedgeTakenInfo() : ConstantMax(nullptr), IsComplete(false) {} BackedgeTakenInfo(BackedgeTakenInfo &&) = default; BackedgeTakenInfo &operator=(BackedgeTakenInfo &&) = default; using EdgeExitInfo = std::pair; /// Initialize BackedgeTakenInfo from a list of exact exit counts. - BackedgeTakenInfo(ArrayRef ExitCounts, bool Complete, - const SCEV *MaxCount, bool MaxOrZero); + BackedgeTakenInfo(ArrayRef ExitCounts, bool IsComplete, + const SCEV *ConstantMax, bool MaxOrZero); /// Test whether this BackedgeTakenInfo contains any computed information, /// or whether it's all SCEVCouldNotCompute values. bool hasAnyInfo() const { - return !ExitNotTaken.empty() || !isa(getMax()); + return !ExitNotTaken.empty() || + !isa(getConstantMax()); } /// Test whether this BackedgeTakenInfo contains complete information. @@ -1347,17 +1425,22 @@ private: /// edge, or SCEVCouldNotCompute. The loop is guaranteed not to exit via /// this block before this number of iterations, but may exit via another /// block. - const SCEV *getExact(BasicBlock *ExitingBlock, ScalarEvolution *SE) const; + const SCEV *getExact(const BasicBlock *ExitingBlock, + ScalarEvolution *SE) const; + + /// Get the constant max backedge taken count for the loop. + const SCEV *getConstantMax(ScalarEvolution *SE) const; - /// Get the max backedge taken count for the loop. - const SCEV *getMax(ScalarEvolution *SE) const; + /// Get the constant max backedge taken count for the particular loop exit. + const SCEV *getConstantMax(const BasicBlock *ExitingBlock, + ScalarEvolution *SE) const; - /// Get the max backedge taken count for the particular loop exit. - const SCEV *getMax(BasicBlock *ExitingBlock, ScalarEvolution *SE) const; + /// Get the symbolic max backedge taken count for the loop. + const SCEV *getSymbolicMax(const Loop *L, ScalarEvolution *SE); /// Return true if the number of times this backedge is taken is either the - /// value returned by getMax or zero. - bool isMaxOrZero(ScalarEvolution *SE) const; + /// value returned by getConstantMax or zero. + bool isConstantMaxOrZero(ScalarEvolution *SE) const; /// Return true if any backedge taken count expressions refer to the given /// subexpression. @@ -1462,6 +1545,13 @@ private: ConstantRange getRangeForAffineAR(const SCEV *Start, const SCEV *Stop, const SCEV *MaxBECount, unsigned BitWidth); + /// Determines the range for the affine non-self-wrapping SCEVAddRecExpr {\p + /// Start,+,\p Stop}. + ConstantRange getRangeForAffineNoSelfWrappingAR(const SCEVAddRecExpr *AddRec, + const SCEV *MaxBECount, + unsigned BitWidth, + RangeSignHint SignHint); + /// Try to compute a range for the affine SCEVAddRecExpr {\p Start,+,\p /// Stop} by "factoring out" a ternary expression from the add recurrence. /// Helper called by \c getRange. @@ -1507,7 +1597,7 @@ private: /// Return the BackedgeTakenInfo for the given loop, lazily computing new /// values if the loop hasn't been analyzed yet. The returned result is /// guaranteed not to be predicated. - const BackedgeTakenInfo &getBackedgeTakenInfo(const Loop *L); + BackedgeTakenInfo &getBackedgeTakenInfo(const Loop *L); /// Similar to getBackedgeTakenInfo, but will add predicates as required /// with the purpose of returning complete information. @@ -1540,6 +1630,11 @@ private: bool ExitIfTrue, bool ControlsExit, bool AllowPredicates = false); + /// Return a symbolic upper bound for the backedge taken count of the loop. + /// This is more general than getConstantMaxBackedgeTakenCount as it returns + /// an arbitrary expression as opposed to only constants. + const SCEV *computeSymbolicMaxBackedgeTakenCount(const Loop *L); + // Helper functions for computeExitLimitFromCond to avoid exponential time // complexity. @@ -1577,6 +1672,10 @@ private: Value *ExitCond, bool ExitIfTrue, bool ControlsExit, bool AllowPredicates); + Optional + computeExitLimitFromCondFromBinOp(ExitLimitCacheTy &Cache, const Loop *L, + Value *ExitCond, bool ExitIfTrue, + bool ControlsExit, bool AllowPredicates); /// Compute the number of times the backedge of the specified loop will /// execute if its exit condition were a conditional branch of the ICmpInst @@ -1655,27 +1754,44 @@ private: /// Return a predecessor of BB (which may not be an immediate predecessor) /// which has exactly one successor from which BB is reachable, or null if /// no such block is found. - std::pair - getPredecessorWithUniqueSuccessorForBB(BasicBlock *BB); + std::pair + getPredecessorWithUniqueSuccessorForBB(const BasicBlock *BB) const; /// Test whether the condition described by Pred, LHS, and RHS is true - /// whenever the given FoundCondValue value evaluates to true. + /// whenever the given FoundCondValue value evaluates to true in given + /// Context. If Context is nullptr, then the found predicate is true + /// everywhere. LHS and FoundLHS may have different type width. bool isImpliedCond(ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS, - Value *FoundCondValue, bool Inverse); + const Value *FoundCondValue, bool Inverse, + const Instruction *Context = nullptr); + + /// Test whether the condition described by Pred, LHS, and RHS is true + /// whenever the given FoundCondValue value evaluates to true in given + /// Context. If Context is nullptr, then the found predicate is true + /// everywhere. LHS and FoundLHS must have same type width. + bool isImpliedCondBalancedTypes(ICmpInst::Predicate Pred, const SCEV *LHS, + const SCEV *RHS, + ICmpInst::Predicate FoundPred, + const SCEV *FoundLHS, const SCEV *FoundRHS, + const Instruction *Context); /// Test whether the condition described by Pred, LHS, and RHS is true /// whenever the condition described by FoundPred, FoundLHS, FoundRHS is - /// true. + /// true in given Context. If Context is nullptr, then the found predicate is + /// true everywhere. bool isImpliedCond(ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS, ICmpInst::Predicate FoundPred, const SCEV *FoundLHS, - const SCEV *FoundRHS); + const SCEV *FoundRHS, + const Instruction *Context = nullptr); /// Test whether the condition described by Pred, LHS, and RHS is true /// whenever the condition described by Pred, FoundLHS, and FoundRHS is - /// true. + /// true in given Context. If Context is nullptr, then the found predicate is + /// true everywhere. bool isImpliedCondOperands(ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS, const SCEV *FoundLHS, - const SCEV *FoundRHS); + const SCEV *FoundRHS, + const Instruction *Context = nullptr); /// Test whether the condition described by Pred, LHS, and RHS is true /// whenever the condition described by Pred, FoundLHS, and FoundRHS is @@ -1708,7 +1824,7 @@ private: /// Return true if the condition denoted by \p LHS \p Pred \p RHS is implied /// by a call to @llvm.experimental.guard in \p BB. - bool isImpliedViaGuard(BasicBlock *BB, ICmpInst::Predicate Pred, + bool isImpliedViaGuard(const BasicBlock *BB, ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS); /// Test whether the condition described by Pred, LHS, and RHS is true @@ -1722,6 +1838,18 @@ private: const SCEV *FoundLHS, const SCEV *FoundRHS); + /// Test whether the condition described by Pred, LHS, and RHS is true + /// whenever the condition described by Pred, FoundLHS, and FoundRHS is + /// true. + /// + /// This routine tries to weaken the known condition basing on fact that + /// FoundLHS is an AddRec. + bool isImpliedCondOperandsViaAddRecStart(ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS, + const SCEV *FoundLHS, + const SCEV *FoundRHS, + const Instruction *Context); + /// Test whether the condition described by Pred, LHS, and RHS is true /// whenever the condition described by Pred, FoundLHS, and FoundRHS is /// true. @@ -1762,15 +1890,6 @@ private: bool splitBinaryAdd(const SCEV *Expr, const SCEV *&L, const SCEV *&R, SCEV::NoWrapFlags &Flags); - /// Compute \p LHS - \p RHS and returns the result as an APInt if it is a - /// constant, and None if it isn't. - /// - /// This is intended to be a cheaper version of getMinusSCEV. We can be - /// frugal here since we just bail out of actually constructing and - /// canonicalizing an expression in the cases where the result isn't going - /// to be a constant. - Optional computeConstantDifference(const SCEV *LHS, const SCEV *RHS); - /// Drop memoized information computed for S. void forgetMemoizedResults(const SCEV *S); @@ -1793,8 +1912,17 @@ private: /// Try to prove NSW or NUW on \p AR relying on ConstantRange manipulation. SCEV::NoWrapFlags proveNoWrapViaConstantRanges(const SCEVAddRecExpr *AR); - bool isMonotonicPredicateImpl(const SCEVAddRecExpr *LHS, - ICmpInst::Predicate Pred, bool &Increasing); + /// Try to prove NSW on \p AR by proving facts about conditions known on + /// entry and backedge. + SCEV::NoWrapFlags proveNoSignedWrapViaInduction(const SCEVAddRecExpr *AR); + + /// Try to prove NUW on \p AR by proving facts about conditions known on + /// entry and backedge. + SCEV::NoWrapFlags proveNoUnsignedWrapViaInduction(const SCEVAddRecExpr *AR); + + Optional + getMonotonicPredicateTypeImpl(const SCEVAddRecExpr *LHS, + ICmpInst::Predicate Pred); /// Return SCEV no-wrap flags that can be proven based on reasoning about /// how poison produced from no-wrap flags on this value (e.g. a nuw add) @@ -1893,6 +2021,9 @@ private: /// Assign A and B to LHS and RHS, respectively. bool matchURem(const SCEV *Expr, const SCEV *&LHS, const SCEV *&RHS); + /// Try to apply information from loop guards for \p L to \p Expr. + const SCEV *applyLoopGuards(const SCEV *Expr, const Loop *L); + /// Look for a SCEV expression with type `SCEVType` and operands `Ops` in /// `UniqueSCEVs`. /// @@ -1901,7 +2032,7 @@ private: /// constructed to look up the SCEV and the third component is the insertion /// point. std::tuple - findExistingSCEVInCache(int SCEVType, ArrayRef Ops); + findExistingSCEVInCache(SCEVTypes SCEVType, ArrayRef Ops); FoldingSet UniqueSCEVs; FoldingSet UniquePreds; diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/ScalarEvolutionDivision.h b/contrib/llvm-project/llvm/include/llvm/Analysis/ScalarEvolutionDivision.h index 480f92c117a0..24f0c51487bd 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/ScalarEvolutionDivision.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/ScalarEvolutionDivision.h @@ -33,6 +33,7 @@ public: // Except in the trivial case described above, we do not know how to divide // Expr by Denominator for the following functions with empty implementation. + void visitPtrToIntExpr(const SCEVPtrToIntExpr *Numerator) {} void visitTruncateExpr(const SCEVTruncateExpr *Numerator) {} void visitZeroExtendExpr(const SCEVZeroExtendExpr *Numerator) {} void visitSignExtendExpr(const SCEVSignExtendExpr *Numerator) {} diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h b/contrib/llvm-project/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h index 0076e02ae1bf..37e675f08afc 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h @@ -35,12 +35,12 @@ class ConstantRange; class Loop; class Type; - enum SCEVTypes { + enum SCEVTypes : unsigned short { // These should be ordered in terms of increasing complexity to make the // folders simpler. scConstant, scTruncate, scZeroExtend, scSignExtend, scAddExpr, scMulExpr, scUDivExpr, scAddRecExpr, scUMaxExpr, scSMaxExpr, scUMinExpr, scSMinExpr, - scUnknown, scCouldNotCompute + scPtrToInt, scUnknown, scCouldNotCompute }; /// This class represents a constant integer value. @@ -74,16 +74,56 @@ class Type; /// This is the base class for unary cast operator classes. class SCEVCastExpr : public SCEV { protected: - const SCEV *Op; + std::array Operands; Type *Ty; - SCEVCastExpr(const FoldingSetNodeIDRef ID, - unsigned SCEVTy, const SCEV *op, Type *ty); + SCEVCastExpr(const FoldingSetNodeIDRef ID, SCEVTypes SCEVTy, const SCEV *op, + Type *ty); public: - const SCEV *getOperand() const { return Op; } + const SCEV *getOperand() const { return Operands[0]; } + const SCEV *getOperand(unsigned i) const { + assert(i == 0 && "Operand index out of range!"); + return Operands[0]; + } + using op_iterator = std::array::const_iterator; + using op_range = iterator_range; + + op_range operands() const { + return make_range(Operands.begin(), Operands.end()); + } + size_t getNumOperands() const { return 1; } Type *getType() const { return Ty; } + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const SCEV *S) { + return S->getSCEVType() == scPtrToInt || S->getSCEVType() == scTruncate || + S->getSCEVType() == scZeroExtend || + S->getSCEVType() == scSignExtend; + } + }; + + /// This class represents a cast from a pointer to a pointer-sized integer + /// value. + class SCEVPtrToIntExpr : public SCEVCastExpr { + friend class ScalarEvolution; + + SCEVPtrToIntExpr(const FoldingSetNodeIDRef ID, const SCEV *Op, Type *ITy); + + public: + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const SCEV *S) { + return S->getSCEVType() == scPtrToInt; + } + }; + + /// This is the base class for unary integral cast operator classes. + class SCEVIntegralCastExpr : public SCEVCastExpr { + protected: + SCEVIntegralCastExpr(const FoldingSetNodeIDRef ID, SCEVTypes SCEVTy, + const SCEV *op, Type *ty); + + public: /// Methods for support type inquiry through isa, cast, and dyn_cast: static bool classof(const SCEV *S) { return S->getSCEVType() == scTruncate || @@ -94,7 +134,7 @@ class Type; /// This class represents a truncation of an integer value to a /// smaller integer value. - class SCEVTruncateExpr : public SCEVCastExpr { + class SCEVTruncateExpr : public SCEVIntegralCastExpr { friend class ScalarEvolution; SCEVTruncateExpr(const FoldingSetNodeIDRef ID, @@ -109,7 +149,7 @@ class Type; /// This class represents a zero extension of a small integer value /// to a larger integer value. - class SCEVZeroExtendExpr : public SCEVCastExpr { + class SCEVZeroExtendExpr : public SCEVIntegralCastExpr { friend class ScalarEvolution; SCEVZeroExtendExpr(const FoldingSetNodeIDRef ID, @@ -124,7 +164,7 @@ class Type; /// This class represents a sign extension of a small integer value /// to a larger integer value. - class SCEVSignExtendExpr : public SCEVCastExpr { + class SCEVSignExtendExpr : public SCEVIntegralCastExpr { friend class ScalarEvolution; SCEVSignExtendExpr(const FoldingSetNodeIDRef ID, @@ -263,16 +303,28 @@ class Type; class SCEVUDivExpr : public SCEV { friend class ScalarEvolution; - const SCEV *LHS; - const SCEV *RHS; + std::array Operands; SCEVUDivExpr(const FoldingSetNodeIDRef ID, const SCEV *lhs, const SCEV *rhs) - : SCEV(ID, scUDivExpr, computeExpressionSize({lhs, rhs})), LHS(lhs), - RHS(rhs) {} + : SCEV(ID, scUDivExpr, computeExpressionSize({lhs, rhs})) { + Operands[0] = lhs; + Operands[1] = rhs; + } public: - const SCEV *getLHS() const { return LHS; } - const SCEV *getRHS() const { return RHS; } + const SCEV *getLHS() const { return Operands[0]; } + const SCEV *getRHS() const { return Operands[1]; } + size_t getNumOperands() const { return 2; } + const SCEV *getOperand(unsigned i) const { + assert((i == 0 || i == 1) && "Operand index out of range!"); + return i == 0 ? getLHS() : getRHS(); + } + + using op_iterator = std::array::const_iterator; + using op_range = iterator_range; + op_range operands() const { + return make_range(Operands.begin(), Operands.end()); + } Type *getType() const { // In most cases the types of LHS and RHS will be the same, but in some @@ -389,7 +441,7 @@ class Type; public: static bool classof(const SCEV *S) { - return isMinMaxType(static_cast(S->getSCEVType())); + return isMinMaxType(S->getSCEVType()); } static enum SCEVTypes negate(enum SCEVTypes T) { @@ -518,6 +570,8 @@ class Type; switch (S->getSCEVType()) { case scConstant: return ((SC*)this)->visitConstant((const SCEVConstant*)S); + case scPtrToInt: + return ((SC *)this)->visitPtrToIntExpr((const SCEVPtrToIntExpr *)S); case scTruncate: return ((SC*)this)->visitTruncateExpr((const SCEVTruncateExpr*)S); case scZeroExtend: @@ -544,9 +598,8 @@ class Type; return ((SC*)this)->visitUnknown((const SCEVUnknown*)S); case scCouldNotCompute: return ((SC*)this)->visitCouldNotCompute((const SCEVCouldNotCompute*)S); - default: - llvm_unreachable("Unknown SCEV type!"); } + llvm_unreachable("Unknown SCEV kind!"); } RetVal visitCouldNotCompute(const SCEVCouldNotCompute *S) { @@ -583,12 +636,13 @@ class Type; switch (S->getSCEVType()) { case scConstant: case scUnknown: - break; + continue; + case scPtrToInt: case scTruncate: case scZeroExtend: case scSignExtend: push(cast(S)->getOperand()); - break; + continue; case scAddExpr: case scMulExpr: case scSMaxExpr: @@ -598,18 +652,17 @@ class Type; case scAddRecExpr: for (const auto *Op : cast(S)->operands()) push(Op); - break; + continue; case scUDivExpr: { const SCEVUDivExpr *UDiv = cast(S); push(UDiv->getLHS()); push(UDiv->getRHS()); - break; + continue; } case scCouldNotCompute: llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!"); - default: - llvm_unreachable("Unknown SCEV kind!"); } + llvm_unreachable("Unknown SCEV kind!"); } } }; @@ -677,6 +730,13 @@ class Type; return Constant; } + const SCEV *visitPtrToIntExpr(const SCEVPtrToIntExpr *Expr) { + const SCEV *Operand = ((SC *)this)->visit(Expr->getOperand()); + return Operand == Expr->getOperand() + ? Expr + : SE.getPtrToIntExpr(Operand, Expr->getType()); + } + const SCEV *visitTruncateExpr(const SCEVTruncateExpr *Expr) { const SCEV *Operand = ((SC*)this)->visit(Expr->getOperand()); return Operand == Expr->getOperand() @@ -787,35 +847,30 @@ class Type; }; using ValueToValueMap = DenseMap; + using ValueToSCEVMapTy = DenseMap; /// The SCEVParameterRewriter takes a scalar evolution expression and updates - /// the SCEVUnknown components following the Map (Value -> Value). + /// the SCEVUnknown components following the Map (Value -> SCEV). class SCEVParameterRewriter : public SCEVRewriteVisitor { public: static const SCEV *rewrite(const SCEV *Scev, ScalarEvolution &SE, - ValueToValueMap &Map, - bool InterpretConsts = false) { - SCEVParameterRewriter Rewriter(SE, Map, InterpretConsts); + ValueToSCEVMapTy &Map) { + SCEVParameterRewriter Rewriter(SE, Map); return Rewriter.visit(Scev); } - SCEVParameterRewriter(ScalarEvolution &SE, ValueToValueMap &M, bool C) - : SCEVRewriteVisitor(SE), Map(M), InterpretConsts(C) {} + SCEVParameterRewriter(ScalarEvolution &SE, ValueToSCEVMapTy &M) + : SCEVRewriteVisitor(SE), Map(M) {} const SCEV *visitUnknown(const SCEVUnknown *Expr) { - Value *V = Expr->getValue(); - if (Map.count(V)) { - Value *NV = Map[V]; - if (InterpretConsts && isa(NV)) - return SE.getConstant(cast(NV)); - return SE.getUnknown(NV); - } - return Expr; + auto I = Map.find(Expr->getValue()); + if (I == Map.end()) + return Expr; + return I->second; } private: - ValueToValueMap ⤅ - bool InterpretConsts; + ValueToSCEVMapTy ⤅ }; using LoopToScevMapT = DenseMap; diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/SparsePropagation.h b/contrib/llvm-project/llvm/include/llvm/Analysis/SparsePropagation.h index fac92e4a25a4..81a2533152de 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/SparsePropagation.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/SparsePropagation.h @@ -485,8 +485,7 @@ void SparseSolver::Solve() { // Process the basic block work list. while (!BBWorkList.empty()) { - BasicBlock *BB = BBWorkList.back(); - BBWorkList.pop_back(); + BasicBlock *BB = BBWorkList.pop_back_val(); LLVM_DEBUG(dbgs() << "\nPopped off BBWL: " << *BB); diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/StackLifetime.h b/contrib/llvm-project/llvm/include/llvm/Analysis/StackLifetime.h index 8abc6cc1ce00..df342a9533ee 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/StackLifetime.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/StackLifetime.h @@ -13,6 +13,7 @@ #include "llvm/ADT/BitVector.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/PassManager.h" #include "llvm/Support/raw_ostream.h" @@ -121,6 +122,8 @@ private: DenseMap, 4>> BBMarkers; + bool HasUnknownLifetimeStartOrEnd = false; + void dumpAllocas() const; void dumpBlockLiveness() const; void dumpLiveRanges() const; @@ -166,16 +169,9 @@ public: static inline raw_ostream &operator<<(raw_ostream &OS, const BitVector &V) { OS << "{"; - int Idx = V.find_first(); - bool First = true; - while (Idx >= 0) { - if (!First) { - OS << ", "; - } - First = false; - OS << Idx; - Idx = V.find_next(Idx); - } + ListSeparator LS; + for (int Idx = V.find_first(); Idx >= 0; Idx = V.find_next(Idx)) + OS << LS << Idx; OS << "}"; return OS; } diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/StackSafetyAnalysis.h b/contrib/llvm-project/llvm/include/llvm/Analysis/StackSafetyAnalysis.h index 846c2e6f7e91..59c1e3e3bd56 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/StackSafetyAnalysis.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/StackSafetyAnalysis.h @@ -51,7 +51,8 @@ public: /// StackSafety assumes that missing parameter information means possibility /// of access to the parameter with any offset, so we can correctly link /// code without StackSafety information, e.g. non-ThinLTO. - std::vector getParamAccesses() const; + std::vector + getParamAccesses(ModuleSummaryIndex &Index) const; }; class StackSafetyGlobalInfo { diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/SyncDependenceAnalysis.h b/contrib/llvm-project/llvm/include/llvm/Analysis/SyncDependenceAnalysis.h index 2f07b3135308..9838d629e93e 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/SyncDependenceAnalysis.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/SyncDependenceAnalysis.h @@ -21,6 +21,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Analysis/LoopInfo.h" #include +#include namespace llvm { @@ -30,6 +31,26 @@ class Loop; class PostDominatorTree; using ConstBlockSet = SmallPtrSet; +struct ControlDivergenceDesc { + // Join points of divergent disjoint paths. + ConstBlockSet JoinDivBlocks; + // Divergent loop exits + ConstBlockSet LoopDivBlocks; +}; + +struct ModifiedPO { + std::vector LoopPO; + std::unordered_map POIndex; + void appendBlock(const BasicBlock &BB) { + POIndex[&BB] = LoopPO.size(); + LoopPO.push_back(&BB); + } + unsigned getIndexOf(const BasicBlock &BB) const { + return POIndex.find(&BB)->second; + } + unsigned size() const { return LoopPO.size(); } + const BasicBlock *getBlockAt(unsigned Idx) const { return LoopPO[Idx]; } +}; /// \brief Relates points of divergent control to join points in /// reducible CFGs. @@ -51,28 +72,19 @@ public: /// header. Those exit blocks are added to the returned set. /// If L is the parent loop of \p Term and an exit of L is in the returned /// set then L is a divergent loop. - const ConstBlockSet &join_blocks(const Instruction &Term); - - /// \brief Computes divergent join points and loop exits (in the surrounding - /// loop) caused by the divergent loop exits of\p Loop. - /// - /// The set of blocks which are reachable by disjoint paths from the - /// loop exits of \p Loop. - /// This treats the loop as a single node in \p Loop's parent loop. - /// The returned set has the same properties as for join_blocks(TermInst&). - const ConstBlockSet &join_blocks(const Loop &Loop); + const ControlDivergenceDesc &getJoinBlocks(const Instruction &Term); private: - static ConstBlockSet EmptyBlockSet; + static ControlDivergenceDesc EmptyDivergenceDesc; + + ModifiedPO LoopPO; - ReversePostOrderTraversal FuncRPOT; const DominatorTree &DT; const PostDominatorTree &PDT; const LoopInfo &LI; - std::map> CachedLoopExitJoins; - std::map> - CachedBranchJoins; + std::map> + CachedControlDivDescs; }; } // namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/TargetLibraryInfo.def b/contrib/llvm-project/llvm/include/llvm/Analysis/TargetLibraryInfo.def index 3864d4955104..defc95d0062a 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/TargetLibraryInfo.def +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/TargetLibraryInfo.def @@ -262,6 +262,12 @@ TLI_DEFINE_STRING_INTERNAL("__atanhf_finite") /// long double __atanhl_finite(long double x); TLI_DEFINE_ENUM_INTERNAL(atanhl_finite) TLI_DEFINE_STRING_INTERNAL("__atanhl_finite") +/// void __atomic_load(size_t size, void *mptr, void *vptr, int smodel); +TLI_DEFINE_ENUM_INTERNAL(atomic_load) +TLI_DEFINE_STRING_INTERNAL("__atomic_load") +/// void __atomic_store(size_t size, void *mptr, void *vptr, int smodel); +TLI_DEFINE_ENUM_INTERNAL(atomic_store) +TLI_DEFINE_STRING_INTERNAL("__atomic_store") /// double __cosh_finite(double x); TLI_DEFINE_ENUM_INTERNAL(cosh_finite) TLI_DEFINE_STRING_INTERNAL("__cosh_finite") @@ -360,6 +366,9 @@ TLI_DEFINE_STRING_INTERNAL("__memcpy_chk") /// void *__memmove_chk(void *s1, const void *s2, size_t n, size_t s1size); TLI_DEFINE_ENUM_INTERNAL(memmove_chk) TLI_DEFINE_STRING_INTERNAL("__memmove_chk") +/// void *__mempcpy_chk(void *s1, const void *s2, size_t n, size_t s1size); +TLI_DEFINE_ENUM_INTERNAL(mempcpy_chk) +TLI_DEFINE_STRING_INTERNAL("__mempcpy_chk") /// void *__memset_chk(void *s, char v, size_t n, size_t s1size); TLI_DEFINE_ENUM_INTERNAL(memset_chk) TLI_DEFINE_STRING_INTERNAL("__memset_chk") @@ -1411,6 +1420,18 @@ TLI_DEFINE_STRING_INTERNAL("utimes") /// void *valloc(size_t size); TLI_DEFINE_ENUM_INTERNAL(valloc) TLI_DEFINE_STRING_INTERNAL("valloc") +/// void *vec_calloc(size_t count, size_t size); +TLI_DEFINE_ENUM_INTERNAL(vec_calloc) +TLI_DEFINE_STRING_INTERNAL("vec_calloc") +/// void vec_free(void *ptr); +TLI_DEFINE_ENUM_INTERNAL(vec_free) +TLI_DEFINE_STRING_INTERNAL("vec_free") +/// void *vec_malloc(size_t size); +TLI_DEFINE_ENUM_INTERNAL(vec_malloc) +TLI_DEFINE_STRING_INTERNAL("vec_malloc") +/// void *vec_realloc(void *ptr, size_t size); +TLI_DEFINE_ENUM_INTERNAL(vec_realloc) +TLI_DEFINE_STRING_INTERNAL("vec_realloc") /// int vfprintf(FILE *stream, const char *format, va_list ap); TLI_DEFINE_ENUM_INTERNAL(vfprintf) TLI_DEFINE_STRING_INTERNAL("vfprintf") diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/TargetLibraryInfo.h b/contrib/llvm-project/llvm/include/llvm/Analysis/TargetLibraryInfo.h index 3a7c26e1463b..34a8a1e3407c 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/TargetLibraryInfo.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/TargetLibraryInfo.h @@ -88,6 +88,7 @@ public: enum VectorLibrary { NoLibrary, // Don't use any vector library. Accelerate, // Use Accelerate framework. + LIBMVEC_X86,// GLIBC Vector Math library. MASSV, // IBM MASS vector library. SVML // Intel short vector math library. }; diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/TargetTransformInfo.h b/contrib/llvm-project/llvm/include/llvm/Analysis/TargetTransformInfo.h index b6698eefdb01..cdfb04424e56 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/TargetTransformInfo.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/TargetTransformInfo.h @@ -21,11 +21,13 @@ #ifndef LLVM_ANALYSIS_TARGETTRANSFORMINFO_H #define LLVM_ANALYSIS_TARGETTRANSFORMINFO_H +#include "llvm/IR/InstrTypes.h" #include "llvm/IR/Operator.h" #include "llvm/IR/PassManager.h" #include "llvm/Pass.h" #include "llvm/Support/AtomicOrdering.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/InstructionCost.h" #include namespace llvm { @@ -42,6 +44,7 @@ class CallBase; class ExtractElementInst; class Function; class GlobalValue; +class InstCombiner; class IntrinsicInst; class LoadInst; class LoopAccessInfo; @@ -56,6 +59,7 @@ class TargetLibraryInfo; class Type; class User; class Value; +struct KnownBits; template class Optional; /// Information about a load/store intrinsic defined by the target. @@ -90,7 +94,7 @@ struct HardwareLoopInfo { Loop *L = nullptr; BasicBlock *ExitBlock = nullptr; BranchInst *ExitBranch = nullptr; - const SCEV *ExitCount = nullptr; + const SCEV *TripCount = nullptr; IntegerType *CountType = nullptr; Value *LoopDecrement = nullptr; // Decrement the loop counter by this // value in every iteration. @@ -114,7 +118,7 @@ class IntrinsicCostAttributes { SmallVector ParamTys; SmallVector Arguments; FastMathFlags FMF; - unsigned VF = 1; + ElementCount VF = ElementCount::getFixed(1); // If ScalarizationCost is UINT_MAX, the cost of scalarizing the // arguments and the return value will be computed based on types. unsigned ScalarizationCost = std::numeric_limits::max(); @@ -125,10 +129,10 @@ public: IntrinsicCostAttributes(Intrinsic::ID Id, const CallBase &CI); IntrinsicCostAttributes(Intrinsic::ID Id, const CallBase &CI, - unsigned Factor); + ElementCount Factor); IntrinsicCostAttributes(Intrinsic::ID Id, const CallBase &CI, - unsigned Factor, unsigned ScalarCost); + ElementCount Factor, unsigned ScalarCost); IntrinsicCostAttributes(Intrinsic::ID Id, Type *RTy, ArrayRef Tys, FastMathFlags Flags); @@ -151,7 +155,7 @@ public: Intrinsic::ID getID() const { return IID; } const IntrinsicInst *getInst() const { return II; } Type *getReturnType() const { return RetTy; } - unsigned getVectorFactor() const { return VF; } + ElementCount getVectorFactor() const { return VF; } FastMathFlags getFlags() const { return FMF; } unsigned getScalarizationCost() const { return ScalarizationCost; } const SmallVectorImpl &getArgs() const { return Arguments; } @@ -228,19 +232,24 @@ public: /// /// Note, this method does not cache the cost calculation and it /// can be expensive in some cases. - int getInstructionCost(const Instruction *I, enum TargetCostKind kind) const { + InstructionCost getInstructionCost(const Instruction *I, + enum TargetCostKind kind) const { + InstructionCost Cost; switch (kind) { case TCK_RecipThroughput: - return getInstructionThroughput(I); - + Cost = getInstructionThroughput(I); + break; case TCK_Latency: - return getInstructionLatency(I); - + Cost = getInstructionLatency(I); + break; case TCK_CodeSize: case TCK_SizeAndLatency: - return getUserCost(I, kind); + Cost = getUserCost(I, kind); + break; } - llvm_unreachable("Unknown instruction cost kind"); + if (Cost == -1) + Cost.setInvalid(); + return Cost; } /// Underlying constants for 'cost' values in this interface. @@ -280,6 +289,9 @@ public: /// individual classes of instructions would be better. unsigned getInliningThresholdMultiplier() const; + /// \returns A value to be added to the inlining threshold. + unsigned adjustInliningThreshold(const CallBase *CB) const; + /// \returns Vector bonus in percent. /// /// Vector bonuses: We want to more aggressively inline vector-dense kernels @@ -323,8 +335,7 @@ public: /// This is a helper function which calls the two-argument getUserCost /// with \p Operands which are the current operands U has. int getUserCost(const User *U, TargetCostKind CostKind) const { - SmallVector Operands(U->value_op_begin(), - U->value_op_end()); + SmallVector Operands(U->operand_values()); return getUserCost(U, Operands, CostKind); } @@ -379,6 +390,8 @@ public: bool isNoopAddrSpaceCast(unsigned FromAS, unsigned ToAS) const; + unsigned getAssumedAddrSpace(const Value *V) const; + /// Rewrite intrinsic call \p II such that \p OldV will be replaced with \p /// NewV, which has a different address space. This should happen for every /// operand index that collectFlatAddressOperands returned for the intrinsic. @@ -542,6 +555,29 @@ public: /// target-independent defaults with information from \p L and \p SE. void getPeelingPreferences(Loop *L, ScalarEvolution &SE, PeelingPreferences &PP) const; + + /// Targets can implement their own combinations for target-specific + /// intrinsics. This function will be called from the InstCombine pass every + /// time a target-specific intrinsic is encountered. + /// + /// \returns None to not do anything target specific or a value that will be + /// returned from the InstCombiner. It is possible to return null and stop + /// further processing of the intrinsic by returning nullptr. + Optional instCombineIntrinsic(InstCombiner &IC, + IntrinsicInst &II) const; + /// Can be used to implement target-specific instruction combining. + /// \see instCombineIntrinsic + Optional + simplifyDemandedUseBitsIntrinsic(InstCombiner &IC, IntrinsicInst &II, + APInt DemandedMask, KnownBits &Known, + bool &KnownBitsComputed) const; + /// Can be used to implement target-specific instruction combining. + /// \see instCombineIntrinsic + Optional simplifyDemandedVectorEltsIntrinsic( + InstCombiner &IC, IntrinsicInst &II, APInt DemandedElts, APInt &UndefElts, + APInt &UndefElts2, APInt &UndefElts3, + std::function + SimplifyAndSetOp) const; /// @} /// \name Scalar Target Information @@ -583,6 +619,11 @@ public: bool isLSRCostLess(TargetTransformInfo::LSRCost &C1, TargetTransformInfo::LSRCost &C2) const; + /// Return true if LSR major cost is number of registers. Targets which + /// implement their own isLSRCostLess and unset number of registers as major + /// cost should return false, otherwise return true. + bool isNumRegsMajorCostOfLSR() const; + /// \returns true if LSR should not optimize a chain that includes \p I. bool isProfitableLSRChainElement(Instruction *I) const; @@ -672,6 +713,9 @@ public: /// Return true if this type is legal. bool isTypeLegal(Type *Ty) const; + /// Returns the estimated number of registers required to represent \p Ty. + unsigned getRegUsageForType(Type *Ty) const; + /// Return true if switches should be turned into lookup tables for the /// target. bool shouldBuildLookupTables() const; @@ -780,8 +824,9 @@ public: /// Return the expected cost of materialization for the given integer /// immediate of the specified type for a given instruction. The cost can be /// zero if the immediate can be folded into the specified instruction. - int getIntImmCostInst(unsigned Opc, unsigned Idx, const APInt &Imm, - Type *Ty, TargetCostKind CostKind) const; + int getIntImmCostInst(unsigned Opc, unsigned Idx, const APInt &Imm, Type *Ty, + TargetCostKind CostKind, + Instruction *Inst = nullptr) const; int getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx, const APInt &Imm, Type *Ty, TargetCostKind CostKind) const; @@ -845,6 +890,10 @@ public: static ReductionKind matchVectorSplittingReduction( const ExtractElementInst *ReduxRoot, unsigned &Opcode, VectorType *&Ty); + static ReductionKind matchVectorReduction(const ExtractElementInst *ReduxRoot, + unsigned &Opcode, VectorType *&Ty, + bool &IsPairwise); + /// Additional information about an operand's possible values. enum OperandValueKind { OK_AnyValue, // Operand can have any value. @@ -881,6 +930,10 @@ public: /// \return The width of the smallest vector register type. unsigned getMinVectorRegisterBitWidth() const; + /// \return The maximum value of vscale if the target specifies an + /// architectural maximum vector length, and None otherwise. + Optional getMaxVScale() const; + /// \return True if the vectorization factor should be chosen to /// make the vector of the smallest element type match the size of a /// vector register. For wider element types, this could result in @@ -894,6 +947,11 @@ public: /// applies when shouldMaximizeVectorBandwidth returns true. unsigned getMinimumVF(unsigned ElemWidth) const; + /// \return The maximum vectorization factor for types of given element + /// bit width and opcode, or 0 if there is no maximum VF. + /// Currently only used by the SLP vectorizer. + unsigned getMaximumVF(unsigned ElemWidth, unsigned Opcode) const; + /// \return True if it should be considered for address type promotion. /// \p AllowPromotionWithoutCommonHeader Set true if promoting \p I is /// profitable without finding other extensions fed by the same input. @@ -996,10 +1054,47 @@ public: int getShuffleCost(ShuffleKind Kind, VectorType *Tp, int Index = 0, VectorType *SubTp = nullptr) const; + /// Represents a hint about the context in which a cast is used. + /// + /// For zext/sext, the context of the cast is the operand, which must be a + /// load of some kind. For trunc, the context is of the cast is the single + /// user of the instruction, which must be a store of some kind. + /// + /// This enum allows the vectorizer to give getCastInstrCost an idea of the + /// type of cast it's dealing with, as not every cast is equal. For instance, + /// the zext of a load may be free, but the zext of an interleaving load can + //// be (very) expensive! + /// + /// See \c getCastContextHint to compute a CastContextHint from a cast + /// Instruction*. Callers can use it if they don't need to override the + /// context and just want it to be calculated from the instruction. + /// + /// FIXME: This handles the types of load/store that the vectorizer can + /// produce, which are the cases where the context instruction is most + /// likely to be incorrect. There are other situations where that can happen + /// too, which might be handled here but in the long run a more general + /// solution of costing multiple instructions at the same times may be better. + enum class CastContextHint : uint8_t { + None, ///< The cast is not used with a load/store of any kind. + Normal, ///< The cast is used with a normal load/store. + Masked, ///< The cast is used with a masked load/store. + GatherScatter, ///< The cast is used with a gather/scatter. + Interleave, ///< The cast is used with an interleaved load/store. + Reversed, ///< The cast is used with a reversed load/store. + }; + + /// Calculates a CastContextHint from \p I. + /// This should be used by callers of getCastInstrCost if they wish to + /// determine the context from some instruction. + /// \returns the CastContextHint for ZExt/SExt/Trunc, None if \p I is nullptr, + /// or if it's another type of cast. + static CastContextHint getCastContextHint(const Instruction *I); + /// \return The expected cost of cast instructions, such as bitcast, trunc, /// zext, etc. If there is an existing instruction that holds Opcode, it /// may be passed in the 'I' parameter. int getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src, + TTI::CastContextHint CCH, TTI::TargetCostKind CostKind = TTI::TCK_SizeAndLatency, const Instruction *I = nullptr) const; @@ -1015,10 +1110,14 @@ public: /// \returns The expected cost of compare and select instructions. If there /// is an existing instruction that holds Opcode, it may be passed in the - /// 'I' parameter. - int getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy = nullptr, - TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput, - const Instruction *I = nullptr) const; + /// 'I' parameter. The \p VecPred parameter can be used to indicate the select + /// is using a compare with the specified predicate as condition. When vector + /// types are passed, \p VecPred must be used for all lanes. + int getCmpSelInstrCost( + unsigned Opcode, Type *ValTy, Type *CondTy = nullptr, + CmpInst::Predicate VecPred = CmpInst::BAD_ICMP_PREDICATE, + TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput, + const Instruction *I = nullptr) const; /// \return The expected cost of vector Insert and Extract. /// Use -1 to indicate that there is no information on the index value. @@ -1086,6 +1185,16 @@ public: VectorType *Ty, VectorType *CondTy, bool IsPairwiseForm, bool IsUnsigned, TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput) const; + /// Calculate the cost of an extended reduction pattern, similar to + /// getArithmeticReductionCost of an Add reduction with an extension and + /// optional multiply. This is the cost of as: + /// ResTy vecreduce.add(ext(Ty A)), or if IsMLA flag is set then: + /// ResTy vecreduce.add(mul(ext(Ty A), ext(Ty B)). The reduction happens + /// on a VectorType with ResTy elements and Ty lanes. + InstructionCost getExtendedAddReductionCost( + bool IsMLA, bool IsUnsigned, Type *ResTy, VectorType *Ty, + TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput) const; + /// \returns The cost of Intrinsic instructions. Analyses the real arguments. /// Three cases are handled: 1. scalar instruction 2. vector instruction /// 3. scalar instruction which is to be vectorized. @@ -1221,6 +1330,24 @@ public: bool useReductionIntrinsic(unsigned Opcode, Type *Ty, ReductionFlags Flags) const; + /// \returns True if the target prefers reductions in loop. + bool preferInLoopReduction(unsigned Opcode, Type *Ty, + ReductionFlags Flags) const; + + /// \returns True if the target prefers reductions select kept in the loop + /// when tail folding. i.e. + /// loop: + /// p = phi (0, s) + /// a = add (p, x) + /// s = select (mask, a, p) + /// vecreduce.add(s) + /// + /// As opposed to the normal scheme of p = phi (0, a) which allows the select + /// to be pulled out of the loop. If the select(.., add, ..) can be predicated + /// by the target, this can lead to cleaner code generation. + bool preferPredicatedReductionSelect(unsigned Opcode, Type *Ty, + ReductionFlags Flags) const; + /// \returns True if the target wants to expand the given reduction intrinsic /// into a shuffle sequence. bool shouldExpandReduction(const IntrinsicInst *II) const; @@ -1229,6 +1356,9 @@ public: /// to a stack reload. unsigned getGISelRematGlobalCost() const; + /// \returns True if the target supports scalable vectors. + bool supportsScalableVectors() const; + /// \name Vector Predication Information /// @{ /// Whether the target supports the %evl parameter of VP intrinsic efficiently @@ -1268,6 +1398,7 @@ public: ArrayRef Operands, TTI::TargetCostKind CostKind) = 0; virtual unsigned getInliningThresholdMultiplier() = 0; + virtual unsigned adjustInliningThreshold(const CallBase *CB) = 0; virtual int getInlinerVectorBonusPercent() = 0; virtual int getMemcpyCost(const Instruction *I) = 0; virtual unsigned @@ -1284,6 +1415,7 @@ public: virtual bool collectFlatAddressOperands(SmallVectorImpl &OpIndexes, Intrinsic::ID IID) const = 0; virtual bool isNoopAddrSpaceCast(unsigned FromAS, unsigned ToAS) const = 0; + virtual unsigned getAssumedAddrSpace(const Value *V) const = 0; virtual Value *rewriteIntrinsicWithAddressSpace(IntrinsicInst *II, Value *OldV, Value *NewV) const = 0; @@ -1301,6 +1433,17 @@ public: AssumptionCache &AC, TargetLibraryInfo *TLI, DominatorTree *DT, const LoopAccessInfo *LAI) = 0; virtual bool emitGetActiveLaneMask() = 0; + virtual Optional instCombineIntrinsic(InstCombiner &IC, + IntrinsicInst &II) = 0; + virtual Optional + simplifyDemandedUseBitsIntrinsic(InstCombiner &IC, IntrinsicInst &II, + APInt DemandedMask, KnownBits &Known, + bool &KnownBitsComputed) = 0; + virtual Optional simplifyDemandedVectorEltsIntrinsic( + InstCombiner &IC, IntrinsicInst &II, APInt DemandedElts, APInt &UndefElts, + APInt &UndefElts2, APInt &UndefElts3, + std::function + SimplifyAndSetOp) = 0; virtual bool isLegalAddImmediate(int64_t Imm) = 0; virtual bool isLegalICmpImmediate(int64_t Imm) = 0; virtual bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, @@ -1309,6 +1452,7 @@ public: Instruction *I) = 0; virtual bool isLSRCostLess(TargetTransformInfo::LSRCost &C1, TargetTransformInfo::LSRCost &C2) = 0; + virtual bool isNumRegsMajorCostOfLSR() = 0; virtual bool isProfitableLSRChainElement(Instruction *I) = 0; virtual bool canMacroFuseCmp() = 0; virtual bool canSaveCmp(Loop *L, BranchInst **BI, ScalarEvolution *SE, @@ -1335,6 +1479,7 @@ public: virtual bool isProfitableToHoist(Instruction *I) = 0; virtual bool useAA() = 0; virtual bool isTypeLegal(Type *Ty) = 0; + virtual unsigned getRegUsageForType(Type *Ty) = 0; virtual bool shouldBuildLookupTables() = 0; virtual bool shouldBuildLookupTablesForConstant(Constant *C) = 0; virtual bool useColdCCForColdCall(Function &F) = 0; @@ -1365,7 +1510,8 @@ public: virtual int getIntImmCost(const APInt &Imm, Type *Ty, TargetCostKind CostKind) = 0; virtual int getIntImmCostInst(unsigned Opc, unsigned Idx, const APInt &Imm, - Type *Ty, TargetCostKind CostKind) = 0; + Type *Ty, TargetCostKind CostKind, + Instruction *Inst = nullptr) = 0; virtual int getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx, const APInt &Imm, Type *Ty, TargetCostKind CostKind) = 0; @@ -1375,8 +1521,10 @@ public: virtual const char *getRegisterClassName(unsigned ClassID) const = 0; virtual unsigned getRegisterBitWidth(bool Vector) const = 0; virtual unsigned getMinVectorRegisterBitWidth() = 0; + virtual Optional getMaxVScale() const = 0; virtual bool shouldMaximizeVectorBandwidth(bool OptSize) const = 0; virtual unsigned getMinimumVF(unsigned ElemWidth) const = 0; + virtual unsigned getMaximumVF(unsigned ElemWidth, unsigned Opcode) const = 0; virtual bool shouldConsiderAddressTypePromotion( const Instruction &I, bool &AllowPromotionWithoutCommonHeader) = 0; virtual unsigned getCacheLineSize() const = 0; @@ -1418,6 +1566,7 @@ public: virtual int getShuffleCost(ShuffleKind Kind, VectorType *Tp, int Index, VectorType *SubTp) = 0; virtual int getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src, + CastContextHint CCH, TTI::TargetCostKind CostKind, const Instruction *I) = 0; virtual int getExtractWithExtendCost(unsigned Opcode, Type *Dst, @@ -1425,6 +1574,7 @@ public: virtual int getCFInstrCost(unsigned Opcode, TTI::TargetCostKind CostKind) = 0; virtual int getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy, + CmpInst::Predicate VecPred, TTI::TargetCostKind CostKind, const Instruction *I) = 0; virtual int getVectorInstrCost(unsigned Opcode, Type *Val, @@ -1452,6 +1602,9 @@ public: virtual int getMinMaxReductionCost(VectorType *Ty, VectorType *CondTy, bool IsPairwiseForm, bool IsUnsigned, TTI::TargetCostKind CostKind) = 0; + virtual InstructionCost getExtendedAddReductionCost( + bool IsMLA, bool IsUnsigned, Type *ResTy, VectorType *Ty, + TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput) = 0; virtual int getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, TTI::TargetCostKind CostKind) = 0; virtual int getCallInstrCost(Function *F, Type *RetTy, @@ -1499,8 +1652,13 @@ public: VectorType *VecTy) const = 0; virtual bool useReductionIntrinsic(unsigned Opcode, Type *Ty, ReductionFlags) const = 0; + virtual bool preferInLoopReduction(unsigned Opcode, Type *Ty, + ReductionFlags) const = 0; + virtual bool preferPredicatedReductionSelect(unsigned Opcode, Type *Ty, + ReductionFlags) const = 0; virtual bool shouldExpandReduction(const IntrinsicInst *II) const = 0; virtual unsigned getGISelRematGlobalCost() const = 0; + virtual bool supportsScalableVectors() const = 0; virtual bool hasActiveVectorLength() const = 0; virtual int getInstructionLatency(const Instruction *I) = 0; }; @@ -1525,6 +1683,9 @@ public: unsigned getInliningThresholdMultiplier() override { return Impl.getInliningThresholdMultiplier(); } + unsigned adjustInliningThreshold(const CallBase *CB) override { + return Impl.adjustInliningThreshold(CB); + } int getInlinerVectorBonusPercent() override { return Impl.getInlinerVectorBonusPercent(); } @@ -1558,6 +1719,10 @@ public: return Impl.isNoopAddrSpaceCast(FromAS, ToAS); } + unsigned getAssumedAddrSpace(const Value *V) const override { + return Impl.getAssumedAddrSpace(V); + } + Value *rewriteIntrinsicWithAddressSpace(IntrinsicInst *II, Value *OldV, Value *NewV) const override { return Impl.rewriteIntrinsicWithAddressSpace(II, OldV, NewV); @@ -1588,6 +1753,26 @@ public: bool emitGetActiveLaneMask() override { return Impl.emitGetActiveLaneMask(); } + Optional instCombineIntrinsic(InstCombiner &IC, + IntrinsicInst &II) override { + return Impl.instCombineIntrinsic(IC, II); + } + Optional + simplifyDemandedUseBitsIntrinsic(InstCombiner &IC, IntrinsicInst &II, + APInt DemandedMask, KnownBits &Known, + bool &KnownBitsComputed) override { + return Impl.simplifyDemandedUseBitsIntrinsic(IC, II, DemandedMask, Known, + KnownBitsComputed); + } + Optional simplifyDemandedVectorEltsIntrinsic( + InstCombiner &IC, IntrinsicInst &II, APInt DemandedElts, APInt &UndefElts, + APInt &UndefElts2, APInt &UndefElts3, + std::function + SimplifyAndSetOp) override { + return Impl.simplifyDemandedVectorEltsIntrinsic( + IC, II, DemandedElts, UndefElts, UndefElts2, UndefElts3, + SimplifyAndSetOp); + } bool isLegalAddImmediate(int64_t Imm) override { return Impl.isLegalAddImmediate(Imm); } @@ -1604,6 +1789,9 @@ public: TargetTransformInfo::LSRCost &C2) override { return Impl.isLSRCostLess(C1, C2); } + bool isNumRegsMajorCostOfLSR() override { + return Impl.isNumRegsMajorCostOfLSR(); + } bool isProfitableLSRChainElement(Instruction *I) override { return Impl.isProfitableLSRChainElement(I); } @@ -1665,6 +1853,9 @@ public: } bool useAA() override { return Impl.useAA(); } bool isTypeLegal(Type *Ty) override { return Impl.isTypeLegal(Ty); } + unsigned getRegUsageForType(Type *Ty) override { + return Impl.getRegUsageForType(Ty); + } bool shouldBuildLookupTables() override { return Impl.shouldBuildLookupTables(); } @@ -1729,9 +1920,10 @@ public: TargetCostKind CostKind) override { return Impl.getIntImmCost(Imm, Ty, CostKind); } - int getIntImmCostInst(unsigned Opc, unsigned Idx, const APInt &Imm, - Type *Ty, TargetCostKind CostKind) override { - return Impl.getIntImmCostInst(Opc, Idx, Imm, Ty, CostKind); + int getIntImmCostInst(unsigned Opc, unsigned Idx, const APInt &Imm, Type *Ty, + TargetCostKind CostKind, + Instruction *Inst = nullptr) override { + return Impl.getIntImmCostInst(Opc, Idx, Imm, Ty, CostKind, Inst); } int getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx, const APInt &Imm, Type *Ty, TargetCostKind CostKind) override { @@ -1753,12 +1945,18 @@ public: unsigned getMinVectorRegisterBitWidth() override { return Impl.getMinVectorRegisterBitWidth(); } + Optional getMaxVScale() const override { + return Impl.getMaxVScale(); + } bool shouldMaximizeVectorBandwidth(bool OptSize) const override { return Impl.shouldMaximizeVectorBandwidth(OptSize); } unsigned getMinimumVF(unsigned ElemWidth) const override { return Impl.getMinimumVF(ElemWidth); } + unsigned getMaximumVF(unsigned ElemWidth, unsigned Opcode) const override { + return Impl.getMaximumVF(ElemWidth, Opcode); + } bool shouldConsiderAddressTypePromotion( const Instruction &I, bool &AllowPromotionWithoutCommonHeader) override { return Impl.shouldConsiderAddressTypePromotion( @@ -1826,9 +2024,9 @@ public: return Impl.getShuffleCost(Kind, Tp, Index, SubTp); } int getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src, - TTI::TargetCostKind CostKind, + CastContextHint CCH, TTI::TargetCostKind CostKind, const Instruction *I) override { - return Impl.getCastInstrCost(Opcode, Dst, Src, CostKind, I); + return Impl.getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I); } int getExtractWithExtendCost(unsigned Opcode, Type *Dst, VectorType *VecTy, unsigned Index) override { @@ -1838,9 +2036,10 @@ public: return Impl.getCFInstrCost(Opcode, CostKind); } int getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy, + CmpInst::Predicate VecPred, TTI::TargetCostKind CostKind, const Instruction *I) override { - return Impl.getCmpSelInstrCost(Opcode, ValTy, CondTy, CostKind, I); + return Impl.getCmpSelInstrCost(Opcode, ValTy, CondTy, VecPred, CostKind, I); } int getVectorInstrCost(unsigned Opcode, Type *Val, unsigned Index) override { return Impl.getVectorInstrCost(Opcode, Val, Index); @@ -1886,6 +2085,12 @@ public: return Impl.getMinMaxReductionCost(Ty, CondTy, IsPairwiseForm, IsUnsigned, CostKind); } + InstructionCost getExtendedAddReductionCost( + bool IsMLA, bool IsUnsigned, Type *ResTy, VectorType *Ty, + TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput) override { + return Impl.getExtendedAddReductionCost(IsMLA, IsUnsigned, ResTy, Ty, + CostKind); + } int getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, TTI::TargetCostKind CostKind) override { return Impl.getIntrinsicInstrCost(ICA, CostKind); @@ -1979,6 +2184,14 @@ public: ReductionFlags Flags) const override { return Impl.useReductionIntrinsic(Opcode, Ty, Flags); } + bool preferInLoopReduction(unsigned Opcode, Type *Ty, + ReductionFlags Flags) const override { + return Impl.preferInLoopReduction(Opcode, Ty, Flags); + } + bool preferPredicatedReductionSelect(unsigned Opcode, Type *Ty, + ReductionFlags Flags) const override { + return Impl.preferPredicatedReductionSelect(Opcode, Ty, Flags); + } bool shouldExpandReduction(const IntrinsicInst *II) const override { return Impl.shouldExpandReduction(II); } @@ -1987,6 +2200,10 @@ public: return Impl.getGISelRematGlobalCost(); } + bool supportsScalableVectors() const override { + return Impl.supportsScalableVectors(); + } + bool hasActiveVectorLength() const override { return Impl.hasActiveVectorLength(); } diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h b/contrib/llvm-project/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h index 0ce975d6d4b5..7e31cb365a87 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h @@ -20,7 +20,7 @@ #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" #include "llvm/IR/GetElementPtrTypeIterator.h" -#include "llvm/IR/Intrinsics.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Operator.h" #include "llvm/IR/Type.h" @@ -46,7 +46,7 @@ public: int getGEPCost(Type *PointeeType, const Value *Ptr, ArrayRef Operands, - TTI::TargetCostKind CostKind = TTI::TCK_SizeAndLatency) { + TTI::TargetCostKind CostKind = TTI::TCK_SizeAndLatency) const { // In the basic model, we just assume that all-constant GEPs will be folded // into their uses via addressing modes. for (unsigned Idx = 0, Size = Operands.size(); Idx != Size; ++Idx) @@ -59,28 +59,31 @@ public: unsigned getEstimatedNumberOfCaseClusters(const SwitchInst &SI, unsigned &JTSize, ProfileSummaryInfo *PSI, - BlockFrequencyInfo *BFI) { + BlockFrequencyInfo *BFI) const { (void)PSI; (void)BFI; JTSize = 0; return SI.getNumCases(); } - unsigned getInliningThresholdMultiplier() { return 1; } + unsigned getInliningThresholdMultiplier() const { return 1; } + unsigned adjustInliningThreshold(const CallBase *CB) const { return 0; } - int getInlinerVectorBonusPercent() { return 150; } + int getInlinerVectorBonusPercent() const { return 150; } - unsigned getMemcpyCost(const Instruction *I) { return TTI::TCC_Expensive; } + unsigned getMemcpyCost(const Instruction *I) const { + return TTI::TCC_Expensive; + } - bool hasBranchDivergence() { return false; } + bool hasBranchDivergence() const { return false; } - bool useGPUDivergenceAnalysis() { return false; } + bool useGPUDivergenceAnalysis() const { return false; } - bool isSourceOfDivergence(const Value *V) { return false; } + bool isSourceOfDivergence(const Value *V) const { return false; } - bool isAlwaysUniform(const Value *V) { return false; } + bool isAlwaysUniform(const Value *V) const { return false; } - unsigned getFlatAddressSpace() { return -1; } + unsigned getFlatAddressSpace() const { return -1; } bool collectFlatAddressOperands(SmallVectorImpl &OpIndexes, Intrinsic::ID IID) const { @@ -89,12 +92,14 @@ public: bool isNoopAddrSpaceCast(unsigned, unsigned) const { return false; } + unsigned getAssumedAddrSpace(const Value *V) const { return -1; } + Value *rewriteIntrinsicWithAddressSpace(IntrinsicInst *II, Value *OldV, Value *NewV) const { return nullptr; } - bool isLoweredToCall(const Function *F) { + bool isLoweredToCall(const Function *F) const { assert(F && "A concrete function must be provided to this routine."); // FIXME: These should almost certainly not be handled here, and instead @@ -132,7 +137,7 @@ public: bool isHardwareLoopProfitable(Loop *L, ScalarEvolution &SE, AssumptionCache &AC, TargetLibraryInfo *LibInfo, - HardwareLoopInfo &HWLoopInfo) { + HardwareLoopInfo &HWLoopInfo) const { return false; } @@ -147,38 +152,60 @@ public: return false; } + Optional instCombineIntrinsic(InstCombiner &IC, + IntrinsicInst &II) const { + return None; + } + + Optional + simplifyDemandedUseBitsIntrinsic(InstCombiner &IC, IntrinsicInst &II, + APInt DemandedMask, KnownBits &Known, + bool &KnownBitsComputed) const { + return None; + } + + Optional simplifyDemandedVectorEltsIntrinsic( + InstCombiner &IC, IntrinsicInst &II, APInt DemandedElts, APInt &UndefElts, + APInt &UndefElts2, APInt &UndefElts3, + std::function + SimplifyAndSetOp) const { + return None; + } + void getUnrollingPreferences(Loop *, ScalarEvolution &, - TTI::UnrollingPreferences &) {} + TTI::UnrollingPreferences &) const {} void getPeelingPreferences(Loop *, ScalarEvolution &, - TTI::PeelingPreferences &) {} + TTI::PeelingPreferences &) const {} - bool isLegalAddImmediate(int64_t Imm) { return false; } + bool isLegalAddImmediate(int64_t Imm) const { return false; } - bool isLegalICmpImmediate(int64_t Imm) { return false; } + bool isLegalICmpImmediate(int64_t Imm) const { return false; } bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, bool HasBaseReg, int64_t Scale, unsigned AddrSpace, - Instruction *I = nullptr) { + Instruction *I = nullptr) const { // Guess that only reg and reg+reg addressing is allowed. This heuristic is // taken from the implementation of LSR. return !BaseGV && BaseOffset == 0 && (Scale == 0 || Scale == 1); } - bool isLSRCostLess(TTI::LSRCost &C1, TTI::LSRCost &C2) { + bool isLSRCostLess(TTI::LSRCost &C1, TTI::LSRCost &C2) const { return std::tie(C1.NumRegs, C1.AddRecCost, C1.NumIVMuls, C1.NumBaseAdds, C1.ScaleCost, C1.ImmCost, C1.SetupCost) < std::tie(C2.NumRegs, C2.AddRecCost, C2.NumIVMuls, C2.NumBaseAdds, C2.ScaleCost, C2.ImmCost, C2.SetupCost); } - bool isProfitableLSRChainElement(Instruction *I) { return false; } + bool isNumRegsMajorCostOfLSR() const { return true; } + + bool isProfitableLSRChainElement(Instruction *I) const { return false; } - bool canMacroFuseCmp() { return false; } + bool canMacroFuseCmp() const { return false; } bool canSaveCmp(Loop *L, BranchInst **BI, ScalarEvolution *SE, LoopInfo *LI, DominatorTree *DT, AssumptionCache *AC, - TargetLibraryInfo *LibInfo) { + TargetLibraryInfo *LibInfo) const { return false; } @@ -186,40 +213,51 @@ public: bool shouldFavorBackedgeIndex(const Loop *L) const { return false; } - bool isLegalMaskedStore(Type *DataType, Align Alignment) { return false; } + bool isLegalMaskedStore(Type *DataType, Align Alignment) const { + return false; + } - bool isLegalMaskedLoad(Type *DataType, Align Alignment) { return false; } + bool isLegalMaskedLoad(Type *DataType, Align Alignment) const { + return false; + } - bool isLegalNTStore(Type *DataType, Align Alignment) { + bool isLegalNTStore(Type *DataType, Align Alignment) const { // By default, assume nontemporal memory stores are available for stores // that are aligned and have a size that is a power of 2. unsigned DataSize = DL.getTypeStoreSize(DataType); return Alignment >= DataSize && isPowerOf2_32(DataSize); } - bool isLegalNTLoad(Type *DataType, Align Alignment) { + bool isLegalNTLoad(Type *DataType, Align Alignment) const { // By default, assume nontemporal memory loads are available for loads that // are aligned and have a size that is a power of 2. unsigned DataSize = DL.getTypeStoreSize(DataType); return Alignment >= DataSize && isPowerOf2_32(DataSize); } - bool isLegalMaskedScatter(Type *DataType, Align Alignment) { return false; } + bool isLegalMaskedScatter(Type *DataType, Align Alignment) const { + return false; + } - bool isLegalMaskedGather(Type *DataType, Align Alignment) { return false; } + bool isLegalMaskedGather(Type *DataType, Align Alignment) const { + return false; + } - bool isLegalMaskedCompressStore(Type *DataType) { return false; } + bool isLegalMaskedCompressStore(Type *DataType) const { return false; } - bool isLegalMaskedExpandLoad(Type *DataType) { return false; } + bool isLegalMaskedExpandLoad(Type *DataType) const { return false; } - bool hasDivRemOp(Type *DataType, bool IsSigned) { return false; } + bool hasDivRemOp(Type *DataType, bool IsSigned) const { return false; } - bool hasVolatileVariant(Instruction *I, unsigned AddrSpace) { return false; } + bool hasVolatileVariant(Instruction *I, unsigned AddrSpace) const { + return false; + } - bool prefersVectorizedAddressing() { return true; } + bool prefersVectorizedAddressing() const { return true; } int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, - bool HasBaseReg, int64_t Scale, unsigned AddrSpace) { + bool HasBaseReg, int64_t Scale, + unsigned AddrSpace) const { // Guess that all legal addressing mode are free. if (isLegalAddressingMode(Ty, BaseGV, BaseOffset, HasBaseReg, Scale, AddrSpace)) @@ -227,80 +265,87 @@ public: return -1; } - bool LSRWithInstrQueries() { return false; } + bool LSRWithInstrQueries() const { return false; } - bool isTruncateFree(Type *Ty1, Type *Ty2) { return false; } + bool isTruncateFree(Type *Ty1, Type *Ty2) const { return false; } - bool isProfitableToHoist(Instruction *I) { return true; } + bool isProfitableToHoist(Instruction *I) const { return true; } - bool useAA() { return false; } + bool useAA() const { return false; } - bool isTypeLegal(Type *Ty) { return false; } + bool isTypeLegal(Type *Ty) const { return false; } - bool shouldBuildLookupTables() { return true; } - bool shouldBuildLookupTablesForConstant(Constant *C) { return true; } + unsigned getRegUsageForType(Type *Ty) const { return 1; } - bool useColdCCForColdCall(Function &F) { return false; } + bool shouldBuildLookupTables() const { return true; } + bool shouldBuildLookupTablesForConstant(Constant *C) const { return true; } + + bool useColdCCForColdCall(Function &F) const { return false; } unsigned getScalarizationOverhead(VectorType *Ty, const APInt &DemandedElts, - bool Insert, bool Extract) { + bool Insert, bool Extract) const { return 0; } unsigned getOperandsScalarizationOverhead(ArrayRef Args, - unsigned VF) { + unsigned VF) const { return 0; } - bool supportsEfficientVectorElementLoadStore() { return false; } + bool supportsEfficientVectorElementLoadStore() const { return false; } - bool enableAggressiveInterleaving(bool LoopHasReductions) { return false; } + bool enableAggressiveInterleaving(bool LoopHasReductions) const { + return false; + } TTI::MemCmpExpansionOptions enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const { return {}; } - bool enableInterleavedAccessVectorization() { return false; } + bool enableInterleavedAccessVectorization() const { return false; } - bool enableMaskedInterleavedAccessVectorization() { return false; } + bool enableMaskedInterleavedAccessVectorization() const { return false; } - bool isFPVectorizationPotentiallyUnsafe() { return false; } + bool isFPVectorizationPotentiallyUnsafe() const { return false; } bool allowsMisalignedMemoryAccesses(LLVMContext &Context, unsigned BitWidth, unsigned AddressSpace, unsigned Alignment, - bool *Fast) { + bool *Fast) const { return false; } - TTI::PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) { + TTI::PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) const { return TTI::PSK_Software; } - bool haveFastSqrt(Type *Ty) { return false; } + bool haveFastSqrt(Type *Ty) const { return false; } - bool isFCmpOrdCheaperThanFCmpZero(Type *Ty) { return true; } + bool isFCmpOrdCheaperThanFCmpZero(Type *Ty) const { return true; } - unsigned getFPOpCost(Type *Ty) { return TargetTransformInfo::TCC_Basic; } + unsigned getFPOpCost(Type *Ty) const { + return TargetTransformInfo::TCC_Basic; + } int getIntImmCodeSizeCost(unsigned Opcode, unsigned Idx, const APInt &Imm, - Type *Ty) { + Type *Ty) const { return 0; } unsigned getIntImmCost(const APInt &Imm, Type *Ty, - TTI::TargetCostKind CostKind) { + TTI::TargetCostKind CostKind) const { return TTI::TCC_Basic; } unsigned getIntImmCostInst(unsigned Opcode, unsigned Idx, const APInt &Imm, - Type *Ty, TTI::TargetCostKind CostKind) { + Type *Ty, TTI::TargetCostKind CostKind, + Instruction *Inst = nullptr) const { return TTI::TCC_Free; } unsigned getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx, const APInt &Imm, Type *Ty, - TTI::TargetCostKind CostKind) { + TTI::TargetCostKind CostKind) const { return TTI::TCC_Free; } @@ -323,15 +368,18 @@ public: unsigned getRegisterBitWidth(bool Vector) const { return 32; } - unsigned getMinVectorRegisterBitWidth() { return 128; } + unsigned getMinVectorRegisterBitWidth() const { return 128; } + + Optional getMaxVScale() const { return None; } bool shouldMaximizeVectorBandwidth(bool OptSize) const { return false; } unsigned getMinimumVF(unsigned ElemWidth) const { return 0; } - bool - shouldConsiderAddressTypePromotion(const Instruction &I, - bool &AllowPromotionWithoutCommonHeader) { + unsigned getMaximumVF(unsigned ElemWidth, unsigned Opcode) const { return 0; } + + bool shouldConsiderAddressTypePromotion( + const Instruction &I, bool &AllowPromotionWithoutCommonHeader) const { AllowPromotionWithoutCommonHeader = false; return false; } @@ -370,7 +418,7 @@ public: unsigned getMaxPrefetchIterationsAhead() const { return UINT_MAX; } bool enableWritePrefetching() const { return false; } - unsigned getMaxInterleaveFactor(unsigned VF) { return 1; } + unsigned getMaxInterleaveFactor(unsigned VF) const { return 1; } unsigned getArithmeticInstrCost(unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, @@ -379,7 +427,7 @@ public: TTI::OperandValueProperties Opd1PropInfo, TTI::OperandValueProperties Opd2PropInfo, ArrayRef Args, - const Instruction *CxtI = nullptr) { + const Instruction *CxtI = nullptr) const { // FIXME: A number of transformation tests seem to require these values // which seems a little odd for how arbitary there are. switch (Opcode) { @@ -398,13 +446,14 @@ public: } unsigned getShuffleCost(TTI::ShuffleKind Kind, VectorType *Ty, int Index, - VectorType *SubTp) { + VectorType *SubTp) const { return 1; } unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src, + TTI::CastContextHint CCH, TTI::TargetCostKind CostKind, - const Instruction *I) { + const Instruction *I) const { switch (Opcode) { default: break; @@ -427,23 +476,24 @@ public: // Identity and pointer-to-pointer casts are free. return 0; break; - case Instruction::Trunc: + case Instruction::Trunc: { // trunc to a native type is free (assuming the target has compare and // shift-right of the same width). - if (DL.isLegalInteger(DL.getTypeSizeInBits(Dst))) + TypeSize DstSize = DL.getTypeSizeInBits(Dst); + if (!DstSize.isScalable() && DL.isLegalInteger(DstSize.getFixedSize())) return 0; break; } + } return 1; } unsigned getExtractWithExtendCost(unsigned Opcode, Type *Dst, - VectorType *VecTy, unsigned Index) { + VectorType *VecTy, unsigned Index) const { return 1; } - unsigned getCFInstrCost(unsigned Opcode, - TTI::TargetCostKind CostKind) { + unsigned getCFInstrCost(unsigned Opcode, TTI::TargetCostKind CostKind) const { // A phi would be free, unless we're costing the throughput because it // will require a register. if (Opcode == Instruction::PHI && CostKind != TTI::TCK_RecipThroughput) @@ -452,12 +502,14 @@ public: } unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy, + CmpInst::Predicate VecPred, TTI::TargetCostKind CostKind, const Instruction *I) const { return 1; } - unsigned getVectorInstrCost(unsigned Opcode, Type *Val, unsigned Index) { + unsigned getVectorInstrCost(unsigned Opcode, Type *Val, + unsigned Index) const { return 1; } @@ -469,32 +521,33 @@ public: unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src, Align Alignment, unsigned AddressSpace, - TTI::TargetCostKind CostKind) { + TTI::TargetCostKind CostKind) const { return 1; } unsigned getGatherScatterOpCost(unsigned Opcode, Type *DataTy, const Value *Ptr, bool VariableMask, Align Alignment, TTI::TargetCostKind CostKind, - const Instruction *I = nullptr) { + const Instruction *I = nullptr) const { return 1; } unsigned getInterleavedMemoryOpCost( unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef Indices, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, - bool UseMaskForCond, bool UseMaskForGaps) { + bool UseMaskForCond, bool UseMaskForGaps) const { return 1; } unsigned getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, - TTI::TargetCostKind CostKind) { + TTI::TargetCostKind CostKind) const { switch (ICA.getID()) { default: break; case Intrinsic::annotation: case Intrinsic::assume: case Intrinsic::sideeffect: + case Intrinsic::pseudoprobe: case Intrinsic::dbg_declare: case Intrinsic::dbg_value: case Intrinsic::dbg_label: @@ -505,6 +558,7 @@ public: case Intrinsic::is_constant: case Intrinsic::lifetime_start: case Intrinsic::lifetime_end: + case Intrinsic::experimental_noalias_scope_decl: case Intrinsic::objectsize: case Intrinsic::ptr_annotation: case Intrinsic::var_annotation: @@ -526,26 +580,38 @@ public: } unsigned getCallInstrCost(Function *F, Type *RetTy, ArrayRef Tys, - TTI::TargetCostKind CostKind) { + TTI::TargetCostKind CostKind) const { return 1; } - unsigned getNumberOfParts(Type *Tp) { return 0; } + unsigned getNumberOfParts(Type *Tp) const { return 0; } unsigned getAddressComputationCost(Type *Tp, ScalarEvolution *, - const SCEV *) { + const SCEV *) const { return 0; } unsigned getArithmeticReductionCost(unsigned, VectorType *, bool, - TTI::TargetCostKind) { return 1; } + TTI::TargetCostKind) const { + return 1; + } unsigned getMinMaxReductionCost(VectorType *, VectorType *, bool, bool, - TTI::TargetCostKind) { return 1; } + TTI::TargetCostKind) const { + return 1; + } + + InstructionCost getExtendedAddReductionCost( + bool IsMLA, bool IsUnsigned, Type *ResTy, VectorType *Ty, + TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput) const { + return 1; + } - unsigned getCostOfKeepingLiveOverCall(ArrayRef Tys) { return 0; } + unsigned getCostOfKeepingLiveOverCall(ArrayRef Tys) const { + return 0; + } - bool getTgtMemIntrinsic(IntrinsicInst *Inst, MemIntrinsicInfo &Info) { + bool getTgtMemIntrinsic(IntrinsicInst *Inst, MemIntrinsicInfo &Info) const { return false; } @@ -559,7 +625,7 @@ public: } Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst, - Type *ExpectedType) { + Type *ExpectedType) const { return nullptr; } @@ -637,22 +703,34 @@ public: return false; } + bool preferInLoopReduction(unsigned Opcode, Type *Ty, + TTI::ReductionFlags Flags) const { + return false; + } + + bool preferPredicatedReductionSelect(unsigned Opcode, Type *Ty, + TTI::ReductionFlags Flags) const { + return false; + } + bool shouldExpandReduction(const IntrinsicInst *II) const { return true; } unsigned getGISelRematGlobalCost() const { return 1; } + bool supportsScalableVectors() const { return false; } + bool hasActiveVectorLength() const { return false; } protected: // Obtain the minimum required size to hold the value (without the sign) // In case of a vector it returns the min required size for one element. - unsigned minRequiredElementSize(const Value *Val, bool &isSigned) { + unsigned minRequiredElementSize(const Value *Val, bool &isSigned) const { if (isa(Val) || isa(Val)) { const auto *VectorValue = cast(Val); // In case of a vector need to pick the max between the min // required size for each element - auto *VT = cast(Val->getType()); + auto *VT = cast(Val->getType()); // Assume unsigned elements isSigned = false; @@ -700,12 +778,12 @@ protected: return Val->getType()->getScalarSizeInBits(); } - bool isStridedAccess(const SCEV *Ptr) { + bool isStridedAccess(const SCEV *Ptr) const { return Ptr && isa(Ptr); } const SCEVConstant *getConstantStrideStep(ScalarEvolution *SE, - const SCEV *Ptr) { + const SCEV *Ptr) const { if (!isStridedAccess(Ptr)) return nullptr; const SCEVAddRecExpr *AddRec = cast(Ptr); @@ -713,7 +791,7 @@ protected: } bool isConstantStridedAccessLessThan(ScalarEvolution *SE, const SCEV *Ptr, - int64_t MergeDistance) { + int64_t MergeDistance) const { const SCEVConstant *Step = getConstantStrideStep(SE, Ptr); if (!Step) return false; @@ -775,7 +853,12 @@ public: uint64_t Field = ConstIdx->getZExtValue(); BaseOffset += DL.getStructLayout(STy)->getElementOffset(Field); } else { - int64_t ElementSize = DL.getTypeAllocSize(GTI.getIndexedType()); + // If this operand is a scalable type, bail out early. + // TODO: handle scalable vectors + if (isa(TargetType)) + return TTI::TCC_Basic; + int64_t ElementSize = + DL.getTypeAllocSize(GTI.getIndexedType()).getFixedSize(); if (ConstIdx) { BaseOffset += ConstIdx->getValue().sextOrTrunc(PtrSizeBits) * ElementSize; @@ -800,30 +883,17 @@ public: int getUserCost(const User *U, ArrayRef Operands, TTI::TargetCostKind CostKind) { auto *TargetTTI = static_cast(this); - - // FIXME: We shouldn't have to special-case intrinsics here. - if (CostKind == TTI::TCK_RecipThroughput) { - if (const IntrinsicInst *II = dyn_cast(U)) { - IntrinsicCostAttributes CostAttrs(*II); - return TargetTTI->getIntrinsicInstrCost(CostAttrs, CostKind); - } - } - + // Handle non-intrinsic calls, invokes, and callbr. // FIXME: Unlikely to be true for anything but CodeSize. - if (const auto *CB = dyn_cast(U)) { - const Function *F = CB->getCalledFunction(); - if (F) { - FunctionType *FTy = F->getFunctionType(); - if (Intrinsic::ID IID = F->getIntrinsicID()) { - IntrinsicCostAttributes Attrs(IID, *CB); - return TargetTTI->getIntrinsicInstrCost(Attrs, CostKind); - } - + auto *CB = dyn_cast(U); + if (CB && !isa(U)) { + if (const Function *F = CB->getCalledFunction()) { if (!TargetTTI->isLoweredToCall(F)) return TTI::TCC_Basic; // Give a basic cost if it will be lowered - return TTI::TCC_Basic * (FTy->getNumParams() + 1); + return TTI::TCC_Basic * (F->getFunctionType()->getNumParams() + 1); } + // For indirect or other calls, scale cost by number of arguments. return TTI::TCC_Basic * (CB->arg_size() + 1); } @@ -835,6 +905,12 @@ public: switch (Opcode) { default: break; + case Instruction::Call: { + assert(isa(U) && "Unexpected non-intrinsic call"); + auto *Intrinsic = cast(U); + IntrinsicCostAttributes CostAttrs(Intrinsic->getIntrinsicID(), *CB); + return TargetTTI->getIntrinsicInstrCost(CostAttrs, CostKind); + } case Instruction::Br: case Instruction::Ret: case Instruction::PHI: @@ -895,7 +971,8 @@ public: case Instruction::SExt: case Instruction::ZExt: case Instruction::AddrSpaceCast: - return TargetTTI->getCastInstrCost(Opcode, Ty, OpTy, CostKind, I); + return TargetTTI->getCastInstrCost( + Opcode, Ty, OpTy, TTI::getCastContextHint(I), CostKind, I); case Instruction::Store: { auto *SI = cast(U); Type *ValTy = U->getOperand(0)->getType(); @@ -912,12 +989,16 @@ public: case Instruction::Select: { Type *CondTy = U->getOperand(0)->getType(); return TargetTTI->getCmpSelInstrCost(Opcode, U->getType(), CondTy, + CmpInst::BAD_ICMP_PREDICATE, CostKind, I); } case Instruction::ICmp: case Instruction::FCmp: { Type *ValTy = U->getOperand(0)->getType(); + // TODO: Also handle ICmp/FCmp constant expressions. return TargetTTI->getCmpSelInstrCost(Opcode, ValTy, U->getType(), + I ? cast(I)->getPredicate() + : CmpInst::BAD_ICMP_PREDICATE, CostKind, I); } case Instruction::InsertElement: { @@ -969,41 +1050,23 @@ public: if (CI) Idx = CI->getZExtValue(); - // Try to match a reduction sequence (series of shufflevector and - // vector adds followed by a extractelement). - unsigned ReduxOpCode; - VectorType *ReduxType; - - switch (TTI::matchVectorSplittingReduction(EEI, ReduxOpCode, - ReduxType)) { - case TTI::RK_Arithmetic: - return TargetTTI->getArithmeticReductionCost(ReduxOpCode, ReduxType, - /*IsPairwiseForm=*/false, - CostKind); - case TTI::RK_MinMax: - return TargetTTI->getMinMaxReductionCost( - ReduxType, cast(CmpInst::makeCmpResultType(ReduxType)), - /*IsPairwiseForm=*/false, /*IsUnsigned=*/false, CostKind); - case TTI::RK_UnsignedMinMax: - return TargetTTI->getMinMaxReductionCost( - ReduxType, cast(CmpInst::makeCmpResultType(ReduxType)), - /*IsPairwiseForm=*/false, /*IsUnsigned=*/true, CostKind); - case TTI::RK_None: - break; - } - - switch (TTI::matchPairwiseReduction(EEI, ReduxOpCode, ReduxType)) { + // Try to match a reduction (a series of shufflevector and vector ops + // followed by an extractelement). + unsigned RdxOpcode; + VectorType *RdxType; + bool IsPairwise; + switch (TTI::matchVectorReduction(EEI, RdxOpcode, RdxType, IsPairwise)) { case TTI::RK_Arithmetic: - return TargetTTI->getArithmeticReductionCost(ReduxOpCode, ReduxType, - /*IsPairwiseForm=*/true, CostKind); + return TargetTTI->getArithmeticReductionCost(RdxOpcode, RdxType, + IsPairwise, CostKind); case TTI::RK_MinMax: return TargetTTI->getMinMaxReductionCost( - ReduxType, cast(CmpInst::makeCmpResultType(ReduxType)), - /*IsPairwiseForm=*/true, /*IsUnsigned=*/false, CostKind); + RdxType, cast(CmpInst::makeCmpResultType(RdxType)), + IsPairwise, /*IsUnsigned=*/false, CostKind); case TTI::RK_UnsignedMinMax: return TargetTTI->getMinMaxReductionCost( - ReduxType, cast(CmpInst::makeCmpResultType(ReduxType)), - /*IsPairwiseForm=*/true, /*IsUnsigned=*/true, CostKind); + RdxType, cast(CmpInst::makeCmpResultType(RdxType)), + IsPairwise, /*IsUnsigned=*/true, CostKind); case TTI::RK_None: break; } @@ -1016,8 +1079,7 @@ public: } int getInstructionLatency(const Instruction *I) { - SmallVector Operands(I->value_op_begin(), - I->value_op_end()); + SmallVector Operands(I->operand_values()); if (getUserCost(I, Operands, TTI::TCK_Latency) == TTI::TCC_Free) return 0; diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/Utils/ImportedFunctionsInliningStatistics.h b/contrib/llvm-project/llvm/include/llvm/Analysis/Utils/ImportedFunctionsInliningStatistics.h new file mode 100644 index 000000000000..d02bcd0e335b --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/Utils/ImportedFunctionsInliningStatistics.h @@ -0,0 +1,112 @@ +//===-- ImportedFunctionsInliningStatistics.h -------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// Generating inliner statistics for imported functions, mostly useful for +// ThinLTO. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_IMPORTEDFUNCTIONSINLININGSTATISTICS_H +#define LLVM_TRANSFORMS_UTILS_IMPORTEDFUNCTIONSINLININGSTATISTICS_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include +#include + +namespace llvm { +class Module; +class Function; +/// Calculate and dump ThinLTO specific inliner stats. +/// The main statistics are: +/// (1) Number of inlined imported functions, +/// (2) Number of imported functions inlined into importing module (indirect), +/// (3) Number of non imported functions inlined into importing module +/// (indirect). +/// The difference between first and the second is that first stat counts +/// all performed inlines on imported functions, but the second one only the +/// functions that have been eventually inlined to a function in the importing +/// module (by a chain of inlines). Because llvm uses bottom-up inliner, it is +/// possible to e.g. import function `A`, `B` and then inline `B` to `A`, +/// and after this `A` might be too big to be inlined into some other function +/// that calls it. It calculates this statistic by building graph, where +/// the nodes are functions, and edges are performed inlines and then by marking +/// the edges starting from not imported function. +/// +/// If `Verbose` is set to true, then it also dumps statistics +/// per each inlined function, sorted by the greatest inlines count like +/// - number of performed inlines +/// - number of performed inlines to importing module +class ImportedFunctionsInliningStatistics { +private: + /// InlineGraphNode represents node in graph of inlined functions. + struct InlineGraphNode { + // Default-constructible and movable. + InlineGraphNode() = default; + InlineGraphNode(InlineGraphNode &&) = default; + InlineGraphNode &operator=(InlineGraphNode &&) = default; + + llvm::SmallVector InlinedCallees; + /// Incremented every direct inline. + int32_t NumberOfInlines = 0; + /// Number of inlines into non imported function (possibly indirect via + /// intermediate inlines). Computed based on graph search. + int32_t NumberOfRealInlines = 0; + bool Imported = false; + bool Visited = false; + }; + +public: + ImportedFunctionsInliningStatistics() = default; + ImportedFunctionsInliningStatistics( + const ImportedFunctionsInliningStatistics &) = delete; + + /// Set information like AllFunctions, ImportedFunctions, ModuleName. + void setModuleInfo(const Module &M); + /// Record inline of @param Callee to @param Caller for statistis. + void recordInline(const Function &Caller, const Function &Callee); + /// Dump stats computed with InlinerStatistics class. + /// If @param Verbose is true then separate statistics for every inlined + /// function will be printed. + void dump(bool Verbose); + +private: + /// Creates new Node in NodeMap and sets attributes, or returns existed one. + InlineGraphNode &createInlineGraphNode(const Function &); + void calculateRealInlines(); + void dfs(InlineGraphNode &GraphNode); + + using NodesMapTy = + llvm::StringMap>; + using SortedNodesTy = + std::vector; + /// Returns vector of elements sorted by + /// (-NumberOfInlines, -NumberOfRealInlines, FunctionName). + SortedNodesTy getSortedNodes(); + +private: + /// This map manage life of all InlineGraphNodes. Unique pointer to + /// InlineGraphNode used since the node pointers are also saved in the + /// InlinedCallees vector. If it would store InlineGraphNode instead then the + /// address of the node would not be invariant. + NodesMapTy NodesMap; + /// Non external functions that have some other function inlined inside. + std::vector NonImportedCallers; + int AllFunctions = 0; + int ImportedFunctions = 0; + StringRef ModuleName; +}; + +enum class InlinerFunctionImportStatsOpts { + No = 0, + Basic = 1, + Verbose = 2, +}; + +} // llvm + +#endif // LLVM_TRANSFORMS_UTILS_IMPORTEDFUNCTIONSINLININGSTATISTICS_H diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/Utils/Local.h b/contrib/llvm-project/llvm/include/llvm/Analysis/Utils/Local.h index f31b56345424..bd82b34165d6 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/Utils/Local.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/Utils/Local.h @@ -30,7 +30,7 @@ Value *EmitGEPOffset(IRBuilderTy *Builder, const DataLayout &DL, User *GEP, bool NoAssumptions = false) { GEPOperator *GEPOp = cast(GEP); Type *IntIdxTy = DL.getIndexType(GEP->getType()); - Value *Result = Constant::getNullValue(IntIdxTy); + Value *Result = nullptr; // If the GEP is inbounds, we know that none of the addressing operations will // overflow in a signed sense. @@ -46,6 +46,7 @@ Value *EmitGEPOffset(IRBuilderTy *Builder, const DataLayout &DL, User *GEP, ++i, ++GTI) { Value *Op = *i; uint64_t Size = DL.getTypeAllocSize(GTI.getIndexedType()) & PtrSizeMask; + Value *Offset; if (Constant *OpC = dyn_cast(Op)) { if (OpC->isZeroValue()) continue; @@ -54,46 +55,47 @@ Value *EmitGEPOffset(IRBuilderTy *Builder, const DataLayout &DL, User *GEP, if (StructType *STy = GTI.getStructTypeOrNull()) { uint64_t OpValue = OpC->getUniqueInteger().getZExtValue(); Size = DL.getStructLayout(STy)->getElementOffset(OpValue); - - if (Size) - Result = Builder->CreateAdd(Result, ConstantInt::get(IntIdxTy, Size), - GEP->getName().str()+".offs"); - continue; + if (!Size) + continue; + + Offset = ConstantInt::get(IntIdxTy, Size); + } else { + // Splat the constant if needed. + if (IntIdxTy->isVectorTy() && !OpC->getType()->isVectorTy()) + OpC = ConstantVector::getSplat( + cast(IntIdxTy)->getElementCount(), OpC); + + Constant *Scale = ConstantInt::get(IntIdxTy, Size); + Constant *OC = + ConstantExpr::getIntegerCast(OpC, IntIdxTy, true /*SExt*/); + Offset = + ConstantExpr::getMul(OC, Scale, false /*NUW*/, isInBounds /*NSW*/); } - - // Splat the constant if needed. - if (IntIdxTy->isVectorTy() && !OpC->getType()->isVectorTy()) - OpC = ConstantVector::getSplat( - cast(IntIdxTy)->getElementCount(), OpC); - - Constant *Scale = ConstantInt::get(IntIdxTy, Size); - Constant *OC = ConstantExpr::getIntegerCast(OpC, IntIdxTy, true /*SExt*/); - Scale = - ConstantExpr::getMul(OC, Scale, false /*NUW*/, isInBounds /*NSW*/); - // Emit an add instruction. - Result = Builder->CreateAdd(Result, Scale, GEP->getName().str()+".offs"); - continue; - } - - // Splat the index if needed. - if (IntIdxTy->isVectorTy() && !Op->getType()->isVectorTy()) - Op = Builder->CreateVectorSplat( - cast(IntIdxTy)->getNumElements(), Op); - - // Convert to correct type. - if (Op->getType() != IntIdxTy) - Op = Builder->CreateIntCast(Op, IntIdxTy, true, Op->getName().str()+".c"); - if (Size != 1) { - // We'll let instcombine(mul) convert this to a shl if possible. - Op = Builder->CreateMul(Op, ConstantInt::get(IntIdxTy, Size), - GEP->getName().str() + ".idx", false /*NUW*/, - isInBounds /*NSW*/); + } else { + // Splat the index if needed. + if (IntIdxTy->isVectorTy() && !Op->getType()->isVectorTy()) + Op = Builder->CreateVectorSplat( + cast(IntIdxTy)->getNumElements(), Op); + + // Convert to correct type. + if (Op->getType() != IntIdxTy) + Op = Builder->CreateIntCast(Op, IntIdxTy, true, Op->getName().str()+".c"); + if (Size != 1) { + // We'll let instcombine(mul) convert this to a shl if possible. + Op = Builder->CreateMul(Op, ConstantInt::get(IntIdxTy, Size), + GEP->getName().str() + ".idx", false /*NUW*/, + isInBounds /*NSW*/); + } + Offset = Op; } - // Emit an add instruction. - Result = Builder->CreateAdd(Op, Result, GEP->getName().str()+".offs"); + if (Result) + Result = Builder->CreateAdd(Result, Offset, GEP->getName().str()+".offs", + false /*NUW*/, isInBounds /*NSW*/); + else + Result = Offset; } - return Result; + return Result ? Result : Constant::getNullValue(IntIdxTy); } } diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/Utils/TFUtils.h b/contrib/llvm-project/llvm/include/llvm/Analysis/Utils/TFUtils.h index 2ab2c7a57d94..ea6bc2cf19ee 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/Utils/TFUtils.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/Utils/TFUtils.h @@ -9,10 +9,11 @@ #ifndef LLVM_ANALYSIS_UTILS_TFUTILS_H #define LLVM_ANALYSIS_UTILS_TFUTILS_H -#include "llvm/Config/config.h" +#include "llvm/Config/llvm-config.h" #ifdef LLVM_HAVE_TF_API #include "llvm/IR/LLVMContext.h" +#include "llvm/Support/JSON.h" #include #include @@ -36,6 +37,141 @@ namespace llvm { class TFModelEvaluatorImpl; class EvaluationResultImpl; +/// TensorSpec encapsulates the specification of a tensor: its dimensions, or +/// "shape" (row-major), its type (see TensorSpec::getDataType specializations +/// for supported types), its name and port (see "TensorFlow: Large-Scale +/// Machine Learning on Heterogeneous Distributed Systems", section 4.2, para 2: +/// https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/45166.pdf) +/// +/// TensorSpec is used to set up a TFModelEvaluator by describing the expected +/// inputs and outputs. +class TensorSpec final { +public: + template + static TensorSpec createSpec(const std::string &Name, + const std::vector &Shape, + int Port = 0) { + return TensorSpec(Name, Port, getDataType(), Shape); + } + + const std::string &name() const { return Name; } + int port() const { return Port; } + int typeIndex() const { return TypeIndex; } + const std::vector &shape() const { return Shape; } + + bool operator==(const TensorSpec &Other) const { + return Name == Other.Name && Port == Other.Port && + TypeIndex == Other.TypeIndex && Shape == Other.Shape; + } + + bool operator!=(const TensorSpec &Other) const { return !(*this == Other); } + + /// Get the number of elements in a tensor with this shape. + size_t getElementCount() const { return ElementCount; } + /// Get the size, in bytes, of one element. + size_t getElementByteSize() const; + + template bool isElementType() const { + return getDataType() == TypeIndex; + } + +private: + TensorSpec(const std::string &Name, int Port, int TypeIndex, + const std::vector &Shape); + + template static int getDataType() { + llvm_unreachable("Undefined tensor type"); + } + + std::string Name; + int Port = 0; + int TypeIndex = 0; + std::vector Shape; + size_t ElementCount = 0; +}; + +/// Construct a TensorSpec from a JSON dictionary of the form: +/// { "name": , +/// "port": , +/// "type": , +/// "shape": } +/// For the "type" field, see the C++ primitive types used in +/// TFUTILS_SUPPORTED_TYPES. +Optional getTensorSpecFromJSON(LLVMContext &Ctx, + const json::Value &Value); + +struct LoggedFeatureSpec { + TensorSpec Spec; + Optional LoggingName; +}; + +/// Load the output specs. If SpecFileOverride is not empty, that path is used. +/// Otherwise, the file is assumed to be called 'output_spec.json' and be found +/// under ModelPath (the model directory). +/// The first output tensor name must match ExpectedDecisionName. +/// In case of error, the return is None and the error is logged. +Optional> +loadOutputSpecs(LLVMContext &Ctx, StringRef ExpectedDecisionName, + StringRef ModelPath, StringRef SpecFileOverride = StringRef()); + +/// Logging utility - given an ordered specification of features, and assuming +/// a scalar reward, allow logging feature values and rewards, and then print +/// as tf.train.SequenceExample text protobuf. +/// The assumption is that, for an event to be logged (i.e. a set of feature +/// values and a reward), the user calls the log* API for each feature exactly +/// once, providing the index matching the position in the feature spec list +/// provided at construction: +/// event 0: +/// logTensorValue(0, ...) +/// logTensorValue(1, ...) +/// ... +/// logReward(...) +/// event 1: +/// logTensorValue(0, ...) +/// logTensorValue(1, ...) +/// ... +/// logReward(...) +/// +/// At the end, call print to generate the protobuf. +class Logger final { +public: + /// Construct a Logger. If IncludeReward is false, then logReward shouldn't + /// be called, and the reward feature won't be printed out. + Logger(const std::vector &FeatureSpecs, + const TensorSpec &RewardSpec, bool IncludeReward) + : FeatureSpecs(FeatureSpecs), RewardSpec(RewardSpec), + RawLogData(FeatureSpecs.size() + IncludeReward), + IncludeReward(IncludeReward) {} + + template void logReward(T Value) { + assert(IncludeReward); + logTensorValue(RawLogData.size() - 1, &Value); + } + + template void logFinalReward(T Value) { + assert(RawLogData.back().empty()); + logReward(Value); + } + + template + void logTensorValue(size_t FeatureID, const T *Value, size_t Size = 1) { + const char *Start = reinterpret_cast(Value); + const char *End = Start + sizeof(T) * Size; + RawLogData[FeatureID].insert(RawLogData[FeatureID].end(), Start, End); + } + + void print(raw_ostream &OS); + +private: + std::vector FeatureSpecs; + TensorSpec RewardSpec; + /// RawData has one entry per feature, plus one more for the reward. + /// Each feature's values are then stored in a vector, in succession. + /// This means the ith event is stored at [*][i] + std::vector> RawLogData; + const bool IncludeReward; +}; + class TFModelEvaluator final { public: /// The result of a model evaluation. Handles the lifetime of the output @@ -44,25 +180,41 @@ public: class EvaluationResult { public: EvaluationResult(const EvaluationResult &) = delete; + EvaluationResult &operator=(const EvaluationResult &Other) = delete; + EvaluationResult(EvaluationResult &&Other); + EvaluationResult &operator=(EvaluationResult &&Other); + ~EvaluationResult(); - /// Get a pointer to the first element of the tensor at Index. + /// Get a (const) pointer to the first element of the tensor at Index. template T *getTensorValue(size_t Index) { return static_cast(getUntypedTensorValue(Index)); } + template const T *getTensorValue(size_t Index) const { + return static_cast(getUntypedTensorValue(Index)); + } + + /// Get a (const) pointer to the untyped data of the tensor. + void *getUntypedTensorValue(size_t Index); + const void *getUntypedTensorValue(size_t Index) const; + private: friend class TFModelEvaluator; EvaluationResult(std::unique_ptr Impl); - void *getUntypedTensorValue(size_t Index); std::unique_ptr Impl; }; TFModelEvaluator(StringRef SavedModelPath, - const std::vector &InputNames, - const std::vector &OutputNames, + const std::vector &InputSpecs, + const std::vector &OutputSpecs, const char *Tags = "serve"); + TFModelEvaluator(StringRef SavedModelPath, + const std::vector &InputSpecs, + function_ref GetOutputSpecs, + size_t OutputSpecsSize, const char *Tags = "serve"); + ~TFModelEvaluator(); TFModelEvaluator(const TFModelEvaluator &) = delete; TFModelEvaluator(TFModelEvaluator &&) = delete; @@ -82,33 +234,32 @@ public: /// otherwise. bool isValid() const { return !!Impl; } - /// Initialize the input at Index as a tensor of the given type and - /// dimensions. - template - void initInput(size_t Index, const std::vector &Dimensions) { - return initInput(Index, getModelTypeIndex(), Dimensions); - } - private: void *getUntypedInput(size_t Index); - template int getModelTypeIndex(); - void initInput(size_t Index, int TypeIndex, - const std::vector &Dimensions); - std::unique_ptr Impl; }; -template <> int TFModelEvaluator::getModelTypeIndex(); -template <> int TFModelEvaluator::getModelTypeIndex(); -template <> int TFModelEvaluator::getModelTypeIndex(); -template <> int TFModelEvaluator::getModelTypeIndex(); -template <> int TFModelEvaluator::getModelTypeIndex(); -template <> int TFModelEvaluator::getModelTypeIndex(); -template <> int TFModelEvaluator::getModelTypeIndex(); -template <> int TFModelEvaluator::getModelTypeIndex(); -template <> int TFModelEvaluator::getModelTypeIndex(); -template <> int TFModelEvaluator::getModelTypeIndex(); +/// List of supported types, as a pair: +/// - C++ type +/// - enum name (implementation-specific) +#define TFUTILS_SUPPORTED_TYPES(M) \ + M(float, TF_FLOAT) \ + M(double, TF_DOUBLE) \ + M(int8_t, TF_INT8) \ + M(uint8_t, TF_UINT8) \ + M(int16_t, TF_INT16) \ + M(uint16_t, TF_UINT16) \ + M(int32_t, TF_INT32) \ + M(uint32_t, TF_UINT32) \ + M(int64_t, TF_INT64) \ + M(uint64_t, TF_UINT64) + +#define TFUTILS_GETDATATYPE_DEF(T, E) \ + template <> int TensorSpec::getDataType(); + +TFUTILS_SUPPORTED_TYPES(TFUTILS_GETDATATYPE_DEF) +#undef TFUTILS_GETDATATYPE_DEF } // namespace llvm #endif // LLVM_HAVE_TF_API diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/ValueLattice.h b/contrib/llvm-project/llvm/include/llvm/Analysis/ValueLattice.h index bf5bab9ced22..108d08033ac3 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/ValueLattice.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/ValueLattice.h @@ -11,6 +11,7 @@ #include "llvm/IR/ConstantRange.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/Instructions.h" // //===----------------------------------------------------------------------===// // ValueLatticeElement @@ -456,6 +457,16 @@ public: if (isConstant() && Other.isConstant()) return ConstantExpr::getCompare(Pred, getConstant(), Other.getConstant()); + if (ICmpInst::isEquality(Pred)) { + // not(C) != C => true, not(C) == C => false. + if ((isNotConstant() && Other.isConstant() && + getNotConstant() == Other.getConstant()) || + (isConstant() && Other.isNotConstant() && + getConstant() == Other.getNotConstant())) + return Pred == ICmpInst::ICMP_NE + ? ConstantInt::getTrue(Ty) : ConstantInt::getFalse(Ty); + } + // Integer constants are represented as ConstantRanges with single // elements. if (!isConstantRange() || !Other.isConstantRange()) diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/ValueTracking.h b/contrib/llvm-project/llvm/include/llvm/Analysis/ValueTracking.h index 9510739ef5ab..86c0991451c5 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/ValueTracking.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/ValueTracking.h @@ -21,12 +21,14 @@ #include "llvm/IR/DataLayout.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Intrinsics.h" +#include "llvm/IR/Operator.h" #include #include namespace llvm { class AddOperator; +class AllocaInst; class APInt; class AssumptionCache; class DominatorTree; @@ -43,6 +45,8 @@ class StringRef; class TargetLibraryInfo; class Value; +constexpr unsigned MaxAnalysisRecursionDepth = 6; + /// Determine which bits of V are known to be either zero or one and return /// them in the KnownZero/KnownOne bit sets. /// @@ -366,14 +370,13 @@ class Value; /// that the returned value has pointer type if the specified value does. If /// the MaxLookup value is non-zero, it limits the number of instructions to /// be stripped off. - Value *GetUnderlyingObject(Value *V, const DataLayout &DL, - unsigned MaxLookup = 6); - inline const Value *GetUnderlyingObject(const Value *V, const DataLayout &DL, + Value *getUnderlyingObject(Value *V, unsigned MaxLookup = 6); + inline const Value *getUnderlyingObject(const Value *V, unsigned MaxLookup = 6) { - return GetUnderlyingObject(const_cast(V), DL, MaxLookup); + return getUnderlyingObject(const_cast(V), MaxLookup); } - /// This method is similar to GetUnderlyingObject except that it can + /// This method is similar to getUnderlyingObject except that it can /// look through phi and select instructions and return multiple objects. /// /// If LoopInfo is passed, loop phis are further analyzed. If a pointer @@ -401,20 +404,30 @@ class Value; /// Since A[i] and A[i-1] are independent pointers, getUnderlyingObjects /// should not assume that Curr and Prev share the same underlying object thus /// it shouldn't look through the phi above. - void GetUnderlyingObjects(const Value *V, + void getUnderlyingObjects(const Value *V, SmallVectorImpl &Objects, - const DataLayout &DL, LoopInfo *LI = nullptr, - unsigned MaxLookup = 6); + LoopInfo *LI = nullptr, unsigned MaxLookup = 6); - /// This is a wrapper around GetUnderlyingObjects and adds support for basic + /// This is a wrapper around getUnderlyingObjects and adds support for basic /// ptrtoint+arithmetic+inttoptr sequences. bool getUnderlyingObjectsForCodeGen(const Value *V, - SmallVectorImpl &Objects, - const DataLayout &DL); + SmallVectorImpl &Objects); + + /// Returns unique alloca where the value comes from, or nullptr. + /// If OffsetZero is true check that V points to the begining of the alloca. + AllocaInst *findAllocaForValue(Value *V, bool OffsetZero = false); + inline const AllocaInst *findAllocaForValue(const Value *V, + bool OffsetZero = false) { + return findAllocaForValue(const_cast(V), OffsetZero); + } /// Return true if the only users of this pointer are lifetime markers. bool onlyUsedByLifetimeMarkers(const Value *V); + /// Return true if the only users of this pointer are lifetime markers or + /// droppable instructions. + bool onlyUsedByLifetimeMarkersOrDroppableInsts(const Value *V); + /// Return true if speculation of the given load must be suppressed to avoid /// ordering or interfering with an active sanitizer. If not suppressed, /// dereferenceability and alignment must be proven separately. Note: This @@ -571,45 +584,65 @@ class Value; /// if, for all i, r is evaluated to poison or op raises UB if vi = poison. /// To filter out operands that raise UB on poison, you can use /// getGuaranteedNonPoisonOp. - bool propagatesPoison(const Instruction *I); + bool propagatesPoison(const Operator *I); - /// Return either nullptr or an operand of I such that I will trigger - /// undefined behavior if I is executed and that operand has a poison - /// value. - const Value *getGuaranteedNonPoisonOp(const Instruction *I); + /// Insert operands of I into Ops such that I will trigger undefined behavior + /// if I is executed and that operand has a poison value. + void getGuaranteedNonPoisonOps(const Instruction *I, + SmallPtrSetImpl &Ops); - /// Return true if the given instruction must trigger undefined behavior. + /// Return true if the given instruction must trigger undefined behavior /// when I is executed with any operands which appear in KnownPoison holding /// a poison value at the point of execution. bool mustTriggerUB(const Instruction *I, const SmallSet& KnownPoison); - /// Return true if this function can prove that if PoisonI is executed - /// and yields a poison value, then that will trigger undefined behavior. + /// Return true if this function can prove that if Inst is executed + /// and yields a poison value or undef bits, then that will trigger + /// undefined behavior. /// /// Note that this currently only considers the basic block that is - /// the parent of I. - bool programUndefinedIfPoison(const Instruction *PoisonI); - - /// Return true if I can create poison from non-poison operands. - /// For vectors, canCreatePoison returns true if there is potential poison in - /// any element of the result when vectors without poison are given as + /// the parent of Inst. + bool programUndefinedIfUndefOrPoison(const Instruction *Inst); + bool programUndefinedIfPoison(const Instruction *Inst); + + /// canCreateUndefOrPoison returns true if Op can create undef or poison from + /// non-undef & non-poison operands. + /// For vectors, canCreateUndefOrPoison returns true if there is potential + /// poison or undef in any element of the result when vectors without + /// undef/poison poison are given as operands. + /// For example, given `Op = shl <2 x i32> %x, <0, 32>`, this function returns + /// true. If Op raises immediate UB but never creates poison or undef + /// (e.g. sdiv I, 0), canCreatePoison returns false. + /// + /// canCreatePoison returns true if Op can create poison from non-poison /// operands. - /// For example, given `I = shl <2 x i32> %x, <0, 32>`, this function returns - /// true. If I raises immediate UB but never creates poison (e.g. sdiv I, 0), - /// canCreatePoison returns false. - bool canCreatePoison(const Instruction *I); - - /// Return true if this function can prove that V is never undef value - /// or poison value. - // + bool canCreateUndefOrPoison(const Operator *Op); + bool canCreatePoison(const Operator *Op); + + /// Return true if V is poison given that ValAssumedPoison is already poison. + /// For example, if ValAssumedPoison is `icmp X, 10` and V is `icmp X, 5`, + /// impliesPoison returns true. + bool impliesPoison(const Value *ValAssumedPoison, const Value *V); + + /// Return true if this function can prove that V does not have undef bits + /// and is never poison. If V is an aggregate value or vector, check whether + /// all elements (except padding) are not undef or poison. + /// Note that this is different from canCreateUndefOrPoison because the + /// function assumes Op's operands are not poison/undef. + /// /// If CtxI and DT are specified this method performs flow-sensitive analysis /// and returns true if it is guaranteed to be never undef or poison /// immediately before the CtxI. bool isGuaranteedNotToBeUndefOrPoison(const Value *V, + AssumptionCache *AC = nullptr, const Instruction *CtxI = nullptr, const DominatorTree *DT = nullptr, unsigned Depth = 0); + bool isGuaranteedNotToBePoison(const Value *V, AssumptionCache *AC = nullptr, + const Instruction *CtxI = nullptr, + const DominatorTree *DT = nullptr, + unsigned Depth = 0); /// Specific patterns of select instructions we can match. enum SelectPatternFlavor { @@ -700,6 +733,14 @@ class Value; /// minimum/maximum flavor. CmpInst::Predicate getInverseMinMaxPred(SelectPatternFlavor SPF); + /// Check if the values in \p VL are select instructions that can be converted + /// to a min or max (vector) intrinsic. Returns the intrinsic ID, if such a + /// conversion is possible, together with a bool indicating whether all select + /// conditions are only used by the selects. Otherwise return + /// Intrinsic::not_intrinsic. + std::pair + canConvertToMinOrMaxIntrinsic(ArrayRef VL); + /// Return true if RHS is known to be implied true by LHS. Return false if /// RHS is known to be implied false by LHS. Otherwise, return None if no /// implication can be made. diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/VecFuncs.def b/contrib/llvm-project/llvm/include/llvm/Analysis/VecFuncs.def index 2f64b0fedc7a..cfc3d6115866 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/VecFuncs.def +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/VecFuncs.def @@ -62,6 +62,87 @@ TLI_DEFINE_VECFUNC("acoshf", "vacoshf", 4) TLI_DEFINE_VECFUNC("atanhf", "vatanhf", 4) +#elif defined(TLI_DEFINE_LIBMVEC_X86_VECFUNCS) +// GLIBC Vector math Functions + +TLI_DEFINE_VECFUNC("sin", "_ZGVbN2v_sin", 2) +TLI_DEFINE_VECFUNC("sin", "_ZGVdN4v_sin", 4) + +TLI_DEFINE_VECFUNC("sinf", "_ZGVbN4v_sinf", 4) +TLI_DEFINE_VECFUNC("sinf", "_ZGVdN8v_sinf", 8) + +TLI_DEFINE_VECFUNC("llvm.sin.f64", "_ZGVbN2v_sin", 2) +TLI_DEFINE_VECFUNC("llvm.sin.f64", "_ZGVdN4v_sin", 4) + +TLI_DEFINE_VECFUNC("llvm.sin.f32", "_ZGVbN4v_sinf", 4) +TLI_DEFINE_VECFUNC("llvm.sin.f32", "_ZGVdN8v_sinf", 8) + +TLI_DEFINE_VECFUNC("cos", "_ZGVbN2v_cos", 2) +TLI_DEFINE_VECFUNC("cos", "_ZGVdN4v_cos", 4) + +TLI_DEFINE_VECFUNC("cosf", "_ZGVbN4v_cosf", 4) +TLI_DEFINE_VECFUNC("cosf", "_ZGVdN8v_cosf", 8) + +TLI_DEFINE_VECFUNC("llvm.cos.f64", "_ZGVbN2v_cos", 2) +TLI_DEFINE_VECFUNC("llvm.cos.f64", "_ZGVdN4v_cos", 4) + +TLI_DEFINE_VECFUNC("llvm.cos.f32", "_ZGVbN4v_cosf", 4) +TLI_DEFINE_VECFUNC("llvm.cos.f32", "_ZGVdN8v_cosf", 8) + +TLI_DEFINE_VECFUNC("pow", "_ZGVbN2vv_pow", 2) +TLI_DEFINE_VECFUNC("pow", "_ZGVdN4vv_pow", 4) + +TLI_DEFINE_VECFUNC("powf", "_ZGVbN4vv_powf", 4) +TLI_DEFINE_VECFUNC("powf", "_ZGVdN8vv_powf", 8) + +TLI_DEFINE_VECFUNC("__pow_finite", "_ZGVbN2vv___pow_finite", 2) +TLI_DEFINE_VECFUNC("__pow_finite", "_ZGVdN4vv___pow_finite", 4) + +TLI_DEFINE_VECFUNC("__powf_finite", "_ZGVbN4vv___powf_finite", 4) +TLI_DEFINE_VECFUNC("__powf_finite", "_ZGVdN8vv___powf_finite", 8) + +TLI_DEFINE_VECFUNC("llvm.pow.f64", "_ZGVbN2vv_pow", 2) +TLI_DEFINE_VECFUNC("llvm.pow.f64", "_ZGVdN4vv_pow", 4) + +TLI_DEFINE_VECFUNC("llvm.pow.f32", "_ZGVbN4vv_powf", 4) +TLI_DEFINE_VECFUNC("llvm.pow.f32", "_ZGVdN8vv_powf", 8) + +TLI_DEFINE_VECFUNC("exp", "_ZGVbN2v_exp", 2) +TLI_DEFINE_VECFUNC("exp", "_ZGVdN4v_exp", 4) + +TLI_DEFINE_VECFUNC("expf", "_ZGVbN4v_expf", 4) +TLI_DEFINE_VECFUNC("expf", "_ZGVdN8v_expf", 8) + +TLI_DEFINE_VECFUNC("__exp_finite", "_ZGVbN2v___exp_finite", 2) +TLI_DEFINE_VECFUNC("__exp_finite", "_ZGVdN4v___exp_finite", 4) + +TLI_DEFINE_VECFUNC("__expf_finite", "_ZGVbN4v___expf_finite", 4) +TLI_DEFINE_VECFUNC("__expf_finite", "_ZGVdN8v___expf_finite", 8) + +TLI_DEFINE_VECFUNC("llvm.exp.f64", "_ZGVbN2v_exp", 2) +TLI_DEFINE_VECFUNC("llvm.exp.f64", "_ZGVdN4v_exp", 4) + +TLI_DEFINE_VECFUNC("llvm.exp.f32", "_ZGVbN4v_expf", 4) +TLI_DEFINE_VECFUNC("llvm.exp.f32", "_ZGVdN8v_expf", 8) + +TLI_DEFINE_VECFUNC("log", "_ZGVbN2v_log", 2) +TLI_DEFINE_VECFUNC("log", "_ZGVdN4v_log", 4) + +TLI_DEFINE_VECFUNC("logf", "_ZGVbN4v_logf", 4) +TLI_DEFINE_VECFUNC("logf", "_ZGVdN8v_logf", 8) + +TLI_DEFINE_VECFUNC("__log_finite", "_ZGVbN2v___log_finite", 2) +TLI_DEFINE_VECFUNC("__log_finite", "_ZGVdN4v___log_finite", 4) + +TLI_DEFINE_VECFUNC("__logf_finite", "_ZGVbN4v___logf_finite", 4) +TLI_DEFINE_VECFUNC("__logf_finite", "_ZGVdN8v___logf_finite", 8) + +TLI_DEFINE_VECFUNC("llvm.log.f64", "_ZGVbN2v_log", 2) +TLI_DEFINE_VECFUNC("llvm.log.f64", "_ZGVdN4v_log", 4) + +TLI_DEFINE_VECFUNC("llvm.log.f32", "_ZGVbN4v_logf", 4) +TLI_DEFINE_VECFUNC("llvm.log.f32", "_ZGVdN8v_logf", 8) + #elif defined(TLI_DEFINE_MASSV_VECFUNCS) // IBM MASS library's vector Functions @@ -245,6 +326,70 @@ TLI_DEFINE_VECFUNC("llvm.log.f32", "__svml_logf4", 4) TLI_DEFINE_VECFUNC("llvm.log.f32", "__svml_logf8", 8) TLI_DEFINE_VECFUNC("llvm.log.f32", "__svml_logf16", 16) +TLI_DEFINE_VECFUNC("log2", "__svml_log22", 2) +TLI_DEFINE_VECFUNC("log2", "__svml_log24", 4) +TLI_DEFINE_VECFUNC("log2", "__svml_log28", 8) + +TLI_DEFINE_VECFUNC("log2f", "__svml_log2f4", 4) +TLI_DEFINE_VECFUNC("log2f", "__svml_log2f8", 8) +TLI_DEFINE_VECFUNC("log2f", "__svml_log2f16", 16) + +TLI_DEFINE_VECFUNC("__log2_finite", "__svml_log22", 2) +TLI_DEFINE_VECFUNC("__log2_finite", "__svml_log24", 4) +TLI_DEFINE_VECFUNC("__log2_finite", "__svml_log28", 8) + +TLI_DEFINE_VECFUNC("__log2f_finite", "__svml_log2f4", 4) +TLI_DEFINE_VECFUNC("__log2f_finite", "__svml_log2f8", 8) +TLI_DEFINE_VECFUNC("__log2f_finite", "__svml_log2f16", 16) + +TLI_DEFINE_VECFUNC("llvm.log2.f64", "__svml_log22", 2) +TLI_DEFINE_VECFUNC("llvm.log2.f64", "__svml_log24", 4) +TLI_DEFINE_VECFUNC("llvm.log2.f64", "__svml_log28", 8) + +TLI_DEFINE_VECFUNC("llvm.log2.f32", "__svml_log2f4", 4) +TLI_DEFINE_VECFUNC("llvm.log2.f32", "__svml_log2f8", 8) +TLI_DEFINE_VECFUNC("llvm.log2.f32", "__svml_log2f16", 16) + +TLI_DEFINE_VECFUNC("log10", "__svml_log102", 2) +TLI_DEFINE_VECFUNC("log10", "__svml_log104", 4) +TLI_DEFINE_VECFUNC("log10", "__svml_log108", 8) + +TLI_DEFINE_VECFUNC("log10f", "__svml_log10f4", 4) +TLI_DEFINE_VECFUNC("log10f", "__svml_log10f8", 8) +TLI_DEFINE_VECFUNC("log10f", "__svml_log10f16", 16) + +TLI_DEFINE_VECFUNC("__log10_finite", "__svml_log102", 2) +TLI_DEFINE_VECFUNC("__log10_finite", "__svml_log104", 4) +TLI_DEFINE_VECFUNC("__log10_finite", "__svml_log108", 8) + +TLI_DEFINE_VECFUNC("__log10f_finite", "__svml_log10f4", 4) +TLI_DEFINE_VECFUNC("__log10f_finite", "__svml_log10f8", 8) +TLI_DEFINE_VECFUNC("__log10f_finite", "__svml_log10f16", 16) + +TLI_DEFINE_VECFUNC("llvm.log10.f64", "__svml_log102", 2) +TLI_DEFINE_VECFUNC("llvm.log10.f64", "__svml_log104", 4) +TLI_DEFINE_VECFUNC("llvm.log10.f64", "__svml_log108", 8) + +TLI_DEFINE_VECFUNC("llvm.log10.f32", "__svml_log10f4", 4) +TLI_DEFINE_VECFUNC("llvm.log10.f32", "__svml_log10f8", 8) +TLI_DEFINE_VECFUNC("llvm.log10.f32", "__svml_log10f16", 16) + +TLI_DEFINE_VECFUNC("sqrt", "__svml_sqrt2", 2) +TLI_DEFINE_VECFUNC("sqrt", "__svml_sqrt4", 4) +TLI_DEFINE_VECFUNC("sqrt", "__svml_sqrt8", 8) + +TLI_DEFINE_VECFUNC("sqrtf", "__svml_sqrtf4", 4) +TLI_DEFINE_VECFUNC("sqrtf", "__svml_sqrtf8", 8) +TLI_DEFINE_VECFUNC("sqrtf", "__svml_sqrtf16", 16) + +TLI_DEFINE_VECFUNC("__sqrt_finite", "__svml_sqrt2", 2) +TLI_DEFINE_VECFUNC("__sqrt_finite", "__svml_sqrt4", 4) +TLI_DEFINE_VECFUNC("__sqrt_finite", "__svml_sqrt8", 8) + +TLI_DEFINE_VECFUNC("__sqrtf_finite", "__svml_sqrtf4", 4) +TLI_DEFINE_VECFUNC("__sqrtf_finite", "__svml_sqrtf8", 8) +TLI_DEFINE_VECFUNC("__sqrtf_finite", "__svml_sqrtf16", 16) + TLI_DEFINE_VECFUNC("exp2", "__svml_exp22", 2) TLI_DEFINE_VECFUNC("exp2", "__svml_exp24", 4) TLI_DEFINE_VECFUNC("exp2", "__svml_exp28", 8) @@ -275,6 +420,7 @@ TLI_DEFINE_VECFUNC("__exp2f_finite", "__svml_exp2f16", 16) #undef TLI_DEFINE_VECFUNC #undef TLI_DEFINE_ACCELERATE_VECFUNCS +#undef TLI_DEFINE_LIBMVEC_X86_VECFUNCS #undef TLI_DEFINE_MASSV_VECFUNCS #undef TLI_DEFINE_SVML_VECFUNCS #undef TLI_DEFINE_MASSV_VECFUNCS_NAMES diff --git a/contrib/llvm-project/llvm/include/llvm/Analysis/VectorUtils.h b/contrib/llvm-project/llvm/include/llvm/Analysis/VectorUtils.h index b1d7850442fb..26cb0e456ed4 100644 --- a/contrib/llvm-project/llvm/include/llvm/Analysis/VectorUtils.h +++ b/contrib/llvm-project/llvm/include/llvm/Analysis/VectorUtils.h @@ -14,12 +14,12 @@ #define LLVM_ANALYSIS_VECTORUTILS_H #include "llvm/ADT/MapVector.h" -#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/LoopAccessAnalysis.h" -#include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Support/CheckedArithmetic.h" namespace llvm { +class TargetLibraryInfo; /// Describes the type of Parameters enum class VFParamKind { @@ -99,7 +99,8 @@ struct VFShape { // Retrieve the VFShape that can be used to map a (scalar) function to itself, // with VF = 1. static VFShape getScalarShape(const CallInst &CI) { - return VFShape::get(CI, /*EC*/ {1, false}, /*HasGlobalPredicate*/ false); + return VFShape::get(CI, ElementCount::getFixed(1), + /*HasGlobalPredicate*/ false); } // Retrieve the basic vectorization shape of the function, where all @@ -114,7 +115,7 @@ struct VFShape { Parameters.push_back( VFParameter({CI.arg_size(), VFParamKind::GlobalPredicate})); - return {EC.Min, EC.Scalable, Parameters}; + return {EC.getKnownMinValue(), EC.isScalable(), Parameters}; } /// Sanity check on the Parameters in the VFShape. bool hasValidParameterList() const; @@ -299,13 +300,17 @@ namespace Intrinsic { typedef unsigned ID; } -/// A helper function for converting Scalar types to vector types. -/// If the incoming type is void, we return void. If the VF is 1, we return -/// the scalar type. -inline Type *ToVectorTy(Type *Scalar, unsigned VF, bool isScalable = false) { - if (Scalar->isVoidTy() || VF == 1) +/// A helper function for converting Scalar types to vector types. If +/// the incoming type is void, we return void. If the EC represents a +/// scalar, we return the scalar type. +inline Type *ToVectorTy(Type *Scalar, ElementCount EC) { + if (Scalar->isVoidTy() || Scalar->isMetadataTy() || EC.isScalar()) return Scalar; - return VectorType::get(Scalar, {VF, isScalable}); + return VectorType::get(Scalar, EC); +} + +inline Type *ToVectorTy(Type *Scalar, unsigned VF) { + return ToVectorTy(Scalar, ElementCount::getFixed(VF)); } /// Identify if the intrinsic is trivially vectorizable. @@ -353,7 +358,7 @@ int getSplatIndex(ArrayRef Mask); /// Get splat value if the input is a splat vector or return nullptr. /// The value may be extracted from a splat constants vector or from /// a sequence of instructions that broadcast a single value into a vector. -const Value *getSplatValue(const Value *V); +Value *getSplatValue(const Value *V); /// Return true if each element of the vector value \p V is poisoned or equal to /// every other non-poisoned element. If an index element is specified, either @@ -539,20 +544,20 @@ createSequentialMask(unsigned Start, unsigned NumInts, unsigned NumUndefs); /// elements, it will be padded with undefs. Value *concatenateVectors(IRBuilderBase &Builder, ArrayRef Vecs); -/// Given a mask vector of the form , Return true if all of the -/// elements of this predicate mask are false or undef. That is, return true -/// if all lanes can be assumed inactive. +/// Given a mask vector of i1, Return true if all of the elements of this +/// predicate mask are known to be false or undef. That is, return true if all +/// lanes can be assumed inactive. bool maskIsAllZeroOrUndef(Value *Mask); -/// Given a mask vector of the form , Return true if all of the -/// elements of this predicate mask are true or undef. That is, return true -/// if all lanes can be assumed active. +/// Given a mask vector of i1, Return true if all of the elements of this +/// predicate mask are known to be true or undef. That is, return true if all +/// lanes can be assumed active. bool maskIsAllOneOrUndef(Value *Mask); /// Given a mask vector of the form , return an APInt (of bitwidth Y) /// for each lane which may be active. APInt possiblyDemandedEltsInMask(Value *Mask); - + /// The group of interleaved loads/stores sharing the same stride and /// close to each other. /// @@ -615,6 +620,11 @@ public: return false; int32_t Key = *MaybeKey; + // Skip if the key is used for either the tombstone or empty special values. + if (DenseMapInfo::getTombstoneKey() == Key || + DenseMapInfo::getEmptyKey() == Key) + return false; + // Skip if there is already a member with the same index. if (Members.find(Key) != Members.end()) return false; @@ -650,11 +660,7 @@ public: /// \returns nullptr if contains no such member. InstTy *getMember(uint32_t Index) const { int32_t Key = SmallestKey + Index; - auto Member = Members.find(Key); - if (Member == Members.end()) - return nullptr; - - return Member->second; + return Members.lookup(Key); } /// Get the index for the given member. Unlike the key in the member @@ -772,9 +778,7 @@ public: /// \returns nullptr if doesn't have such group. InterleaveGroup * getInterleaveGroup(const Instruction *Instr) const { - if (InterleaveGroupMap.count(Instr)) - return InterleaveGroupMap.find(Instr)->second; - return nullptr; + return InterleaveGroupMap.lookup(Instr); } iterator_range *>> diff --git a/contrib/llvm-project/llvm/include/llvm/BinaryFormat/COFF.h b/contrib/llvm-project/llvm/include/llvm/BinaryFormat/COFF.h index 1919d7f0dece..716d649f7c51 100644 --- a/contrib/llvm-project/llvm/include/llvm/BinaryFormat/COFF.h +++ b/contrib/llvm-project/llvm/include/llvm/BinaryFormat/COFF.h @@ -311,6 +311,7 @@ enum SectionCharacteristics : uint32_t { IMAGE_SCN_ALIGN_2048BYTES = 0x00C00000, IMAGE_SCN_ALIGN_4096BYTES = 0x00D00000, IMAGE_SCN_ALIGN_8192BYTES = 0x00E00000, + IMAGE_SCN_ALIGN_MASK = 0x00F00000, IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000, IMAGE_SCN_MEM_DISCARDABLE = 0x02000000, IMAGE_SCN_MEM_NOT_CACHED = 0x04000000, diff --git a/contrib/llvm-project/llvm/include/llvm/BinaryFormat/Dwarf.def b/contrib/llvm-project/llvm/include/llvm/BinaryFormat/Dwarf.def index f0337ef4fb54..f69877bb50df 100644 --- a/contrib/llvm-project/llvm/include/llvm/BinaryFormat/Dwarf.def +++ b/contrib/llvm-project/llvm/include/llvm/BinaryFormat/Dwarf.def @@ -17,7 +17,7 @@ defined HANDLE_DW_VIRTUALITY || defined HANDLE_DW_DEFAULTED || \ defined HANDLE_DW_CC || defined HANDLE_DW_LNS || defined HANDLE_DW_LNE || \ defined HANDLE_DW_LNCT || defined HANDLE_DW_MACRO || \ - defined HANDLE_MACRO_FLAG || \ + defined HANDLE_DW_MACRO_GNU || defined HANDLE_MACRO_FLAG || \ defined HANDLE_DW_RLE || defined HANDLE_DW_LLE || \ (defined HANDLE_DW_CFA && defined HANDLE_DW_CFA_PRED) || \ defined HANDLE_DW_APPLE_PROPERTY || defined HANDLE_DW_UT || \ @@ -88,6 +88,10 @@ #define HANDLE_DW_MACRO(ID, NAME) #endif +#ifndef HANDLE_DW_MACRO_GNU +#define HANDLE_DW_MACRO_GNU(ID, NAME) +#endif + #ifndef HANDLE_MACRO_FLAG #define HANDLE_MACRO_FLAG(ID, NAME) #endif @@ -837,6 +841,18 @@ HANDLE_DW_MACRO(0x0a, import_sup) HANDLE_DW_MACRO(0x0b, define_strx) HANDLE_DW_MACRO(0x0c, undef_strx) +// GNU .debug_macro extension. +HANDLE_DW_MACRO_GNU(0x01, define) +HANDLE_DW_MACRO_GNU(0x02, undef) +HANDLE_DW_MACRO_GNU(0x03, start_file) +HANDLE_DW_MACRO_GNU(0x04, end_file) +HANDLE_DW_MACRO_GNU(0x05, define_indirect) +HANDLE_DW_MACRO_GNU(0x06, undef_indirect) +HANDLE_DW_MACRO_GNU(0x07, transparent_include) +HANDLE_DW_MACRO_GNU(0x08, define_indirect_alt) +HANDLE_DW_MACRO_GNU(0x09, undef_indirect_alt) +HANDLE_DW_MACRO_GNU(0x0a, transparent_include_alt) + // DWARF v5 Macro header flags. HANDLE_MACRO_FLAG(0x01, OFFSET_SIZE) HANDLE_MACRO_FLAG(0x02, DEBUG_LINE_OFFSET) @@ -986,6 +1002,7 @@ HANDLE_DW_SECT(8, RNGLISTS) #undef HANDLE_DW_LNE #undef HANDLE_DW_LNCT #undef HANDLE_DW_MACRO +#undef HANDLE_DW_MACRO_GNU #undef HANDLE_MACRO_FLAG #undef HANDLE_DW_RLE #undef HANDLE_DW_LLE diff --git a/contrib/llvm-project/llvm/include/llvm/BinaryFormat/Dwarf.h b/contrib/llvm-project/llvm/include/llvm/BinaryFormat/Dwarf.h index 4e8b708f39bb..cafc5be686bc 100644 --- a/contrib/llvm-project/llvm/include/llvm/BinaryFormat/Dwarf.h +++ b/contrib/llvm-project/llvm/include/llvm/BinaryFormat/Dwarf.h @@ -27,6 +27,8 @@ #include "llvm/Support/FormatVariadicDetails.h" #include "llvm/ADT/Triple.h" +#include + namespace llvm { class StringRef; @@ -118,10 +120,11 @@ enum LocationAtom { #include "llvm/BinaryFormat/Dwarf.def" DW_OP_lo_user = 0xe0, DW_OP_hi_user = 0xff, - DW_OP_LLVM_fragment = 0x1000, ///< Only used in LLVM metadata. - DW_OP_LLVM_convert = 0x1001, ///< Only used in LLVM metadata. - DW_OP_LLVM_tag_offset = 0x1002, ///< Only used in LLVM metadata. - DW_OP_LLVM_entry_value = 0x1003, ///< Only used in LLVM metadata. + DW_OP_LLVM_fragment = 0x1000, ///< Only used in LLVM metadata. + DW_OP_LLVM_convert = 0x1001, ///< Only used in LLVM metadata. + DW_OP_LLVM_tag_offset = 0x1002, ///< Only used in LLVM metadata. + DW_OP_LLVM_entry_value = 0x1003, ///< Only used in LLVM metadata. + DW_OP_LLVM_implicit_pointer = 0x1004, ///< Only used in LLVM metadata. }; enum TypeKind : uint8_t { @@ -183,6 +186,7 @@ enum SourceLanguage { }; inline bool isCPlusPlus(SourceLanguage S) { + bool result = false; // Deliberately enumerate all the language options so we get a warning when // new language options are added (-Wswitch) that'll hopefully help keep this // switch up-to-date when new C++ versions are added. @@ -191,7 +195,8 @@ inline bool isCPlusPlus(SourceLanguage S) { case DW_LANG_C_plus_plus_03: case DW_LANG_C_plus_plus_11: case DW_LANG_C_plus_plus_14: - return true; + result = true; + break; case DW_LANG_C89: case DW_LANG_C: case DW_LANG_Ada83: @@ -230,9 +235,68 @@ inline bool isCPlusPlus(SourceLanguage S) { case DW_LANG_BORLAND_Delphi: case DW_LANG_lo_user: case DW_LANG_hi_user: - return false; + result = false; + break; } - llvm_unreachable("Invalid source language"); + + return result; +} + +inline bool isFortran(SourceLanguage S) { + bool result = false; + // Deliberately enumerate all the language options so we get a warning when + // new language options are added (-Wswitch) that'll hopefully help keep this + // switch up-to-date when new Fortran versions are added. + switch (S) { + case DW_LANG_Fortran77: + case DW_LANG_Fortran90: + case DW_LANG_Fortran95: + case DW_LANG_Fortran03: + case DW_LANG_Fortran08: + result = true; + break; + case DW_LANG_C89: + case DW_LANG_C: + case DW_LANG_Ada83: + case DW_LANG_C_plus_plus: + case DW_LANG_Cobol74: + case DW_LANG_Cobol85: + case DW_LANG_Pascal83: + case DW_LANG_Modula2: + case DW_LANG_Java: + case DW_LANG_C99: + case DW_LANG_Ada95: + case DW_LANG_PLI: + case DW_LANG_ObjC: + case DW_LANG_ObjC_plus_plus: + case DW_LANG_UPC: + case DW_LANG_D: + case DW_LANG_Python: + case DW_LANG_OpenCL: + case DW_LANG_Go: + case DW_LANG_Modula3: + case DW_LANG_Haskell: + case DW_LANG_C_plus_plus_03: + case DW_LANG_C_plus_plus_11: + case DW_LANG_OCaml: + case DW_LANG_Rust: + case DW_LANG_C11: + case DW_LANG_Swift: + case DW_LANG_Julia: + case DW_LANG_Dylan: + case DW_LANG_C_plus_plus_14: + case DW_LANG_RenderScript: + case DW_LANG_BLISS: + case DW_LANG_Mips_Assembler: + case DW_LANG_GOOGLE_RenderScript: + case DW_LANG_BORLAND_Delphi: + case DW_LANG_lo_user: + case DW_LANG_hi_user: + result = false; + break; + } + + return result; } enum CaseSensitivity { @@ -309,6 +373,14 @@ enum MacroEntryType { DW_MACRO_hi_user = 0xff }; +/// GNU .debug_macro macro information entry type encodings. +enum GnuMacroEntryType { +#define HANDLE_DW_MACRO_GNU(ID, NAME) DW_MACRO_GNU_##NAME = ID, +#include "llvm/BinaryFormat/Dwarf.def" + DW_MACRO_GNU_lo_user = 0xe0, + DW_MACRO_GNU_hi_user = 0xff +}; + /// DWARF v5 range list entry encoding values. enum RnglistEntries { #define HANDLE_DW_RLE(ID, NAME) DW_RLE_##NAME = ID, @@ -472,6 +544,7 @@ StringRef LNStandardString(unsigned Standard); StringRef LNExtendedString(unsigned Encoding); StringRef MacinfoString(unsigned Encoding); StringRef MacroString(unsigned Encoding); +StringRef GnuMacroString(unsigned Encoding); StringRef RangeListEncodingString(unsigned Encoding); StringRef LocListEncodingString(unsigned Encoding); StringRef CallFrameString(unsigned Encoding, Triple::ArchType Arch); @@ -483,6 +556,7 @@ StringRef GDBIndexEntryLinkageString(GDBIndexEntryLinkage Linkage); StringRef IndexString(unsigned Idx); StringRef FormatString(DwarfFormat Format); StringRef FormatString(bool IsDWARF64); +StringRef RLEString(unsigned RLE); /// @} /// \defgroup DwarfConstantsParsing Dwarf constants parsing functions @@ -674,6 +748,11 @@ template <> struct EnumTraits : public std::true_type { static constexpr char Type[3] = "OP"; static constexpr StringRef (*StringFn)(unsigned) = &OperationEncodingString; }; + +inline uint64_t computeTombstoneAddress(uint8_t AddressByteSize) { + return std::numeric_limits::max() >> (8 - AddressByteSize) * 8; +} + } // End of namespace dwarf /// Dwarf constants format_provider diff --git a/contrib/llvm-project/llvm/include/llvm/BinaryFormat/DynamicTags.def b/contrib/llvm-project/llvm/include/llvm/BinaryFormat/DynamicTags.def index aec408bd2d72..c08f8a53bdb5 100644 --- a/contrib/llvm-project/llvm/include/llvm/BinaryFormat/DynamicTags.def +++ b/contrib/llvm-project/llvm/include/llvm/BinaryFormat/DynamicTags.def @@ -120,6 +120,7 @@ DYNAMIC_TAG(VERNEEDNUM, 0X6FFFFFFF) // The number of entries in DT_VERNEED. // AArch64 specific dynamic table entries AARCH64_DYNAMIC_TAG(AARCH64_BTI_PLT, 0x70000001) AARCH64_DYNAMIC_TAG(AARCH64_PAC_PLT, 0x70000003) +AARCH64_DYNAMIC_TAG(AARCH64_VARIANT_PCS, 0x70000005) // Hexagon specific dynamic table entries HEXAGON_DYNAMIC_TAG(HEXAGON_SYMSZ, 0x70000000) diff --git a/contrib/llvm-project/llvm/include/llvm/BinaryFormat/ELF.h b/contrib/llvm-project/llvm/include/llvm/BinaryFormat/ELF.h index 21a5c26883cd..1552303b610c 100644 --- a/contrib/llvm-project/llvm/include/llvm/BinaryFormat/ELF.h +++ b/contrib/llvm-project/llvm/include/llvm/BinaryFormat/ELF.h @@ -107,13 +107,17 @@ struct Elf64_Ehdr { unsigned char getDataEncoding() const { return e_ident[EI_DATA]; } }; -// File types +// File types. +// See current registered ELF types at: +// http://www.sco.com/developers/gabi/latest/ch4.eheader.html enum { ET_NONE = 0, // No file type ET_REL = 1, // Relocatable file ET_EXEC = 2, // Executable file ET_DYN = 3, // Shared object file ET_CORE = 4, // Core file + ET_LOOS = 0xfe00, // Beginning of operating system-specific codes + ET_HIOS = 0xfeff, // Operating system-specific ET_LOPROC = 0xff00, // Beginning of processor-specific codes ET_HIPROC = 0xffff // Processor-specific }; @@ -312,6 +316,7 @@ enum { EM_LANAI = 244, // Lanai 32-bit processor EM_BPF = 247, // Linux kernel bpf virtual machine EM_VE = 251, // NEC SX-Aurora VE + EM_CSKY = 252, // C-SKY 32-bit processor }; // Object file classes. @@ -359,6 +364,14 @@ enum { ELFOSABI_LAST_ARCH = 255 // Last Architecture-specific OS ABI }; +// AMDGPU OS ABI Version identification. +enum { + // ELFABIVERSION_AMDGPU_HSA_V1 does not exist because OS ABI identification + // was never defined for V1. + ELFABIVERSION_AMDGPU_HSA_V2 = 0, + ELFABIVERSION_AMDGPU_HSA_V3 = 1, +}; + #define ELF_RELOC(name, value) name = value, // X86_64 relocations. @@ -686,41 +699,39 @@ enum : unsigned { EF_AMDGPU_MACH_R600_LAST = EF_AMDGPU_MACH_R600_TURKS, // AMDGCN-based processors. - - // AMDGCN GFX6. - EF_AMDGPU_MACH_AMDGCN_GFX600 = 0x020, - EF_AMDGPU_MACH_AMDGCN_GFX601 = 0x021, - // AMDGCN GFX7. - EF_AMDGPU_MACH_AMDGCN_GFX700 = 0x022, - EF_AMDGPU_MACH_AMDGCN_GFX701 = 0x023, - EF_AMDGPU_MACH_AMDGCN_GFX702 = 0x024, - EF_AMDGPU_MACH_AMDGCN_GFX703 = 0x025, - EF_AMDGPU_MACH_AMDGCN_GFX704 = 0x026, - // AMDGCN GFX8. - EF_AMDGPU_MACH_AMDGCN_GFX801 = 0x028, - EF_AMDGPU_MACH_AMDGCN_GFX802 = 0x029, - EF_AMDGPU_MACH_AMDGCN_GFX803 = 0x02a, - EF_AMDGPU_MACH_AMDGCN_GFX810 = 0x02b, - // AMDGCN GFX9. - EF_AMDGPU_MACH_AMDGCN_GFX900 = 0x02c, - EF_AMDGPU_MACH_AMDGCN_GFX902 = 0x02d, - EF_AMDGPU_MACH_AMDGCN_GFX904 = 0x02e, - EF_AMDGPU_MACH_AMDGCN_GFX906 = 0x02f, - EF_AMDGPU_MACH_AMDGCN_GFX908 = 0x030, - EF_AMDGPU_MACH_AMDGCN_GFX909 = 0x031, - // AMDGCN GFX10. - EF_AMDGPU_MACH_AMDGCN_GFX1010 = 0x033, - EF_AMDGPU_MACH_AMDGCN_GFX1011 = 0x034, - EF_AMDGPU_MACH_AMDGCN_GFX1012 = 0x035, - EF_AMDGPU_MACH_AMDGCN_GFX1030 = 0x036, - - // Reserved for AMDGCN-based processors. - EF_AMDGPU_MACH_AMDGCN_RESERVED0 = 0x027, - EF_AMDGPU_MACH_AMDGCN_RESERVED1 = 0x032, + EF_AMDGPU_MACH_AMDGCN_GFX600 = 0x020, + EF_AMDGPU_MACH_AMDGCN_GFX601 = 0x021, + EF_AMDGPU_MACH_AMDGCN_GFX700 = 0x022, + EF_AMDGPU_MACH_AMDGCN_GFX701 = 0x023, + EF_AMDGPU_MACH_AMDGCN_GFX702 = 0x024, + EF_AMDGPU_MACH_AMDGCN_GFX703 = 0x025, + EF_AMDGPU_MACH_AMDGCN_GFX704 = 0x026, + EF_AMDGPU_MACH_AMDGCN_RESERVED_0X27 = 0x027, + EF_AMDGPU_MACH_AMDGCN_GFX801 = 0x028, + EF_AMDGPU_MACH_AMDGCN_GFX802 = 0x029, + EF_AMDGPU_MACH_AMDGCN_GFX803 = 0x02a, + EF_AMDGPU_MACH_AMDGCN_GFX810 = 0x02b, + EF_AMDGPU_MACH_AMDGCN_GFX900 = 0x02c, + EF_AMDGPU_MACH_AMDGCN_GFX902 = 0x02d, + EF_AMDGPU_MACH_AMDGCN_GFX904 = 0x02e, + EF_AMDGPU_MACH_AMDGCN_GFX906 = 0x02f, + EF_AMDGPU_MACH_AMDGCN_GFX908 = 0x030, + EF_AMDGPU_MACH_AMDGCN_GFX909 = 0x031, + EF_AMDGPU_MACH_AMDGCN_GFX90C = 0x032, + EF_AMDGPU_MACH_AMDGCN_GFX1010 = 0x033, + EF_AMDGPU_MACH_AMDGCN_GFX1011 = 0x034, + EF_AMDGPU_MACH_AMDGCN_GFX1012 = 0x035, + EF_AMDGPU_MACH_AMDGCN_GFX1030 = 0x036, + EF_AMDGPU_MACH_AMDGCN_GFX1031 = 0x037, + EF_AMDGPU_MACH_AMDGCN_GFX1032 = 0x038, + EF_AMDGPU_MACH_AMDGCN_GFX1033 = 0x039, + EF_AMDGPU_MACH_AMDGCN_GFX602 = 0x03a, + EF_AMDGPU_MACH_AMDGCN_GFX705 = 0x03b, + EF_AMDGPU_MACH_AMDGCN_GFX805 = 0x03c, // First/last AMDGCN-based processors. EF_AMDGPU_MACH_AMDGCN_FIRST = EF_AMDGPU_MACH_AMDGCN_GFX600, - EF_AMDGPU_MACH_AMDGCN_LAST = EF_AMDGPU_MACH_AMDGCN_GFX1030, + EF_AMDGPU_MACH_AMDGCN_LAST = EF_AMDGPU_MACH_AMDGCN_GFX805, // Indicates if the "xnack" target feature is enabled for all code contained // in the object. @@ -777,6 +788,12 @@ enum { #include "ELFRelocs/VE.def" }; + +// ELF Relocation types for CSKY +enum { +#include "ELFRelocs/CSKY.def" +}; + #undef ELF_RELOC // Section header. @@ -854,10 +871,11 @@ enum : unsigned { SHT_LLVM_ADDRSIG = 0x6fff4c03, // List of address-significant symbols // for safe ICF. SHT_LLVM_DEPENDENT_LIBRARIES = - 0x6fff4c04, // LLVM Dependent Library Specifiers. - SHT_LLVM_SYMPART = 0x6fff4c05, // Symbol partition specification. - SHT_LLVM_PART_EHDR = 0x6fff4c06, // ELF header for loadable partition. - SHT_LLVM_PART_PHDR = 0x6fff4c07, // Phdrs for loadable partition. + 0x6fff4c04, // LLVM Dependent Library Specifiers. + SHT_LLVM_SYMPART = 0x6fff4c05, // Symbol partition specification. + SHT_LLVM_PART_EHDR = 0x6fff4c06, // ELF header for loadable partition. + SHT_LLVM_PART_PHDR = 0x6fff4c07, // Phdrs for loadable partition. + SHT_LLVM_BB_ADDR_MAP = 0x6fff4c08, // LLVM Basic Block Address Map. // Android's experimental support for SHT_RELR sections. // https://android.googlesource.com/platform/bionic/+/b7feec74547f84559a1467aca02708ff61346d2a/libc/include/elf.h#512 SHT_ANDROID_RELR = 0x6fffff00, // Relocation entries; only offsets. diff --git a/contrib/llvm-project/llvm/include/llvm/BinaryFormat/ELFRelocs/CSKY.def b/contrib/llvm-project/llvm/include/llvm/BinaryFormat/ELFRelocs/CSKY.def new file mode 100644 index 000000000000..c5f2dbae8033 --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/BinaryFormat/ELFRelocs/CSKY.def @@ -0,0 +1,74 @@ + +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +ELF_RELOC(R_CKCORE_NONE, 0) +ELF_RELOC(R_CKCORE_ADDR32, 1) +ELF_RELOC(R_CKCORE_PCREL_IMM8_4, 2) +ELF_RELOC(R_CKCORE_PCREL_IMM11_2, 3) +ELF_RELOC(R_CKCORE_PCREL_IMM4_2, 4) +ELF_RELOC(R_CKCORE_PCREL32, 5) +ELF_RELOC(R_CKCORE_PCREL_JSR_IMM11_2, 6) +ELF_RELOC(R_CKCORE_GNU_VTINHERIT, 7) +ELF_RELOC(R_CKCORE_GNU_VTENTRY, 8) +ELF_RELOC(R_CKCORE_RELATIVE, 9) +ELF_RELOC(R_CKCORE_COPY, 10) +ELF_RELOC(R_CKCORE_GLOB_DAT, 11) +ELF_RELOC(R_CKCORE_JUMP_SLOT, 12) +ELF_RELOC(R_CKCORE_GOTOFF, 13) +ELF_RELOC(R_CKCORE_GOTPC, 14) +ELF_RELOC(R_CKCORE_GOT32, 15) +ELF_RELOC(R_CKCORE_PLT32, 16) +ELF_RELOC(R_CKCORE_ADDRGOT, 17) +ELF_RELOC(R_CKCORE_ADDRPLT, 18) +ELF_RELOC(R_CKCORE_PCREL_IMM26_2, 19) +ELF_RELOC(R_CKCORE_PCREL_IMM16_2, 20) +ELF_RELOC(R_CKCORE_PCREL_IMM16_4, 21) +ELF_RELOC(R_CKCORE_PCREL_IMM10_2, 22) +ELF_RELOC(R_CKCORE_PCREL_IMM10_4, 23) +ELF_RELOC(R_CKCORE_ADDR_HI16, 24) +ELF_RELOC(R_CKCORE_ADDR_LO16, 25) +ELF_RELOC(R_CKCORE_GOTPC_HI16, 26) +ELF_RELOC(R_CKCORE_GOTPC_LO16, 27) +ELF_RELOC(R_CKCORE_GOTOFF_HI16, 28) +ELF_RELOC(R_CKCORE_GOTOFF_LO16, 29) +ELF_RELOC(R_CKCORE_GOT12, 30) +ELF_RELOC(R_CKCORE_GOT_HI16, 31) +ELF_RELOC(R_CKCORE_GOT_LO16, 32) +ELF_RELOC(R_CKCORE_PLT12, 33) +ELF_RELOC(R_CKCORE_PLT_HI16, 34) +ELF_RELOC(R_CKCORE_PLT_LO16, 35) +ELF_RELOC(R_CKCORE_ADDRGOT_HI16, 36) +ELF_RELOC(R_CKCORE_ADDRGOT_LO16, 37) +ELF_RELOC(R_CKCORE_ADDRPLT_HI16, 38) +ELF_RELOC(R_CKCORE_ADDRPLT_LO16, 39) +ELF_RELOC(R_CKCORE_PCREL_JSR_IMM26_2, 40) +ELF_RELOC(R_CKCORE_TOFFSET_LO16, 41) +ELF_RELOC(R_CKCORE_DOFFSET_LO16, 42) +ELF_RELOC(R_CKCORE_PCREL_IMM18_2, 43) +ELF_RELOC(R_CKCORE_DOFFSET_IMM18, 44) +ELF_RELOC(R_CKCORE_DOFFSET_IMM18_2, 45) +ELF_RELOC(R_CKCORE_DOFFSET_IMM18_4, 46) +ELF_RELOC(R_CKCORE_GOTOFF_IMM18, 47) +ELF_RELOC(R_CKCORE_GOT_IMM18_4, 48) +ELF_RELOC(R_CKCORE_PLT_IMM18_4, 49) +ELF_RELOC(R_CKCORE_PCREL_IMM7_4, 50) +ELF_RELOC(R_CKCORE_TLS_LE32, 51) +ELF_RELOC(R_CKCORE_TLS_IE32, 52) +ELF_RELOC(R_CKCORE_TLS_GD32, 53) +ELF_RELOC(R_CKCORE_TLS_LDM32, 54) +ELF_RELOC(R_CKCORE_TLS_LDO32, 55) +ELF_RELOC(R_CKCORE_TLS_DTPMOD32, 56) +ELF_RELOC(R_CKCORE_TLS_DTPOFF32, 57) +ELF_RELOC(R_CKCORE_TLS_TPOFF32, 58) +ELF_RELOC(R_CKCORE_PCREL_FLRW_IMM8_4, 59) +ELF_RELOC(R_CKCORE_NOJSRI, 60) +ELF_RELOC(R_CKCORE_CALLGRAPH, 61) +ELF_RELOC(R_CKCORE_IRELATIVE, 62) +ELF_RELOC(R_CKCORE_PCREL_BLOOP_IMM4_4, 63) +ELF_RELOC(R_CKCORE_PCREL_BLOOP_IMM12_4, 64) +ELF_RELOC(R_CKCORE_PCREL_VLRW_IMM12_1, 65) +ELF_RELOC(R_CKCORE_PCREL_VLRW_IMM12_2, 66) +ELF_RELOC(R_CKCORE_PCREL_VLRW_IMM12_4, 67) +ELF_RELOC(R_CKCORE_PCREL_VLRW_IMM12_8, 68) diff --git a/contrib/llvm-project/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def b/contrib/llvm-project/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def index e28c9caaefaf..0422aa0606d7 100644 --- a/contrib/llvm-project/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def +++ b/contrib/llvm-project/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def @@ -97,8 +97,14 @@ #undef R_PPC64_DTPREL16_HIGH #undef R_PPC64_DTPREL16_HIGHA #undef R_PPC64_REL24_NOTOC +#undef R_PPC64_PCREL_OPT #undef R_PPC64_PCREL34 #undef R_PPC64_GOT_PCREL34 +#undef R_PPC64_TPREL34 +#undef R_PPC64_DTPREL34 +#undef R_PPC64_GOT_TLSGD_PCREL34 +#undef R_PPC64_GOT_TLSLD_PCREL34 +#undef R_PPC64_GOT_TPREL_PCREL34 #undef R_PPC64_IRELATIVE #undef R_PPC64_REL16 #undef R_PPC64_REL16_LO @@ -194,8 +200,14 @@ ELF_RELOC(R_PPC64_TPREL16_HIGHA, 113) ELF_RELOC(R_PPC64_DTPREL16_HIGH, 114) ELF_RELOC(R_PPC64_DTPREL16_HIGHA, 115) ELF_RELOC(R_PPC64_REL24_NOTOC, 116) +ELF_RELOC(R_PPC64_PCREL_OPT, 123) ELF_RELOC(R_PPC64_PCREL34, 132) ELF_RELOC(R_PPC64_GOT_PCREL34, 133) +ELF_RELOC(R_PPC64_TPREL34, 146) +ELF_RELOC(R_PPC64_DTPREL34, 147) +ELF_RELOC(R_PPC64_GOT_TLSGD_PCREL34, 148) +ELF_RELOC(R_PPC64_GOT_TLSLD_PCREL34, 149) +ELF_RELOC(R_PPC64_GOT_TPREL_PCREL34, 150) ELF_RELOC(R_PPC64_IRELATIVE, 248) ELF_RELOC(R_PPC64_REL16, 249) ELF_RELOC(R_PPC64_REL16_LO, 250) diff --git a/contrib/llvm-project/llvm/include/llvm/BinaryFormat/MachO.h b/contrib/llvm-project/llvm/include/llvm/BinaryFormat/MachO.h index e43fea0a2465..f5d5ec328b5e 100644 --- a/contrib/llvm-project/llvm/include/llvm/BinaryFormat/MachO.h +++ b/contrib/llvm-project/llvm/include/llvm/BinaryFormat/MachO.h @@ -83,6 +83,7 @@ enum { MH_NO_HEAP_EXECUTION = 0x01000000u, MH_APP_EXTENSION_SAFE = 0x02000000u, MH_NLIST_OUTOFSYNC_WITH_DYLDINFO = 0x04000000u, + MH_SIM_SUPPORT = 0x08000000u, MH_DYLIB_IN_CACHE = 0x80000000u, }; @@ -495,7 +496,8 @@ enum PlatformType { PLATFORM_MACCATALYST = 6, PLATFORM_IOSSIMULATOR = 7, PLATFORM_TVOSSIMULATOR = 8, - PLATFORM_WATCHOSSIMULATOR = 9 + PLATFORM_WATCHOSSIMULATOR = 9, + PLATFORM_DRIVERKIT = 10, }; // Values for tools enum in build_tool_version. @@ -1492,6 +1494,7 @@ enum CPUSubTypeARM { enum CPUSubTypeARM64 { CPU_SUBTYPE_ARM64_ALL = 0, + CPU_SUBTYPE_ARM64_V8 = 1, CPU_SUBTYPE_ARM64E = 2, }; diff --git a/contrib/llvm-project/llvm/include/llvm/BinaryFormat/Wasm.h b/contrib/llvm-project/llvm/include/llvm/BinaryFormat/Wasm.h index 1aca692e30a7..063c6a3f9449 100644 --- a/contrib/llvm-project/llvm/include/llvm/BinaryFormat/Wasm.h +++ b/contrib/llvm-project/llvm/include/llvm/BinaryFormat/Wasm.h @@ -41,7 +41,7 @@ struct WasmDylinkInfo { uint32_t MemoryAlignment; // P2 alignment of memory uint32_t TableSize; // Table size in elements uint32_t TableAlignment; // P2 alignment of table - std::vector Needed; // Shared library depenedencies + std::vector Needed; // Shared library dependencies }; struct WasmProducerInfo { @@ -67,11 +67,17 @@ struct WasmLimits { uint64_t Maximum; }; -struct WasmTable { +struct WasmTableType { uint8_t ElemType; WasmLimits Limits; }; +struct WasmTable { + uint32_t Index; + WasmTableType Type; + StringRef SymbolName; // from the "linking" section +}; + struct WasmInitExpr { uint8_t Opcode; union { @@ -114,7 +120,7 @@ struct WasmImport { union { uint32_t SigIndex; WasmGlobalType Global; - WasmTable Table; + WasmTableType Table; WasmLimits Memory; WasmEventType Event; }; @@ -140,8 +146,11 @@ struct WasmFunction { struct WasmDataSegment { uint32_t InitFlags; - uint32_t MemoryIndex; // present if InitFlags & WASM_SEGMENT_HAS_MEMINDEX - WasmInitExpr Offset; // present if InitFlags & WASM_SEGMENT_IS_PASSIVE == 0 + // Present if InitFlags & WASM_DATA_SEGMENT_HAS_MEMINDEX. + uint32_t MemoryIndex; + // Present if InitFlags & WASM_DATA_SEGMENT_IS_PASSIVE == 0. + WasmInitExpr Offset; + ArrayRef Content; StringRef Name; // from the "segment info" section uint32_t Alignment; @@ -186,15 +195,22 @@ struct WasmSymbolInfo { // For symbols to be exported from the final module Optional ExportName; union { - // For function or global symbols, the index in function or global index - // space. + // For function, table, or global symbols, the index in function, table, or + // global index space. uint32_t ElementIndex; // For a data symbols, the address of the data relative to segment. WasmDataReference DataRef; }; }; -struct WasmFunctionName { +enum class NameType { + FUNCTION, + GLOBAL, + DATA_SEGMENT, +}; + +struct WasmDebugName { + NameType Type; uint32_t Index; StringRef Name; }; @@ -231,7 +247,6 @@ enum : unsigned { WASM_TYPE_F64 = 0x7C, WASM_TYPE_V128 = 0x7B, WASM_TYPE_FUNCREF = 0x70, - WASM_TYPE_EXNREF = 0x68, WASM_TYPE_EXTERNREF = 0x6F, WASM_TYPE_FUNC = 0x60, WASM_TYPE_NORESULT = 0x40, // for blocks with no result values @@ -251,6 +266,7 @@ enum : unsigned { WASM_OPCODE_END = 0x0b, WASM_OPCODE_CALL = 0x10, WASM_OPCODE_LOCAL_GET = 0x20, + WASM_OPCODE_LOCAL_SET = 0x21, WASM_OPCODE_GLOBAL_GET = 0x23, WASM_OPCODE_GLOBAL_SET = 0x24, WASM_OPCODE_I32_STORE = 0x36, @@ -287,8 +303,8 @@ enum : unsigned { }; enum : unsigned { - WASM_SEGMENT_IS_PASSIVE = 0x01, - WASM_SEGMENT_HAS_MEMINDEX = 0x02, + WASM_DATA_SEGMENT_IS_PASSIVE = 0x01, + WASM_DATA_SEGMENT_HAS_MEMINDEX = 0x02, }; // Feature policy prefixes used in the custom "target_features" section @@ -300,8 +316,10 @@ enum : uint8_t { // Kind codes used in the custom "name" section enum : unsigned { - WASM_NAMES_FUNCTION = 0x1, - WASM_NAMES_LOCAL = 0x2, + WASM_NAMES_FUNCTION = 1, + WASM_NAMES_LOCAL = 2, + WASM_NAMES_GLOBAL = 7, + WASM_NAMES_DATA_SEGMENT = 9, }; // Kind codes used in the custom "linking" section @@ -316,6 +334,8 @@ enum : unsigned { enum : unsigned { WASM_COMDAT_DATA = 0x0, WASM_COMDAT_FUNCTION = 0x1, + // GLOBAL, EVENT, and TABLE are in here but LLVM doesn't use them yet. + WASM_COMDAT_SECTION = 0x5, }; // Kind codes used in the custom "linking" section in the WASM_SYMBOL_TABLE @@ -325,6 +345,7 @@ enum WasmSymbolType : unsigned { WASM_SYMBOL_TYPE_GLOBAL = 0x2, WASM_SYMBOL_TYPE_SECTION = 0x3, WASM_SYMBOL_TYPE_EVENT = 0x4, + WASM_SYMBOL_TYPE_TABLE = 0x5, }; // Kinds of event attributes. @@ -360,7 +381,7 @@ enum class ValType { F32 = WASM_TYPE_F32, F64 = WASM_TYPE_F64, V128 = WASM_TYPE_V128, - EXNREF = WASM_TYPE_EXNREF, + FUNCREF = WASM_TYPE_FUNCREF, EXTERNREF = WASM_TYPE_EXTERNREF, }; diff --git a/contrib/llvm-project/llvm/include/llvm/BinaryFormat/WasmRelocs.def b/contrib/llvm-project/llvm/include/llvm/BinaryFormat/WasmRelocs.def index 05c5147e6314..dca63eca9455 100644 --- a/contrib/llvm-project/llvm/include/llvm/BinaryFormat/WasmRelocs.def +++ b/contrib/llvm-project/llvm/include/llvm/BinaryFormat/WasmRelocs.def @@ -20,3 +20,8 @@ WASM_RELOC(R_WASM_MEMORY_ADDR_LEB64, 14) WASM_RELOC(R_WASM_MEMORY_ADDR_SLEB64, 15) WASM_RELOC(R_WASM_MEMORY_ADDR_I64, 16) WASM_RELOC(R_WASM_MEMORY_ADDR_REL_SLEB64, 17) +WASM_RELOC(R_WASM_TABLE_INDEX_SLEB64, 18) +WASM_RELOC(R_WASM_TABLE_INDEX_I64, 19) +WASM_RELOC(R_WASM_TABLE_NUMBER_LEB, 20) +WASM_RELOC(R_WASM_MEMORY_ADDR_TLS_SLEB, 21) +WASM_RELOC(R_WASM_FUNCTION_OFFSET_I64, 22) diff --git a/contrib/llvm-project/llvm/include/llvm/BinaryFormat/WasmTraits.h b/contrib/llvm-project/llvm/include/llvm/BinaryFormat/WasmTraits.h new file mode 100644 index 000000000000..e34182499187 --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/BinaryFormat/WasmTraits.h @@ -0,0 +1,68 @@ +//===- WasmTraits.h - DenseMap traits for the Wasm structures ---*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file provides llvm::DenseMapInfo traits for the Wasm structures. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BINARYFORMAT_WASMTRAITS_H +#define LLVM_BINARYFORMAT_WASMTRAITS_H + +#include "llvm/ADT/Hashing.h" +#include "llvm/BinaryFormat/Wasm.h" + +namespace llvm { + +template struct DenseMapInfo; + +// Traits for using WasmSignature in a DenseMap. +template <> struct DenseMapInfo { + static wasm::WasmSignature getEmptyKey() { + wasm::WasmSignature Sig; + Sig.State = wasm::WasmSignature::Empty; + return Sig; + } + static wasm::WasmSignature getTombstoneKey() { + wasm::WasmSignature Sig; + Sig.State = wasm::WasmSignature::Tombstone; + return Sig; + } + static unsigned getHashValue(const wasm::WasmSignature &Sig) { + uintptr_t H = hash_value(Sig.State); + for (auto Ret : Sig.Returns) + H = hash_combine(H, Ret); + for (auto Param : Sig.Params) + H = hash_combine(H, Param); + return H; + } + static bool isEqual(const wasm::WasmSignature &LHS, + const wasm::WasmSignature &RHS) { + return LHS == RHS; + } +}; + +// Traits for using WasmGlobalType in a DenseMap +template <> struct DenseMapInfo { + static wasm::WasmGlobalType getEmptyKey() { + return wasm::WasmGlobalType{1, true}; + } + static wasm::WasmGlobalType getTombstoneKey() { + return wasm::WasmGlobalType{2, true}; + } + static unsigned getHashValue(const wasm::WasmGlobalType &GlobalType) { + return hash_combine(GlobalType.Type, GlobalType.Mutable); + } + static bool isEqual(const wasm::WasmGlobalType &LHS, + const wasm::WasmGlobalType &RHS) { + return LHS == RHS; + } +}; + +} // end namespace llvm + +#endif // LLVM_BINARYFORMAT_WASMTRAITS_H diff --git a/contrib/llvm-project/llvm/include/llvm/BinaryFormat/XCOFF.h b/contrib/llvm-project/llvm/include/llvm/BinaryFormat/XCOFF.h index 5a7ce80a2f62..48e1baf72689 100644 --- a/contrib/llvm-project/llvm/include/llvm/BinaryFormat/XCOFF.h +++ b/contrib/llvm-project/llvm/include/llvm/BinaryFormat/XCOFF.h @@ -18,6 +18,7 @@ namespace llvm { class StringRef; +template class SmallString; namespace XCOFF { @@ -28,6 +29,7 @@ constexpr size_t NameSize = 8; constexpr size_t SymbolTableEntrySize = 18; constexpr size_t RelocationSerializationSize32 = 10; constexpr uint16_t RelocOverflow = 65535; +constexpr uint8_t AllocRegNo = 31; enum ReservedSectionNum : int16_t { N_DEBUG = -2, N_ABS = -1, N_UNDEF = 0 }; @@ -294,6 +296,115 @@ enum CFileCpuId : uint8_t { StringRef getMappingClassString(XCOFF::StorageMappingClass SMC); StringRef getRelocationTypeString(XCOFF::RelocationType Type); +SmallString<32> parseParmsType(uint32_t Value, unsigned ParmsNum); + +struct TracebackTable { + enum LanguageID : uint8_t { + C, + Fortran, + Pascal, + Ada, + PL1, + Basic, + Lisp, + Cobol, + Modula2, + CPlusPlus, + Rpg, + PL8, + PLIX = PL8, + Assembly, + Java, + ObjectiveC + }; + // Byte 1 + static constexpr uint32_t VersionMask = 0xFF00'0000; + static constexpr uint8_t VersionShift = 24; + + // Byte 2 + static constexpr uint32_t LanguageIdMask = 0x00FF'0000; + static constexpr uint8_t LanguageIdShift = 16; + + // Byte 3 + static constexpr uint32_t IsGlobaLinkageMask = 0x0000'8000; + static constexpr uint32_t IsOutOfLineEpilogOrPrologueMask = 0x0000'4000; + static constexpr uint32_t HasTraceBackTableOffsetMask = 0x0000'2000; + static constexpr uint32_t IsInternalProcedureMask = 0x0000'1000; + static constexpr uint32_t HasControlledStorageMask = 0x0000'0800; + static constexpr uint32_t IsTOClessMask = 0x0000'0400; + static constexpr uint32_t IsFloatingPointPresentMask = 0x0000'0200; + static constexpr uint32_t IsFloatingPointOperationLogOrAbortEnabledMask = + 0x0000'0100; + + // Byte 4 + static constexpr uint32_t IsInterruptHandlerMask = 0x0000'0080; + static constexpr uint32_t IsFunctionNamePresentMask = 0x0000'0040; + static constexpr uint32_t IsAllocaUsedMask = 0x0000'0020; + static constexpr uint32_t OnConditionDirectiveMask = 0x0000'001C; + static constexpr uint32_t IsCRSavedMask = 0x0000'0002; + static constexpr uint32_t IsLRSavedMask = 0x0000'0001; + static constexpr uint8_t OnConditionDirectiveShift = 2; + + // Byte 5 + static constexpr uint32_t IsBackChainStoredMask = 0x8000'0000; + static constexpr uint32_t IsFixupMask = 0x4000'0000; + static constexpr uint32_t FPRSavedMask = 0x3F00'0000; + static constexpr uint32_t FPRSavedShift = 24; + + // Byte 6 + static constexpr uint32_t HasVectorInfoMask = 0x0080'0000; + static constexpr uint32_t HasExtensionTableMask = 0x0040'0000; + static constexpr uint32_t GPRSavedMask = 0x003F'0000; + static constexpr uint32_t GPRSavedShift = 16; + + // Byte 7 + static constexpr uint32_t NumberOfFixedParmsMask = 0x0000'FF00; + static constexpr uint8_t NumberOfFixedParmsShift = 8; + + // Byte 8 + static constexpr uint32_t NumberOfFloatingPointParmsMask = 0x0000'00FE; + static constexpr uint32_t HasParmsOnStackMask = 0x0000'0001; + static constexpr uint8_t NumberOfFloatingPointParmsShift = 1; + + // Masks to select leftmost bits for decoding parameter type information. + // Bit to use when vector info is not presented. + static constexpr uint32_t ParmTypeIsFloatingBit = 0x8000'0000; + static constexpr uint32_t ParmTypeFloatingIsDoubleBit = 0x4000'0000; + // Bits to use when vector info is presented. + static constexpr uint32_t ParmTypeIsFixedBits = 0x0000'0000; + static constexpr uint32_t ParmTypeIsVectorBits = 0x4000'0000; + static constexpr uint32_t ParmTypeIsFloatingBits = 0x8000'0000; + static constexpr uint32_t ParmTypeIsDoubleBits = 0xC000'0000; + static constexpr uint32_t ParmTypeMask = 0xC000'0000; + + // Vector extension + static constexpr uint16_t NumberOfVRSavedMask = 0xFC00; + static constexpr uint16_t IsVRSavedOnStackMask = 0x0200; + static constexpr uint16_t HasVarArgsMask = 0x0100; + static constexpr uint8_t NumberOfVRSavedShift = 10; + + static constexpr uint16_t NumberOfVectorParmsMask = 0x00FE; + static constexpr uint16_t HasVMXInstructionMask = 0x0001; + static constexpr uint8_t NumberOfVectorParmsShift = 1; + + static constexpr uint32_t ParmTypeIsVectorCharBit = 0x0000'0000; + static constexpr uint32_t ParmTypeIsVectorShortBit = 0x4000'0000; + static constexpr uint32_t ParmTypeIsVectorIntBit = 0x8000'0000; + static constexpr uint32_t ParmTypeIsVectorFloatBit = 0xC000'0000; +}; + +// Extended Traceback table flags. +enum ExtendedTBTableFlag : uint8_t { + TB_OS1 = 0x80, ///< Reserved for OS use. + TB_RESERVED = 0x40, ///< Reserved for compiler. + TB_SSP_CANARY = 0x20, ///< stack smasher canary present on stack. + TB_OS2 = 0x10, ///< Reserved for OS use. + TB_EH_INFO = 0x08, ///< Exception handling info present. + TB_LONGTBTABLE2 = 0x01 ///< Additional tbtable extension exists. +}; + +StringRef getNameForTracebackTableLanguageId(TracebackTable::LanguageID LangId); +SmallString<32> getExtendedTBTableFlagString(uint8_t Flag); } // end namespace XCOFF } // end namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/Bitcode/BitcodeCommon.h b/contrib/llvm-project/llvm/include/llvm/Bitcode/BitcodeCommon.h new file mode 100644 index 000000000000..6a3e74550bc4 --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/Bitcode/BitcodeCommon.h @@ -0,0 +1,30 @@ +//===- BitcodeCommon.h - Common code for encode/decode --------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This header defines common code to be used by BitcodeWriter and +// BitcodeReader. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BITCODE_BITCODECOMMON_H +#define LLVM_BITCODE_BITCODECOMMON_H + +#include "llvm/ADT/Bitfields.h" + +namespace llvm { + +struct AllocaPackedValues { + using Align = Bitfield::Element; + using UsedWithInAlloca = Bitfield::Element; + using ExplicitType = Bitfield::Element; + using SwiftError = Bitfield::Element; +}; + +} // namespace llvm + +#endif // LLVM_BITCODE_BITCODECOMMON_H diff --git a/contrib/llvm-project/llvm/include/llvm/Bitcode/BitcodeConvenience.h b/contrib/llvm-project/llvm/include/llvm/Bitcode/BitcodeConvenience.h new file mode 100644 index 000000000000..0060d014ba82 --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/Bitcode/BitcodeConvenience.h @@ -0,0 +1,486 @@ +//===- llvm/Bitcode/BitcodeConvenience.h - Convenience Wrappers -*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +/// +/// \file Convenience wrappers for the LLVM bitcode format and bitstream APIs. +/// +/// This allows you to use a sort of DSL to declare and use bitcode +/// abbreviations and records. Example: +/// +/// \code +/// using Metadata = BCRecordLayout< +/// METADATA_ID, // ID +/// BCFixed<16>, // Module format major version +/// BCFixed<16>, // Module format minor version +/// BCBlob // misc. version information +/// >; +/// Metadata metadata(Out); +/// metadata.emit(ScratchRecord, VERSION_MAJOR, VERSION_MINOR, Data); +/// \endcode +/// +/// For details on the bitcode format, see +/// http://llvm.org/docs/BitCodeFormat.html +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BITCODE_BITCODECONVENIENCE_H +#define LLVM_BITCODE_BITCODECONVENIENCE_H + +#include "llvm/Bitstream/BitCodes.h" +#include "llvm/Bitstream/BitstreamWriter.h" +#include + +namespace llvm { +namespace detail { +/// Convenience base for all kinds of bitcode abbreviation fields. +/// +/// This just defines common properties queried by the metaprogramming. +template class BCField { +public: + static const bool IsCompound = Compound; + + /// Asserts that the given data is a valid value for this field. + template static void assertValid(const T &data) {} + + /// Converts a raw numeric representation of this value to its preferred + /// type. + template static T convert(T rawValue) { return rawValue; } +}; +} // namespace detail + +/// Represents a literal operand in a bitcode record. +/// +/// The value of a literal operand is the same for all instances of the record, +/// so it is only emitted in the abbreviation definition. +/// +/// Note that because this uses a compile-time template, you cannot have a +/// literal operand that is fixed at run-time without dropping down to the +/// raw LLVM APIs. +template class BCLiteral : public detail::BCField<> { +public: + static void emitOp(llvm::BitCodeAbbrev &abbrev) { + abbrev.Add(llvm::BitCodeAbbrevOp(Value)); + } + + template static void assertValid(const T &data) { + assert(data == Value && "data value does not match declared literal value"); + } +}; + +/// Represents a fixed-width value in a bitcode record. +/// +/// Note that the LLVM bitcode format only supports unsigned values. +template class BCFixed : public detail::BCField<> { +public: + static_assert(Width <= 64, "fixed-width field is too large"); + + static void emitOp(llvm::BitCodeAbbrev &abbrev) { + abbrev.Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed, Width)); + } + + static void assertValid(const bool &data) { + assert(llvm::isUInt(data) && + "data value does not fit in the given bit width"); + } + + template static void assertValid(const T &data) { + assert(data >= 0 && "cannot encode signed integers"); + assert(llvm::isUInt(data) && + "data value does not fit in the given bit width"); + } +}; + +/// Represents a variable-width value in a bitcode record. +/// +/// The \p Width parameter should include the continuation bit. +/// +/// Note that the LLVM bitcode format only supports unsigned values. +template class BCVBR : public detail::BCField<> { + static_assert(Width >= 2, "width does not have room for continuation bit"); + +public: + static void emitOp(llvm::BitCodeAbbrev &abbrev) { + abbrev.Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, Width)); + } + + template static void assertValid(const T &data) { + assert(data >= 0 && "cannot encode signed integers"); + } +}; + +/// Represents a character encoded in LLVM's Char6 encoding. +/// +/// This format is suitable for encoding decimal numbers (without signs or +/// exponents) and C identifiers (without dollar signs), but not much else. +/// +/// \sa http://llvm.org/docs/BitCodeFormat.html#char6-encoded-value +class BCChar6 : public detail::BCField<> { +public: + static void emitOp(llvm::BitCodeAbbrev &abbrev) { + abbrev.Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Char6)); + } + + template static void assertValid(const T &data) { + assert(llvm::BitCodeAbbrevOp::isChar6(data) && "invalid Char6 data"); + } + + template char convert(T rawValue) { + return static_cast(rawValue); + } +}; + +/// Represents an untyped blob of bytes. +/// +/// If present, this must be the last field in a record. +class BCBlob : public detail::BCField { +public: + static void emitOp(llvm::BitCodeAbbrev &abbrev) { + abbrev.Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); + } +}; + +/// Represents an array of some other type. +/// +/// If present, this must be the last field in a record. +template class BCArray : public detail::BCField { + static_assert(!ElementTy::IsCompound, "arrays can only contain scalar types"); + +public: + static void emitOp(llvm::BitCodeAbbrev &abbrev) { + abbrev.Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Array)); + ElementTy::emitOp(abbrev); + } +}; + +namespace detail { +/// Attaches the last field to an abbreviation. +/// +/// This is the base case for \c emitOps. +/// +/// \sa BCRecordLayout::emitAbbrev +template static void emitOps(llvm::BitCodeAbbrev &abbrev) { + FieldTy::emitOp(abbrev); +} + +/// Attaches fields to an abbreviation. +/// +/// This is the recursive case for \c emitOps. +/// +/// \sa BCRecordLayout::emitAbbrev +template +static void emitOps(llvm::BitCodeAbbrev &abbrev) { + static_assert(!FieldTy::IsCompound, + "arrays and blobs may not appear in the middle of a record"); + FieldTy::emitOp(abbrev); + emitOps(abbrev); +} + +/// Helper class for dealing with a scalar element in the middle of a record. +/// +/// \sa BCRecordLayout +template class BCRecordCoding { +public: + template + static void emit(llvm::BitstreamWriter &Stream, BufferTy &buffer, + unsigned code, ElementDataTy element, DataTy &&...data) { + static_assert(!ElementTy::IsCompound, + "arrays and blobs may not appear in the middle of a record"); + ElementTy::assertValid(element); + buffer.push_back(element); + BCRecordCoding::emit(Stream, buffer, code, + std::forward(data)...); + } + + template + static void read(ArrayRef buffer, ElementDataTy &element, + DataTy &&...data) { + assert(!buffer.empty() && "too few elements in buffer"); + element = ElementTy::convert(buffer.front()); + BCRecordCoding::read(buffer.slice(1), + std::forward(data)...); + } + + template + static void read(ArrayRef buffer, NoneType, DataTy &&...data) { + assert(!buffer.empty() && "too few elements in buffer"); + BCRecordCoding::read(buffer.slice(1), + std::forward(data)...); + } +}; + +/// Helper class for dealing with a scalar element at the end of a record. +/// +/// This has a separate implementation because up until now we've only been +/// \em building the record (into a data buffer), and now we need to hand it +/// off to the BitstreamWriter to be emitted. +/// +/// \sa BCRecordLayout +template class BCRecordCoding { +public: + template + static void emit(llvm::BitstreamWriter &Stream, BufferTy &buffer, + unsigned code, const DataTy &data) { + static_assert(!ElementTy::IsCompound, + "arrays and blobs need special handling"); + ElementTy::assertValid(data); + buffer.push_back(data); + Stream.EmitRecordWithAbbrev(code, buffer); + } + + template + static void read(ArrayRef buffer, DataTy &data) { + assert(buffer.size() == 1 && "record data does not match layout"); + data = ElementTy::convert(buffer.front()); + } + + template static void read(ArrayRef buffer, NoneType) { + assert(buffer.size() == 1 && "record data does not match layout"); + (void)buffer; + } + + template static void read(ArrayRef buffer) = delete; +}; + +/// Helper class for dealing with an array at the end of a record. +/// +/// \sa BCRecordLayout::emitRecord +template class BCRecordCoding> { +public: + template + static void emit(llvm::BitstreamWriter &Stream, BufferTy &buffer, + unsigned code, StringRef data) { + // TODO: validate array data. + Stream.EmitRecordWithArray(code, buffer, data); + } + + template + static void emit(llvm::BitstreamWriter &Stream, BufferTy &buffer, + unsigned code, const ArrayTy &array) { +#ifndef NDEBUG + for (auto &element : array) + ElementTy::assertValid(element); +#endif + buffer.reserve(buffer.size() + std::distance(array.begin(), array.end())); + std::copy(array.begin(), array.end(), std::back_inserter(buffer)); + Stream.EmitRecordWithAbbrev(code, buffer); + } + + template + static void emit(llvm::BitstreamWriter &Stream, BufferTy &buffer, + unsigned code, ElementDataTy element, DataTy... data) { + std::array array{{element, data...}}; + emit(Stream, buffer, code, array); + } + + template + static void emit(llvm::BitstreamWriter &Stream, BufferTy &Buffer, + unsigned code, NoneType) { + Stream.EmitRecordWithAbbrev(code, Buffer); + } + + template + static void read(ArrayRef Buffer, ArrayRef &rawData) { + rawData = Buffer; + } + + template + static void read(ArrayRef buffer, ArrayTy &array) { + array.append(llvm::map_iterator(buffer.begin(), T::convert), + llvm::map_iterator(buffer.end(), T::convert)); + } + + template static void read(ArrayRef buffer, NoneType) { + (void)buffer; + } + + template static void read(ArrayRef buffer) = delete; +}; + +/// Helper class for dealing with a blob at the end of a record. +/// +/// \sa BCRecordLayout +template <> class BCRecordCoding { +public: + template + static void emit(llvm::BitstreamWriter &Stream, BufferTy &buffer, + unsigned code, StringRef data) { + Stream.EmitRecordWithBlob(code, buffer, data); + } + + template static void read(ArrayRef buffer) { (void)buffer; } + + /// Blob data is not stored in the buffer if you are using the correct + /// accessor; this method should not be used. + template + static void read(ArrayRef buffer, DataTy &data) = delete; +}; + +/// A type trait whose \c type field is the last of its template parameters. +template struct last_type { + using type = typename last_type::type; +}; + +template struct last_type { using type = Head; }; + +/// A type trait whose \c value field is \c true if the last type is BCBlob. +template +using has_blob = std::is_same::type>; + +/// A type trait whose \c value field is \c true if the given type is a +/// BCArray (of any element kind). +template struct is_array { +private: + template static bool check(BCArray *); + static int check(...); + +public: + typedef bool value_type; + static constexpr bool value = !std::is_same::value; +}; + +/// A type trait whose \c value field is \c true if the last type is a +/// BCArray (of any element kind). +template +using has_array = is_array::type>; +} // namespace detail + +/// Represents a single bitcode record type. +/// +/// This class template is meant to be instantiated and then given a name, +/// so that from then on that name can be used. +template class BCGenericRecordLayout { + llvm::BitstreamWriter &Stream; + +public: + /// The abbreviation code used for this record in the current block. + /// + /// Note that this is not the same as the semantic record code, which is the + /// first field of the record. + const unsigned AbbrevCode; + + /// Create a layout and register it with the given bitstream writer. + explicit BCGenericRecordLayout(llvm::BitstreamWriter &Stream) + : Stream(Stream), AbbrevCode(emitAbbrev(Stream)) {} + + /// Emit a record to the bitstream writer, using the given buffer for scratch + /// space. + /// + /// Note that even fixed arguments must be specified here. + template + void emit(BufferTy &buffer, unsigned id, Data &&...data) const { + emitRecord(Stream, buffer, AbbrevCode, id, std::forward(data)...); + } + + /// Registers this record's layout with the bitstream reader. + /// + /// eturns The abbreviation code for the newly-registered record type. + static unsigned emitAbbrev(llvm::BitstreamWriter &Stream) { + auto Abbrev = std::make_shared(); + detail::emitOps(*Abbrev); + return Stream.EmitAbbrev(std::move(Abbrev)); + } + + /// Emit a record identified by \p abbrCode to bitstream reader \p Stream, + /// using \p buffer for scratch space. + /// + /// Note that even fixed arguments must be specified here. Blobs are passed + /// as StringRefs, while arrays can be passed inline, as aggregates, or as + /// pre-encoded StringRef data. Skipped values and empty arrays should use + /// the special Nothing value. + template + static void emitRecord(llvm::BitstreamWriter &Stream, BufferTy &buffer, + unsigned abbrCode, unsigned recordID, Data &&...data) { + static_assert(sizeof...(data) <= sizeof...(Fields) || + detail::has_array::value, + "Too many record elements"); + static_assert(sizeof...(data) >= sizeof...(Fields), + "Too few record elements"); + buffer.clear(); + detail::BCRecordCoding::emit( + Stream, buffer, abbrCode, recordID, std::forward(data)...); + } + + /// Extract record data from \p buffer into the given data fields. + /// + /// Note that even fixed arguments must be specified here. Pass \c Nothing + /// if you don't care about a particular parameter. Blob data is not included + /// in the buffer and should be handled separately by the caller. + template + static void readRecord(ArrayRef buffer, Data &&...data) { + static_assert(sizeof...(data) <= sizeof...(Fields), + "Too many record elements"); + static_assert(sizeof...(Fields) <= + sizeof...(data) + detail::has_blob::value, + "Too few record elements"); + return detail::BCRecordCoding::read(buffer, + std::forward(data)...); + } + + /// Extract record data from \p buffer into the given data fields. + /// + /// Note that even fixed arguments must be specified here. Pass \c Nothing + /// if you don't care about a particular parameter. Blob data is not included + /// in the buffer and should be handled separately by the caller. + template + static void readRecord(BufferTy &buffer, Data &&...data) { + return readRecord(llvm::makeArrayRef(buffer), std::forward(data)...); + } +}; + +/// A record with a fixed record code. +template +class BCRecordLayout + : public BCGenericRecordLayout, Fields...> { + using Base = BCGenericRecordLayout, Fields...>; + +public: + enum : unsigned { + /// The record code associated with this layout. + Code = RecordCode + }; + + /// Create a layout and register it with the given bitstream writer. + explicit BCRecordLayout(llvm::BitstreamWriter &Stream) : Base(Stream) {} + + /// Emit a record to the bitstream writer, using the given buffer for scratch + /// space. + /// + /// Note that even fixed arguments must be specified here. + template + void emit(BufferTy &buffer, Data &&...data) const { + Base::emit(buffer, RecordCode, std::forward(data)...); + } + + /// Emit a record identified by \p abbrCode to bitstream reader \p Stream, + /// using \p buffer for scratch space. + /// + /// Note that even fixed arguments must be specified here. Currently, arrays + /// and blobs can only be passed as StringRefs. + template + static void emitRecord(llvm::BitstreamWriter &Stream, BufferTy &buffer, + unsigned abbrCode, Data &&...data) { + Base::emitRecord(Stream, buffer, abbrCode, RecordCode, + std::forward(data)...); + } +}; + +/// RAII object to pair entering and exiting a sub-block. +class BCBlockRAII { + llvm::BitstreamWriter &Stream; + +public: + BCBlockRAII(llvm::BitstreamWriter &Stream, unsigned block, unsigned abbrev) + : Stream(Stream) { + Stream.EnterSubblock(block, abbrev); + } + + ~BCBlockRAII() { Stream.ExitBlock(); } +}; +} // namespace llvm + +#endif diff --git a/contrib/llvm-project/llvm/include/llvm/Bitcode/BitcodeWriter.h b/contrib/llvm-project/llvm/include/llvm/Bitcode/BitcodeWriter.h index 4beb89d30e00..7ad2d37a2a35 100644 --- a/contrib/llvm-project/llvm/include/llvm/Bitcode/BitcodeWriter.h +++ b/contrib/llvm-project/llvm/include/llvm/Bitcode/BitcodeWriter.h @@ -47,7 +47,7 @@ class raw_ostream; public: /// Create a BitcodeWriter that writes to Buffer. - BitcodeWriter(SmallVectorImpl &Buffer); + BitcodeWriter(SmallVectorImpl &Buffer, raw_fd_stream *FS = nullptr); ~BitcodeWriter(); @@ -152,10 +152,18 @@ class raw_ostream; const std::map *ModuleToSummariesForIndex = nullptr); - /// Save a copy of the llvm IR as data in the __LLVM,__bitcode section. + /// If EmbedBitcode is set, save a copy of the llvm IR as data in the + /// __LLVM,__bitcode section (.llvmbc on non-MacOS). + /// If available, pass the serialized module via the Buf parameter. If not, + /// pass an empty (default-initialized) MemoryBufferRef, and the serialization + /// will be handled by this API. The same behavior happens if the provided Buf + /// is not bitcode (i.e. if it's invalid data or even textual LLVM assembly). + /// If EmbedCmdline is set, the command line is also exported in + /// the corresponding section (__LLVM,_cmdline / .llvmcmd) - even if CmdArgs + /// were empty. void EmbedBitcodeInModule(Module &M, MemoryBufferRef Buf, bool EmbedBitcode, - bool EmbedMarker, - const std::vector *CmdArgs); + bool EmbedCmdline, + const std::vector &CmdArgs); } // end namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/contrib/llvm-project/llvm/include/llvm/Bitcode/LLVMBitCodes.h index de4fe6630324..5b4854d6c95e 100644 --- a/contrib/llvm-project/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/contrib/llvm-project/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -168,7 +168,8 @@ enum TypeCodes { TYPE_CODE_TOKEN = 22, // TOKEN - TYPE_CODE_BFLOAT = 23 // BRAIN FLOATING POINT + TYPE_CODE_BFLOAT = 23, // BRAIN FLOATING POINT + TYPE_CODE_X86_AMX = 24 // X86 AMX }; enum OperandBundleTagCode { @@ -338,7 +339,11 @@ enum MetadataCodes { METADATA_INDEX_OFFSET = 38, // [offset] METADATA_INDEX = 39, // [bitpos] METADATA_LABEL = 40, // [distinct, scope, name, file, line] - METADATA_COMMON_BLOCK = 44, // [distinct, scope, name, variable,...] + METADATA_STRING_TYPE = 41, // [distinct, name, size, align,...] + // Codes 42 and 43 are reserved for support for Fortran array specific debug + // info. + METADATA_COMMON_BLOCK = 44, // [distinct, scope, name, variable,...] + METADATA_GENERIC_SUBRANGE = 45 // [distinct, count, lo, up, stride] }; // The constants block (CONSTANTS_BLOCK_ID) describes emission for each @@ -371,6 +376,7 @@ enum ConstantsCodes { // asmdialect,asmstr,conststr] CST_CODE_CE_GEP_WITH_INRANGE_INDEX = 24, // [opty, flags, n x operands] CST_CODE_CE_UNOP = 25, // CE_UNOP: [opcode, opval] + CST_CODE_POISON = 26, // POISON }; /// CastOpcodes - These are values used in the bitcode files to encode which @@ -536,8 +542,9 @@ enum FunctionCodes { FUNC_CODE_DEBUG_LOC = 35, // DEBUG_LOC: [Line,Col,ScopeVal, IAVal] FUNC_CODE_INST_FENCE = 36, // FENCE: [ordering, synchscope] - FUNC_CODE_INST_CMPXCHG_OLD = 37, // CMPXCHG: [ptrty,ptr,cmp,new, align, vol, - // ordering, synchscope] + FUNC_CODE_INST_CMPXCHG_OLD = 37, // CMPXCHG: [ptrty, ptr, cmp, val, vol, + // ordering, synchscope, + // failure_ordering?, weak?] FUNC_CODE_INST_ATOMICRMW = 38, // ATOMICRMW: [ptrty,ptr,val, operation, // align, vol, // ordering, synchscope] @@ -551,8 +558,9 @@ enum FunctionCodes { FUNC_CODE_INST_GEP = 43, // GEP: [inbounds, n x operands] FUNC_CODE_INST_STORE = 44, // STORE: [ptrty,ptr,valty,val, align, vol] FUNC_CODE_INST_STOREATOMIC = 45, // STORE: [ptrty,ptr,val, align, vol - FUNC_CODE_INST_CMPXCHG = 46, // CMPXCHG: [ptrty,ptr,valty,cmp,new, align, - // vol,ordering,synchscope] + FUNC_CODE_INST_CMPXCHG = 46, // CMPXCHG: [ptrty, ptr, cmp, val, vol, + // success_ordering, synchscope, + // failure_ordering, weak] FUNC_CODE_INST_LANDINGPAD = 47, // LANDINGPAD: [ty,val,num,id0,val0...] FUNC_CODE_INST_CLEANUPRET = 48, // CLEANUPRET: [val] or [val,bb#] FUNC_CODE_INST_CATCHRET = 49, // CATCHRET: [val,bb#] @@ -644,6 +652,11 @@ enum AttributeKindCodes { ATTR_KIND_NO_MERGE = 66, ATTR_KIND_NULL_POINTER_IS_VALID = 67, ATTR_KIND_NOUNDEF = 68, + ATTR_KIND_BYREF = 69, + ATTR_KIND_MUSTPROGRESS = 70, + ATTR_KIND_NO_CALLBACK = 71, + ATTR_KIND_HOT = 72, + ATTR_KIND_NO_PROFILE = 73, }; enum ComdatSelectionKindCodes { diff --git a/contrib/llvm-project/llvm/include/llvm/Bitstream/BitCodes.h b/contrib/llvm-project/llvm/include/llvm/Bitstream/BitCodes.h index 41a3de3b20ef..9cd4e535a470 100644 --- a/contrib/llvm-project/llvm/include/llvm/Bitstream/BitCodes.h +++ b/contrib/llvm-project/llvm/include/llvm/Bitstream/BitCodes.h @@ -18,6 +18,7 @@ #define LLVM_BITSTREAM_BITCODES_H #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" #include @@ -137,13 +138,7 @@ public: } /// isChar6 - Return true if this character is legal in the Char6 encoding. - static bool isChar6(char C) { - if (C >= 'a' && C <= 'z') return true; - if (C >= 'A' && C <= 'Z') return true; - if (C >= '0' && C <= '9') return true; - if (C == '.' || C == '_') return true; - return false; - } + static bool isChar6(char C) { return isAlnum(C) || C == '.' || C == '_'; } static unsigned EncodeChar6(char C) { if (C >= 'a' && C <= 'z') return C-'a'; if (C >= 'A' && C <= 'Z') return C-'A'+26; diff --git a/contrib/llvm-project/llvm/include/llvm/Bitstream/BitstreamWriter.h b/contrib/llvm-project/llvm/include/llvm/Bitstream/BitstreamWriter.h index c0ead19dc71d..3954df4897ae 100644 --- a/contrib/llvm-project/llvm/include/llvm/Bitstream/BitstreamWriter.h +++ b/contrib/llvm-project/llvm/include/llvm/Bitstream/BitstreamWriter.h @@ -20,17 +20,28 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Bitstream/BitCodes.h" #include "llvm/Support/Endian.h" +#include "llvm/Support/raw_ostream.h" +#include #include namespace llvm { class BitstreamWriter { + /// Out - The buffer that keeps unflushed bytes. SmallVectorImpl &Out; + /// FS - The file stream that Out flushes to. If FS is nullptr, it does not + /// support read or seek, Out cannot be flushed until all data are written. + raw_fd_stream *FS; + + /// FlushThreshold - If FS is valid, this is the threshold (unit B) to flush + /// FS. + const uint64_t FlushThreshold; + /// CurBit - Always between 0 and 31 inclusive, specifies the next bit to use. unsigned CurBit; - /// CurValue - The current value. Only bits < CurBit are valid. + /// CurValue - The current value. Only bits < CurBit are valid. uint32_t CurValue; /// CurCodeSize - This is the declared size of code values used for the @@ -64,15 +75,19 @@ class BitstreamWriter { void WriteByte(unsigned char Value) { Out.push_back(Value); + FlushToFile(); } void WriteWord(unsigned Value) { Value = support::endian::byte_swap(Value); Out.append(reinterpret_cast(&Value), reinterpret_cast(&Value + 1)); + FlushToFile(); } - size_t GetBufferOffset() const { return Out.size(); } + uint64_t GetNumOfFlushedBytes() const { return FS ? FS->tell() : 0; } + + size_t GetBufferOffset() const { return Out.size() + GetNumOfFlushedBytes(); } size_t GetWordIndex() const { size_t Offset = GetBufferOffset(); @@ -80,9 +95,29 @@ class BitstreamWriter { return Offset / 4; } + /// If the related file stream supports reading, seeking and writing, flush + /// the buffer if its size is above a threshold. + void FlushToFile() { + if (!FS) + return; + if (Out.size() < FlushThreshold) + return; + FS->write((char *)&Out.front(), Out.size()); + Out.clear(); + } + public: - explicit BitstreamWriter(SmallVectorImpl &O) - : Out(O), CurBit(0), CurValue(0), CurCodeSize(2) {} + /// Create a BitstreamWriter that writes to Buffer \p O. + /// + /// \p FS is the file stream that \p O flushes to incrementally. If \p FS is + /// null, \p O does not flush incrementially, but writes to disk at the end. + /// + /// \p FlushThreshold is the threshold (unit M) to flush \p O if \p FS is + /// valid. + BitstreamWriter(SmallVectorImpl &O, raw_fd_stream *FS = nullptr, + uint32_t FlushThreshold = 512) + : Out(O), FS(FS), FlushThreshold(FlushThreshold << 20), CurBit(0), + CurValue(0), CurCodeSize(2) {} ~BitstreamWriter() { assert(CurBit == 0 && "Unflushed data remaining"); @@ -103,12 +138,60 @@ public: /// with the specified value. void BackpatchWord(uint64_t BitNo, unsigned NewWord) { using namespace llvm::support; - unsigned ByteNo = BitNo / 8; - assert((!endian::readAtBitAlignment( - &Out[ByteNo], BitNo & 7)) && - "Expected to be patching over 0-value placeholders"); - endian::writeAtBitAlignment( - &Out[ByteNo], NewWord, BitNo & 7); + uint64_t ByteNo = BitNo / 8; + uint64_t StartBit = BitNo & 7; + uint64_t NumOfFlushedBytes = GetNumOfFlushedBytes(); + + if (ByteNo >= NumOfFlushedBytes) { + assert((!endian::readAtBitAlignment( + &Out[ByteNo - NumOfFlushedBytes], StartBit)) && + "Expected to be patching over 0-value placeholders"); + endian::writeAtBitAlignment( + &Out[ByteNo - NumOfFlushedBytes], NewWord, StartBit); + return; + } + + // If the byte offset to backpatch is flushed, use seek to backfill data. + // First, save the file position to restore later. + uint64_t CurPos = FS->tell(); + + // Copy data to update into Bytes from the file FS and the buffer Out. + char Bytes[9]; // Use one more byte to silence a warning from Visual C++. + size_t BytesNum = StartBit ? 8 : 4; + size_t BytesFromDisk = std::min(static_cast(BytesNum), NumOfFlushedBytes - ByteNo); + size_t BytesFromBuffer = BytesNum - BytesFromDisk; + + // When unaligned, copy existing data into Bytes from the file FS and the + // buffer Out so that it can be updated before writing. For debug builds + // read bytes unconditionally in order to check that the existing value is 0 + // as expected. +#ifdef NDEBUG + if (StartBit) +#endif + { + FS->seek(ByteNo); + ssize_t BytesRead = FS->read(Bytes, BytesFromDisk); + (void)BytesRead; // silence warning + assert(BytesRead >= 0 && static_cast(BytesRead) == BytesFromDisk); + for (size_t i = 0; i < BytesFromBuffer; ++i) + Bytes[BytesFromDisk + i] = Out[i]; + assert((!endian::readAtBitAlignment( + Bytes, StartBit)) && + "Expected to be patching over 0-value placeholders"); + } + + // Update Bytes in terms of bit offset and value. + endian::writeAtBitAlignment(Bytes, NewWord, + StartBit); + + // Copy updated data back to the file FS and the buffer Out. + FS->seek(ByteNo); + FS->write(Bytes, BytesFromDisk); + for (size_t i = 0; i < BytesFromBuffer; ++i) + Out[i] = Bytes[BytesFromDisk + i]; + + // Restore the file position. + FS->seek(CurPos); } void BackpatchWord64(uint64_t BitNo, uint64_t Val) { diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/Analysis.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/Analysis.h index fe610b5bdc8d..bdfb416d9bd9 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/Analysis.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/Analysis.h @@ -92,11 +92,6 @@ void computeValueLLTs(const DataLayout &DL, Type &Ty, /// ExtractTypeInfo - Returns the type info, possibly bitcast, encoded in V. GlobalValue *ExtractTypeInfo(Value *V); -/// hasInlineAsmMemConstraint - Return true if the inline asm instruction being -/// processed uses a memory 'm' constraint. -bool hasInlineAsmMemConstraint(InlineAsm::ConstraintInfoVector &CInfos, - const TargetLowering &TLI); - /// getFCmpCondCode - Return the ISD condition code corresponding to /// the given LLVM IR floating-point condition code. This includes /// consideration of global floating-point math flags. diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/AntiDepBreaker.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/AntiDepBreaker.h index d75c13e2dd75..0553d7d452a4 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/AntiDepBreaker.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/AntiDepBreaker.h @@ -17,7 +17,6 @@ #include "llvm/ADT/iterator_range.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/ScheduleDAG.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/Support/Compiler.h" #include diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/AsmPrinter.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/AsmPrinter.h index 0eb950861af6..76486b0b48ce 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/AsmPrinter.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/AsmPrinter.h @@ -66,6 +66,7 @@ class MCSymbol; class MCTargetOptions; class MDNode; class Module; +class PseudoProbeHandler; class raw_ostream; class StackMaps; class StringRef; @@ -139,9 +140,30 @@ public: using GOTEquivUsePair = std::pair; MapVector GlobalGOTEquivs; + /// struct HandlerInfo and Handlers permit users or target extended + /// AsmPrinter to add their own handlers. + struct HandlerInfo { + std::unique_ptr Handler; + const char *TimerName; + const char *TimerDescription; + const char *TimerGroupName; + const char *TimerGroupDescription; + + HandlerInfo(std::unique_ptr Handler, + const char *TimerName, const char *TimerDescription, + const char *TimerGroupName, const char *TimerGroupDescription) + : Handler(std::move(Handler)), TimerName(TimerName), + TimerDescription(TimerDescription), TimerGroupName(TimerGroupName), + TimerGroupDescription(TimerGroupDescription) {} + }; + private: MCSymbol *CurrentFnEnd = nullptr; - MCSymbol *CurExceptionSym = nullptr; + + /// Map a basic block section ID to the exception symbol associated with that + /// section. Map entries are assigned and looked up via + /// AsmPrinter::getMBBExceptionSym. + DenseMap MBBSectionExceptionSyms; // The symbol used to represent the start of the current BB section of the // function. This is used to calculate the size of the BB section. @@ -158,26 +180,10 @@ private: protected: MCSymbol *CurrentFnBegin = nullptr; - /// Protected struct HandlerInfo and Handlers permit target extended - /// AsmPrinter adds their own handlers. - struct HandlerInfo { - std::unique_ptr Handler; - const char *TimerName; - const char *TimerDescription; - const char *TimerGroupName; - const char *TimerGroupDescription; - - HandlerInfo(std::unique_ptr Handler, - const char *TimerName, const char *TimerDescription, - const char *TimerGroupName, const char *TimerGroupDescription) - : Handler(std::move(Handler)), TimerName(TimerName), - TimerDescription(TimerDescription), TimerGroupName(TimerGroupName), - TimerGroupDescription(TimerGroupDescription) {} - }; - /// A vector of all debug/EH info emitters we should use. This vector /// maintains ownership of the emitters. - SmallVector Handlers; + std::vector Handlers; + size_t NumUserHandlers = 0; public: struct SrcMgrDiagInfo { @@ -201,6 +207,10 @@ private: /// If the target supports dwarf debug info, this pointer is non-null. DwarfDebug *DD = nullptr; + /// A handler that supports pseudo probe emission with embedded inline + /// context. + PseudoProbeHandler *PP = nullptr; + /// If the current module uses dwarf CFI annotations strictly for debugging. bool isCFIMoveForDebugging = false; @@ -216,6 +226,14 @@ public: uint16_t getDwarfVersion() const; void setDwarfVersion(uint16_t Version); + bool isDwarf64() const; + + /// Returns 4 for DWARF32 and 8 for DWARF64. + unsigned int getDwarfOffsetByteSize() const; + + /// Returns 4 for DWARF32 and 12 for DWARF64. + unsigned int getUnitLengthFieldByteSize() const; + bool isPositionIndependent() const; /// Return true if assembly output should contain comments. @@ -230,7 +248,10 @@ public: MCSymbol *getFunctionBegin() const { return CurrentFnBegin; } MCSymbol *getFunctionEnd() const { return CurrentFnEnd; } - MCSymbol *getCurExceptionSym(); + + // Return the exception symbol associated with the MBB section containing a + // given basic block. + MCSymbol *getMBBExceptionSym(const MachineBasicBlock &MBB); /// Return information about object file lowering. const TargetLoweringObjectFile &getObjFileLowering() const; @@ -342,6 +363,10 @@ public: void emitStackSizeSection(const MachineFunction &MF); + void emitBBAddrMapSection(const MachineFunction &MF); + + void emitPseudoProbe(const MachineInstr &MI); + void emitRemarksSection(remarks::RemarkStreamer &RS); enum CFIMoveType { CFI_M_None, CFI_M_EH, CFI_M_Debug }; @@ -369,6 +394,32 @@ public: /// so, emit it and return true, otherwise do nothing and return false. bool emitSpecialLLVMGlobal(const GlobalVariable *GV); + /// `llvm.global_ctors` and `llvm.global_dtors` are arrays of Structor + /// structs. + /// + /// Priority - init priority + /// Func - global initialization or global clean-up function + /// ComdatKey - associated data + struct Structor { + int Priority = 0; + Constant *Func = nullptr; + GlobalValue *ComdatKey = nullptr; + + Structor() = default; + }; + + /// This method gathers an array of Structors and then sorts them out by + /// Priority. + /// @param List The initializer of `llvm.global_ctors` or `llvm.global_dtors` + /// array. + /// @param[out] Structors Sorted Structor structs by Priority. + void preprocessXXStructorList(const DataLayout &DL, const Constant *List, + SmallVector &Structors); + + /// This method emits `llvm.global_ctors` or `llvm.global_dtors` list. + virtual void emitXXStructorList(const DataLayout &DL, const Constant *List, + bool IsCtor); + /// Emit an alignment directive to the specified power of two boundary. If a /// global value is specified, and if that global has an explicit alignment /// requested, it will override the alignment request if required for @@ -403,6 +454,11 @@ public: // Overridable Hooks //===------------------------------------------------------------------===// + void addAsmPrinterHandler(HandlerInfo Handler) { + Handlers.insert(Handlers.begin(), std::move(Handler)); + NumUserHandlers++; + } + // Targets can, or in the case of EmitInstruction, must implement these to // customize output. @@ -534,9 +590,6 @@ public: emitLabelPlusOffset(Label, 0, Size, IsSectionRelative); } - /// Emit something like ".long Label + Offset". - void emitDwarfOffset(const MCSymbol *Label, uint64_t Offset) const; - //===------------------------------------------------------------------===// // Dwarf Emission Helper Routines //===------------------------------------------------------------------===// @@ -557,7 +610,7 @@ public: unsigned GetSizeOfEncodedValue(unsigned Encoding) const; /// Emit reference to a ttype global with a specified encoding. - void emitTTypeReference(const GlobalValue *GV, unsigned Encoding) const; + virtual void emitTTypeReference(const GlobalValue *GV, unsigned Encoding); /// Emit a reference to a symbol for use in dwarf. Different object formats /// represent this in different ways. Some use a relocation others encode @@ -565,18 +618,39 @@ public: void emitDwarfSymbolReference(const MCSymbol *Label, bool ForceOffset = false) const; - /// Emit the 4-byte offset of a string from the start of its section. + /// Emit the 4- or 8-byte offset of a string from the start of its section. /// /// When possible, emit a DwarfStringPool section offset without any /// relocations, and without using the symbol. Otherwise, defers to \a /// emitDwarfSymbolReference(). + /// + /// The length of the emitted value depends on the DWARF format. void emitDwarfStringOffset(DwarfStringPoolEntry S) const; - /// Emit the 4-byte offset of a string from the start of its section. + /// Emit the 4-or 8-byte offset of a string from the start of its section. void emitDwarfStringOffset(DwarfStringPoolEntryRef S) const { emitDwarfStringOffset(S.getEntry()); } + /// Emit something like ".long Label + Offset" or ".quad Label + Offset" + /// depending on the DWARF format. + void emitDwarfOffset(const MCSymbol *Label, uint64_t Offset) const; + + /// Emit 32- or 64-bit value depending on the DWARF format. + void emitDwarfLengthOrOffset(uint64_t Value) const; + + /// Emit a special value of 0xffffffff if producing 64-bit debugging info. + void maybeEmitDwarf64Mark() const; + + /// Emit a unit length field. The actual format, DWARF32 or DWARF64, is chosen + /// according to the settings. + void emitDwarfUnitLength(uint64_t Length, const Twine &Comment) const; + + /// Emit a unit length field. The actual format, DWARF32 or DWARF64, is chosen + /// according to the settings. + void emitDwarfUnitLength(const MCSymbol *Hi, const MCSymbol *Lo, + const Twine &Comment) const; + /// Emit reference to a call site with a specified encoding void emitCallSiteOffset(const MCSymbol *Hi, const MCSymbol *Lo, unsigned Encoding) const; @@ -713,12 +787,13 @@ private: void emitModuleIdents(Module &M); /// Emit bytes for llvm.commandline metadata. void emitModuleCommandLines(Module &M); - void emitXXStructorList(const DataLayout &DL, const Constant *List, - bool isCtor); GCMetadataPrinter *GetOrCreateGCPrinter(GCStrategy &S); /// Emit GlobalAlias or GlobalIFunc. void emitGlobalIndirectSymbol(Module &M, const GlobalIndirectSymbol &GIS); + + /// This method decides whether the specified basic block requires a label. + bool shouldEmitLabelForBasicBlock(const MachineBasicBlock &MBB) const; }; } // end namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/AsmPrinterHandler.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/AsmPrinterHandler.h index 899d067d03f0..dc81a3040097 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/AsmPrinterHandler.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/AsmPrinterHandler.h @@ -23,8 +23,10 @@ class MachineBasicBlock; class MachineFunction; class MachineInstr; class MCSymbol; +class Module; -typedef MCSymbol *ExceptionSymbolProvider(AsmPrinter *Asm); +typedef MCSymbol *ExceptionSymbolProvider(AsmPrinter *Asm, + const MachineBasicBlock *MBB); /// Collects and handles AsmPrinter objects required to build debug /// or EH information. @@ -36,6 +38,8 @@ public: /// this tracks that size. virtual void setSymbolSize(const MCSymbol *Sym, uint64_t Size) = 0; + virtual void beginModule(Module *M) {} + /// Emit all sections that should come after the content. virtual void endModule() = 0; @@ -74,6 +78,7 @@ public: /// Process end of a basic block during basic block sections. virtual void endBasicBlock(const MachineBasicBlock &MBB) {} }; + } // End of namespace llvm #endif diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/BasicBlockSectionUtils.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/BasicBlockSectionUtils.h new file mode 100644 index 000000000000..d8da3be0cd4c --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/BasicBlockSectionUtils.h @@ -0,0 +1,30 @@ +//===- BasicBlockSectionUtils.h - Utilities for basic block sections --===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_BASICBLOCKSECTIONUTILS_H +#define LLVM_CODEGEN_BASICBLOCKSECTIONUTILS_H + +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/CommandLine.h" + +namespace llvm { + +extern cl::opt BBSectionsColdTextPrefix; + +class MachineFunction; +class MachineBasicBlock; + +using MachineBasicBlockComparator = + function_ref; + +void sortBasicBlocksAndUpdateBranches(MachineFunction &MF, + MachineBasicBlockComparator MBBCmp); + +} // end namespace llvm + +#endif // LLVM_CODEGEN_BASICBLOCKSECTIONUTILS_H diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/BasicTTIImpl.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/BasicTTIImpl.h index 407f09063dce..9514dd22be80 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/BasicTTIImpl.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/BasicTTIImpl.h @@ -40,7 +40,6 @@ #include "llvm/IR/Operator.h" #include "llvm/IR/Type.h" #include "llvm/IR/Value.h" -#include "llvm/MC/MCSchedule.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" @@ -115,12 +114,14 @@ private: /// Estimate a cost of subvector extraction as a sequence of extract and /// insert operations. - unsigned getExtractSubvectorOverhead(FixedVectorType *VTy, int Index, + unsigned getExtractSubvectorOverhead(VectorType *VTy, int Index, FixedVectorType *SubVTy) { assert(VTy && SubVTy && "Can only extract subvectors from vectors"); int NumSubElts = SubVTy->getNumElements(); - assert((Index + NumSubElts) <= (int)VTy->getNumElements() && + assert((!isa(VTy) || + (Index + NumSubElts) <= + (int)cast(VTy)->getNumElements()) && "SK_ExtractSubvector index out of range"); unsigned Cost = 0; @@ -138,12 +139,14 @@ private: /// Estimate a cost of subvector insertion as a sequence of extract and /// insert operations. - unsigned getInsertSubvectorOverhead(FixedVectorType *VTy, int Index, + unsigned getInsertSubvectorOverhead(VectorType *VTy, int Index, FixedVectorType *SubVTy) { assert(VTy && SubVTy && "Can only insert subvectors into vectors"); int NumSubElts = SubVTy->getNumElements(); - assert((Index + NumSubElts) <= (int)VTy->getNumElements() && + assert((!isa(VTy) || + (Index + NumSubElts) <= + (int)cast(VTy)->getNumElements()) && "SK_InsertSubvector index out of range"); unsigned Cost = 0; @@ -222,7 +225,11 @@ public: } bool isNoopAddrSpaceCast(unsigned FromAS, unsigned ToAS) const { - return getTLI()->isNoopAddrSpaceCast(FromAS, ToAS); + return getTLI()->getTargetMachine().isNoopAddrSpaceCast(FromAS, ToAS); + } + + unsigned getAssumedAddrSpace(const Value *V) const { + return getTLI()->getTargetMachine().getAssumedAddrSpace(V); } Value *rewriteIntrinsicWithAddressSpace(IntrinsicInst *II, Value *OldV, @@ -265,6 +272,10 @@ public: return TargetTransformInfoImplBase::isLSRCostLess(C1, C2); } + bool isNumRegsMajorCostOfLSR() { + return TargetTransformInfoImplBase::isNumRegsMajorCostOfLSR(); + } + bool isProfitableLSRChainElement(Instruction *I) { return TargetTransformInfoImplBase::isProfitableLSRChainElement(I); } @@ -294,6 +305,10 @@ public: return getTLI()->isTypeLegal(VT); } + unsigned getRegUsageForType(Type *Ty) { + return getTLI()->getTypeLegalizationCost(DL, Ty).first; + } + int getGEPCost(Type *PointeeType, const Value *Ptr, ArrayRef Operands) { return BaseT::getGEPCost(PointeeType, Ptr, Operands); @@ -386,6 +401,7 @@ public: } unsigned getInliningThresholdMultiplier() { return 1; } + unsigned adjustInliningThreshold(const CallBase *CB) { return 0; } int getInlinerVectorBonusPercent() { return 150; } @@ -477,6 +493,30 @@ public: return BaseT::emitGetActiveLaneMask(); } + Optional instCombineIntrinsic(InstCombiner &IC, + IntrinsicInst &II) { + return BaseT::instCombineIntrinsic(IC, II); + } + + Optional simplifyDemandedUseBitsIntrinsic(InstCombiner &IC, + IntrinsicInst &II, + APInt DemandedMask, + KnownBits &Known, + bool &KnownBitsComputed) { + return BaseT::simplifyDemandedUseBitsIntrinsic(IC, II, DemandedMask, Known, + KnownBitsComputed); + } + + Optional simplifyDemandedVectorEltsIntrinsic( + InstCombiner &IC, IntrinsicInst &II, APInt DemandedElts, APInt &UndefElts, + APInt &UndefElts2, APInt &UndefElts3, + std::function + SimplifyAndSetOp) { + return BaseT::simplifyDemandedVectorEltsIntrinsic( + IC, II, DemandedElts, UndefElts, UndefElts2, UndefElts3, + SimplifyAndSetOp); + } + int getInstructionLatency(const Instruction *I) { if (isa(I)) return getST()->getSchedModel().DefaultLoadLatency; @@ -532,6 +572,8 @@ public: unsigned getRegisterBitWidth(bool Vector) const { return 32; } + Optional getMaxVScale() const { return None; } + /// Estimate the overhead of scalarizing an instruction. Insert and Extract /// are set if the demanded result elements need to be inserted and/or /// extracted from vectors. @@ -567,7 +609,7 @@ public: return thisT()->getScalarizationOverhead(Ty, DemandedElts, Insert, Extract); } - /// Estimate the overhead of scalarizing an instructions unique + /// Estimate the overhead of scalarizing an instruction's unique /// non-constant operands. The types of the arguments are ordinarily /// scalar, in which case the costs are multiplied with VF. unsigned getOperandsScalarizationOverhead(ArrayRef Args, @@ -575,8 +617,14 @@ public: unsigned Cost = 0; SmallPtrSet UniqueOperands; for (const Value *A : Args) { + // Disregard things like metadata arguments. + Type *Ty = A->getType(); + if (!Ty->isIntOrIntVectorTy() && !Ty->isFPOrFPVectorTy() && + !Ty->isPtrOrPtrVectorTy()) + continue; + if (!isa(A) && UniqueOperands.insert(A).second) { - auto *VecTy = dyn_cast(A->getType()); + auto *VecTy = dyn_cast(Ty); if (VecTy) { // If A is a vector operand, VF should be 1 or correspond to A. assert((VF == 1 || @@ -584,7 +632,7 @@ public: "Vector argument does not match VF"); } else - VecTy = FixedVectorType::get(A->getType(), VF); + VecTy = FixedVectorType::get(Ty, VF); Cost += getScalarizationOverhead(VecTy, false, true); } @@ -658,7 +706,8 @@ public: if (auto *VTy = dyn_cast(Ty)) { unsigned Num = cast(VTy)->getNumElements(); unsigned Cost = thisT()->getArithmeticInstrCost( - Opcode, VTy->getScalarType(), CostKind); + Opcode, VTy->getScalarType(), CostKind, Opd1Info, Opd2Info, + Opd1PropInfo, Opd2PropInfo, Args, CxtI); // Return the cost of multiple scalar invocation plus the cost of // inserting and extracting the values. return getScalarizationOverhead(VTy, Args) + Num * Cost; @@ -681,19 +730,20 @@ public: case TTI::SK_PermuteTwoSrc: return getPermuteShuffleOverhead(cast(Tp)); case TTI::SK_ExtractSubvector: - return getExtractSubvectorOverhead(cast(Tp), Index, + return getExtractSubvectorOverhead(Tp, Index, cast(SubTp)); case TTI::SK_InsertSubvector: - return getInsertSubvectorOverhead(cast(Tp), Index, + return getInsertSubvectorOverhead(Tp, Index, cast(SubTp)); } llvm_unreachable("Unknown TTI::ShuffleKind"); } unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src, + TTI::CastContextHint CCH, TTI::TargetCostKind CostKind, const Instruction *I = nullptr) { - if (BaseT::getCastInstrCost(Opcode, Dst, Src, CostKind, I) == 0) + if (BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I) == 0) return 0; const TargetLoweringBase *TLI = getTLI(); @@ -731,15 +781,12 @@ public: return 0; LLVM_FALLTHROUGH; case Instruction::SExt: - if (!I) - break; - - if (getTLI()->isExtFree(I)) + if (I && getTLI()->isExtFree(I)) return 0; // If this is a zext/sext of a load, return 0 if the corresponding // extending load exists on target. - if (I && isa(I->getOperand(0))) { + if (CCH == TTI::CastContextHint::Normal) { EVT ExtVT = EVT::getEVT(Dst); EVT LoadVT = EVT::getEVT(Src); unsigned LType = @@ -814,7 +861,7 @@ public: unsigned SplitCost = (!SplitSrc || !SplitDst) ? TTI->getVectorSplitCost() : 0; return SplitCost + - (2 * TTI->getCastInstrCost(Opcode, SplitDstTy, SplitSrcTy, + (2 * TTI->getCastInstrCost(Opcode, SplitDstTy, SplitSrcTy, CCH, CostKind, I)); } @@ -822,7 +869,7 @@ public: // the operation will get scalarized. unsigned Num = cast(DstVTy)->getNumElements(); unsigned Cost = thisT()->getCastInstrCost( - Opcode, Dst->getScalarType(), Src->getScalarType(), CostKind, I); + Opcode, Dst->getScalarType(), Src->getScalarType(), CCH, CostKind, I); // Return the cost of multiple scalar invocation plus the cost of // inserting and extracting the values. @@ -847,7 +894,7 @@ public: return thisT()->getVectorInstrCost(Instruction::ExtractElement, VecTy, Index) + thisT()->getCastInstrCost(Opcode, Dst, VecTy->getElementType(), - TTI::TCK_RecipThroughput); + TTI::CastContextHint::None, TTI::TCK_RecipThroughput); } unsigned getCFInstrCost(unsigned Opcode, TTI::TargetCostKind CostKind) { @@ -855,6 +902,7 @@ public: } unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy, + CmpInst::Predicate VecPred, TTI::TargetCostKind CostKind, const Instruction *I = nullptr) { const TargetLoweringBase *TLI = getTLI(); @@ -863,7 +911,8 @@ public: // TODO: Handle other cost kinds. if (CostKind != TTI::TCK_RecipThroughput) - return BaseT::getCmpSelInstrCost(Opcode, ValTy, CondTy, CostKind, I); + return BaseT::getCmpSelInstrCost(Opcode, ValTy, CondTy, VecPred, CostKind, + I); // Selects on vectors are actually vector selects. if (ISD == ISD::SELECT) { @@ -888,7 +937,7 @@ public: if (CondTy) CondTy = CondTy->getScalarType(); unsigned Cost = thisT()->getCmpSelInstrCost( - Opcode, ValVTy->getScalarType(), CondTy, CostKind, I); + Opcode, ValVTy->getScalarType(), CondTy, VecPred, CostKind, I); // Return the cost of multiple scalar invocation plus the cost of // inserting and extracting the values. @@ -922,7 +971,11 @@ public: return Cost; if (Src->isVectorTy() && - Src->getPrimitiveSizeInBits() < LT.second.getSizeInBits()) { + // In practice it's not currently possible to have a change in lane + // length for extending loads or truncating stores so both types should + // have the same scalable property. + TypeSize::isKnownLT(Src->getPrimitiveSizeInBits(), + LT.second.getSizeInBits())) { // This is a vector load that legalizes to a larger type than the vector // itself. Unless the corresponding extending load or truncating store is // legal, then this will scalarize. @@ -945,6 +998,51 @@ public: return Cost; } + unsigned getGatherScatterOpCost(unsigned Opcode, Type *DataTy, + const Value *Ptr, bool VariableMask, + Align Alignment, TTI::TargetCostKind CostKind, + const Instruction *I = nullptr) { + auto *VT = cast(DataTy); + // Assume the target does not have support for gather/scatter operations + // and provide a rough estimate. + // + // First, compute the cost of extracting the individual addresses and the + // individual memory operations. + int LoadCost = + VT->getNumElements() * + (getVectorInstrCost( + Instruction::ExtractElement, + FixedVectorType::get(PointerType::get(VT->getElementType(), 0), + VT->getNumElements()), + -1) + + getMemoryOpCost(Opcode, VT->getElementType(), Alignment, 0, CostKind)); + + // Next, compute the cost of packing the result in a vector. + int PackingCost = getScalarizationOverhead(VT, Opcode != Instruction::Store, + Opcode == Instruction::Store); + + int ConditionalCost = 0; + if (VariableMask) { + // Compute the cost of conditionally executing the memory operations with + // variable masks. This includes extracting the individual conditions, a + // branches and PHIs to combine the results. + // NOTE: Estimating the cost of conditionally executing the memory + // operations accurately is quite difficult and the current solution + // provides a very rough estimate only. + ConditionalCost = + VT->getNumElements() * + (getVectorInstrCost( + Instruction::ExtractElement, + FixedVectorType::get(Type::getInt1Ty(DataTy->getContext()), + VT->getNumElements()), + -1) + + getCFInstrCost(Instruction::Br, CostKind) + + getCFInstrCost(Instruction::PHI, CostKind)); + } + + return LoadCost + PackingCost + ConditionalCost; + } + unsigned getInterleavedMemoryOpCost( unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef Indices, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, @@ -1099,76 +1197,52 @@ public: /// Get intrinsic cost based on arguments. unsigned getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, TTI::TargetCostKind CostKind) { - Intrinsic::ID IID = ICA.getID(); - - // Special case some scalar intrinsics. - if (CostKind != TTI::TCK_RecipThroughput) { - switch (IID) { - default: - break; - case Intrinsic::cttz: - if (getTLI()->isCheapToSpeculateCttz()) - return TargetTransformInfo::TCC_Basic; - break; - case Intrinsic::ctlz: - if (getTLI()->isCheapToSpeculateCtlz()) - return TargetTransformInfo::TCC_Basic; - break; - case Intrinsic::memcpy: - return thisT()->getMemcpyCost(ICA.getInst()); - // TODO: other libc intrinsics. - } - return BaseT::getIntrinsicInstrCost(ICA, CostKind); - } - + // Check for generically free intrinsics. if (BaseT::getIntrinsicInstrCost(ICA, CostKind) == 0) return 0; - // TODO: Combine these two logic paths. + // Assume that target intrinsics are cheap. + Intrinsic::ID IID = ICA.getID(); + if (Function::isTargetIntrinsic(IID)) + return TargetTransformInfo::TCC_Basic; + if (ICA.isTypeBasedOnly()) return getTypeBasedIntrinsicInstrCost(ICA, CostKind); Type *RetTy = ICA.getReturnType(); - unsigned VF = ICA.getVectorFactor(); - unsigned RetVF = - (RetTy->isVectorTy() ? cast(RetTy)->getNumElements() - : 1); - assert((RetVF == 1 || VF == 1) && "VF > 1 and RetVF is a vector type"); + + ElementCount VF = ICA.getVectorFactor(); + ElementCount RetVF = + (RetTy->isVectorTy() ? cast(RetTy)->getElementCount() + : ElementCount::getFixed(1)); + assert((RetVF.isScalar() || VF.isScalar()) && + "VF > 1 and RetVF is a vector type"); const IntrinsicInst *I = ICA.getInst(); const SmallVectorImpl &Args = ICA.getArgs(); FastMathFlags FMF = ICA.getFlags(); - switch (IID) { - default: { - // Assume that we need to scalarize this intrinsic. - SmallVector Types; - for (const Value *Op : Args) { - Type *OpTy = Op->getType(); - assert(VF == 1 || !OpTy->isVectorTy()); - Types.push_back(VF == 1 ? OpTy : FixedVectorType::get(OpTy, VF)); - } + default: + break; - if (VF > 1 && !RetTy->isVoidTy()) - RetTy = FixedVectorType::get(RetTy, VF); - - // Compute the scalarization overhead based on Args for a vector - // intrinsic. A vectorizer will pass a scalar RetTy and VF > 1, while - // CostModel will pass a vector RetTy and VF is 1. - unsigned ScalarizationCost = std::numeric_limits::max(); - if (RetVF > 1 || VF > 1) { - ScalarizationCost = 0; - if (!RetTy->isVoidTy()) - ScalarizationCost += - getScalarizationOverhead(cast(RetTy), true, false); - ScalarizationCost += getOperandsScalarizationOverhead(Args, VF); - } + case Intrinsic::cttz: + // FIXME: If necessary, this should go in target-specific overrides. + if (VF.isScalar() && RetVF.isScalar() && + getTLI()->isCheapToSpeculateCttz()) + return TargetTransformInfo::TCC_Basic; + break; + + case Intrinsic::ctlz: + // FIXME: If necessary, this should go in target-specific overrides. + if (VF.isScalar() && RetVF.isScalar() && + getTLI()->isCheapToSpeculateCtlz()) + return TargetTransformInfo::TCC_Basic; + break; + + case Intrinsic::memcpy: + return thisT()->getMemcpyCost(ICA.getInst()); - IntrinsicCostAttributes Attrs(IID, RetTy, Types, FMF, - ScalarizationCost, I); - return thisT()->getIntrinsicInstrCost(Attrs, CostKind); - } case Intrinsic::masked_scatter: { - assert(VF == 1 && "Can't vectorize types here."); + assert(VF.isScalar() && "Can't vectorize types here."); const Value *Mask = Args[3]; bool VarMask = !isa(Mask); Align Alignment = cast(Args[2])->getAlignValue(); @@ -1177,31 +1251,57 @@ public: VarMask, Alignment, CostKind, I); } case Intrinsic::masked_gather: { - assert(VF == 1 && "Can't vectorize types here."); + assert(VF.isScalar() && "Can't vectorize types here."); const Value *Mask = Args[2]; bool VarMask = !isa(Mask); Align Alignment = cast(Args[1])->getAlignValue(); return thisT()->getGatherScatterOpCost(Instruction::Load, RetTy, Args[0], VarMask, Alignment, CostKind, I); } - case Intrinsic::experimental_vector_reduce_add: - case Intrinsic::experimental_vector_reduce_mul: - case Intrinsic::experimental_vector_reduce_and: - case Intrinsic::experimental_vector_reduce_or: - case Intrinsic::experimental_vector_reduce_xor: - case Intrinsic::experimental_vector_reduce_v2_fadd: - case Intrinsic::experimental_vector_reduce_v2_fmul: - case Intrinsic::experimental_vector_reduce_smax: - case Intrinsic::experimental_vector_reduce_smin: - case Intrinsic::experimental_vector_reduce_fmax: - case Intrinsic::experimental_vector_reduce_fmin: - case Intrinsic::experimental_vector_reduce_umax: - case Intrinsic::experimental_vector_reduce_umin: { + case Intrinsic::experimental_vector_extract: { + // FIXME: Handle case where a scalable vector is extracted from a scalable + // vector + if (isa(RetTy)) + return BaseT::getIntrinsicInstrCost(ICA, CostKind); + unsigned Index = cast(Args[1])->getZExtValue(); + return thisT()->getShuffleCost(TTI::SK_ExtractSubvector, + cast(Args[0]->getType()), + Index, cast(RetTy)); + } + case Intrinsic::experimental_vector_insert: { + // FIXME: Handle case where a scalable vector is inserted into a scalable + // vector + if (isa(Args[1]->getType())) + return BaseT::getIntrinsicInstrCost(ICA, CostKind); + unsigned Index = cast(Args[2])->getZExtValue(); + return thisT()->getShuffleCost( + TTI::SK_InsertSubvector, cast(Args[0]->getType()), Index, + cast(Args[1]->getType())); + } + case Intrinsic::vector_reduce_add: + case Intrinsic::vector_reduce_mul: + case Intrinsic::vector_reduce_and: + case Intrinsic::vector_reduce_or: + case Intrinsic::vector_reduce_xor: + case Intrinsic::vector_reduce_smax: + case Intrinsic::vector_reduce_smin: + case Intrinsic::vector_reduce_fmax: + case Intrinsic::vector_reduce_fmin: + case Intrinsic::vector_reduce_umax: + case Intrinsic::vector_reduce_umin: { IntrinsicCostAttributes Attrs(IID, RetTy, Args[0]->getType(), FMF, 1, I); - return getIntrinsicInstrCost(Attrs, CostKind); + return getTypeBasedIntrinsicInstrCost(Attrs, CostKind); + } + case Intrinsic::vector_reduce_fadd: + case Intrinsic::vector_reduce_fmul: { + IntrinsicCostAttributes Attrs( + IID, RetTy, {Args[0]->getType(), Args[1]->getType()}, FMF, 1, I); + return getTypeBasedIntrinsicInstrCost(Attrs, CostKind); } case Intrinsic::fshl: case Intrinsic::fshr: { + if (isa(RetTy)) + return BaseT::getIntrinsicInstrCost(ICA, CostKind); const Value *X = Args[0]; const Value *Y = Args[1]; const Value *Z = Args[2]; @@ -1232,14 +1332,48 @@ public: // For non-rotates (X != Y) we must add shift-by-zero handling costs. if (X != Y) { Type *CondTy = RetTy->getWithNewBitWidth(1); - Cost += thisT()->getCmpSelInstrCost(BinaryOperator::ICmp, RetTy, CondTy, - CostKind); - Cost += thisT()->getCmpSelInstrCost(BinaryOperator::Select, RetTy, - CondTy, CostKind); + Cost += + thisT()->getCmpSelInstrCost(BinaryOperator::ICmp, RetTy, CondTy, + CmpInst::BAD_ICMP_PREDICATE, CostKind); + Cost += + thisT()->getCmpSelInstrCost(BinaryOperator::Select, RetTy, CondTy, + CmpInst::BAD_ICMP_PREDICATE, CostKind); } return Cost; } } + // TODO: Handle the remaining intrinsic with scalable vector type + if (isa(RetTy)) + return BaseT::getIntrinsicInstrCost(ICA, CostKind); + + // Assume that we need to scalarize this intrinsic. + SmallVector Types; + for (const Value *Op : Args) { + Type *OpTy = Op->getType(); + assert(VF.isScalar() || !OpTy->isVectorTy()); + Types.push_back(VF.isScalar() + ? OpTy + : FixedVectorType::get(OpTy, VF.getKnownMinValue())); + } + + if (VF.isVector() && !RetTy->isVoidTy()) + RetTy = FixedVectorType::get(RetTy, VF.getKnownMinValue()); + + // Compute the scalarization overhead based on Args for a vector + // intrinsic. A vectorizer will pass a scalar RetTy and VF > 1, while + // CostModel will pass a vector RetTy and VF is 1. + unsigned ScalarizationCost = std::numeric_limits::max(); + if (RetVF.isVector() || VF.isVector()) { + ScalarizationCost = 0; + if (!RetTy->isVoidTy()) + ScalarizationCost += + getScalarizationOverhead(cast(RetTy), true, false); + ScalarizationCost += + getOperandsScalarizationOverhead(Args, VF.getKnownMinValue()); + } + + IntrinsicCostAttributes Attrs(IID, RetTy, Types, FMF, ScalarizationCost, I); + return thisT()->getTypeBasedIntrinsicInstrCost(Attrs, CostKind); } /// Get intrinsic cost based on argument types. @@ -1255,10 +1389,21 @@ public: unsigned ScalarizationCostPassed = ICA.getScalarizationCost(); bool SkipScalarizationCost = ICA.skipScalarizationCost(); - auto *VecOpTy = Tys.empty() ? nullptr : dyn_cast(Tys[0]); + VectorType *VecOpTy = nullptr; + if (!Tys.empty()) { + // The vector reduction operand is operand 0 except for fadd/fmul. + // Their operand 0 is a scalar start value, so the vector op is operand 1. + unsigned VecTyIndex = 0; + if (IID == Intrinsic::vector_reduce_fadd || + IID == Intrinsic::vector_reduce_fmul) + VecTyIndex = 1; + assert(Tys.size() > VecTyIndex && "Unexpected IntrinsicCostAttributes"); + VecOpTy = dyn_cast(Tys[VecTyIndex]); + } + // Library call cost - other than size, make it expensive. + unsigned SingleCallCost = CostKind == TTI::TCK_CodeSize ? 1 : 10; SmallVector ISDs; - unsigned SingleCallCost = 10; // Library call cost. Make it expensive. switch (IID) { default: { // Assume that we need to scalarize this intrinsic. @@ -1327,13 +1472,15 @@ public: break; case Intrinsic::minnum: ISDs.push_back(ISD::FMINNUM); - if (FMF.noNaNs()) - ISDs.push_back(ISD::FMINIMUM); break; case Intrinsic::maxnum: ISDs.push_back(ISD::FMAXNUM); - if (FMF.noNaNs()) - ISDs.push_back(ISD::FMAXIMUM); + break; + case Intrinsic::minimum: + ISDs.push_back(ISD::FMINIMUM); + break; + case Intrinsic::maximum: + ISDs.push_back(ISD::FMAXIMUM); break; case Intrinsic::copysign: ISDs.push_back(ISD::FCOPYSIGN); @@ -1375,6 +1522,7 @@ public: case Intrinsic::lifetime_start: case Intrinsic::lifetime_end: case Intrinsic::sideeffect: + case Intrinsic::pseudoprobe: return 0; case Intrinsic::masked_store: { Type *Ty = Tys[0]; @@ -1388,50 +1536,72 @@ public: return thisT()->getMaskedMemoryOpCost(Instruction::Load, Ty, TyAlign, 0, CostKind); } - case Intrinsic::experimental_vector_reduce_add: + case Intrinsic::vector_reduce_add: return thisT()->getArithmeticReductionCost(Instruction::Add, VecOpTy, /*IsPairwiseForm=*/false, CostKind); - case Intrinsic::experimental_vector_reduce_mul: + case Intrinsic::vector_reduce_mul: return thisT()->getArithmeticReductionCost(Instruction::Mul, VecOpTy, /*IsPairwiseForm=*/false, CostKind); - case Intrinsic::experimental_vector_reduce_and: + case Intrinsic::vector_reduce_and: return thisT()->getArithmeticReductionCost(Instruction::And, VecOpTy, /*IsPairwiseForm=*/false, CostKind); - case Intrinsic::experimental_vector_reduce_or: + case Intrinsic::vector_reduce_or: return thisT()->getArithmeticReductionCost(Instruction::Or, VecOpTy, /*IsPairwiseForm=*/false, CostKind); - case Intrinsic::experimental_vector_reduce_xor: + case Intrinsic::vector_reduce_xor: return thisT()->getArithmeticReductionCost(Instruction::Xor, VecOpTy, /*IsPairwiseForm=*/false, CostKind); - case Intrinsic::experimental_vector_reduce_v2_fadd: + case Intrinsic::vector_reduce_fadd: // FIXME: Add new flag for cost of strict reductions. return thisT()->getArithmeticReductionCost(Instruction::FAdd, VecOpTy, /*IsPairwiseForm=*/false, CostKind); - case Intrinsic::experimental_vector_reduce_v2_fmul: + case Intrinsic::vector_reduce_fmul: // FIXME: Add new flag for cost of strict reductions. return thisT()->getArithmeticReductionCost(Instruction::FMul, VecOpTy, /*IsPairwiseForm=*/false, CostKind); - case Intrinsic::experimental_vector_reduce_smax: - case Intrinsic::experimental_vector_reduce_smin: - case Intrinsic::experimental_vector_reduce_fmax: - case Intrinsic::experimental_vector_reduce_fmin: + case Intrinsic::vector_reduce_smax: + case Intrinsic::vector_reduce_smin: + case Intrinsic::vector_reduce_fmax: + case Intrinsic::vector_reduce_fmin: return thisT()->getMinMaxReductionCost( VecOpTy, cast(CmpInst::makeCmpResultType(VecOpTy)), /*IsPairwiseForm=*/false, /*IsUnsigned=*/false, CostKind); - case Intrinsic::experimental_vector_reduce_umax: - case Intrinsic::experimental_vector_reduce_umin: + case Intrinsic::vector_reduce_umax: + case Intrinsic::vector_reduce_umin: return thisT()->getMinMaxReductionCost( VecOpTy, cast(CmpInst::makeCmpResultType(VecOpTy)), /*IsPairwiseForm=*/false, /*IsUnsigned=*/true, CostKind); + case Intrinsic::abs: + case Intrinsic::smax: + case Intrinsic::smin: + case Intrinsic::umax: + case Intrinsic::umin: { + // abs(X) = select(icmp(X,0),X,sub(0,X)) + // minmax(X,Y) = select(icmp(X,Y),X,Y) + Type *CondTy = RetTy->getWithNewBitWidth(1); + unsigned Cost = 0; + // TODO: Ideally getCmpSelInstrCost would accept an icmp condition code. + Cost += + thisT()->getCmpSelInstrCost(BinaryOperator::ICmp, RetTy, CondTy, + CmpInst::BAD_ICMP_PREDICATE, CostKind); + Cost += + thisT()->getCmpSelInstrCost(BinaryOperator::Select, RetTy, CondTy, + CmpInst::BAD_ICMP_PREDICATE, CostKind); + // TODO: Should we add an OperandValueProperties::OP_Zero property? + if (IID == Intrinsic::abs) + Cost += thisT()->getArithmeticInstrCost( + BinaryOperator::Sub, RetTy, CostKind, TTI::OK_UniformConstantValue); + return Cost; + } case Intrinsic::sadd_sat: case Intrinsic::ssub_sat: { Type *CondTy = RetTy->getWithNewBitWidth(1); @@ -1447,10 +1617,12 @@ public: IntrinsicCostAttributes Attrs(OverflowOp, OpTy, {RetTy, RetTy}, FMF, ScalarizationCostPassed); Cost += thisT()->getIntrinsicInstrCost(Attrs, CostKind); - Cost += thisT()->getCmpSelInstrCost(BinaryOperator::ICmp, RetTy, CondTy, - CostKind); - Cost += 2 * thisT()->getCmpSelInstrCost(BinaryOperator::Select, RetTy, - CondTy, CostKind); + Cost += + thisT()->getCmpSelInstrCost(BinaryOperator::ICmp, RetTy, CondTy, + CmpInst::BAD_ICMP_PREDICATE, CostKind); + Cost += 2 * thisT()->getCmpSelInstrCost( + BinaryOperator::Select, RetTy, CondTy, + CmpInst::BAD_ICMP_PREDICATE, CostKind); return Cost; } case Intrinsic::uadd_sat: @@ -1466,8 +1638,9 @@ public: IntrinsicCostAttributes Attrs(OverflowOp, OpTy, {RetTy, RetTy}, FMF, ScalarizationCostPassed); Cost += thisT()->getIntrinsicInstrCost(Attrs, CostKind); - Cost += thisT()->getCmpSelInstrCost(BinaryOperator::Select, RetTy, CondTy, - CostKind); + Cost += + thisT()->getCmpSelInstrCost(BinaryOperator::Select, RetTy, CondTy, + CmpInst::BAD_ICMP_PREDICATE, CostKind); return Cost; } case Intrinsic::smul_fix: @@ -1477,13 +1650,14 @@ public: unsigned ExtOp = IID == Intrinsic::smul_fix ? Instruction::SExt : Instruction::ZExt; + TTI::CastContextHint CCH = TTI::CastContextHint::None; unsigned Cost = 0; - Cost += 2 * thisT()->getCastInstrCost(ExtOp, ExtTy, RetTy, CostKind); + Cost += 2 * thisT()->getCastInstrCost(ExtOp, ExtTy, RetTy, CCH, CostKind); Cost += thisT()->getArithmeticInstrCost(Instruction::Mul, ExtTy, CostKind); Cost += 2 * thisT()->getCastInstrCost(Instruction::Trunc, RetTy, ExtTy, - CostKind); + CCH, CostKind); Cost += thisT()->getArithmeticInstrCost(Instruction::LShr, RetTy, CostKind, TTI::OK_AnyValue, TTI::OK_UniformConstantValue); @@ -1511,10 +1685,12 @@ public: // Overflow -> (LHSSign != RHSSign) && (LHSSign != SumSign) unsigned Cost = 0; Cost += thisT()->getArithmeticInstrCost(Opcode, SumTy, CostKind); - Cost += 3 * thisT()->getCmpSelInstrCost(BinaryOperator::ICmp, SumTy, - OverflowTy, CostKind); - Cost += 2 * thisT()->getCmpSelInstrCost(BinaryOperator::ICmp, OverflowTy, - OverflowTy, CostKind); + Cost += 3 * thisT()->getCmpSelInstrCost( + Instruction::ICmp, SumTy, OverflowTy, + CmpInst::BAD_ICMP_PREDICATE, CostKind); + Cost += 2 * thisT()->getCmpSelInstrCost( + Instruction::Select, OverflowTy, OverflowTy, + CmpInst::BAD_ICMP_PREDICATE, CostKind); Cost += thisT()->getArithmeticInstrCost(BinaryOperator::And, OverflowTy, CostKind); return Cost; @@ -1529,8 +1705,9 @@ public: unsigned Cost = 0; Cost += thisT()->getArithmeticInstrCost(Opcode, SumTy, CostKind); - Cost += thisT()->getCmpSelInstrCost(BinaryOperator::ICmp, SumTy, - OverflowTy, CostKind); + Cost += + thisT()->getCmpSelInstrCost(BinaryOperator::ICmp, SumTy, OverflowTy, + CmpInst::BAD_ICMP_PREDICATE, CostKind); return Cost; } case Intrinsic::smul_with_overflow: @@ -1542,13 +1719,14 @@ public: unsigned ExtOp = IID == Intrinsic::smul_fix ? Instruction::SExt : Instruction::ZExt; + TTI::CastContextHint CCH = TTI::CastContextHint::None; unsigned Cost = 0; - Cost += 2 * thisT()->getCastInstrCost(ExtOp, ExtTy, MulTy, CostKind); + Cost += 2 * thisT()->getCastInstrCost(ExtOp, ExtTy, MulTy, CCH, CostKind); Cost += thisT()->getArithmeticInstrCost(Instruction::Mul, ExtTy, CostKind); Cost += 2 * thisT()->getCastInstrCost(Instruction::Trunc, MulTy, ExtTy, - CostKind); + CCH, CostKind); Cost += thisT()->getArithmeticInstrCost(Instruction::LShr, MulTy, CostKind, TTI::OK_AnyValue, TTI::OK_UniformConstantValue); @@ -1558,8 +1736,9 @@ public: CostKind, TTI::OK_AnyValue, TTI::OK_UniformConstantValue); - Cost += thisT()->getCmpSelInstrCost(BinaryOperator::ICmp, MulTy, - OverflowTy, CostKind); + Cost += + thisT()->getCmpSelInstrCost(BinaryOperator::ICmp, MulTy, OverflowTy, + CmpInst::BAD_ICMP_PREDICATE, CostKind); return Cost; } case Intrinsic::ctpop: @@ -1568,7 +1747,12 @@ public: // library call but still not a cheap instruction. SingleCallCost = TargetTransformInfo::TCC_Expensive; break; - // FIXME: ctlz, cttz, ... + case Intrinsic::ctlz: + ISDs.push_back(ISD::CTLZ); + break; + case Intrinsic::cttz: + ISDs.push_back(ISD::CTTZ); + break; case Intrinsic::bswap: ISDs.push_back(ISD::BSWAP); break; @@ -1604,7 +1788,7 @@ public: } } - auto MinLegalCostI = std::min_element(LegalCost.begin(), LegalCost.end()); + auto *MinLegalCostI = std::min_element(LegalCost.begin(), LegalCost.end()); if (MinLegalCostI != LegalCost.end()) return *MinLegalCostI; @@ -1801,9 +1985,10 @@ public: (IsPairwise + 1) * thisT()->getShuffleCost(TTI::SK_ExtractSubvector, Ty, NumVecElts, SubTy); MinMaxCost += - thisT()->getCmpSelInstrCost(CmpOpcode, SubTy, CondTy, CostKind) + + thisT()->getCmpSelInstrCost(CmpOpcode, SubTy, CondTy, + CmpInst::BAD_ICMP_PREDICATE, CostKind) + thisT()->getCmpSelInstrCost(Instruction::Select, SubTy, CondTy, - CostKind); + CmpInst::BAD_ICMP_PREDICATE, CostKind); Ty = SubTy; ++LongVectorCount; } @@ -1825,15 +2010,37 @@ public: thisT()->getShuffleCost(TTI::SK_PermuteSingleSrc, Ty, 0, Ty); MinMaxCost += NumReduxLevels * - (thisT()->getCmpSelInstrCost(CmpOpcode, Ty, CondTy, CostKind) + + (thisT()->getCmpSelInstrCost(CmpOpcode, Ty, CondTy, + CmpInst::BAD_ICMP_PREDICATE, CostKind) + thisT()->getCmpSelInstrCost(Instruction::Select, Ty, CondTy, - CostKind)); + CmpInst::BAD_ICMP_PREDICATE, CostKind)); // The last min/max should be in vector registers and we counted it above. // So just need a single extractelement. return ShuffleCost + MinMaxCost + thisT()->getVectorInstrCost(Instruction::ExtractElement, Ty, 0); } + InstructionCost getExtendedAddReductionCost(bool IsMLA, bool IsUnsigned, + Type *ResTy, VectorType *Ty, + TTI::TargetCostKind CostKind) { + // Without any native support, this is equivalent to the cost of + // vecreduce.add(ext) or if IsMLA vecreduce.add(mul(ext, ext)) + VectorType *ExtTy = VectorType::get(ResTy, Ty); + unsigned RedCost = thisT()->getArithmeticReductionCost( + Instruction::Add, ExtTy, false, CostKind); + unsigned MulCost = 0; + unsigned ExtCost = thisT()->getCastInstrCost( + IsUnsigned ? Instruction::ZExt : Instruction::SExt, ExtTy, Ty, + TTI::CastContextHint::None, CostKind); + if (IsMLA) { + MulCost = + thisT()->getArithmeticInstrCost(Instruction::Mul, ExtTy, CostKind); + ExtCost *= 2; + } + + return RedCost + MulCost + ExtCost; + } + unsigned getVectorSplitCost() { return 1; } /// @} diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/CalcSpillWeights.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/CalcSpillWeights.h index 9b8b7324f30a..78dae81f596e 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/CalcSpillWeights.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/CalcSpillWeights.h @@ -44,64 +44,60 @@ class VirtRegMap; /// Calculate auxiliary information for a virtual register such as its /// spill weight and allocation hint. class VirtRegAuxInfo { - public: - using NormalizingFn = float (*)(float, unsigned, unsigned); - - private: MachineFunction &MF; LiveIntervals &LIS; - VirtRegMap *VRM; + const VirtRegMap &VRM; const MachineLoopInfo &Loops; const MachineBlockFrequencyInfo &MBFI; - DenseMap Hint; - NormalizingFn normalize; public: - VirtRegAuxInfo(MachineFunction &mf, LiveIntervals &lis, - VirtRegMap *vrm, const MachineLoopInfo &loops, - const MachineBlockFrequencyInfo &mbfi, - NormalizingFn norm = normalizeSpillWeight) - : MF(mf), LIS(lis), VRM(vrm), Loops(loops), MBFI(mbfi), normalize(norm) {} + VirtRegAuxInfo(MachineFunction &MF, LiveIntervals &LIS, + const VirtRegMap &VRM, const MachineLoopInfo &Loops, + const MachineBlockFrequencyInfo &MBFI) + : MF(MF), LIS(LIS), VRM(VRM), Loops(Loops), MBFI(MBFI) {} + + virtual ~VirtRegAuxInfo() = default; /// (re)compute li's spill weight and allocation hint. - void calculateSpillWeightAndHint(LiveInterval &li); + void calculateSpillWeightAndHint(LiveInterval &LI); - /// Compute future expected spill weight of a split artifact of li + /// Compute future expected spill weight of a split artifact of LI /// that will span between start and end slot indexes. - /// \param li The live interval to be split. - /// \param start The expected begining of the split artifact. Instructions + /// \param LI The live interval to be split. + /// \param Start The expected beginning of the split artifact. Instructions /// before start will not affect the weight. - /// \param end The expected end of the split artifact. Instructions + /// \param End The expected end of the split artifact. Instructions /// after end will not affect the weight. /// \return The expected spill weight of the split artifact. Returns - /// negative weight for unspillable li. - float futureWeight(LiveInterval &li, SlotIndex start, SlotIndex end); + /// negative weight for unspillable LI. + float futureWeight(LiveInterval &LI, SlotIndex Start, SlotIndex End); + + /// Compute spill weights and allocation hints for all virtual register + /// live intervals. + void calculateSpillWeightsAndHints(); + protected: /// Helper function for weight calculations. - /// (Re)compute li's spill weight and allocation hint, or, for non null + /// (Re)compute LI's spill weight and allocation hint, or, for non null /// start and end - compute future expected spill weight of a split - /// artifact of li that will span between start and end slot indexes. - /// \param li The live interval for which to compute the weight. - /// \param start The expected begining of the split artifact. Instructions + /// artifact of LI that will span between start and end slot indexes. + /// \param LI The live interval for which to compute the weight. + /// \param Start The expected beginning of the split artifact. Instructions /// before start will not affect the weight. Relevant for /// weight calculation of future split artifact. - /// \param end The expected end of the split artifact. Instructions + /// \param End The expected end of the split artifact. Instructions /// after end will not affect the weight. Relevant for /// weight calculation of future split artifact. - /// \return The spill weight. Returns negative weight for unspillable li. - float weightCalcHelper(LiveInterval &li, SlotIndex *start = nullptr, - SlotIndex *end = nullptr); - }; - - /// Compute spill weights and allocation hints for all virtual register - /// live intervals. - void calculateSpillWeightsAndHints(LiveIntervals &LIS, MachineFunction &MF, - VirtRegMap *VRM, - const MachineLoopInfo &MLI, - const MachineBlockFrequencyInfo &MBFI, - VirtRegAuxInfo::NormalizingFn norm = - normalizeSpillWeight); + /// \return The spill weight. Returns negative weight for unspillable LI. + float weightCalcHelper(LiveInterval &LI, SlotIndex *Start = nullptr, + SlotIndex *End = nullptr); + /// Weight normalization function. + virtual float normalize(float UseDefFreq, unsigned Size, + unsigned NumInstr) { + return normalizeSpillWeight(UseDefFreq, Size, NumInstr); + } + }; } // end namespace llvm #endif // LLVM_CODEGEN_CALCSPILLWEIGHTS_H diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/CallingConvLower.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/CallingConvLower.h index 8ebe788ac360..2fe4e371263b 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/CallingConvLower.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/CallingConvLower.h @@ -16,7 +16,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/Register.h" #include "llvm/CodeGen/TargetCallingConv.h" #include "llvm/IR/CallingConv.h" #include "llvm/MC/MCRegisterInfo.h" @@ -25,6 +25,7 @@ namespace llvm { class CCState; +class MachineFunction; class MVT; class TargetRegisterInfo; @@ -339,6 +340,11 @@ public: return Regs.size(); } + void DeallocateReg(MCPhysReg Reg) { + assert(isAllocated(Reg) && "Trying to deallocate an unallocated register"); + MarkUnallocated(Reg); + } + /// AllocateReg - Attempt to allocate one register. If it is not available, /// return zero. Otherwise, return the register, marking it and any aliases /// as allocated. @@ -432,10 +438,7 @@ public: return AllocateStack(Size, Align(Alignment)); } - void ensureMaxAlignment(Align Alignment) { - if (!AnalyzingMustTailForwardedRegs) - MF.getFrameInfo().ensureMaxAlignment(Alignment); - } + void ensureMaxAlignment(Align Alignment); /// Version of AllocateStack with extra register to be shadowed. LLVM_ATTRIBUTE_DEPRECATED(unsigned AllocateStack(unsigned Size, @@ -572,6 +575,8 @@ public: private: /// MarkAllocated - Mark a register and all of its aliases as allocated. void MarkAllocated(MCPhysReg Reg); + + void MarkUnallocated(MCPhysReg Reg); }; } // end namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h new file mode 100644 index 000000000000..893bc6e013f4 --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h @@ -0,0 +1,1144 @@ +//===- Construction of codegen pass pipelines ------------------*- C++ -*--===// +// +// 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 +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// Interfaces for registering analysis passes, producing common pass manager +/// configurations, and parsing of pass pipelines. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_CODEGENPASSBUILDER_H +#define LLVM_CODEGEN_CODEGENPASSBUILDER_H + +#include "llvm/ADT/FunctionExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/BasicAliasAnalysis.h" +#include "llvm/Analysis/CFLAndersAliasAnalysis.h" +#include "llvm/Analysis/CFLSteensAliasAnalysis.h" +#include "llvm/Analysis/ScopedNoAliasAA.h" +#include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/Analysis/TypeBasedAliasAnalysis.h" +#include "llvm/CodeGen/ExpandReductions.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachinePassManager.h" +#include "llvm/CodeGen/PreISelIntrinsicLowering.h" +#include "llvm/CodeGen/UnreachableBlockElim.h" +#include "llvm/IR/IRPrintingPasses.h" +#include "llvm/IR/PassManager.h" +#include "llvm/IR/Verifier.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCTargetOptions.h" +#include "llvm/Support/CodeGen.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Target/CGPassBuilderOption.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Scalar/ConstantHoisting.h" +#include "llvm/Transforms/Scalar/LoopPassManager.h" +#include "llvm/Transforms/Scalar/LoopStrengthReduce.h" +#include "llvm/Transforms/Scalar/LowerConstantIntrinsics.h" +#include "llvm/Transforms/Scalar/MergeICmps.h" +#include "llvm/Transforms/Scalar/PartiallyInlineLibCalls.h" +#include "llvm/Transforms/Scalar/ScalarizeMaskedMemIntrin.h" +#include "llvm/Transforms/Utils.h" +#include "llvm/Transforms/Utils/EntryExitInstrumenter.h" +#include "llvm/Transforms/Utils/LowerInvoke.h" +#include +#include +#include +#include + +namespace llvm { + +// FIXME: Dummy target independent passes definitions that have not yet been +// ported to new pass manager. Once they do, remove these. +#define DUMMY_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) \ + struct PASS_NAME : public PassInfoMixin { \ + template PASS_NAME(Ts &&...) {} \ + PreservedAnalyses run(Function &, FunctionAnalysisManager &) { \ + return PreservedAnalyses::all(); \ + } \ + }; +#define DUMMY_MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR) \ + struct PASS_NAME : public PassInfoMixin { \ + template PASS_NAME(Ts &&...) {} \ + PreservedAnalyses run(Module &, ModuleAnalysisManager &) { \ + return PreservedAnalyses::all(); \ + } \ + }; +#define DUMMY_MACHINE_MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR) \ + struct PASS_NAME : public PassInfoMixin { \ + template PASS_NAME(Ts &&...) {} \ + Error run(Module &, MachineFunctionAnalysisManager &) { \ + return Error::success(); \ + } \ + PreservedAnalyses run(MachineFunction &, \ + MachineFunctionAnalysisManager &) { \ + llvm_unreachable("this api is to make new PM api happy"); \ + } \ + static AnalysisKey Key; \ + }; +#define DUMMY_MACHINE_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) \ + struct PASS_NAME : public PassInfoMixin { \ + template PASS_NAME(Ts &&...) {} \ + PreservedAnalyses run(MachineFunction &, \ + MachineFunctionAnalysisManager &) { \ + return PreservedAnalyses::all(); \ + } \ + static AnalysisKey Key; \ + }; +#include "MachinePassRegistry.def" + +/// This class provides access to building LLVM's passes. +/// +/// Its members provide the baseline state available to passes during their +/// construction. The \c MachinePassRegistry.def file specifies how to construct +/// all of the built-in passes, and those may reference these members during +/// construction. +template class CodeGenPassBuilder { +public: + explicit CodeGenPassBuilder(LLVMTargetMachine &TM, CGPassBuilderOption Opts, + PassInstrumentationCallbacks *PIC) + : TM(TM), Opt(Opts), PIC(PIC) { + // Target could set CGPassBuilderOption::MISchedPostRA to true to achieve + // substitutePass(&PostRASchedulerID, &PostMachineSchedulerID) + + // Target should override TM.Options.EnableIPRA in their target-specific + // LLVMTM ctor. See TargetMachine::setGlobalISel for example. + if (Opt.EnableIPRA) + TM.Options.EnableIPRA = *Opt.EnableIPRA; + + if (Opt.EnableGlobalISelAbort) + TM.Options.GlobalISelAbort = *Opt.EnableGlobalISelAbort; + + if (!Opt.OptimizeRegAlloc) + Opt.OptimizeRegAlloc = getOptLevel() != CodeGenOpt::None; + } + + Error buildPipeline(ModulePassManager &MPM, MachineFunctionPassManager &MFPM, + raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut, + CodeGenFileType FileType) const; + + void registerModuleAnalyses(ModuleAnalysisManager &) const; + void registerFunctionAnalyses(FunctionAnalysisManager &) const; + void registerMachineFunctionAnalyses(MachineFunctionAnalysisManager &) const; + std::pair getPassNameFromLegacyName(StringRef) const; + + void registerAnalyses(MachineFunctionAnalysisManager &MFAM) const { + registerModuleAnalyses(*MFAM.MAM); + registerFunctionAnalyses(*MFAM.FAM); + registerMachineFunctionAnalyses(MFAM); + } + + PassInstrumentationCallbacks *getPassInstrumentationCallbacks() const { + return PIC; + } + +protected: + template using has_key_t = decltype(PassT::Key); + + template + using is_module_pass_t = decltype(std::declval().run( + std::declval(), std::declval())); + + template + using is_function_pass_t = decltype(std::declval().run( + std::declval(), std::declval())); + + // Function object to maintain state while adding codegen IR passes. + class AddIRPass { + public: + AddIRPass(ModulePassManager &MPM, bool DebugPM, bool Check = true) + : MPM(MPM), FPM(DebugPM) { + if (Check) + AddingFunctionPasses = false; + } + ~AddIRPass() { + MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); + } + + // Add Function Pass + template + std::enable_if_t::value> + operator()(PassT &&Pass) { + if (AddingFunctionPasses && !*AddingFunctionPasses) + AddingFunctionPasses = true; + FPM.addPass(std::forward(Pass)); + } + + // Add Module Pass + template + std::enable_if_t::value && + !is_detected::value> + operator()(PassT &&Pass) { + assert((!AddingFunctionPasses || !*AddingFunctionPasses) && + "could not add module pass after adding function pass"); + MPM.addPass(std::forward(Pass)); + } + + private: + ModulePassManager &MPM; + FunctionPassManager FPM; + // The codegen IR pipeline are mostly function passes with the exceptions of + // a few loop and module passes. `AddingFunctionPasses` make sures that + // we could only add module passes at the beginning of the pipeline. Once + // we begin adding function passes, we could no longer add module passes. + // This special-casing introduces less adaptor passes. If we have the need + // of adding module passes after function passes, we could change the + // implementation to accommodate that. + Optional AddingFunctionPasses; + }; + + // Function object to maintain state while adding codegen machine passes. + class AddMachinePass { + public: + AddMachinePass(MachineFunctionPassManager &PM) : PM(PM) {} + + template void operator()(PassT &&Pass) { + static_assert( + is_detected::value, + "Machine function pass must define a static member variable `Key`."); + for (auto &C : BeforeCallbacks) + if (!C(&PassT::Key)) + return; + PM.addPass(std::forward(Pass)); + for (auto &C : AfterCallbacks) + C(&PassT::Key); + } + + template void insertPass(AnalysisKey *ID, PassT Pass) { + AfterCallbacks.emplace_back( + [this, ID, Pass = std::move(Pass)](AnalysisKey *PassID) { + if (PassID == ID) + this->PM.addPass(std::move(Pass)); + }); + } + + void disablePass(AnalysisKey *ID) { + BeforeCallbacks.emplace_back( + [ID](AnalysisKey *PassID) { return PassID != ID; }); + } + + MachineFunctionPassManager releasePM() { return std::move(PM); } + + private: + MachineFunctionPassManager &PM; + SmallVector, 4> BeforeCallbacks; + SmallVector, 4> AfterCallbacks; + }; + + LLVMTargetMachine &TM; + CGPassBuilderOption Opt; + PassInstrumentationCallbacks *PIC; + + /// Target override these hooks to parse target-specific analyses. + void registerTargetAnalysis(ModuleAnalysisManager &) const {} + void registerTargetAnalysis(FunctionAnalysisManager &) const {} + void registerTargetAnalysis(MachineFunctionAnalysisManager &) const {} + std::pair getTargetPassNameFromLegacyName(StringRef) const { + return {"", false}; + } + + template TMC &getTM() const { return static_cast(TM); } + CodeGenOpt::Level getOptLevel() const { return TM.getOptLevel(); } + + /// Check whether or not GlobalISel should abort on error. + /// When this is disabled, GlobalISel will fall back on SDISel instead of + /// erroring out. + bool isGlobalISelAbortEnabled() const { + return TM.Options.GlobalISelAbort == GlobalISelAbortMode::Enable; + } + + /// Check whether or not a diagnostic should be emitted when GlobalISel + /// uses the fallback path. In other words, it will emit a diagnostic + /// when GlobalISel failed and isGlobalISelAbortEnabled is false. + bool reportDiagnosticWhenGlobalISelFallback() const { + return TM.Options.GlobalISelAbort == GlobalISelAbortMode::DisableWithDiag; + } + + /// addInstSelector - This method should install an instruction selector pass, + /// which converts from LLVM code to machine instructions. + Error addInstSelector(AddMachinePass &) const { + return make_error("addInstSelector is not overridden", + inconvertibleErrorCode()); + } + + /// Add passes that optimize instruction level parallelism for out-of-order + /// targets. These passes are run while the machine code is still in SSA + /// form, so they can use MachineTraceMetrics to control their heuristics. + /// + /// All passes added here should preserve the MachineDominatorTree, + /// MachineLoopInfo, and MachineTraceMetrics analyses. + void addILPOpts(AddMachinePass &) const {} + + /// This method may be implemented by targets that want to run passes + /// immediately before register allocation. + void addPreRegAlloc(AddMachinePass &) const {} + + /// addPreRewrite - Add passes to the optimized register allocation pipeline + /// after register allocation is complete, but before virtual registers are + /// rewritten to physical registers. + /// + /// These passes must preserve VirtRegMap and LiveIntervals, and when running + /// after RABasic or RAGreedy, they should take advantage of LiveRegMatrix. + /// When these passes run, VirtRegMap contains legal physreg assignments for + /// all virtual registers. + /// + /// Note if the target overloads addRegAssignAndRewriteOptimized, this may not + /// be honored. This is also not generally used for the the fast variant, + /// where the allocation and rewriting are done in one pass. + void addPreRewrite(AddMachinePass &) const {} + + /// Add passes to be run immediately after virtual registers are rewritten + /// to physical registers. + void addPostRewrite(AddMachinePass &) const {} + + /// This method may be implemented by targets that want to run passes after + /// register allocation pass pipeline but before prolog-epilog insertion. + void addPostRegAlloc(AddMachinePass &) const {} + + /// This method may be implemented by targets that want to run passes after + /// prolog-epilog insertion and before the second instruction scheduling pass. + void addPreSched2(AddMachinePass &) const {} + + /// This pass may be implemented by targets that want to run passes + /// immediately before machine code is emitted. + void addPreEmitPass(AddMachinePass &) const {} + + /// Targets may add passes immediately before machine code is emitted in this + /// callback. This is called even later than `addPreEmitPass`. + // FIXME: Rename `addPreEmitPass` to something more sensible given its actual + // position and remove the `2` suffix here as this callback is what + // `addPreEmitPass` *should* be but in reality isn't. + void addPreEmitPass2(AddMachinePass &) const {} + + /// {{@ For GlobalISel + /// + + /// addPreISel - This method should add any "last minute" LLVM->LLVM + /// passes (which are run just before instruction selector). + void addPreISel(AddIRPass &) const { + llvm_unreachable("addPreISel is not overridden"); + } + + /// This method should install an IR translator pass, which converts from + /// LLVM code to machine instructions with possibly generic opcodes. + Error addIRTranslator(AddMachinePass &) const { + return make_error("addIRTranslator is not overridden", + inconvertibleErrorCode()); + } + + /// This method may be implemented by targets that want to run passes + /// immediately before legalization. + void addPreLegalizeMachineIR(AddMachinePass &) const {} + + /// This method should install a legalize pass, which converts the instruction + /// sequence into one that can be selected by the target. + Error addLegalizeMachineIR(AddMachinePass &) const { + return make_error("addLegalizeMachineIR is not overridden", + inconvertibleErrorCode()); + } + + /// This method may be implemented by targets that want to run passes + /// immediately before the register bank selection. + void addPreRegBankSelect(AddMachinePass &) const {} + + /// This method should install a register bank selector pass, which + /// assigns register banks to virtual registers without a register + /// class or register banks. + Error addRegBankSelect(AddMachinePass &) const { + return make_error("addRegBankSelect is not overridden", + inconvertibleErrorCode()); + } + + /// This method may be implemented by targets that want to run passes + /// immediately before the (global) instruction selection. + void addPreGlobalInstructionSelect(AddMachinePass &) const {} + + /// This method should install a (global) instruction selector pass, which + /// converts possibly generic instructions to fully target-specific + /// instructions, thereby constraining all generic virtual registers to + /// register classes. + Error addGlobalInstructionSelect(AddMachinePass &) const { + return make_error( + "addGlobalInstructionSelect is not overridden", + inconvertibleErrorCode()); + } + /// @}} + + /// High level function that adds all passes necessary to go from llvm IR + /// representation to the MI representation. + /// Adds IR based lowering and target specific optimization passes and finally + /// the core instruction selection passes. + /// \returns true if an error occurred, false otherwise. + void addISelPasses(AddIRPass &) const; + + /// Add the actual instruction selection passes. This does not include + /// preparation passes on IR. + Error addCoreISelPasses(AddMachinePass &) const; + + /// Add the complete, standard set of LLVM CodeGen passes. + /// Fully developed targets will not generally override this. + Error addMachinePasses(AddMachinePass &) const; + + /// Add passes to lower exception handling for the code generator. + void addPassesToHandleExceptions(AddIRPass &) const; + + /// Add common target configurable passes that perform LLVM IR to IR + /// transforms following machine independent optimization. + void addIRPasses(AddIRPass &) const; + + /// Add pass to prepare the LLVM IR for code generation. This should be done + /// before exception handling preparation passes. + void addCodeGenPrepare(AddIRPass &) const; + + /// Add common passes that perform LLVM IR to IR transforms in preparation for + /// instruction selection. + void addISelPrepare(AddIRPass &) const; + + /// Methods with trivial inline returns are convenient points in the common + /// codegen pass pipeline where targets may insert passes. Methods with + /// out-of-line standard implementations are major CodeGen stages called by + /// addMachinePasses. Some targets may override major stages when inserting + /// passes is insufficient, but maintaining overriden stages is more work. + /// + + /// addMachineSSAOptimization - Add standard passes that optimize machine + /// instructions in SSA form. + void addMachineSSAOptimization(AddMachinePass &) const; + + /// addFastRegAlloc - Add the minimum set of target-independent passes that + /// are required for fast register allocation. + Error addFastRegAlloc(AddMachinePass &) const; + + /// addOptimizedRegAlloc - Add passes related to register allocation. + /// LLVMTargetMachine provides standard regalloc passes for most targets. + void addOptimizedRegAlloc(AddMachinePass &) const; + + /// Add passes that optimize machine instructions after register allocation. + void addMachineLateOptimization(AddMachinePass &) const; + + /// addGCPasses - Add late codegen passes that analyze code for garbage + /// collection. This should return true if GC info should be printed after + /// these passes. + void addGCPasses(AddMachinePass &) const {} + + /// Add standard basic block placement passes. + void addBlockPlacement(AddMachinePass &) const; + + using CreateMCStreamer = + std::function>(MCContext &)>; + void addAsmPrinter(AddMachinePass &, CreateMCStreamer) const { + llvm_unreachable("addAsmPrinter is not overridden"); + } + + /// Utilities for targets to add passes to the pass manager. + /// + + /// createTargetRegisterAllocator - Create the register allocator pass for + /// this target at the current optimization level. + void addTargetRegisterAllocator(AddMachinePass &, bool Optimized) const; + + /// addMachinePasses helper to create the target-selected or overriden + /// regalloc pass. + void addRegAllocPass(AddMachinePass &, bool Optimized) const; + + /// Add core register alloator passes which do the actual register assignment + /// and rewriting. \returns true if any passes were added. + Error addRegAssignmentFast(AddMachinePass &) const; + Error addRegAssignmentOptimized(AddMachinePass &) const; + +private: + DerivedT &derived() { return static_cast(*this); } + const DerivedT &derived() const { + return static_cast(*this); + } +}; + +template +Error CodeGenPassBuilder::buildPipeline( + ModulePassManager &MPM, MachineFunctionPassManager &MFPM, + raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut, + CodeGenFileType FileType) const { + AddIRPass addIRPass(MPM, Opt.DebugPM); + addISelPasses(addIRPass); + + AddMachinePass addPass(MFPM); + if (auto Err = addCoreISelPasses(addPass)) + return std::move(Err); + + if (auto Err = derived().addMachinePasses(addPass)) + return std::move(Err); + + derived().addAsmPrinter( + addPass, [this, &Out, DwoOut, FileType](MCContext &Ctx) { + return this->TM.createMCStreamer(Out, DwoOut, FileType, Ctx); + }); + + addPass(FreeMachineFunctionPass()); + return Error::success(); +} + +static inline AAManager registerAAAnalyses(CFLAAType UseCFLAA) { + AAManager AA; + + // The order in which these are registered determines their priority when + // being queried. + + switch (UseCFLAA) { + case CFLAAType::Steensgaard: + AA.registerFunctionAnalysis(); + break; + case CFLAAType::Andersen: + AA.registerFunctionAnalysis(); + break; + case CFLAAType::Both: + AA.registerFunctionAnalysis(); + AA.registerFunctionAnalysis(); + break; + default: + break; + } + + // Basic AliasAnalysis support. + // Add TypeBasedAliasAnalysis before BasicAliasAnalysis so that + // BasicAliasAnalysis wins if they disagree. This is intended to help + // support "obvious" type-punning idioms. + AA.registerFunctionAnalysis(); + AA.registerFunctionAnalysis(); + AA.registerFunctionAnalysis(); + + return AA; +} + +template +void CodeGenPassBuilder::registerModuleAnalyses( + ModuleAnalysisManager &MAM) const { +#define MODULE_ANALYSIS(NAME, PASS_NAME, CONSTRUCTOR) \ + MAM.registerPass([&] { return PASS_NAME CONSTRUCTOR; }); +#include "MachinePassRegistry.def" + derived().registerTargetAnalysis(MAM); +} + +template +void CodeGenPassBuilder::registerFunctionAnalyses( + FunctionAnalysisManager &FAM) const { + FAM.registerPass([this] { return registerAAAnalyses(this->Opt.UseCFLAA); }); + +#define FUNCTION_ANALYSIS(NAME, PASS_NAME, CONSTRUCTOR) \ + FAM.registerPass([&] { return PASS_NAME CONSTRUCTOR; }); +#include "MachinePassRegistry.def" + derived().registerTargetAnalysis(FAM); +} + +template +void CodeGenPassBuilder::registerMachineFunctionAnalyses( + MachineFunctionAnalysisManager &MFAM) const { +#define MACHINE_FUNCTION_ANALYSIS(NAME, PASS_NAME, CONSTRUCTOR) \ + MFAM.registerPass([&] { return PASS_NAME CONSTRUCTOR; }); +#include "MachinePassRegistry.def" + derived().registerTargetAnalysis(MFAM); +} + +// FIXME: For new PM, use pass name directly in commandline seems good. +// Translate stringfied pass name to its old commandline name. Returns the +// matching legacy name and a boolean value indicating if the pass is a machine +// pass. +template +std::pair +CodeGenPassBuilder::getPassNameFromLegacyName(StringRef Name) const { + std::pair Ret; + if (Name.empty()) + return Ret; + +#define FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) \ + if (Name == NAME) \ + Ret = {#PASS_NAME, false}; +#define DUMMY_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) \ + if (Name == NAME) \ + Ret = {#PASS_NAME, false}; +#define MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR) \ + if (Name == NAME) \ + Ret = {#PASS_NAME, false}; +#define DUMMY_MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR) \ + if (Name == NAME) \ + Ret = {#PASS_NAME, false}; +#define MACHINE_MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR) \ + if (Name == NAME) \ + Ret = {#PASS_NAME, true}; +#define DUMMY_MACHINE_MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR) \ + if (Name == NAME) \ + Ret = {#PASS_NAME, true}; +#define MACHINE_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) \ + if (Name == NAME) \ + Ret = {#PASS_NAME, true}; +#define DUMMY_MACHINE_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) \ + if (Name == NAME) \ + Ret = {#PASS_NAME, true}; +#include "llvm/CodeGen/MachinePassRegistry.def" + + if (Ret.first.empty()) + Ret = derived().getTargetPassNameFromLegacyName(Name); + + if (Ret.first.empty()) + report_fatal_error(Twine('\"') + Twine(Name) + + Twine("\" pass could not be found.")); + + return Ret; +} + +template +void CodeGenPassBuilder::addISelPasses(AddIRPass &addPass) const { + if (TM.useEmulatedTLS()) + addPass(LowerEmuTLSPass()); + + addPass(PreISelIntrinsicLoweringPass()); + + derived().addIRPasses(addPass); + derived().addCodeGenPrepare(addPass); + addPassesToHandleExceptions(addPass); + derived().addISelPrepare(addPass); +} + +/// Add common target configurable passes that perform LLVM IR to IR transforms +/// following machine independent optimization. +template +void CodeGenPassBuilder::addIRPasses(AddIRPass &addPass) const { + // Before running any passes, run the verifier to determine if the input + // coming from the front-end and/or optimizer is valid. + if (!Opt.DisableVerify) + addPass(VerifierPass()); + + // Run loop strength reduction before anything else. + if (getOptLevel() != CodeGenOpt::None && !Opt.DisableLSR) { + addPass(createFunctionToLoopPassAdaptor( + LoopStrengthReducePass(), /*UseMemorySSA*/ true, Opt.DebugPM)); + // FIXME: use -stop-after so we could remove PrintLSR + if (Opt.PrintLSR) + addPass(PrintFunctionPass(dbgs(), "\n\n*** Code after LSR ***\n")); + } + + if (getOptLevel() != CodeGenOpt::None) { + // The MergeICmpsPass tries to create memcmp calls by grouping sequences of + // loads and compares. ExpandMemCmpPass then tries to expand those calls + // into optimally-sized loads and compares. The transforms are enabled by a + // target lowering hook. + if (!Opt.DisableMergeICmps) + addPass(MergeICmpsPass()); + addPass(ExpandMemCmpPass()); + } + + // Run GC lowering passes for builtin collectors + // TODO: add a pass insertion point here + addPass(GCLoweringPass()); + addPass(ShadowStackGCLoweringPass()); + addPass(LowerConstantIntrinsicsPass()); + + // Make sure that no unreachable blocks are instruction selected. + addPass(UnreachableBlockElimPass()); + + // Prepare expensive constants for SelectionDAG. + if (getOptLevel() != CodeGenOpt::None && !Opt.DisableConstantHoisting) + addPass(ConstantHoistingPass()); + + if (getOptLevel() != CodeGenOpt::None && !Opt.DisablePartialLibcallInlining) + addPass(PartiallyInlineLibCallsPass()); + + // Instrument function entry and exit, e.g. with calls to mcount(). + addPass(EntryExitInstrumenterPass(/*PostInlining=*/true)); + + // Add scalarization of target's unsupported masked memory intrinsics pass. + // the unsupported intrinsic will be replaced with a chain of basic blocks, + // that stores/loads element one-by-one if the appropriate mask bit is set. + addPass(ScalarizeMaskedMemIntrinPass()); + + // Expand reduction intrinsics into shuffle sequences if the target wants to. + addPass(ExpandReductionsPass()); +} + +/// Turn exception handling constructs into something the code generators can +/// handle. +template +void CodeGenPassBuilder::addPassesToHandleExceptions( + AddIRPass &addPass) const { + const MCAsmInfo *MCAI = TM.getMCAsmInfo(); + assert(MCAI && "No MCAsmInfo"); + switch (MCAI->getExceptionHandlingType()) { + case ExceptionHandling::SjLj: + // SjLj piggy-backs on dwarf for this bit. The cleanups done apply to both + // Dwarf EH prepare needs to be run after SjLj prepare. Otherwise, + // catch info can get misplaced when a selector ends up more than one block + // removed from the parent invoke(s). This could happen when a landing + // pad is shared by multiple invokes and is also a target of a normal + // edge from elsewhere. + addPass(SjLjEHPreparePass()); + LLVM_FALLTHROUGH; + case ExceptionHandling::DwarfCFI: + case ExceptionHandling::ARM: + case ExceptionHandling::AIX: + addPass(DwarfEHPass(getOptLevel())); + break; + case ExceptionHandling::WinEH: + // We support using both GCC-style and MSVC-style exceptions on Windows, so + // add both preparation passes. Each pass will only actually run if it + // recognizes the personality function. + addPass(WinEHPass()); + addPass(DwarfEHPass(getOptLevel())); + break; + case ExceptionHandling::Wasm: + // Wasm EH uses Windows EH instructions, but it does not need to demote PHIs + // on catchpads and cleanuppads because it does not outline them into + // funclets. Catchswitch blocks are not lowered in SelectionDAG, so we + // should remove PHIs there. + addPass(WinEHPass(/*DemoteCatchSwitchPHIOnly=*/false)); + addPass(WasmEHPass()); + break; + case ExceptionHandling::None: + addPass(LowerInvokePass()); + + // The lower invoke pass may create unreachable code. Remove it. + addPass(UnreachableBlockElimPass()); + break; + } +} + +/// Add pass to prepare the LLVM IR for code generation. This should be done +/// before exception handling preparation passes. +template +void CodeGenPassBuilder::addCodeGenPrepare(AddIRPass &addPass) const { + if (getOptLevel() != CodeGenOpt::None && !Opt.DisableCGP) + addPass(CodeGenPreparePass()); + // TODO: Default ctor'd RewriteSymbolPass is no-op. + // addPass(RewriteSymbolPass()); +} + +/// Add common passes that perform LLVM IR to IR transforms in preparation for +/// instruction selection. +template +void CodeGenPassBuilder::addISelPrepare(AddIRPass &addPass) const { + derived().addPreISel(addPass); + + // Add both the safe stack and the stack protection passes: each of them will + // only protect functions that have corresponding attributes. + addPass(SafeStackPass()); + addPass(StackProtectorPass()); + + if (Opt.PrintISelInput) + addPass(PrintFunctionPass(dbgs(), + "\n\n*** Final LLVM Code input to ISel ***\n")); + + // All passes which modify the LLVM IR are now complete; run the verifier + // to ensure that the IR is valid. + if (!Opt.DisableVerify) + addPass(VerifierPass()); +} + +template +Error CodeGenPassBuilder::addCoreISelPasses( + AddMachinePass &addPass) const { + // Enable FastISel with -fast-isel, but allow that to be overridden. + TM.setO0WantsFastISel(Opt.EnableFastISelOption.getValueOr(true)); + + // Determine an instruction selector. + enum class SelectorType { SelectionDAG, FastISel, GlobalISel }; + SelectorType Selector; + + if (Opt.EnableFastISelOption && *Opt.EnableFastISelOption == true) + Selector = SelectorType::FastISel; + else if ((Opt.EnableGlobalISelOption && + *Opt.EnableGlobalISelOption == true) || + (TM.Options.EnableGlobalISel && + (!Opt.EnableGlobalISelOption || + *Opt.EnableGlobalISelOption == false))) + Selector = SelectorType::GlobalISel; + else if (TM.getOptLevel() == CodeGenOpt::None && TM.getO0WantsFastISel()) + Selector = SelectorType::FastISel; + else + Selector = SelectorType::SelectionDAG; + + // Set consistently TM.Options.EnableFastISel and EnableGlobalISel. + if (Selector == SelectorType::FastISel) { + TM.setFastISel(true); + TM.setGlobalISel(false); + } else if (Selector == SelectorType::GlobalISel) { + TM.setFastISel(false); + TM.setGlobalISel(true); + } + + // Add instruction selector passes. + if (Selector == SelectorType::GlobalISel) { + if (auto Err = derived().addIRTranslator(addPass)) + return std::move(Err); + + derived().addPreLegalizeMachineIR(addPass); + + if (auto Err = derived().addLegalizeMachineIR(addPass)) + return std::move(Err); + + // Before running the register bank selector, ask the target if it + // wants to run some passes. + derived().addPreRegBankSelect(addPass); + + if (auto Err = derived().addRegBankSelect(addPass)) + return std::move(Err); + + derived().addPreGlobalInstructionSelect(addPass); + + if (auto Err = derived().addGlobalInstructionSelect(addPass)) + return std::move(Err); + + // Pass to reset the MachineFunction if the ISel failed. + addPass(ResetMachineFunctionPass(reportDiagnosticWhenGlobalISelFallback(), + isGlobalISelAbortEnabled())); + + // Provide a fallback path when we do not want to abort on + // not-yet-supported input. + if (!isGlobalISelAbortEnabled()) + if (auto Err = derived().addInstSelector(addPass)) + return std::move(Err); + + } else if (auto Err = derived().addInstSelector(addPass)) + return std::move(Err); + + // Expand pseudo-instructions emitted by ISel. Don't run the verifier before + // FinalizeISel. + addPass(FinalizeISelPass()); + + // // Print the instruction selected machine code... + // printAndVerify("After Instruction Selection"); + + return Error::success(); +} + +/// Add the complete set of target-independent postISel code generator passes. +/// +/// This can be read as the standard order of major LLVM CodeGen stages. Stages +/// with nontrivial configuration or multiple passes are broken out below in +/// add%Stage routines. +/// +/// Any CodeGenPassBuilder::addXX routine may be overriden by the +/// Target. The addPre/Post methods with empty header implementations allow +/// injecting target-specific fixups just before or after major stages. +/// Additionally, targets have the flexibility to change pass order within a +/// stage by overriding default implementation of add%Stage routines below. Each +/// technique has maintainability tradeoffs because alternate pass orders are +/// not well supported. addPre/Post works better if the target pass is easily +/// tied to a common pass. But if it has subtle dependencies on multiple passes, +/// the target should override the stage instead. +template +Error CodeGenPassBuilder::addMachinePasses( + AddMachinePass &addPass) const { + // Add passes that optimize machine instructions in SSA form. + if (getOptLevel() != CodeGenOpt::None) { + derived().addMachineSSAOptimization(addPass); + } else { + // If the target requests it, assign local variables to stack slots relative + // to one another and simplify frame index references where possible. + addPass(LocalStackSlotPass()); + } + + if (TM.Options.EnableIPRA) + addPass(RegUsageInfoPropagationPass()); + + // Run pre-ra passes. + derived().addPreRegAlloc(addPass); + + // Run register allocation and passes that are tightly coupled with it, + // including phi elimination and scheduling. + if (*Opt.OptimizeRegAlloc) { + derived().addOptimizedRegAlloc(addPass); + } else { + if (auto Err = derived().addFastRegAlloc(addPass)) + return Err; + } + + // Run post-ra passes. + derived().addPostRegAlloc(addPass); + + // Insert prolog/epilog code. Eliminate abstract frame index references... + if (getOptLevel() != CodeGenOpt::None) { + addPass(PostRAMachineSinkingPass()); + addPass(ShrinkWrapPass()); + } + + addPass(PrologEpilogInserterPass()); + + /// Add passes that optimize machine instructions after register allocation. + if (getOptLevel() != CodeGenOpt::None) + derived().addMachineLateOptimization(addPass); + + // Expand pseudo instructions before second scheduling pass. + addPass(ExpandPostRAPseudosPass()); + + // Run pre-sched2 passes. + derived().addPreSched2(addPass); + + if (Opt.EnableImplicitNullChecks) + addPass(ImplicitNullChecksPass()); + + // Second pass scheduler. + // Let Target optionally insert this pass by itself at some other + // point. + if (getOptLevel() != CodeGenOpt::None && + !TM.targetSchedulesPostRAScheduling()) { + if (Opt.MISchedPostRA) + addPass(PostMachineSchedulerPass()); + else + addPass(PostRASchedulerPass()); + } + + // GC + derived().addGCPasses(addPass); + + // Basic block placement. + if (getOptLevel() != CodeGenOpt::None) + derived().addBlockPlacement(addPass); + + // Insert before XRay Instrumentation. + addPass(FEntryInserterPass()); + + addPass(XRayInstrumentationPass()); + addPass(PatchableFunctionPass()); + + derived().addPreEmitPass(addPass); + + if (TM.Options.EnableIPRA) + // Collect register usage information and produce a register mask of + // clobbered registers, to be used to optimize call sites. + addPass(RegUsageInfoCollectorPass()); + + addPass(FuncletLayoutPass()); + + addPass(StackMapLivenessPass()); + addPass(LiveDebugValuesPass()); + + if (TM.Options.EnableMachineOutliner && getOptLevel() != CodeGenOpt::None && + Opt.EnableMachineOutliner != RunOutliner::NeverOutline) { + bool RunOnAllFunctions = + (Opt.EnableMachineOutliner == RunOutliner::AlwaysOutline); + bool AddOutliner = RunOnAllFunctions || TM.Options.SupportsDefaultOutlining; + if (AddOutliner) + addPass(MachineOutlinerPass(RunOnAllFunctions)); + } + + // Add passes that directly emit MI after all other MI passes. + derived().addPreEmitPass2(addPass); + + return Error::success(); +} + +/// Add passes that optimize machine instructions in SSA form. +template +void CodeGenPassBuilder::addMachineSSAOptimization( + AddMachinePass &addPass) const { + // Pre-ra tail duplication. + addPass(EarlyTailDuplicatePass()); + + // Optimize PHIs before DCE: removing dead PHI cycles may make more + // instructions dead. + addPass(OptimizePHIsPass()); + + // This pass merges large allocas. StackSlotColoring is a different pass + // which merges spill slots. + addPass(StackColoringPass()); + + // If the target requests it, assign local variables to stack slots relative + // to one another and simplify frame index references where possible. + addPass(LocalStackSlotPass()); + + // With optimization, dead code should already be eliminated. However + // there is one known exception: lowered code for arguments that are only + // used by tail calls, where the tail calls reuse the incoming stack + // arguments directly (see t11 in test/CodeGen/X86/sibcall.ll). + addPass(DeadMachineInstructionElimPass()); + + // Allow targets to insert passes that improve instruction level parallelism, + // like if-conversion. Such passes will typically need dominator trees and + // loop info, just like LICM and CSE below. + derived().addILPOpts(addPass); + + addPass(EarlyMachineLICMPass()); + addPass(MachineCSEPass()); + + addPass(MachineSinkingPass()); + + addPass(PeepholeOptimizerPass()); + // Clean-up the dead code that may have been generated by peephole + // rewriting. + addPass(DeadMachineInstructionElimPass()); +} + +//===---------------------------------------------------------------------===// +/// Register Allocation Pass Configuration +//===---------------------------------------------------------------------===// + +/// Instantiate the default register allocator pass for this target for either +/// the optimized or unoptimized allocation path. This will be added to the pass +/// manager by addFastRegAlloc in the unoptimized case or addOptimizedRegAlloc +/// in the optimized case. +/// +/// A target that uses the standard regalloc pass order for fast or optimized +/// allocation may still override this for per-target regalloc +/// selection. But -regalloc=... always takes precedence. +template +void CodeGenPassBuilder::addTargetRegisterAllocator( + AddMachinePass &addPass, bool Optimized) const { + if (Optimized) + addPass(RAGreedyPass()); + else + addPass(RAFastPass()); +} + +/// Find and instantiate the register allocation pass requested by this target +/// at the current optimization level. Different register allocators are +/// defined as separate passes because they may require different analysis. +template +void CodeGenPassBuilder::addRegAllocPass(AddMachinePass &addPass, + bool Optimized) const { + if (Opt.RegAlloc == RegAllocType::Default) + // With no -regalloc= override, ask the target for a regalloc pass. + derived().addTargetRegisterAllocator(addPass, Optimized); + else if (Opt.RegAlloc == RegAllocType::Basic) + addPass(RABasicPass()); + else if (Opt.RegAlloc == RegAllocType::Fast) + addPass(RAFastPass()); + else if (Opt.RegAlloc == RegAllocType::Greedy) + addPass(RAGreedyPass()); + else if (Opt.RegAlloc == RegAllocType::PBQP) + addPass(RAPBQPPass()); + else + llvm_unreachable("unknonwn register allocator type"); +} + +template +Error CodeGenPassBuilder::addRegAssignmentFast( + AddMachinePass &addPass) const { + if (Opt.RegAlloc != RegAllocType::Default && + Opt.RegAlloc != RegAllocType::Fast) + return make_error( + "Must use fast (default) register allocator for unoptimized regalloc.", + inconvertibleErrorCode()); + + addRegAllocPass(addPass, false); + return Error::success(); +} + +template +Error CodeGenPassBuilder::addRegAssignmentOptimized( + AddMachinePass &addPass) const { + // Add the selected register allocation pass. + addRegAllocPass(addPass, true); + + // Allow targets to change the register assignments before rewriting. + derived().addPreRewrite(addPass); + + // Finally rewrite virtual registers. + addPass(VirtRegRewriterPass()); + // Perform stack slot coloring and post-ra machine LICM. + // + // FIXME: Re-enable coloring with register when it's capable of adding + // kill markers. + addPass(StackSlotColoringPass()); + + return Error::success(); +} + +/// Add the minimum set of target-independent passes that are required for +/// register allocation. No coalescing or scheduling. +template +Error CodeGenPassBuilder::addFastRegAlloc( + AddMachinePass &addPass) const { + addPass(PHIEliminationPass()); + addPass(TwoAddressInstructionPass()); + return derived().addRegAssignmentFast(addPass); +} + +/// Add standard target-independent passes that are tightly coupled with +/// optimized register allocation, including coalescing, machine instruction +/// scheduling, and register allocation itself. +template +void CodeGenPassBuilder::addOptimizedRegAlloc( + AddMachinePass &addPass) const { + addPass(DetectDeadLanesPass()); + + addPass(ProcessImplicitDefsPass()); + + // Edge splitting is smarter with machine loop info. + addPass(PHIEliminationPass()); + + // Eventually, we want to run LiveIntervals before PHI elimination. + if (Opt.EarlyLiveIntervals) + addPass(LiveIntervalsPass()); + + addPass(TwoAddressInstructionPass()); + addPass(RegisterCoalescerPass()); + + // The machine scheduler may accidentally create disconnected components + // when moving subregister definitions around, avoid this by splitting them to + // separate vregs before. Splitting can also improve reg. allocation quality. + addPass(RenameIndependentSubregsPass()); + + // PreRA instruction scheduling. + addPass(MachineSchedulerPass()); + + if (derived().addRegAssignmentOptimized(addPass)) { + // Allow targets to expand pseudo instructions depending on the choice of + // registers before MachineCopyPropagation. + derived().addPostRewrite(addPass); + + // Copy propagate to forward register uses and try to eliminate COPYs that + // were not coalesced. + addPass(MachineCopyPropagationPass()); + + // Run post-ra machine LICM to hoist reloads / remats. + // + // FIXME: can this move into MachineLateOptimization? + addPass(MachineLICMPass()); + } +} + +//===---------------------------------------------------------------------===// +/// Post RegAlloc Pass Configuration +//===---------------------------------------------------------------------===// + +/// Add passes that optimize machine instructions after register allocation. +template +void CodeGenPassBuilder::addMachineLateOptimization( + AddMachinePass &addPass) const { + // Branch folding must be run after regalloc and prolog/epilog insertion. + addPass(BranchFolderPass()); + + // Tail duplication. + // Note that duplicating tail just increases code size and degrades + // performance for targets that require Structured Control Flow. + // In addition it can also make CFG irreducible. Thus we disable it. + if (!TM.requiresStructuredCFG()) + addPass(TailDuplicatePass()); + + // Copy propagation. + addPass(MachineCopyPropagationPass()); +} + +/// Add standard basic block placement passes. +template +void CodeGenPassBuilder::addBlockPlacement( + AddMachinePass &addPass) const { + addPass(MachineBlockPlacementPass()); + // Run a separate pass to collect block placement statistics. + if (Opt.EnableBlockPlacementStats) + addPass(MachineBlockPlacementStatsPass()); +} + +} // namespace llvm + +#endif // LLVM_CODEGEN_CODEGENPASSBUILDER_H diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/CommandFlags.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/CommandFlags.h index 1b77556dcbb1..e6c64cd4dd8e 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/CommandFlags.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/CommandFlags.h @@ -14,6 +14,7 @@ #include "llvm/ADT/FloatingPointMode.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Triple.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Intrinsics.h" #include "llvm/MC/MCTargetOptionsCommandFlags.h" @@ -74,6 +75,8 @@ bool getDontPlaceZerosInBSS(); bool getEnableGuaranteedTailCallOpt(); +bool getEnableAIXExtendedAltivecABI(); + bool getDisableTailCalls(); bool getStackSymbolOrdering(); @@ -94,8 +97,16 @@ Optional getExplicitDataSections(); bool getFunctionSections(); Optional getExplicitFunctionSections(); +bool getIgnoreXCOFFVisibility(); + +bool getXCOFFTracebackTable(); + std::string getBBSections(); +std::string getStackProtectorGuard(); +unsigned getStackProtectorGuardOffset(); +std::string getStackProtectorGuardReg(); + unsigned getTLSSize(); bool getEmulatedTLS(); @@ -114,8 +125,14 @@ bool getEnableAddrsig(); bool getEmitCallSiteInfo(); +bool getEnableMachineFunctionSplitter(); + bool getEnableDebugEntryValues(); +bool getPseudoProbeForProfiling(); + +bool getValueTrackingVariableLocations(); + bool getForceDwarfFrameSection(); bool getXRayOmitFunctionIndex(); @@ -128,9 +145,16 @@ struct RegisterCodeGenFlags { llvm::BasicBlockSection getBBSectionsMode(llvm::TargetOptions &Options); -// Common utility function tightly tied to the options listed here. Initializes -// a TargetOptions object with CodeGen flags and returns it. -TargetOptions InitTargetOptionsFromCodeGenFlags(); +llvm::StackProtectorGuards +getStackProtectorGuardMode(llvm::TargetOptions &Options); + +/// Common utility function tightly tied to the options listed here. Initializes +/// a TargetOptions object with CodeGen flags and returns it. +/// \p TheTriple is used to determine the default value for options if +/// options are not explicitly specified. If those triple dependant options +/// value do not have effect for your component, a default Triple() could be +/// passed in. +TargetOptions InitTargetOptionsFromCodeGenFlags(const llvm::Triple &TheTriple); std::string getCPUStr(); diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/DIE.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/DIE.h index c7baaf6aef3d..3efef6ec0acd 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/DIE.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/DIE.h @@ -247,6 +247,7 @@ public: unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const; void print(raw_ostream &O) const; + uint64_t getIndex() const { return Index; } }; //===--------------------------------------------------------------------===// @@ -382,12 +383,12 @@ private: static_assert(std::is_standard_layout::value || std::is_pointer::value, "Expected standard layout or pointer"); - new (reinterpret_cast(Val.buffer)) T(V); + new (reinterpret_cast(&Val)) T(V); } - template T *get() { return reinterpret_cast(Val.buffer); } + template T *get() { return reinterpret_cast(&Val); } template const T *get() const { - return reinterpret_cast(Val.buffer); + return reinterpret_cast(&Val); } template void destruct() { get()->~T(); } @@ -589,7 +590,6 @@ public: T &operator*() const { return *static_cast(N); } bool operator==(const iterator &X) const { return N == X.N; } - bool operator!=(const iterator &X) const { return N != X.N; } }; class const_iterator @@ -612,7 +612,6 @@ public: const T &operator*() const { return *static_cast(N); } bool operator==(const const_iterator &X) const { return N == X.N; } - bool operator!=(const const_iterator &X) const { return N != X.N; } }; iterator begin() { @@ -788,7 +787,7 @@ public: /// Get the absolute offset within the .debug_info or .debug_types section /// for this DIE. - unsigned getDebugSectionOffset() const; + uint64_t getDebugSectionOffset() const; /// Compute the offset of this DIE and all its children. /// @@ -864,14 +863,11 @@ class DIEUnit { /// a valid section depending on the client that is emitting DWARF. MCSection *Section; uint64_t Offset; /// .debug_info or .debug_types absolute section offset. - uint32_t Length; /// The length in bytes of all of the DIEs in this unit. - const uint16_t Version; /// The Dwarf version number for this unit. - const uint8_t AddrSize; /// The size in bytes of an address for this unit. protected: virtual ~DIEUnit() = default; public: - DIEUnit(uint16_t Version, uint8_t AddrSize, dwarf::Tag UnitTag); + explicit DIEUnit(dwarf::Tag UnitTag); DIEUnit(const DIEUnit &RHS) = delete; DIEUnit(DIEUnit &&RHS) = delete; void operator=(const DIEUnit &RHS) = delete; @@ -893,19 +889,14 @@ public: /// /// \returns Section pointer which can be NULL. MCSection *getSection() const { return Section; } - void setDebugSectionOffset(unsigned O) { Offset = O; } - unsigned getDebugSectionOffset() const { return Offset; } - void setLength(uint64_t L) { Length = L; } - uint64_t getLength() const { return Length; } - uint16_t getDwarfVersion() const { return Version; } - uint16_t getAddressSize() const { return AddrSize; } + void setDebugSectionOffset(uint64_t O) { Offset = O; } + uint64_t getDebugSectionOffset() const { return Offset; } DIE &getUnitDie() { return Die; } const DIE &getUnitDie() const { return Die; } }; struct BasicDIEUnit final : DIEUnit { - BasicDIEUnit(uint16_t Version, uint8_t AddrSize, dwarf::Tag UnitTag) - : DIEUnit(Version, AddrSize, UnitTag) {} + explicit BasicDIEUnit(dwarf::Tag UnitTag) : DIEUnit(UnitTag) {} }; //===--------------------------------------------------------------------===// diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/DbgEntityHistoryCalculator.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/DbgEntityHistoryCalculator.h index f7fc74a27fca..bca6065b1643 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/DbgEntityHistoryCalculator.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/DbgEntityHistoryCalculator.h @@ -12,6 +12,7 @@ #include "llvm/ADT/MapVector.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/LexicalScopes.h" #include namespace llvm { @@ -23,6 +24,24 @@ class MachineFunction; class MachineInstr; class TargetRegisterInfo; +/// Record instruction ordering so we can query their relative positions within +/// a function. Meta instructions are given the same ordinal as the preceding +/// non-meta instruction. Class state is invalid if MF is modified after +/// calling initialize. +class InstructionOrdering { +public: + void initialize(const MachineFunction &MF); + void clear() { InstNumberMap.clear(); } + + /// Check if instruction \p A comes before \p B, where \p A and \p B both + /// belong to the MachineFunction passed to initialize(). + bool isBefore(const MachineInstr *A, const MachineInstr *B) const; + +private: + /// Each instruction is assigned an order number. + DenseMap InstNumberMap; +}; + /// For each user variable, keep a list of instruction ranges where this /// variable is accessible. The variables are listed in order of appearance. class DbgValueHistoryMap { @@ -52,6 +71,8 @@ public: /// register-described debug values that have their end index /// set to this entry's position in the entry vector. class Entry { + friend DbgValueHistoryMap; + public: enum EntryKind { DbgValue, Clobber }; @@ -89,6 +110,9 @@ public: return Entries[Index]; } + /// Drop location ranges which exist entirely outside each variable's scope. + void trimLocationRanges(const MachineFunction &MF, LexicalScopes &LScopes, + const InstructionOrdering &Ordering); bool empty() const { return VarEntries.empty(); } void clear() { VarEntries.clear(); } EntriesMap::const_iterator begin() const { return VarEntries.begin(); } diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/DebugHandlerBase.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/DebugHandlerBase.h index 4ff0fdea36ae..45823b2ba349 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/DebugHandlerBase.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/DebugHandlerBase.h @@ -110,8 +110,13 @@ protected: virtual void endFunctionImpl(const MachineFunction *MF) = 0; virtual void skippedNonDebugFunction() {} +private: + InstructionOrdering InstOrdering; + // AsmPrinterHandler overrides. public: + void beginModule(Module *M) override; + void beginInstruction(const MachineInstr *MI) override; void endInstruction() override; @@ -129,8 +134,13 @@ public: /// If this type is derived from a base type then return base type size. static uint64_t getBaseTypeSize(const DIType *Ty); + + /// Return true if type encoding is unsigned. + static bool isUnsignedDIType(const DIType *Ty); + + const InstructionOrdering &getInstOrdering() const { return InstOrdering; } }; -} +} // namespace llvm #endif diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/DwarfStringPoolEntry.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/DwarfStringPoolEntry.h index e189352a7b2d..abeba62707c1 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/DwarfStringPoolEntry.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/DwarfStringPoolEntry.h @@ -21,7 +21,7 @@ struct DwarfStringPoolEntry { static constexpr unsigned NotIndexed = -1; MCSymbol *Symbol; - unsigned Offset; + uint64_t Offset; unsigned Index; bool isIndexed() const { return Index != NotIndexed; } @@ -47,7 +47,7 @@ public: assert(getMapEntry()->second.Symbol && "No symbol available!"); return getMapEntry()->second.Symbol; } - unsigned getOffset() const { return getMapEntry()->second.Offset; } + uint64_t getOffset() const { return getMapEntry()->second.Offset; } bool isIndexed() const { return MapEntryAndIndexed.getInt(); } unsigned getIndex() const { assert(isIndexed()); diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/FastISel.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/FastISel.h index 7662179db44d..26bf4ab2618c 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/FastISel.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/FastISel.h @@ -224,10 +224,6 @@ protected: /// makes sense (for example, on function calls) MachineInstr *EmitStartPt; - /// Last local value flush point. On a subsequent flush, no local value will - /// sink past this point. - MachineBasicBlock::iterator LastFlushPoint; - public: virtual ~FastISel(); @@ -246,7 +242,7 @@ public: /// be appended. void startNewBlock(); - /// Flush the local value map and sink local values if possible. + /// Flush the local value map. void finishBasicBlock(); /// Return current debug location information. @@ -313,10 +309,7 @@ public: void removeDeadCode(MachineBasicBlock::iterator I, MachineBasicBlock::iterator E); - struct SavePoint { - MachineBasicBlock::iterator InsertPt; - DebugLoc DL; - }; + using SavePoint = MachineBasicBlock::iterator; /// Prepare InsertPt to begin inserting instructions into the local /// value area and return the old insert position. @@ -497,7 +490,10 @@ protected: /// - \c Add has a constant operand. bool canFoldAddIntoGEP(const User *GEP, const Value *Add); - /// Test whether the given value has exactly one use. + /// Test whether the register associated with this value has exactly one use, + /// in which case that single use is killing. Note that multiple IR values + /// may map onto the same register, in which case this is not the same as + /// checking that an IR value has one use. bool hasTrivialKill(const Value *V); /// Create a machine mem operand from the given instruction. @@ -510,18 +506,6 @@ protected: unsigned NumArgs); bool lowerCallTo(CallLoweringInfo &CLI); - bool isCommutativeIntrinsic(IntrinsicInst const *II) { - switch (II->getIntrinsicID()) { - case Intrinsic::sadd_with_overflow: - case Intrinsic::uadd_with_overflow: - case Intrinsic::smul_with_overflow: - case Intrinsic::umul_with_overflow: - return true; - default: - return false; - } - } - bool lowerCall(const CallInst *I); /// Select and emit code for a binary operator instruction, which has /// an opcode which directly corresponds to the given ISD opcode. @@ -536,7 +520,6 @@ protected: bool selectFreeze(const User *I); bool selectCast(const User *I, unsigned Opcode); bool selectExtractValue(const User *U); - bool selectInsertValue(const User *I); bool selectXRayCustomEvent(const CallInst *II); bool selectXRayTypedEvent(const CallInst *II); @@ -572,20 +555,6 @@ private: /// Removes dead local value instructions after SavedLastLocalvalue. void removeDeadLocalValueCode(MachineInstr *SavedLastLocalValue); - struct InstOrderMap { - DenseMap Orders; - MachineInstr *FirstTerminator = nullptr; - unsigned FirstTerminatorOrder = std::numeric_limits::max(); - - void initialize(MachineBasicBlock *MBB, - MachineBasicBlock::iterator LastFlushPoint); - }; - - /// Sinks the local value materialization instruction LocalMI to its first use - /// in the basic block, or deletes it if it is not used. - void sinkLocalValueMaterialization(MachineInstr &LocalMI, Register DefReg, - InstOrderMap &OrderMap); - /// Insertion point before trying to select the current instruction. MachineBasicBlock::iterator SavedInsertPt; diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h index c99ca00eac29..b6bde0249f88 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h @@ -91,13 +91,33 @@ public: /// Track virtual registers created for exception pointers. DenseMap CatchPadExceptionPointers; - /// Keep track of frame indices allocated for statepoints as they could be - /// used across basic block boundaries (e.g. for an invoke). For each - /// gc.statepoint instruction, maps uniqued llvm IR values to the slots they - /// were spilled in. If a value is mapped to None it means we visited the - /// value but didn't spill it (because it was a constant, for instance). - using StatepointSpillMapTy = DenseMap>; - DenseMap StatepointSpillMaps; + /// Helper object to track which of three possible relocation mechanisms are + /// used for a particular value being relocated over a statepoint. + struct StatepointRelocationRecord { + enum RelocType { + // Value did not need to be relocated and can be used directly. + NoRelocate, + // Value was spilled to stack and needs filled at the gc.relocate. + Spill, + // Value was lowered to tied def and gc.relocate should be replaced with + // copy from vreg. + VReg, + } type = NoRelocate; + // Payload contains either frame index of the stack slot in which the value + // was spilled, or virtual register which contains the re-definition. + union payload_t { + payload_t() : FI(-1) {} + int FI; + Register Reg; + } payload; + }; + + /// Keep track of each value which was relocated and the strategy used to + /// relocate that value. This information is required when visiting + /// gc.relocates which may appear in following blocks. + using StatepointSpillMapTy = + DenseMap; + DenseMap StatepointRelocationMaps; /// StaticAllocaMap - Keep track of frame indices for fixed sized allocas in /// the entry block. This allows the allocas to be efficiently referenced diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/CSEInfo.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/CSEInfo.h index 8bd9e9443552..f76dec57c840 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/CSEInfo.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/CSEInfo.h @@ -16,14 +16,12 @@ #include "llvm/CodeGen/CSEConfigBase.h" #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" #include "llvm/CodeGen/GlobalISel/GISelWorkList.h" -#include "llvm/CodeGen/GlobalISel/Utils.h" -#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/IR/PassManager.h" -#include "llvm/Pass.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/CodeGen.h" namespace llvm { +class MachineBasicBlock; /// A class that wraps MachineInstrs and derives from FoldingSetNode in order to /// be uniqued in a CSEMap. The tradeoff here is extra memory allocations for @@ -184,6 +182,8 @@ public: const GISelInstProfileBuilder &addNodeIDRegNum(Register Reg) const; + const GISelInstProfileBuilder &addNodeIDReg(Register Reg) const; + const GISelInstProfileBuilder &addNodeIDImmediate(int64_t Imm) const; const GISelInstProfileBuilder & addNodeIDMBB(const MachineBasicBlock *MBB) const; diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h index 4d60dffb91db..26ae7129f04a 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h @@ -17,8 +17,11 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/TargetCallingConv.h" +#include "llvm/IR/Attributes.h" #include "llvm/IR/CallingConv.h" +#include "llvm/IR/Type.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MachineValueType.h" #include @@ -26,16 +29,14 @@ namespace llvm { -class CCState; class CallBase; class DataLayout; class Function; +class FunctionLoweringInfo; class MachineIRBuilder; -class MachineOperand; struct MachinePointerInfo; class MachineRegisterInfo; class TargetLowering; -class Type; class Value; class CallLowering { @@ -43,21 +44,30 @@ class CallLowering { virtual void anchor(); public: - struct ArgInfo { + struct BaseArgInfo { + Type *Ty; + SmallVector Flags; + bool IsFixed; + + BaseArgInfo(Type *Ty, + ArrayRef Flags = ArrayRef(), + bool IsFixed = true) + : Ty(Ty), Flags(Flags.begin(), Flags.end()), IsFixed(IsFixed) {} + + BaseArgInfo() : Ty(nullptr), IsFixed(false) {} + }; + + struct ArgInfo : public BaseArgInfo { SmallVector Regs; // If the argument had to be split into multiple parts according to the // target calling convention, then this contains the original vregs // if the argument was an incoming arg. SmallVector OrigRegs; - Type *Ty; - SmallVector Flags; - bool IsFixed; ArgInfo(ArrayRef Regs, Type *Ty, ArrayRef Flags = ArrayRef(), bool IsFixed = true) - : Regs(Regs.begin(), Regs.end()), Ty(Ty), - Flags(Flags.begin(), Flags.end()), IsFixed(IsFixed) { + : BaseArgInfo(Ty, Flags, IsFixed), Regs(Regs.begin(), Regs.end()) { if (!Regs.empty() && Flags.empty()) this->Flags.push_back(ISD::ArgFlagsTy()); // FIXME: We should have just one way of saying "no register". @@ -66,7 +76,7 @@ public: "only void types should have no register"); } - ArgInfo() : Ty(nullptr), IsFixed(false) {} + ArgInfo() : BaseArgInfo() {} }; struct CallLoweringInfo { @@ -102,6 +112,15 @@ public: /// True if the call is to a vararg function. bool IsVarArg = false; + + /// True if the function's return value can be lowered to registers. + bool CanLowerReturn = true; + + /// VReg to hold the hidden sret parameter. + Register DemoteRegister; + + /// The stack index for sret demotion. + int DemoteStackIndex; }; /// Argument handling is mostly uniform between the four places that @@ -111,15 +130,18 @@ public: /// argument should go, exactly what happens can vary slightly. This /// class abstracts the differences. struct ValueHandler { - ValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, - CCAssignFn *AssignFn) - : MIRBuilder(MIRBuilder), MRI(MRI), AssignFn(AssignFn) {} + ValueHandler(bool IsIncoming, MachineIRBuilder &MIRBuilder, + MachineRegisterInfo &MRI, CCAssignFn *AssignFn) + : MIRBuilder(MIRBuilder), MRI(MRI), AssignFn(AssignFn), + IsIncomingArgumentHandler(IsIncoming) {} virtual ~ValueHandler() = default; /// Returns true if the handler is dealing with incoming arguments, /// i.e. those that move values from some physical location to vregs. - virtual bool isIncomingArgumentHandler() const = 0; + bool isIncomingArgumentHandler() const { + return IsIncomingArgumentHandler; + } /// Materialize a VReg containing the address of the specified /// stack-based object. This is either based on a FrameIndex or @@ -147,6 +169,7 @@ public: virtual void assignValueToAddress(const ArgInfo &Arg, Register Addr, uint64_t Size, MachinePointerInfo &MPO, CCValAssign &VA) { + assert(Arg.Regs.size() == 1); assignValueToAddress(Arg.Regs[0], Addr, Size, MPO, VA); } @@ -177,9 +200,22 @@ public: CCAssignFn *AssignFn; private: + bool IsIncomingArgumentHandler; virtual void anchor(); }; + struct IncomingValueHandler : public ValueHandler { + IncomingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, + CCAssignFn *AssignFn) + : ValueHandler(true, MIRBuilder, MRI, AssignFn) {} + }; + + struct OutgoingValueHandler : public ValueHandler { + OutgoingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, + CCAssignFn *AssignFn) + : ValueHandler(false, MIRBuilder, MRI, AssignFn) {} + }; + protected: /// Getter for generic TargetLowering class. const TargetLowering *getTLI() const { @@ -192,6 +228,17 @@ protected: return static_cast(TLI); } + /// \returns Flags corresponding to the attributes on the \p ArgIdx-th + /// parameter of \p Call. + ISD::ArgFlagsTy getAttributesForArgIdx(const CallBase &Call, + unsigned ArgIdx) const; + + /// Adds flags to \p Flags based off of the attributes in \p Attrs. + /// \p OpIdx is the index in \p Attrs to add flags from. + void addArgFlagsFromAttributes(ISD::ArgFlagsTy &Flags, + const AttributeList &Attrs, + unsigned OpIdx) const; + template void setArgFlags(ArgInfo &Arg, unsigned OpIdx, const DataLayout &DL, const FuncInfoTy &FuncInfo) const; @@ -215,7 +262,7 @@ protected: MachineIRBuilder &MIRBuilder) const; /// Invoke Handler::assignArg on each of the given \p Args and then use - /// \p Callback to move them to the assigned locations. + /// \p Handler to move them to the assigned locations. /// /// \return True if everything has succeeded, false otherwise. bool handleAssignments(MachineIRBuilder &MIRBuilder, @@ -235,6 +282,14 @@ protected: CCAssignFn &AssignFnFixed, CCAssignFn &AssignFnVarArg) const; + /// Check whether parameters to a call that are passed in callee saved + /// registers are the same as from the calling function. This needs to be + /// checked for tail call eligibility. + bool parametersInCSRMatch(const MachineRegisterInfo &MRI, + const uint32_t *CallerPreservedMask, + const SmallVectorImpl &ArgLocs, + const SmallVectorImpl &OutVals) const; + /// \returns True if the calling convention for a callee and its caller pass /// results in the same way. Typically used for tail call eligibility checks. /// @@ -265,20 +320,73 @@ public: return false; } + /// Load the returned value from the stack into virtual registers in \p VRegs. + /// It uses the frame index \p FI and the start offset from \p DemoteReg. + /// The loaded data size will be determined from \p RetTy. + void insertSRetLoads(MachineIRBuilder &MIRBuilder, Type *RetTy, + ArrayRef VRegs, Register DemoteReg, + int FI) const; + + /// Store the return value given by \p VRegs into stack starting at the offset + /// specified in \p DemoteReg. + void insertSRetStores(MachineIRBuilder &MIRBuilder, Type *RetTy, + ArrayRef VRegs, Register DemoteReg) const; + + /// Insert the hidden sret ArgInfo to the beginning of \p SplitArgs. + /// This function should be called from the target specific + /// lowerFormalArguments when \p F requires the sret demotion. + void insertSRetIncomingArgument(const Function &F, + SmallVectorImpl &SplitArgs, + Register &DemoteReg, MachineRegisterInfo &MRI, + const DataLayout &DL) const; + + /// For the call-base described by \p CB, insert the hidden sret ArgInfo to + /// the OrigArgs field of \p Info. + void insertSRetOutgoingArgument(MachineIRBuilder &MIRBuilder, + const CallBase &CB, + CallLoweringInfo &Info) const; + + /// \return True if the return type described by \p Outs can be returned + /// without performing sret demotion. + bool checkReturn(CCState &CCInfo, SmallVectorImpl &Outs, + CCAssignFn *Fn) const; + + /// Get the type and the ArgFlags for the split components of \p RetTy as + /// returned by \c ComputeValueVTs. + void getReturnInfo(CallingConv::ID CallConv, Type *RetTy, AttributeList Attrs, + SmallVectorImpl &Outs, + const DataLayout &DL) const; + + /// Toplevel function to check the return type based on the target calling + /// convention. \return True if the return value of \p MF can be returned + /// without performing sret demotion. + bool checkReturnTypeForCallConv(MachineFunction &MF) const; + + /// This hook must be implemented to check whether the return values + /// described by \p Outs can fit into the return registers. If false + /// is returned, an sret-demotion is performed. + virtual bool canLowerReturn(MachineFunction &MF, CallingConv::ID CallConv, + SmallVectorImpl &Outs, + bool IsVarArg) const { + return true; + } + /// This hook must be implemented to lower outgoing return values, described /// by \p Val, into the specified virtual registers \p VRegs. /// This hook is used by GlobalISel. /// + /// \p FLI is required for sret demotion. + /// /// \p SwiftErrorVReg is non-zero if the function has a swifterror parameter /// that needs to be implicitly returned. /// /// \return True if the lowering succeeds, false otherwise. virtual bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, - ArrayRef VRegs, + ArrayRef VRegs, FunctionLoweringInfo &FLI, Register SwiftErrorVReg) const { if (!supportSwiftError()) { assert(SwiftErrorVReg == 0 && "attempt to use unsupported swifterror"); - return lowerReturn(MIRBuilder, Val, VRegs); + return lowerReturn(MIRBuilder, Val, VRegs, FLI); } return false; } @@ -286,7 +394,8 @@ public: /// This hook behaves as the extended lowerReturn function, but for targets /// that do not support swifterror value promotion. virtual bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, - ArrayRef VRegs) const { + ArrayRef VRegs, + FunctionLoweringInfo &FLI) const { return false; } @@ -299,12 +408,13 @@ public: /// the second in \c VRegs[1], and so on. For each argument, there will be one /// register for each non-aggregate type, as returned by \c computeValueLLTs. /// \p MIRBuilder is set to the proper insertion for the argument - /// lowering. + /// lowering. \p FLI is required for sret demotion. /// /// \return True if the lowering succeeded, false otherwise. virtual bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F, - ArrayRef> VRegs) const { + ArrayRef> VRegs, + FunctionLoweringInfo &FLI) const { return false; } diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h index c317b7ed4c54..8570f5ca5dd5 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h @@ -17,6 +17,8 @@ #ifndef LLVM_CODEGEN_GLOBALISEL_COMBINER_HELPER_H #define LLVM_CODEGEN_GLOBALISEL_COMBINER_HELPER_H +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/CodeGen/LowLevelType.h" #include "llvm/CodeGen/Register.h" #include "llvm/Support/Alignment.h" @@ -25,12 +27,15 @@ namespace llvm { class GISelChangeObserver; class MachineIRBuilder; +class MachineInstrBuilder; class MachineRegisterInfo; class MachineInstr; class MachineOperand; class GISelKnownBits; class MachineDominatorTree; class LegalizerInfo; +struct LegalityQuery; +class TargetLowering; struct PreferredTuple { LLT Ty; // The result type of the extend. @@ -50,6 +55,37 @@ struct PtrAddChain { Register Base; }; +struct RegisterImmPair { + Register Reg; + int64_t Imm; +}; + +struct ShiftOfShiftedLogic { + MachineInstr *Logic; + MachineInstr *Shift2; + Register LogicNonShiftReg; + uint64_t ValSum; +}; + +using OperandBuildSteps = + SmallVector, 4>; +struct InstructionBuildSteps { + unsigned Opcode = 0; /// The opcode for the produced instruction. + OperandBuildSteps OperandFns; /// Operands to be added to the instruction. + InstructionBuildSteps() = default; + InstructionBuildSteps(unsigned Opcode, const OperandBuildSteps &OperandFns) + : Opcode(Opcode), OperandFns(OperandFns) {} +}; + +struct InstructionStepsMatchInfo { + /// Describes instructions to be built during a combine. + SmallVector InstrsToBuild; + InstructionStepsMatchInfo() = default; + InstructionStepsMatchInfo( + std::initializer_list InstrsToBuild) + : InstrsToBuild(InstrsToBuild) {} +}; + class CombinerHelper { protected: MachineIRBuilder &Builder; @@ -69,6 +105,12 @@ public: return KB; } + const TargetLowering &getTargetLowering() const; + + /// \return true if the combine is running prior to legalization, or if \p + /// Query is legal on the target. + bool isLegalOrBeforeLegalizer(const LegalityQuery &Query) const; + /// MachineRegisterInfo::replaceRegWith() and inform the observer of the changes void replaceRegWith(MachineRegisterInfo &MRI, Register FromReg, Register ToReg) const; @@ -107,12 +149,17 @@ public: bool matchCombineIndexedLoadStore(MachineInstr &MI, IndexedLoadStoreMatchInfo &MatchInfo); void applyCombineIndexedLoadStore(MachineInstr &MI, IndexedLoadStoreMatchInfo &MatchInfo); - bool matchSextAlreadyExtended(MachineInstr &MI); - bool applySextAlreadyExtended(MachineInstr &MI); + bool matchSextTruncSextLoad(MachineInstr &MI); + bool applySextTruncSextLoad(MachineInstr &MI); - bool matchElideBrByInvertingCond(MachineInstr &MI); - void applyElideBrByInvertingCond(MachineInstr &MI); - bool tryElideBrByInvertingCond(MachineInstr &MI); + /// Match sext_inreg(load p), imm -> sextload p + bool matchSextInRegOfLoad(MachineInstr &MI, std::tuple &MatchInfo); + bool applySextInRegOfLoad(MachineInstr &MI, std::tuple &MatchInfo); + + /// If a brcond's true block is not the fallthrough, make it so by inverting + /// the condition and swapping operands. + bool matchOptBrCondByInvertingCond(MachineInstr &MI); + void applyOptBrCondByInvertingCond(MachineInstr &MI); /// If \p MI is G_CONCAT_VECTORS, try to combine it. /// Returns true if MI changed. @@ -189,10 +236,28 @@ public: bool matchPtrAddImmedChain(MachineInstr &MI, PtrAddChain &MatchInfo); bool applyPtrAddImmedChain(MachineInstr &MI, PtrAddChain &MatchInfo); + /// Fold (shift (shift base, x), y) -> (shift base (x+y)) + bool matchShiftImmedChain(MachineInstr &MI, RegisterImmPair &MatchInfo); + bool applyShiftImmedChain(MachineInstr &MI, RegisterImmPair &MatchInfo); + + /// If we have a shift-by-constant of a bitwise logic op that itself has a + /// shift-by-constant operand with identical opcode, we may be able to convert + /// that into 2 independent shifts followed by the logic op. + bool matchShiftOfShiftedLogic(MachineInstr &MI, + ShiftOfShiftedLogic &MatchInfo); + bool applyShiftOfShiftedLogic(MachineInstr &MI, + ShiftOfShiftedLogic &MatchInfo); + /// Transform a multiply by a power-of-2 value to a left shift. bool matchCombineMulToShl(MachineInstr &MI, unsigned &ShiftVal); bool applyCombineMulToShl(MachineInstr &MI, unsigned &ShiftVal); + // Transform a G_SHL with an extended source into a narrower shift if + // possible. + bool matchCombineShlOfExtend(MachineInstr &MI, RegisterImmPair &MatchData); + bool applyCombineShlOfExtend(MachineInstr &MI, + const RegisterImmPair &MatchData); + /// Reduce a shift by a constant to an unmerge and a shift on a half sized /// type. This will not produce a shift smaller than \p TargetShiftSize. bool matchCombineShiftToUnmerge(MachineInstr &MI, unsigned TargetShiftSize, @@ -200,6 +265,86 @@ public: bool applyCombineShiftToUnmerge(MachineInstr &MI, const unsigned &ShiftVal); bool tryCombineShiftToUnmerge(MachineInstr &MI, unsigned TargetShiftAmount); + /// Transform G_UNMERGE(G_MERGE ty X, Y, Z) -> ty X, Y, Z. + bool + matchCombineUnmergeMergeToPlainValues(MachineInstr &MI, + SmallVectorImpl &Operands); + bool + applyCombineUnmergeMergeToPlainValues(MachineInstr &MI, + SmallVectorImpl &Operands); + + /// Transform G_UNMERGE Constant -> Constant1, Constant2, ... + bool matchCombineUnmergeConstant(MachineInstr &MI, + SmallVectorImpl &Csts); + bool applyCombineUnmergeConstant(MachineInstr &MI, + SmallVectorImpl &Csts); + + /// Transform X, Y = G_UNMERGE Z -> X = G_TRUNC Z. + bool matchCombineUnmergeWithDeadLanesToTrunc(MachineInstr &MI); + bool applyCombineUnmergeWithDeadLanesToTrunc(MachineInstr &MI); + + /// Transform X, Y = G_UNMERGE(G_ZEXT(Z)) -> X = G_ZEXT(Z); Y = G_CONSTANT 0 + bool matchCombineUnmergeZExtToZExt(MachineInstr &MI); + bool applyCombineUnmergeZExtToZExt(MachineInstr &MI); + + /// Transform fp_instr(cst) to constant result of the fp operation. + bool matchCombineConstantFoldFpUnary(MachineInstr &MI, + Optional &Cst); + bool applyCombineConstantFoldFpUnary(MachineInstr &MI, + Optional &Cst); + + /// Transform IntToPtr(PtrToInt(x)) to x if cast is in the same address space. + bool matchCombineI2PToP2I(MachineInstr &MI, Register &Reg); + bool applyCombineI2PToP2I(MachineInstr &MI, Register &Reg); + + /// Transform PtrToInt(IntToPtr(x)) to x. + bool matchCombineP2IToI2P(MachineInstr &MI, Register &Reg); + bool applyCombineP2IToI2P(MachineInstr &MI, Register &Reg); + + /// Transform G_ADD (G_PTRTOINT x), y -> G_PTRTOINT (G_PTR_ADD x, y) + /// Transform G_ADD y, (G_PTRTOINT x) -> G_PTRTOINT (G_PTR_ADD x, y) + bool matchCombineAddP2IToPtrAdd(MachineInstr &MI, + std::pair &PtrRegAndCommute); + bool applyCombineAddP2IToPtrAdd(MachineInstr &MI, + std::pair &PtrRegAndCommute); + + // Transform G_PTR_ADD (G_PTRTOINT C1), C2 -> C1 + C2 + bool matchCombineConstPtrAddToI2P(MachineInstr &MI, int64_t &NewCst); + bool applyCombineConstPtrAddToI2P(MachineInstr &MI, int64_t &NewCst); + + /// Transform anyext(trunc(x)) to x. + bool matchCombineAnyExtTrunc(MachineInstr &MI, Register &Reg); + bool applyCombineAnyExtTrunc(MachineInstr &MI, Register &Reg); + + /// Transform [asz]ext([asz]ext(x)) to [asz]ext x. + bool matchCombineExtOfExt(MachineInstr &MI, + std::tuple &MatchInfo); + bool applyCombineExtOfExt(MachineInstr &MI, + std::tuple &MatchInfo); + + /// Transform fneg(fneg(x)) to x. + bool matchCombineFNegOfFNeg(MachineInstr &MI, Register &Reg); + + /// Match fabs(fabs(x)) to fabs(x). + bool matchCombineFAbsOfFAbs(MachineInstr &MI, Register &Src); + bool applyCombineFAbsOfFAbs(MachineInstr &MI, Register &Src); + + /// Transform trunc ([asz]ext x) to x or ([asz]ext x) or (trunc x). + bool matchCombineTruncOfExt(MachineInstr &MI, + std::pair &MatchInfo); + bool applyCombineTruncOfExt(MachineInstr &MI, + std::pair &MatchInfo); + + /// Transform trunc (shl x, K) to shl (trunc x), + /// K => K < VT.getScalarSizeInBits(). + bool matchCombineTruncOfShl(MachineInstr &MI, + std::pair &MatchInfo); + bool applyCombineTruncOfShl(MachineInstr &MI, + std::pair &MatchInfo); + + /// Transform G_MUL(x, -1) to G_SUB(0, x) + bool applyCombineMulByNegativeOne(MachineInstr &MI); + /// Return true if any explicit use operand on \p MI is defined by a /// G_IMPLICIT_DEF. bool matchAnyExplicitUseIsUndef(MachineInstr &MI); @@ -214,6 +359,13 @@ public: /// Return true if a G_STORE instruction \p MI is storing an undef value. bool matchUndefStore(MachineInstr &MI); + /// Return true if a G_SELECT instruction \p MI has an undef comparison. + bool matchUndefSelectCmp(MachineInstr &MI); + + /// Return true if a G_SELECT instruction \p MI has a constant comparison. If + /// true, \p OpIdx will store the operand index of the known selected value. + bool matchConstantSelectCmp(MachineInstr &MI, unsigned &OpIdx); + /// Replace an instruction with a G_FCONSTANT with value \p C. bool replaceInstWithFConstant(MachineInstr &MI, double C); @@ -226,6 +378,9 @@ public: /// Delete \p MI and replace all of its uses with its \p OpIdx-th operand. bool replaceSingleDefInstWithOperand(MachineInstr &MI, unsigned OpIdx); + /// Delete \p MI and replace all of its uses with \p Replacement. + bool replaceSingleDefInstWithReg(MachineInstr &MI, Register Replacement); + /// Return true if \p MOP1 and \p MOP2 are register operands are defined by /// equivalent instructions. bool matchEqualDefs(const MachineOperand &MOP1, const MachineOperand &MOP2); @@ -243,6 +398,12 @@ public: /// Check if operand \p OpIdx is zero. bool matchOperandIsZero(MachineInstr &MI, unsigned OpIdx); + /// Check if operand \p OpIdx is undef. + bool matchOperandIsUndef(MachineInstr &MI, unsigned OpIdx); + + /// Check if operand \p OpIdx is known to be a power of 2. + bool matchOperandIsKnownToBeAPowerOfTwo(MachineInstr &MI, unsigned OpIdx); + /// Erase \p MI bool eraseInst(MachineInstr &MI); @@ -252,6 +413,79 @@ public: bool applySimplifyAddToSub(MachineInstr &MI, std::tuple &MatchInfo); + /// Match (logic_op (op x...), (op y...)) -> (op (logic_op x, y)) + bool + matchHoistLogicOpWithSameOpcodeHands(MachineInstr &MI, + InstructionStepsMatchInfo &MatchInfo); + + /// Replace \p MI with a series of instructions described in \p MatchInfo. + bool applyBuildInstructionSteps(MachineInstr &MI, + InstructionStepsMatchInfo &MatchInfo); + + /// Match ashr (shl x, C), C -> sext_inreg (C) + bool matchAshrShlToSextInreg(MachineInstr &MI, + std::tuple &MatchInfo); + bool applyAshShlToSextInreg(MachineInstr &MI, + std::tuple &MatchInfo); + /// \return true if \p MI is a G_AND instruction whose operands are x and y + /// where x & y == x or x & y == y. (E.g., one of operands is all-ones value.) + /// + /// \param [in] MI - The G_AND instruction. + /// \param [out] Replacement - A register the G_AND should be replaced with on + /// success. + bool matchRedundantAnd(MachineInstr &MI, Register &Replacement); + + /// \return true if \p MI is a G_OR instruction whose operands are x and y + /// where x | y == x or x | y == y. (E.g., one of operands is all-zeros + /// value.) + /// + /// \param [in] MI - The G_OR instruction. + /// \param [out] Replacement - A register the G_OR should be replaced with on + /// success. + bool matchRedundantOr(MachineInstr &MI, Register &Replacement); + + /// \return true if \p MI is a G_SEXT_INREG that can be erased. + bool matchRedundantSExtInReg(MachineInstr &MI); + + /// Combine inverting a result of a compare into the opposite cond code. + bool matchNotCmp(MachineInstr &MI, SmallVectorImpl &RegsToNegate); + bool applyNotCmp(MachineInstr &MI, SmallVectorImpl &RegsToNegate); + + /// Fold (xor (and x, y), y) -> (and (not x), y) + ///{ + bool matchXorOfAndWithSameReg(MachineInstr &MI, + std::pair &MatchInfo); + bool applyXorOfAndWithSameReg(MachineInstr &MI, + std::pair &MatchInfo); + ///} + + /// Combine G_PTR_ADD with nullptr to G_INTTOPTR + bool matchPtrAddZero(MachineInstr &MI); + bool applyPtrAddZero(MachineInstr &MI); + + /// Combine G_UREM x, (known power of 2) to an add and bitmasking. + bool applySimplifyURemByPow2(MachineInstr &MI); + + bool matchCombineInsertVecElts(MachineInstr &MI, + SmallVectorImpl &MatchInfo); + + bool applyCombineInsertVecElts(MachineInstr &MI, + SmallVectorImpl &MatchInfo); + + /// Match expression trees of the form + /// + /// \code + /// sN *a = ... + /// sM val = a[0] | (a[1] << N) | (a[2] << 2N) | (a[3] << 3N) ... + /// \endcode + /// + /// And check if the tree can be replaced with a M-bit load + possibly a + /// bswap. + bool matchLoadOrCombine(MachineInstr &MI, + std::function &MatchInfo); + bool applyLoadOrCombine(MachineInstr &MI, + std::function &MatchInfo); + /// Try to transform \p MI by using all of the above /// combine functions. Returns true if changed. bool tryCombine(MachineInstr &MI); @@ -280,6 +514,30 @@ private: /// \returns true if a candidate is found. bool findPreIndexCandidate(MachineInstr &MI, Register &Addr, Register &Base, Register &Offset); + + /// Helper function for matchLoadOrCombine. Searches for Registers + /// which may have been produced by a load instruction + some arithmetic. + /// + /// \param [in] Root - The search root. + /// + /// \returns The Registers found during the search. + Optional> + findCandidatesForLoadOrCombine(const MachineInstr *Root) const; + + /// Helper function for matchLoadOrCombine. + /// + /// Checks if every register in \p RegsToVisit is defined by a load + /// instruction + some arithmetic. + /// + /// \param [out] MemOffset2Idx - Maps the byte positions each load ends up + /// at to the index of the load. + /// \param [in] MemSizeInBits - The number of bits each load should produce. + /// + /// \returns The lowest-index load found and the lowest index on success. + Optional> findLoadOffsetsForLoadOrCombine( + SmallDenseMap &MemOffset2Idx, + const SmallVector &RegsToVisit, + const unsigned MemSizeInBits); }; } // namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/GISelChangeObserver.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/GISelChangeObserver.h index d8fe4b3103db..dd7f04a33f4b 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/GISelChangeObserver.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/GISelChangeObserver.h @@ -51,7 +51,7 @@ public: /// For convenience, finishedChangingAllUsesOfReg() will report the completion /// of the changes. The use list may change between this call and /// finishedChangingAllUsesOfReg(). - void changingAllUsesOfReg(const MachineRegisterInfo &MRI, unsigned Reg); + void changingAllUsesOfReg(const MachineRegisterInfo &MRI, Register Reg); /// All instructions reported as changing by changingAllUsesOfReg() have /// finished being changed. void finishedChangingAllUsesOfReg(); diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/GISelKnownBits.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/GISelKnownBits.h index 55cf54d6e946..eafed3760738 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/GISelKnownBits.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/GISelKnownBits.h @@ -13,13 +13,11 @@ #ifndef LLVM_CODEGEN_GLOBALISEL_KNOWNBITSINFO_H #define LLVM_CODEGEN_GLOBALISEL_KNOWNBITSINFO_H -#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/Register.h" -#include "llvm/IR/PassManager.h" #include "llvm/InitializePasses.h" -#include "llvm/Pass.h" #include "llvm/Support/KnownBits.h" namespace llvm { @@ -36,10 +34,16 @@ class GISelKnownBits : public GISelChangeObserver { /// Cache maintained during a computeKnownBits request. SmallDenseMap ComputeKnownBitsCache; + void computeKnownBitsMin(Register Src0, Register Src1, KnownBits &Known, + const APInt &DemandedElts, + unsigned Depth = 0); + + unsigned computeNumSignBitsMin(Register Src0, Register Src1, + const APInt &DemandedElts, unsigned Depth = 0); + public: GISelKnownBits(MachineFunction &MF, unsigned MaxDepth = 6); virtual ~GISelKnownBits() = default; - void setMF(MachineFunction &MF); const MachineFunction &getMachineFunction() const { return MF; diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/GISelWorkList.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/GISelWorkList.h index b0bb519283b1..9e7ade3ee329 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/GISelWorkList.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/GISelWorkList.h @@ -11,9 +11,6 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/Support/Debug.h" namespace llvm { diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h index 751ab67c4e97..8eab8a5846a7 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h @@ -20,12 +20,14 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/FunctionLoweringInfo.h" #include "llvm/CodeGen/GlobalISel/CSEMIRBuilder.h" -#include "llvm/CodeGen/SwiftErrorValueTracking.h" #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/SwiftErrorValueTracking.h" #include "llvm/CodeGen/SwitchLoweringUtils.h" #include "llvm/IR/Intrinsics.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/CodeGen.h" #include #include @@ -36,8 +38,8 @@ class BasicBlock; class CallInst; class CallLowering; class Constant; +class ConstrainedFPIntrinsic; class DataLayout; -class FunctionLoweringInfo; class Instruction; class MachineBasicBlock; class MachineFunction; @@ -217,12 +219,14 @@ private: /// Translate an LLVM string intrinsic (memcpy, memset, ...). bool translateMemFunc(const CallInst &CI, MachineIRBuilder &MIRBuilder, - Intrinsic::ID ID); + unsigned Opcode); void getStackGuard(Register DstReg, MachineIRBuilder &MIRBuilder); bool translateOverflowIntrinsic(const CallInst &CI, unsigned Op, MachineIRBuilder &MIRBuilder); + bool translateFixedPointIntrinsic(unsigned Op, const CallInst &CI, + MachineIRBuilder &MIRBuilder); /// Helper function for translateSimpleIntrinsic. /// \return The generic opcode for \p IntrinsicID if \p IntrinsicID is a @@ -256,6 +260,19 @@ private: /// \pre \p U is a call instruction. bool translateCall(const User &U, MachineIRBuilder &MIRBuilder); + /// When an invoke or a cleanupret unwinds to the next EH pad, there are + /// many places it could ultimately go. In the IR, we have a single unwind + /// destination, but in the machine CFG, we enumerate all the possible blocks. + /// This function skips over imaginary basic blocks that hold catchswitch + /// instructions, and finds all the "real" machine + /// basic block destinations. As those destinations may not be successors of + /// EHPadBB, here we also calculate the edge probability to those + /// destinations. The passed-in Prob is the edge probability to EHPadBB. + bool findUnwindDestinations( + const BasicBlock *EHPadBB, BranchProbability Prob, + SmallVectorImpl> + &UnwindDests); + bool translateInvoke(const User &U, MachineIRBuilder &MIRBuilder); bool translateCallBr(const User &U, MachineIRBuilder &MIRBuilder); @@ -287,11 +304,37 @@ private: /// MachineBasicBlocks for the function have been created. void finishPendingPhis(); + /// Translate \p Inst into a unary operation \p Opcode. + /// \pre \p U is a unary operation. + bool translateUnaryOp(unsigned Opcode, const User &U, + MachineIRBuilder &MIRBuilder); + /// Translate \p Inst into a binary operation \p Opcode. /// \pre \p U is a binary operation. bool translateBinaryOp(unsigned Opcode, const User &U, MachineIRBuilder &MIRBuilder); + /// If the set of cases should be emitted as a series of branches, return + /// true. If we should emit this as a bunch of and/or'd together conditions, + /// return false. + bool shouldEmitAsBranches(const std::vector &Cases); + /// Helper method for findMergedConditions. + /// This function emits a branch and is used at the leaves of an OR or an + /// AND operator tree. + void emitBranchForMergedCondition(const Value *Cond, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + MachineBasicBlock *CurBB, + MachineBasicBlock *SwitchBB, + BranchProbability TProb, + BranchProbability FProb, bool InvertCond); + /// Used during condbr translation to find trees of conditions that can be + /// optimized. + void findMergedConditions(const Value *Cond, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, MachineBasicBlock *CurBB, + MachineBasicBlock *SwitchBB, + Instruction::BinaryOps Opc, BranchProbability TProb, + BranchProbability FProb, bool InvertCond); + /// Translate branch (br) instruction. /// \pre \p U is a branch instruction. bool translateBr(const User &U, MachineIRBuilder &MIRBuilder); @@ -305,19 +348,23 @@ private: void emitSwitchCase(SwitchCG::CaseBlock &CB, MachineBasicBlock *SwitchBB, MachineIRBuilder &MIB); - bool lowerJumpTableWorkItem(SwitchCG::SwitchWorkListItem W, - MachineBasicBlock *SwitchMBB, - MachineBasicBlock *CurMBB, - MachineBasicBlock *DefaultMBB, - MachineIRBuilder &MIB, - MachineFunction::iterator BBI, - BranchProbability UnhandledProbs, - SwitchCG::CaseClusterIt I, - MachineBasicBlock *Fallthrough, - bool FallthroughUnreachable); - - bool lowerSwitchRangeWorkItem(SwitchCG::CaseClusterIt I, - Value *Cond, + /// Generate for for the BitTest header block, which precedes each sequence of + /// BitTestCases. + void emitBitTestHeader(SwitchCG::BitTestBlock &BTB, + MachineBasicBlock *SwitchMBB); + /// Generate code to produces one "bit test" for a given BitTestCase \p B. + void emitBitTestCase(SwitchCG::BitTestBlock &BB, MachineBasicBlock *NextMBB, + BranchProbability BranchProbToNext, Register Reg, + SwitchCG::BitTestCase &B, MachineBasicBlock *SwitchBB); + + bool lowerJumpTableWorkItem( + SwitchCG::SwitchWorkListItem W, MachineBasicBlock *SwitchMBB, + MachineBasicBlock *CurMBB, MachineBasicBlock *DefaultMBB, + MachineIRBuilder &MIB, MachineFunction::iterator BBI, + BranchProbability UnhandledProbs, SwitchCG::CaseClusterIt I, + MachineBasicBlock *Fallthrough, bool FallthroughUnreachable); + + bool lowerSwitchRangeWorkItem(SwitchCG::CaseClusterIt I, Value *Cond, MachineBasicBlock *Fallthrough, bool FallthroughUnreachable, BranchProbability UnhandledProbs, @@ -325,6 +372,14 @@ private: MachineIRBuilder &MIB, MachineBasicBlock *SwitchMBB); + bool lowerBitTestWorkItem( + SwitchCG::SwitchWorkListItem W, MachineBasicBlock *SwitchMBB, + MachineBasicBlock *CurMBB, MachineBasicBlock *DefaultMBB, + MachineIRBuilder &MIB, MachineFunction::iterator BBI, + BranchProbability DefaultProb, BranchProbability UnhandledProbs, + SwitchCG::CaseClusterIt I, MachineBasicBlock *Fallthrough, + bool FallthroughUnreachable); + bool lowerSwitchWorkItem(SwitchCG::SwitchWorkListItem W, Value *Cond, MachineBasicBlock *SwitchMBB, MachineBasicBlock *DefaultMBB, @@ -351,8 +406,6 @@ private: /// \pre \p U is a return instruction. bool translateRet(const User &U, MachineIRBuilder &MIRBuilder); - bool translateFSub(const User &U, MachineIRBuilder &MIRBuilder); - bool translateFNeg(const User &U, MachineIRBuilder &MIRBuilder); bool translateAdd(const User &U, MachineIRBuilder &MIRBuilder) { @@ -437,6 +490,9 @@ private: bool translateFAdd(const User &U, MachineIRBuilder &MIRBuilder) { return translateBinaryOp(TargetOpcode::G_FADD, U, MIRBuilder); } + bool translateFSub(const User &U, MachineIRBuilder &MIRBuilder) { + return translateBinaryOp(TargetOpcode::G_FSUB, U, MIRBuilder); + } bool translateFMul(const User &U, MachineIRBuilder &MIRBuilder) { return translateBinaryOp(TargetOpcode::G_FMUL, U, MIRBuilder); } @@ -515,6 +571,8 @@ private: /// Current target configuration. Controls how the pass handles errors. const TargetPassConfig *TPC; + CodeGenOpt::Level OptLevel; + /// Current optimization remark emitter. Used to report failures. std::unique_ptr ORE; @@ -614,12 +672,12 @@ private: BranchProbability getEdgeProbability(const MachineBasicBlock *Src, const MachineBasicBlock *Dst) const; - void addSuccessorWithProb(MachineBasicBlock *Src, MachineBasicBlock *Dst, - BranchProbability Prob); + void addSuccessorWithProb( + MachineBasicBlock *Src, MachineBasicBlock *Dst, + BranchProbability Prob = BranchProbability::getUnknown()); public: - // Ctor, nothing fancy. - IRTranslator(); + IRTranslator(CodeGenOpt::Level OptLevel = CodeGenOpt::None); StringRef getPassName() const override { return "IRTranslator"; } diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h index 1af96cb4a9ee..5b8243a93e7f 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h @@ -112,6 +112,14 @@ enum { /// - InsnID - Instruction ID /// - Expected opcode GIM_CheckOpcode, + + /// Check the opcode on the specified instruction, checking 2 acceptable + /// alternatives. + /// - InsnID - Instruction ID + /// - Expected opcode + /// - Alternative expected opcode + GIM_CheckOpcodeIsEither, + /// Check the instruction has the right number of operands /// - InsnID - Instruction ID /// - Expected number of operands @@ -164,6 +172,15 @@ enum { GIM_CheckMemorySizeEqualToLLT, GIM_CheckMemorySizeLessThanLLT, GIM_CheckMemorySizeGreaterThanLLT, + + /// Check if this is a vector that can be treated as a vector splat + /// constant. This is valid for both G_BUILD_VECTOR as well as + /// G_BUILD_VECTOR_TRUNC. For AllOnes refers to individual bits, so a -1 + /// element. + /// - InsnID - Instruction ID + GIM_CheckIsBuildVectorAllOnes, + GIM_CheckIsBuildVectorAllZeros, + /// Check a generic C++ instruction predicate /// - InsnID - Instruction ID /// - PredicateID - The ID of the predicate function to call @@ -237,6 +254,15 @@ enum { /// - OtherOpIdx - Other operand index GIM_CheckIsSameOperand, + /// Predicates with 'let PredicateCodeUsesOperands = 1' need to examine some + /// named operands that will be recorded in RecordedOperands. Names of these + /// operands are referenced in predicate argument list. Emitter determines + /// StoreIdx(corresponds to the order in which names appear in argument list). + /// - InsnID - Instruction ID + /// - OpIdx - Operand index + /// - StoreIdx - Store location in RecordedOperands. + GIM_RecordNamedOperand, + /// Fail the current try-block, or completely fail to match if there is no /// current try-block. GIM_Reject, @@ -429,6 +455,11 @@ protected: std::vector Renderers; RecordedMIVector MIs; DenseMap TempRegisters; + /// Named operands that predicate with 'let PredicateCodeUsesOperands = 1' + /// referenced in its argument list. Operands are inserted at index set by + /// emitter, it corresponds to the order in which names appear in argument + /// list. Currently such predicates don't have more then 3 arguments. + std::array RecordedOperands; MatcherState(unsigned MaxRenderers); }; @@ -489,21 +520,13 @@ protected: llvm_unreachable( "Subclasses must override this with a tablegen-erated function"); } - virtual bool testMIPredicate_MI(unsigned, const MachineInstr &) const { + virtual bool testMIPredicate_MI( + unsigned, const MachineInstr &, + const std::array &Operands) const { llvm_unreachable( "Subclasses must override this with a tablegen-erated function"); } - /// Constrain a register operand of an instruction \p I to a specified - /// register class. This could involve inserting COPYs before (for uses) or - /// after (for defs) and may replace the operand of \p I. - /// \returns whether operand regclass constraining succeeded. - bool constrainOperandRegToRegClass(MachineInstr &I, unsigned OpIdx, - const TargetRegisterClass &RC, - const TargetInstrInfo &TII, - const TargetRegisterInfo &TRI, - const RegisterBankInfo &RBI) const; - bool isOperandImmEqual(const MachineOperand &MO, int64_t Value, const MachineRegisterInfo &MRI) const; diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h index 73ac578d61be..82e26b0bc355 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h @@ -154,24 +154,31 @@ bool InstructionSelector::executeMatchTable( break; } - case GIM_CheckOpcode: { + case GIM_CheckOpcode: + case GIM_CheckOpcodeIsEither: { int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t Expected = MatchTable[CurrentIdx++]; + int64_t Expected0 = MatchTable[CurrentIdx++]; + int64_t Expected1 = -1; + if (MatcherOpcode == GIM_CheckOpcodeIsEither) + Expected1 = MatchTable[CurrentIdx++]; assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); unsigned Opcode = State.MIs[InsnID]->getOpcode(); DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIM_CheckOpcode(MIs[" << InsnID - << "], ExpectedOpcode=" << Expected - << ") // Got=" << Opcode << "\n"); - if (Opcode != Expected) { + dbgs() << CurrentIdx << ": GIM_CheckOpcode(MIs[" << InsnID + << "], ExpectedOpcode=" << Expected0; + if (MatcherOpcode == GIM_CheckOpcodeIsEither) + dbgs() << " || " << Expected1; + dbgs() << ") // Got=" << Opcode << "\n"; + ); + + if (Opcode != Expected0 && Opcode != Expected1) { if (handleReject() == RejectAndGiveUp) return false; } break; } - case GIM_SwitchOpcode: { int64_t InsnID = MatchTable[CurrentIdx++]; int64_t LowerBound = MatchTable[CurrentIdx++]; @@ -193,7 +200,7 @@ bool InstructionSelector::executeMatchTable( CurrentIdx = MatchTable[CurrentIdx + (Opcode - LowerBound)]; if (!CurrentIdx) { CurrentIdx = Default; - break; + break; } OnFailResumeAt.push_back(Default); break; @@ -321,6 +328,35 @@ bool InstructionSelector::executeMatchTable( return false; break; } + case GIM_CheckIsBuildVectorAllOnes: + case GIM_CheckIsBuildVectorAllZeros: { + int64_t InsnID = MatchTable[CurrentIdx++]; + + DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), + dbgs() << CurrentIdx + << ": GIM_CheckBuildVectorAll{Zeros|Ones}(MIs[" + << InsnID << "])\n"); + assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); + + const MachineInstr *MI = State.MIs[InsnID]; + assert((MI->getOpcode() == TargetOpcode::G_BUILD_VECTOR || + MI->getOpcode() == TargetOpcode::G_BUILD_VECTOR_TRUNC) && + "Expected G_BUILD_VECTOR or G_BUILD_VECTOR_TRUNC"); + + if (MatcherOpcode == GIM_CheckIsBuildVectorAllOnes) { + if (!isBuildVectorAllOnes(*MI, MRI)) { + if (handleReject() == RejectAndGiveUp) + return false; + } + } else { + if (!isBuildVectorAllZeros(*MI, MRI)) { + if (handleReject() == RejectAndGiveUp) + return false; + } + } + + break; + } case GIM_CheckCxxInsnPredicate: { int64_t InsnID = MatchTable[CurrentIdx++]; int64_t Predicate = MatchTable[CurrentIdx++]; @@ -331,7 +367,8 @@ bool InstructionSelector::executeMatchTable( assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); assert(Predicate > GIPFP_MI_Invalid && "Expected a valid predicate"); - if (!testMIPredicate_MI(Predicate, *State.MIs[InsnID])) + if (!testMIPredicate_MI(Predicate, *State.MIs[InsnID], + State.RecordedOperands)) if (handleReject() == RejectAndGiveUp) return false; break; @@ -581,6 +618,20 @@ bool InstructionSelector::executeMatchTable( break; } + case GIM_RecordNamedOperand: { + int64_t InsnID = MatchTable[CurrentIdx++]; + int64_t OpIdx = MatchTable[CurrentIdx++]; + uint64_t StoreIdx = MatchTable[CurrentIdx++]; + + DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), + dbgs() << CurrentIdx << ": GIM_RecordNamedOperand(MIs[" + << InsnID << "]->getOperand(" << OpIdx + << "), StoreIdx=" << StoreIdx << ")\n"); + assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); + assert(StoreIdx < State.RecordedOperands.size() && "Index out of range"); + State.RecordedOperands[StoreIdx] = &State.MIs[InsnID]->getOperand(OpIdx); + break; + } case GIM_CheckRegBankForClass: { int64_t InsnID = MatchTable[CurrentIdx++]; int64_t OpIdx = MatchTable[CurrentIdx++]; @@ -1007,8 +1058,12 @@ bool InstructionSelector::executeMatchTable( int64_t OpIdx = MatchTable[CurrentIdx++]; int64_t RCEnum = MatchTable[CurrentIdx++]; assert(OutMIs[InsnID] && "Attempted to add to undefined instruction"); - constrainOperandRegToRegClass(*OutMIs[InsnID].getInstr(), OpIdx, - *TRI.getRegClass(RCEnum), TII, TRI, RBI); + MachineInstr &I = *OutMIs[InsnID].getInstr(); + MachineFunction &MF = *I.getParent()->getParent(); + MachineRegisterInfo &MRI = MF.getRegInfo(); + const TargetRegisterClass &RC = *TRI.getRegClass(RCEnum); + MachineOperand &MO = I.getOperand(OpIdx); + constrainOperandRegClass(MF, TRI, MRI, TII, RBI, I, RC, MO); DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), dbgs() << CurrentIdx << ": GIR_ConstrainOperandRC(OutMIs[" << InsnID << "], " << OpIdx << ", " << RCEnum diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h index 016b0bacab85..e7bda3b4bd97 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h @@ -105,19 +105,23 @@ public: Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg()); // zext(trunc x) - > and (aext/copy/trunc x), mask + // zext(sext x) -> and (sext x), mask Register TruncSrc; - if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) { + Register SextSrc; + if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc))) || + mi_match(SrcReg, MRI, m_GSExt(m_Reg(SextSrc)))) { LLT DstTy = MRI.getType(DstReg); if (isInstUnsupported({TargetOpcode::G_AND, {DstTy}}) || isConstantUnsupported(DstTy)) return false; LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;); LLT SrcTy = MRI.getType(SrcReg); - APInt Mask = APInt::getAllOnesValue(SrcTy.getScalarSizeInBits()); - auto MIBMask = Builder.buildConstant( - DstTy, Mask.zext(DstTy.getScalarSizeInBits())); - Builder.buildAnd(DstReg, Builder.buildAnyExtOrTrunc(DstTy, TruncSrc), - MIBMask); + APInt MaskVal = APInt::getAllOnesValue(SrcTy.getScalarSizeInBits()); + auto Mask = Builder.buildConstant( + DstTy, MaskVal.zext(DstTy.getScalarSizeInBits())); + auto Extended = SextSrc ? Builder.buildSExtOrTrunc(DstTy, SextSrc) : + Builder.buildAnyExtOrTrunc(DstTy, TruncSrc); + Builder.buildAnd(DstReg, Extended, Mask); markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts); return true; } @@ -482,7 +486,7 @@ public: MachineRegisterInfo &MRI, MachineIRBuilder &Builder, SmallVectorImpl &UpdatedDefs, - GISelObserverWrapper &Observer) { + GISelChangeObserver &Observer) { if (!llvm::canReplaceReg(DstReg, SrcReg, MRI)) { Builder.buildCopy(DstReg, SrcReg); UpdatedDefs.push_back(DstReg); @@ -502,20 +506,78 @@ public: Observer.changedInstr(*UseMI); } - bool tryCombineMerges(MachineInstr &MI, - SmallVectorImpl &DeadInsts, - SmallVectorImpl &UpdatedDefs, - GISelObserverWrapper &Observer) { + /// Return the operand index in \p MI that defines \p Def + static unsigned getDefIndex(const MachineInstr &MI, Register SearchDef) { + unsigned DefIdx = 0; + for (const MachineOperand &Def : MI.defs()) { + if (Def.getReg() == SearchDef) + break; + ++DefIdx; + } + + return DefIdx; + } + + bool tryCombineUnmergeValues(MachineInstr &MI, + SmallVectorImpl &DeadInsts, + SmallVectorImpl &UpdatedDefs, + GISelChangeObserver &Observer) { assert(MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES); unsigned NumDefs = MI.getNumOperands() - 1; - MachineInstr *SrcDef = - getDefIgnoringCopies(MI.getOperand(NumDefs).getReg(), MRI); + Register SrcReg = MI.getOperand(NumDefs).getReg(); + MachineInstr *SrcDef = getDefIgnoringCopies(SrcReg, MRI); if (!SrcDef) return false; LLT OpTy = MRI.getType(MI.getOperand(NumDefs).getReg()); LLT DestTy = MRI.getType(MI.getOperand(0).getReg()); + + if (SrcDef->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) { + // %0:_(<4 x s16>) = G_FOO + // %1:_(<2 x s16>), %2:_(<2 x s16>) = G_UNMERGE_VALUES %0 + // %3:_(s16), %4:_(s16) = G_UNMERGE_VALUES %1 + // + // %3:_(s16), %4:_(s16), %5:_(s16), %6:_(s16) = G_UNMERGE_VALUES %0 + const unsigned NumSrcOps = SrcDef->getNumOperands(); + Register SrcUnmergeSrc = SrcDef->getOperand(NumSrcOps - 1).getReg(); + LLT SrcUnmergeSrcTy = MRI.getType(SrcUnmergeSrc); + + // If we need to decrease the number of vector elements in the result type + // of an unmerge, this would involve the creation of an equivalent unmerge + // to copy back to the original result registers. + LegalizeActionStep ActionStep = LI.getAction( + {TargetOpcode::G_UNMERGE_VALUES, {OpTy, SrcUnmergeSrcTy}}); + switch (ActionStep.Action) { + case LegalizeActions::Lower: + case LegalizeActions::Unsupported: + break; + case LegalizeActions::FewerElements: + case LegalizeActions::NarrowScalar: + if (ActionStep.TypeIdx == 1) + return false; + break; + default: + return false; + } + + Builder.setInstrAndDebugLoc(MI); + auto NewUnmerge = Builder.buildUnmerge(DestTy, SrcUnmergeSrc); + + // TODO: Should we try to process out the other defs now? If the other + // defs of the source unmerge are also unmerged, we end up with a separate + // unmerge for each one. + unsigned SrcDefIdx = getDefIndex(*SrcDef, SrcReg); + for (unsigned I = 0; I != NumDefs; ++I) { + Register Def = MI.getOperand(I).getReg(); + replaceRegOrBuildCopy(Def, NewUnmerge.getReg(SrcDefIdx * NumDefs + I), + MRI, Builder, UpdatedDefs, Observer); + } + + markInstAndDefDead(MI, *SrcDef, DeadInsts, SrcDefIdx); + return true; + } + MachineInstr *MergeI = SrcDef; unsigned ConvertOp = 0; @@ -743,9 +805,12 @@ public: Changed = tryCombineSExt(MI, DeadInsts, UpdatedDefs); break; case TargetOpcode::G_UNMERGE_VALUES: - Changed = tryCombineMerges(MI, DeadInsts, UpdatedDefs, WrapperObserver); + Changed = + tryCombineUnmergeValues(MI, DeadInsts, UpdatedDefs, WrapperObserver); break; case TargetOpcode::G_MERGE_VALUES: + case TargetOpcode::G_BUILD_VECTOR: + case TargetOpcode::G_CONCAT_VECTORS: // If any of the users of this merge are an unmerge, then add them to the // artifact worklist in case there's folding that can be done looking up. for (MachineInstr &U : MRI.use_instructions(MI.getOperand(0).getReg())) { @@ -829,7 +894,8 @@ private: /// dead. /// MI is not marked dead. void markDefDead(MachineInstr &MI, MachineInstr &DefMI, - SmallVectorImpl &DeadInsts) { + SmallVectorImpl &DeadInsts, + unsigned DefIdx = 0) { // Collect all the copy instructions that are made dead, due to deleting // this instruction. Collect all of them until the Trunc(DefMI). // Eg, @@ -856,8 +922,27 @@ private: break; PrevMI = TmpDef; } - if (PrevMI == &DefMI && MRI.hasOneUse(DefMI.getOperand(0).getReg())) - DeadInsts.push_back(&DefMI); + + if (PrevMI == &DefMI) { + unsigned I = 0; + bool IsDead = true; + for (MachineOperand &Def : DefMI.defs()) { + if (I != DefIdx) { + if (!MRI.use_empty(Def.getReg())) { + IsDead = false; + break; + } + } else { + if (!MRI.hasOneUse(DefMI.getOperand(DefIdx).getReg())) + break; + } + + ++I; + } + + if (IsDead) + DeadInsts.push_back(&DefMI); + } } /// Mark MI as dead. If a def of one of MI's operands, DefMI, would also be @@ -866,9 +951,10 @@ private: /// copies in between the extends and the truncs, and this attempts to collect /// the in between copies if they're dead. void markInstAndDefDead(MachineInstr &MI, MachineInstr &DefMI, - SmallVectorImpl &DeadInsts) { + SmallVectorImpl &DeadInsts, + unsigned DefIdx = 0) { DeadInsts.push_back(&MI); - markDefDead(MI, DefMI, DeadInsts); + markDefDead(MI, DefMI, DeadInsts, DefIdx); } /// Erase the dead instructions in the list and call the observer hooks. diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/Legalizer.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/Legalizer.h index e59bf1b91262..690e84f79a6b 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/Legalizer.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/Legalizer.h @@ -64,9 +64,6 @@ public: MachineFunctionProperties::Property::NoPHIs); } - bool combineExtracts(MachineInstr &MI, MachineRegisterInfo &MRI, - const TargetInstrInfo &TII); - bool runOnMachineFunction(MachineFunction &MF) override; static MFResult diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h index 058aacf38634..4a982b00125d 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h @@ -32,6 +32,7 @@ class LegalizerInfo; class Legalizer; class MachineRegisterInfo; class GISelChangeObserver; +class TargetLowering; class LegalizerHelper { public: @@ -45,6 +46,7 @@ public: private: MachineRegisterInfo &MRI; const LegalizerInfo &LI; + const TargetLowering &TLI; public: enum LegalizeResult { @@ -62,6 +64,7 @@ public: /// Expose LegalizerInfo so the clients can re-use. const LegalizerInfo &getLegalizerInfo() const { return LI; } + const TargetLowering &getTargetLowering() const { return TLI; } LegalizerHelper(MachineFunction &MF, GISelChangeObserver &Observer, MachineIRBuilder &B); @@ -154,6 +157,10 @@ public: /// def by inserting a G_BITCAST from \p CastTy void bitcastDst(MachineInstr &MI, LLT CastTy, unsigned OpIdx); + /// Widen \p OrigReg to \p WideTy by merging to a wider type, padding with + /// G_IMPLICIT_DEF, and producing dead results. + Register widenWithUnmerge(LLT WideTy, Register OrigReg); + private: LegalizeResult widenScalarMergeValues(MachineInstr &MI, unsigned TypeIdx, LLT WideTy); @@ -163,8 +170,10 @@ private: widenScalarExtract(MachineInstr &MI, unsigned TypeIdx, LLT WideTy); LegalizeResult widenScalarInsert(MachineInstr &MI, unsigned TypeIdx, LLT WideTy); - LegalizeResult widenScalarAddSubSat(MachineInstr &MI, unsigned TypeIdx, - LLT WideTy); + LegalizeResult widenScalarAddoSubo(MachineInstr &MI, unsigned TypeIdx, + LLT WideTy); + LegalizeResult widenScalarAddSubShlSat(MachineInstr &MI, unsigned TypeIdx, + LLT WideTy); /// Helper function to split a wide generic register into bitwise blocks with /// the given Type (which implies the number of blocks needed). The generic @@ -191,11 +200,19 @@ private: LLT PartTy, ArrayRef PartRegs, LLT LeftoverTy = LLT(), ArrayRef LeftoverRegs = {}); - /// Unmerge \p SrcReg into \p Parts with the greatest common divisor type with - /// \p DstTy and \p NarrowTy. Returns the GCD type. + /// Unmerge \p SrcReg into smaller sized values, and append them to \p + /// Parts. The elements of \p Parts will be the greatest common divisor type + /// of \p DstTy, \p NarrowTy and the type of \p SrcReg. This will compute and + /// return the GCD type. LLT extractGCDType(SmallVectorImpl &Parts, LLT DstTy, LLT NarrowTy, Register SrcReg); + /// Unmerge \p SrcReg into \p GCDTy typed registers. This will append all of + /// the unpacked registers to \p Parts. This version is if the common unmerge + /// type is already known. + void extractGCDType(SmallVectorImpl &Parts, LLT GCDTy, + Register SrcReg); + /// Produce a merge of values in \p VRegs to define \p DstReg. Perform a merge /// from the least common multiple type, and convert as appropriate to \p /// DstReg. @@ -228,7 +245,23 @@ private: ArrayRef Src1Regs, ArrayRef Src2Regs, LLT NarrowTy); + void changeOpcode(MachineInstr &MI, unsigned NewOpcode); + public: + /// Return the alignment to use for a stack temporary object with the given + /// type. + Align getStackTemporaryAlignment(LLT Type, Align MinAlign = Align()) const; + + /// Create a stack temporary based on the size in bytes and the alignment + MachineInstrBuilder createStackTemporary(TypeSize Bytes, Align Alignment, + MachinePointerInfo &PtrInfo); + + /// Get a pointer to vector element \p Index located in memory for a vector of + /// type \p VecTy starting at a base address of \p VecPtr. If \p Index is out + /// of bounds the returned pointer is unspecified, but will be within the + /// vector bounds. + Register getVectorElementPointer(Register VecPtr, LLT VecTy, Register Index); + LegalizeResult fewerElementsVectorImplicitDef(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy); @@ -256,9 +289,11 @@ public: LegalizeResult fewerElementsVectorUnmergeValues(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy); - LegalizeResult fewerElementsVectorBuildVector(MachineInstr &MI, - unsigned TypeIdx, - LLT NarrowTy); + LegalizeResult fewerElementsVectorMerge(MachineInstr &MI, unsigned TypeIdx, + LLT NarrowTy); + LegalizeResult fewerElementsVectorExtractInsertVectorElt(MachineInstr &MI, + unsigned TypeIdx, + LLT NarrowTy); LegalizeResult reduceLoadStoreWidth(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy); @@ -281,6 +316,7 @@ public: LegalizeResult narrowScalarShift(MachineInstr &MI, unsigned TypeIdx, LLT Ty); LegalizeResult narrowScalarMul(MachineInstr &MI, LLT Ty); + LegalizeResult narrowScalarFPTOI(MachineInstr &MI, unsigned TypeIdx, LLT Ty); LegalizeResult narrowScalarExtract(MachineInstr &MI, unsigned TypeIdx, LLT Ty); LegalizeResult narrowScalarInsert(MachineInstr &MI, unsigned TypeIdx, LLT Ty); @@ -291,34 +327,52 @@ public: LegalizeResult narrowScalarCTTZ(MachineInstr &MI, unsigned TypeIdx, LLT Ty); LegalizeResult narrowScalarCTPOP(MachineInstr &MI, unsigned TypeIdx, LLT Ty); + /// Perform Bitcast legalize action on G_EXTRACT_VECTOR_ELT. + LegalizeResult bitcastExtractVectorElt(MachineInstr &MI, unsigned TypeIdx, + LLT CastTy); + + /// Perform Bitcast legalize action on G_INSERT_VECTOR_ELT. + LegalizeResult bitcastInsertVectorElt(MachineInstr &MI, unsigned TypeIdx, + LLT CastTy); + LegalizeResult lowerBitcast(MachineInstr &MI); - LegalizeResult lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty); + LegalizeResult lowerLoad(MachineInstr &MI); + LegalizeResult lowerStore(MachineInstr &MI); + LegalizeResult lowerBitCount(MachineInstr &MI); LegalizeResult lowerU64ToF32BitOps(MachineInstr &MI); - LegalizeResult lowerUITOFP(MachineInstr &MI, unsigned TypeIdx, LLT Ty); - LegalizeResult lowerSITOFP(MachineInstr &MI, unsigned TypeIdx, LLT Ty); - LegalizeResult lowerFPTOUI(MachineInstr &MI, unsigned TypeIdx, LLT Ty); + LegalizeResult lowerUITOFP(MachineInstr &MI); + LegalizeResult lowerSITOFP(MachineInstr &MI); + LegalizeResult lowerFPTOUI(MachineInstr &MI); LegalizeResult lowerFPTOSI(MachineInstr &MI); LegalizeResult lowerFPTRUNC_F64_TO_F16(MachineInstr &MI); - LegalizeResult lowerFPTRUNC(MachineInstr &MI, unsigned TypeIdx, LLT Ty); + LegalizeResult lowerFPTRUNC(MachineInstr &MI); + LegalizeResult lowerFPOWI(MachineInstr &MI); - LegalizeResult lowerMinMax(MachineInstr &MI, unsigned TypeIdx, LLT Ty); - LegalizeResult lowerFCopySign(MachineInstr &MI, unsigned TypeIdx, LLT Ty); + LegalizeResult lowerMinMax(MachineInstr &MI); + LegalizeResult lowerFCopySign(MachineInstr &MI); LegalizeResult lowerFMinNumMaxNum(MachineInstr &MI); LegalizeResult lowerFMad(MachineInstr &MI); LegalizeResult lowerIntrinsicRound(MachineInstr &MI); LegalizeResult lowerFFloor(MachineInstr &MI); LegalizeResult lowerMergeValues(MachineInstr &MI); LegalizeResult lowerUnmergeValues(MachineInstr &MI); + LegalizeResult lowerExtractInsertVectorElt(MachineInstr &MI); LegalizeResult lowerShuffleVector(MachineInstr &MI); LegalizeResult lowerDynStackAlloc(MachineInstr &MI); LegalizeResult lowerExtract(MachineInstr &MI); LegalizeResult lowerInsert(MachineInstr &MI); LegalizeResult lowerSADDO_SSUBO(MachineInstr &MI); + LegalizeResult lowerAddSubSatToMinMax(MachineInstr &MI); + LegalizeResult lowerAddSubSatToAddoSubo(MachineInstr &MI); + LegalizeResult lowerShlSat(MachineInstr &MI); LegalizeResult lowerBswap(MachineInstr &MI); LegalizeResult lowerBitreverse(MachineInstr &MI); LegalizeResult lowerReadWriteRegister(MachineInstr &MI); + LegalizeResult lowerSMULH_UMULH(MachineInstr &MI); + LegalizeResult lowerSelect(MachineInstr &MI); + }; /// Helper function that creates a libcall to the given \p Name using the given diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h index 61e0418757bc..c0a89b6ae619 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h @@ -37,7 +37,6 @@ extern cl::opt DisableGISelLegalityCheck; class LegalizerHelper; class MachineInstr; -class MachineIRBuilder; class MachineRegisterInfo; class MCInstrInfo; class GISelChangeObserver; @@ -183,7 +182,7 @@ struct TypePairAndMemDesc { MemSize == Other.MemSize; } - /// \returns true if this memory access is legal with for the acecss described + /// \returns true if this memory access is legal with for the access described /// by \p Other (The alignment is sufficient for the size and result type). bool isCompatible(const TypePairAndMemDesc &Other) const { return Type0 == Other.Type0 && Type1 == Other.Type1 && @@ -218,11 +217,19 @@ Predicate any(Predicate P0, Predicate P1, Args... args) { return any(any(P0, P1), args...); } -/// True iff the given type index is the specified types. +/// True iff the given type index is the specified type. LegalityPredicate typeIs(unsigned TypeIdx, LLT TypesInit); /// True iff the given type index is one of the specified types. LegalityPredicate typeInSet(unsigned TypeIdx, std::initializer_list TypesInit); + +/// True iff the given type index is not the specified type. +inline LegalityPredicate typeIsNot(unsigned TypeIdx, LLT Type) { + return [=](const LegalityQuery &Query) { + return Query.Types[TypeIdx] != Type; + }; +} + /// True iff the given types for the given pair of type indexes is one of the /// specified type pairs. LegalityPredicate @@ -308,6 +315,11 @@ LegalizeMutation changeElementTo(unsigned TypeIdx, unsigned FromTypeIdx); /// Keep the same scalar or element type as the given type. LegalizeMutation changeElementTo(unsigned TypeIdx, LLT Ty); +/// Change the scalar size or element size to have the same scalar size as type +/// index \p FromIndex. Unlike changeElementTo, this discards pointer types and +/// only changes the size. +LegalizeMutation changeElementSizeTo(unsigned TypeIdx, unsigned FromTypeIdx); + /// Widen the scalar type or vector element type for the given type index to the /// next power of 2. LegalizeMutation widenScalarOrEltToNextPow2(unsigned TypeIdx, unsigned Min = 0); @@ -616,8 +628,7 @@ public: /// The instruction is lowered when type index 0 is any type in the given /// list. Keep type index 0 as the same type. LegalizeRuleSet &lowerFor(std::initializer_list Types) { - return actionFor(LegalizeAction::Lower, Types, - LegalizeMutations::changeTo(0, 0)); + return actionFor(LegalizeAction::Lower, Types); } /// The instruction is lowered when type index 0 is any type in the given /// list. @@ -628,8 +639,7 @@ public: /// The instruction is lowered when type indexes 0 and 1 is any type pair in /// the given list. Keep type index 0 as the same type. LegalizeRuleSet &lowerFor(std::initializer_list> Types) { - return actionFor(LegalizeAction::Lower, Types, - LegalizeMutations::changeTo(0, 0)); + return actionFor(LegalizeAction::Lower, Types); } /// The instruction is lowered when type indexes 0 and 1 is any type pair in /// the given list. @@ -654,6 +664,15 @@ public: Types2); } + /// The instruction is emitted as a library call. + LegalizeRuleSet &libcall() { + using namespace LegalizeMutations; + // We have no choice but conservatively assume that predicate-less lowering + // properly handles all type indices by design: + markAllIdxsAsCovered(); + return actionIf(LegalizeAction::Libcall, always); + } + /// Like legalIf, but for the Libcall action. LegalizeRuleSet &libcallIf(LegalityPredicate Predicate) { // We have no choice but conservatively assume that a libcall with a @@ -696,6 +715,13 @@ public: markAllIdxsAsCovered(); return actionIf(LegalizeAction::NarrowScalar, Predicate, Mutation); } + /// Narrow the scalar, specified in mutation, when type indexes 0 and 1 is any + /// type pair in the given list. + LegalizeRuleSet & + narrowScalarFor(std::initializer_list> Types, + LegalizeMutation Mutation) { + return actionFor(LegalizeAction::NarrowScalar, Types, Mutation); + } /// Add more elements to reach the type selected by the mutation if the /// predicate is true. @@ -800,6 +826,13 @@ public: LegalizeMutations::scalarize(TypeIdx)); } + LegalizeRuleSet &scalarizeIf(LegalityPredicate Predicate, unsigned TypeIdx) { + using namespace LegalityPredicates; + return actionIf(LegalizeAction::FewerElements, + all(Predicate, isVector(typeIdx(TypeIdx))), + LegalizeMutations::scalarize(TypeIdx)); + } + /// Ensure the scalar or element is at least as wide as Ty. LegalizeRuleSet &minScalarOrElt(unsigned TypeIdx, const LLT Ty) { using namespace LegalityPredicates; @@ -857,7 +890,10 @@ public: return actionIf( LegalizeAction::NarrowScalar, [=](const LegalityQuery &Query) { - return scalarWiderThan(TypeIdx, Ty.getSizeInBits()) && Predicate(Query); + const LLT QueryTy = Query.Types[TypeIdx]; + return QueryTy.isScalar() && + QueryTy.getSizeInBits() > Ty.getSizeInBits() && + Predicate(Query); }, changeElementTo(typeIdx(TypeIdx), Ty)); } @@ -883,11 +919,25 @@ public: return Query.Types[LargeTypeIdx].getScalarSizeInBits() > Query.Types[TypeIdx].getSizeInBits(); }, + LegalizeMutations::changeElementSizeTo(TypeIdx, LargeTypeIdx)); + } + + /// Narrow the scalar to match the size of another. + LegalizeRuleSet &maxScalarSameAs(unsigned TypeIdx, unsigned NarrowTypeIdx) { + typeIdx(TypeIdx); + return narrowScalarIf( [=](const LegalityQuery &Query) { - LLT T = Query.Types[LargeTypeIdx]; - return std::make_pair(TypeIdx, - T.isVector() ? T.getElementType() : T); - }); + return Query.Types[NarrowTypeIdx].getScalarSizeInBits() < + Query.Types[TypeIdx].getSizeInBits(); + }, + LegalizeMutations::changeElementSizeTo(TypeIdx, NarrowTypeIdx)); + } + + /// Change the type \p TypeIdx to have the same scalar size as type \p + /// SameSizeIdx. + LegalizeRuleSet &scalarSameSizeAs(unsigned TypeIdx, unsigned SameSizeIdx) { + return minScalarSameAs(TypeIdx, SameSizeIdx) + .maxScalarSameAs(TypeIdx, SameSizeIdx); } /// Conditionally widen the scalar or elt to match the size of another. @@ -1207,6 +1257,12 @@ public: bool isLegal(const LegalityQuery &Query) const { return getAction(Query).Action == LegalizeAction::Legal; } + + bool isLegalOrCustom(const LegalityQuery &Query) const { + auto Action = getAction(Query).Action; + return Action == LegalizeAction::Legal || Action == LegalizeAction::Custom; + } + bool isLegal(const MachineInstr &MI, const MachineRegisterInfo &MRI) const; bool isLegalOrCustom(const MachineInstr &MI, const MachineRegisterInfo &MRI) const; diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/Localizer.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/Localizer.h index 67e450641eaf..1d1afff7f934 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/Localizer.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/Localizer.h @@ -52,9 +52,6 @@ private: /// TTI used for getting remat costs for instructions. TargetTransformInfo *TTI; - /// Check whether or not \p MI needs to be moved close to its uses. - bool shouldLocalize(const MachineInstr &MI); - /// Check if \p MOUse is used in the same basic block as \p Def. /// If the use is in the same block, we say it is local. /// When the use is not local, \p InsertMBB will contain the basic @@ -67,6 +64,11 @@ private: typedef SmallSetVector LocalizedSetVecT; + /// If \p Op is a phi operand and not unique in that phi, that is, + /// there are other operands in the phi with the same register, + /// return true. + bool isNonUniquePhiValue(MachineOperand &Op) const; + /// Do inter-block localization from the entry block. bool localizeInterBlock(MachineFunction &MF, LocalizedSetVecT &LocalizedInstrs); diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h index 043be086ff41..55d6d365fbb4 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h @@ -39,11 +39,25 @@ inline OneUse_match m_OneUse(const SubPat &SP) { return SP; } +template struct OneNonDBGUse_match { + SubPatternT SubPat; + OneNonDBGUse_match(const SubPatternT &SP) : SubPat(SP) {} + + bool match(const MachineRegisterInfo &MRI, Register Reg) { + return MRI.hasOneNonDBGUse(Reg) && SubPat.match(MRI, Reg); + } +}; + +template +inline OneNonDBGUse_match m_OneNonDBGUse(const SubPat &SP) { + return SP; +} + struct ConstantMatch { int64_t &CR; ConstantMatch(int64_t &C) : CR(C) {} bool match(const MachineRegisterInfo &MRI, Register Reg) { - if (auto MaybeCst = getConstantVRegVal(Reg, MRI)) { + if (auto MaybeCst = getConstantVRegSExtVal(Reg, MRI)) { CR = *MaybeCst; return true; } @@ -53,6 +67,29 @@ struct ConstantMatch { inline ConstantMatch m_ICst(int64_t &Cst) { return ConstantMatch(Cst); } +/// Matcher for a specific constant value. +struct SpecificConstantMatch { + int64_t RequestedVal; + SpecificConstantMatch(int64_t RequestedVal) : RequestedVal(RequestedVal) {} + bool match(const MachineRegisterInfo &MRI, Register Reg) { + int64_t MatchedVal; + return mi_match(Reg, MRI, m_ICst(MatchedVal)) && MatchedVal == RequestedVal; + } +}; + +/// Matches a constant equal to \p RequestedValue. +inline SpecificConstantMatch m_SpecificICst(int64_t RequestedValue) { + return SpecificConstantMatch(RequestedValue); +} + +///{ +/// Convenience matchers for specific integer values. +inline SpecificConstantMatch m_ZeroInt() { return SpecificConstantMatch(0); } +inline SpecificConstantMatch m_AllOnesInt() { + return SpecificConstantMatch(-1); +} +///} + // TODO: Rework this for different kinds of MachineOperand. // Currently assumes the Src for a match is a register. // We might want to support taking in some MachineOperands and call getReg on @@ -197,6 +234,12 @@ m_GAdd(const LHS &L, const RHS &R) { return BinaryOp_match(L, R); } +template +inline BinaryOp_match +m_GPtrAdd(const LHS &L, const RHS &R) { + return BinaryOp_match(L, R); +} + template inline BinaryOp_match m_GSub(const LHS &L, const RHS &R) { @@ -233,6 +276,12 @@ m_GAnd(const LHS &L, const RHS &R) { return BinaryOp_match(L, R); } +template +inline BinaryOp_match +m_GXor(const LHS &L, const RHS &R) { + return BinaryOp_match(L, R); +} + template inline BinaryOp_match m_GOr(const LHS &L, const RHS &R) { @@ -251,6 +300,12 @@ m_GLShr(const LHS &L, const RHS &R) { return BinaryOp_match(L, R); } +template +inline BinaryOp_match +m_GAShr(const LHS &L, const RHS &R) { + return BinaryOp_match(L, R); +} + // Helper for unary instructions (G_[ZSA]EXT/G_TRUNC) etc template struct UnaryOp_match { SrcTy L; @@ -384,6 +439,51 @@ struct CheckType { inline CheckType m_SpecificType(LLT Ty) { return Ty; } +template +struct TernaryOp_match { + Src0Ty Src0; + Src1Ty Src1; + Src2Ty Src2; + + TernaryOp_match(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2) + : Src0(Src0), Src1(Src1), Src2(Src2) {} + template + bool match(const MachineRegisterInfo &MRI, OpTy &&Op) { + MachineInstr *TmpMI; + if (mi_match(Op, MRI, m_MInstr(TmpMI))) { + if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 4) { + return (Src0.match(MRI, TmpMI->getOperand(1).getReg()) && + Src1.match(MRI, TmpMI->getOperand(2).getReg()) && + Src2.match(MRI, TmpMI->getOperand(3).getReg())); + } + } + return false; + } +}; +template +inline TernaryOp_match +m_GInsertVecElt(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2) { + return TernaryOp_match(Src0, Src1, Src2); +} + +/// Matches a register negated by a G_SUB. +/// G_SUB 0, %negated_reg +template +inline BinaryOp_match +m_Neg(const SrcTy &&Src) { + return m_GSub(m_ZeroInt(), Src); +} + +/// Matches a register not-ed by a G_XOR. +/// G_XOR %not_reg, -1 +template +inline BinaryOp_match +m_Not(const SrcTy &&Src) { + return m_GXor(Src, m_AllOnesInt()); +} + } // namespace GMIPatternMatch } // namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h index d6498345f25c..1ab4cd704824 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -18,9 +18,10 @@ #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/TargetOpcodes.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DebugLoc.h" - +#include "llvm/IR/Module.h" namespace llvm { @@ -223,6 +224,7 @@ class MachineIRBuilder { protected: void validateTruncExt(const LLT Dst, const LLT Src, bool IsExtend); + void validateUnaryOp(const LLT Res, const LLT Op0); void validateBinaryOp(const LLT Res, const LLT Op0, const LLT Op1); void validateShiftOp(const LLT Res, const LLT Op0, const LLT Op1); @@ -250,6 +252,11 @@ public: setDebugLoc(MI.getDebugLoc()); } + MachineIRBuilder(MachineInstr &MI, GISelChangeObserver &Observer) : + MachineIRBuilder(MI) { + setChangeObserver(Observer); + } + virtual ~MachineIRBuilder() = default; MachineIRBuilder(const MachineIRBuilderState &BState) : State(BState) {} @@ -729,7 +736,7 @@ public: /// depend on bit 0 (for now). /// /// \return The newly created instruction. - MachineInstrBuilder buildBrCond(Register Tst, MachineBasicBlock &Dest); + MachineInstrBuilder buildBrCond(const SrcOp &Tst, MachineBasicBlock &Dest); /// Build and insert G_BRINDIRECT \p Tgt /// @@ -813,7 +820,17 @@ public: /// /// \return a MachineInstrBuilder for the newly created instruction. MachineInstrBuilder buildLoad(const DstOp &Res, const SrcOp &Addr, - MachineMemOperand &MMO); + MachineMemOperand &MMO) { + return buildLoadInstr(TargetOpcode::G_LOAD, Res, Addr, MMO); + } + + /// Build and insert a G_LOAD instruction, while constructing the + /// MachineMemOperand. + MachineInstrBuilder + buildLoad(const DstOp &Res, const SrcOp &Addr, MachinePointerInfo PtrInfo, + Align Alignment, + MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone, + const AAMDNodes &AAInfo = AAMDNodes()); /// Build and insert `Res = Addr, MMO`. /// @@ -847,6 +864,14 @@ public: MachineInstrBuilder buildStore(const SrcOp &Val, const SrcOp &Addr, MachineMemOperand &MMO); + /// Build and insert a G_STORE instruction, while constructing the + /// MachineMemOperand. + MachineInstrBuilder + buildStore(const SrcOp &Val, const SrcOp &Addr, MachinePointerInfo PtrInfo, + Align Alignment, + MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone, + const AAMDNodes &AAInfo = AAMDNodes()); + /// Build and insert `Res0, ... = G_EXTRACT Src, Idx0`. /// /// \pre setBasicBlock or setMI must have been called. @@ -938,6 +963,23 @@ public: MachineInstrBuilder buildBuildVectorTrunc(const DstOp &Res, ArrayRef Ops); + /// Build and insert a vector splat of a scalar \p Src using a + /// G_INSERT_VECTOR_ELT and G_SHUFFLE_VECTOR idiom. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p Src must have the same type as the element type of \p Dst + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildShuffleSplat(const DstOp &Res, const SrcOp &Src); + + /// Build and insert \p Res = G_SHUFFLE_VECTOR \p Src1, \p Src2, \p Mask + /// + /// \pre setBasicBlock or setMI must have been called. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildShuffleVector(const DstOp &Res, const SrcOp &Src1, + const SrcOp &Src2, ArrayRef Mask); + /// Build and insert \p Res = G_CONCAT_VECTORS \p Op0, ... /// /// G_CONCAT_VECTORS creates a vector from the concatenation of 2 or more @@ -1521,6 +1563,13 @@ public: return buildInstr(TargetOpcode::G_FSUB, {Dst}, {Src0, Src1}, Flags); } + /// Build and insert \p Res = G_FDIV \p Op0, \p Op1 + MachineInstrBuilder buildFDiv(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1, + Optional Flags = None) { + return buildInstr(TargetOpcode::G_FDIV, {Dst}, {Src0, Src1}, Flags); + } + /// Build and insert \p Res = G_FMA \p Op0, \p Op1, \p Op2 MachineInstrBuilder buildFMA(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, const SrcOp &Src2, @@ -1583,6 +1632,13 @@ public: return buildInstr(TargetOpcode::G_FEXP2, {Dst}, {Src}, Flags); } + /// Build and insert \p Dst = G_FPOW \p Src0, \p Src1 + MachineInstrBuilder buildFPow(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1, + Optional Flags = None) { + return buildInstr(TargetOpcode::G_FPOW, {Dst}, {Src0, Src1}, Flags); + } + /// Build and insert \p Res = G_FCOPYSIGN \p Op0, \p Op1 MachineInstrBuilder buildFCopysign(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1) { @@ -1633,6 +1689,11 @@ public: return buildInstr(TargetOpcode::G_UMAX, {Dst}, {Src0, Src1}); } + /// Build and insert \p Dst = G_ABS \p Src + MachineInstrBuilder buildAbs(const DstOp &Dst, const SrcOp &Src) { + return buildInstr(TargetOpcode::G_ABS, {Dst}, {Src}); + } + /// Build and insert \p Res = G_JUMP_TABLE \p JTI /// /// G_JUMP_TABLE sets \p Res to the address of the jump table specified by @@ -1641,6 +1702,101 @@ public: /// \return a MachineInstrBuilder for the newly created instruction. MachineInstrBuilder buildJumpTable(const LLT PtrTy, unsigned JTI); + /// Build and insert \p Res = G_VECREDUCE_SEQ_FADD \p ScalarIn, \p VecIn + /// + /// \p ScalarIn is the scalar accumulator input to start the sequential + /// reduction operation of \p VecIn. + MachineInstrBuilder buildVecReduceSeqFAdd(const DstOp &Dst, + const SrcOp &ScalarIn, + const SrcOp &VecIn) { + return buildInstr(TargetOpcode::G_VECREDUCE_SEQ_FADD, {Dst}, + {ScalarIn, {VecIn}}); + } + + /// Build and insert \p Res = G_VECREDUCE_SEQ_FMUL \p ScalarIn, \p VecIn + /// + /// \p ScalarIn is the scalar accumulator input to start the sequential + /// reduction operation of \p VecIn. + MachineInstrBuilder buildVecReduceSeqFMul(const DstOp &Dst, + const SrcOp &ScalarIn, + const SrcOp &VecIn) { + return buildInstr(TargetOpcode::G_VECREDUCE_SEQ_FMUL, {Dst}, + {ScalarIn, {VecIn}}); + } + + /// Build and insert \p Res = G_VECREDUCE_FADD \p Src + /// + /// \p ScalarIn is the scalar accumulator input to the reduction operation of + /// \p VecIn. + MachineInstrBuilder buildVecReduceFAdd(const DstOp &Dst, + const SrcOp &ScalarIn, + const SrcOp &VecIn) { + return buildInstr(TargetOpcode::G_VECREDUCE_FADD, {Dst}, {ScalarIn, VecIn}); + } + + /// Build and insert \p Res = G_VECREDUCE_FMUL \p Src + /// + /// \p ScalarIn is the scalar accumulator input to the reduction operation of + /// \p VecIn. + MachineInstrBuilder buildVecReduceFMul(const DstOp &Dst, + const SrcOp &ScalarIn, + const SrcOp &VecIn) { + return buildInstr(TargetOpcode::G_VECREDUCE_FMUL, {Dst}, {ScalarIn, VecIn}); + } + + /// Build and insert \p Res = G_VECREDUCE_FMAX \p Src + MachineInstrBuilder buildVecReduceFMax(const DstOp &Dst, const SrcOp &Src) { + return buildInstr(TargetOpcode::G_VECREDUCE_FMAX, {Dst}, {Src}); + } + + /// Build and insert \p Res = G_VECREDUCE_FMIN \p Src + MachineInstrBuilder buildVecReduceFMin(const DstOp &Dst, const SrcOp &Src) { + return buildInstr(TargetOpcode::G_VECREDUCE_FMIN, {Dst}, {Src}); + } + /// Build and insert \p Res = G_VECREDUCE_ADD \p Src + MachineInstrBuilder buildVecReduceAdd(const DstOp &Dst, const SrcOp &Src) { + return buildInstr(TargetOpcode::G_VECREDUCE_ADD, {Dst}, {Src}); + } + + /// Build and insert \p Res = G_VECREDUCE_MUL \p Src + MachineInstrBuilder buildVecReduceMul(const DstOp &Dst, const SrcOp &Src) { + return buildInstr(TargetOpcode::G_VECREDUCE_MUL, {Dst}, {Src}); + } + + /// Build and insert \p Res = G_VECREDUCE_AND \p Src + MachineInstrBuilder buildVecReduceAnd(const DstOp &Dst, const SrcOp &Src) { + return buildInstr(TargetOpcode::G_VECREDUCE_AND, {Dst}, {Src}); + } + + /// Build and insert \p Res = G_VECREDUCE_OR \p Src + MachineInstrBuilder buildVecReduceOr(const DstOp &Dst, const SrcOp &Src) { + return buildInstr(TargetOpcode::G_VECREDUCE_OR, {Dst}, {Src}); + } + + /// Build and insert \p Res = G_VECREDUCE_XOR \p Src + MachineInstrBuilder buildVecReduceXor(const DstOp &Dst, const SrcOp &Src) { + return buildInstr(TargetOpcode::G_VECREDUCE_XOR, {Dst}, {Src}); + } + + /// Build and insert \p Res = G_VECREDUCE_SMAX \p Src + MachineInstrBuilder buildVecReduceSMax(const DstOp &Dst, const SrcOp &Src) { + return buildInstr(TargetOpcode::G_VECREDUCE_SMAX, {Dst}, {Src}); + } + + /// Build and insert \p Res = G_VECREDUCE_SMIN \p Src + MachineInstrBuilder buildVecReduceSMin(const DstOp &Dst, const SrcOp &Src) { + return buildInstr(TargetOpcode::G_VECREDUCE_SMIN, {Dst}, {Src}); + } + + /// Build and insert \p Res = G_VECREDUCE_UMAX \p Src + MachineInstrBuilder buildVecReduceUMax(const DstOp &Dst, const SrcOp &Src) { + return buildInstr(TargetOpcode::G_VECREDUCE_UMAX, {Dst}, {Src}); + } + + /// Build and insert \p Res = G_VECREDUCE_UMIN \p Src + MachineInstrBuilder buildVecReduceUMin(const DstOp &Dst, const SrcOp &Src) { + return buildInstr(TargetOpcode::G_VECREDUCE_UMIN, {Dst}, {Src}); + } virtual MachineInstrBuilder buildInstr(unsigned Opc, ArrayRef DstOps, ArrayRef SrcOps, Optional Flags = None); diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h index 8725d96efd82..da785406bc31 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h @@ -104,36 +104,37 @@ public: /// Currently the TableGen-like file would look like: /// \code /// PartialMapping[] = { - /// /*32-bit add*/ {0, 32, GPR}, // Scalar entry repeated for first vec elt. - /// /*2x32-bit add*/ {0, 32, GPR}, {32, 32, GPR}, - /// /*<2x32-bit> vadd {0, 64, VPR} + /// /*32-bit add*/ {0, 32, GPR}, // Scalar entry repeated for first + /// // vec elt. + /// /*2x32-bit add*/ {0, 32, GPR}, {32, 32, GPR}, + /// /*<2x32-bit> vadd*/ {0, 64, VPR} /// }; // PartialMapping duplicated. /// /// ValueMapping[] { - /// /*plain 32-bit add*/ {&PartialMapping[0], 1}, + /// /*plain 32-bit add*/ {&PartialMapping[0], 1}, /// /*expanded vadd on 2xadd*/ {&PartialMapping[1], 2}, - /// /*plain <2x32-bit> vadd*/ {&PartialMapping[3], 1} + /// /*plain <2x32-bit> vadd*/ {&PartialMapping[3], 1} /// }; /// \endcode /// /// With the array of pointer, we would have: /// \code /// PartialMapping[] = { - /// /*32-bit add lower */ {0, 32, GPR}, + /// /*32-bit add lower */ { 0, 32, GPR}, /// /*32-bit add upper */ {32, 32, GPR}, - /// /*<2x32-bit> vadd {0, 64, VPR} + /// /*<2x32-bit> vadd */ { 0, 64, VPR} /// }; // No more duplication. /// /// BreakDowns[] = { - /// /*AddBreakDown*/ &PartialMapping[0], + /// /*AddBreakDown*/ &PartialMapping[0], /// /*2xAddBreakDown*/ &PartialMapping[0], &PartialMapping[1], - /// /*VAddBreakDown*/ &PartialMapping[2] + /// /*VAddBreakDown*/ &PartialMapping[2] /// }; // Addresses of PartialMapping duplicated (smaller). /// /// ValueMapping[] { - /// /*plain 32-bit add*/ {&BreakDowns[0], 1}, + /// /*plain 32-bit add*/ {&BreakDowns[0], 1}, /// /*expanded vadd on 2xadd*/ {&BreakDowns[1], 2}, - /// /*plain <2x32-bit> vadd*/ {&BreakDowns[3], 1} + /// /*plain <2x32-bit> vadd*/ {&BreakDowns[3], 1} /// }; /// \endcode /// diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/Utils.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/Utils.h index 42d86917721a..68553ab5b1a8 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/Utils.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/Utils.h @@ -18,11 +18,12 @@ #include "llvm/CodeGen/Register.h" #include "llvm/Support/Alignment.h" #include "llvm/Support/LowLevelTypeImpl.h" -#include "llvm/Support/MachineValueType.h" +#include namespace llvm { class AnalysisUsage; +class GISelKnownBits; class MachineFunction; class MachineInstr; class MachineOperand; @@ -33,10 +34,10 @@ class MachineRegisterInfo; class MCInstrDesc; class RegisterBankInfo; class TargetInstrInfo; +class TargetLowering; class TargetPassConfig; class TargetRegisterInfo; class TargetRegisterClass; -class Twine; class ConstantFP; class APFloat; @@ -51,9 +52,10 @@ Register constrainRegToClass(MachineRegisterInfo &MRI, /// Constrain the Register operand OpIdx, so that it is now constrained to the /// TargetRegisterClass passed as an argument (RegClass). -/// If this fails, create a new virtual register in the correct class and -/// insert a COPY before \p InsertPt if it is a use or after if it is a -/// definition. The debug location of \p InsertPt is used for the new copy. +/// If this fails, create a new virtual register in the correct class and insert +/// a COPY before \p InsertPt if it is a use or after if it is a definition. +/// In both cases, the function also updates the register of RegMo. The debug +/// location of \p InsertPt is used for the new copy. /// /// \return The virtual register constrained to the right register class. Register constrainOperandRegClass(const MachineFunction &MF, @@ -63,12 +65,13 @@ Register constrainOperandRegClass(const MachineFunction &MF, const RegisterBankInfo &RBI, MachineInstr &InsertPt, const TargetRegisterClass &RegClass, - const MachineOperand &RegMO); + MachineOperand &RegMO); -/// Try to constrain Reg so that it is usable by argument OpIdx of the -/// provided MCInstrDesc \p II. If this fails, create a new virtual -/// register in the correct class and insert a COPY before \p InsertPt -/// if it is a use or after if it is a definition. +/// Try to constrain Reg so that it is usable by argument OpIdx of the provided +/// MCInstrDesc \p II. If this fails, create a new virtual register in the +/// correct class and insert a COPY before \p InsertPt if it is a use or after +/// if it is a definition. In both cases, the function also updates the register +/// of RegMo. /// This is equivalent to constrainOperandRegClass(..., RegClass, ...) /// with RegClass obtained from the MCInstrDesc. The debug location of \p /// InsertPt is used for the new copy. @@ -80,7 +83,7 @@ Register constrainOperandRegClass(const MachineFunction &MF, const TargetInstrInfo &TII, const RegisterBankInfo &RBI, MachineInstr &InsertPt, const MCInstrDesc &II, - const MachineOperand &RegMO, unsigned OpIdx); + MachineOperand &RegMO, unsigned OpIdx); /// Mutate the newly-selected instruction \p I to constrain its (possibly /// generic) virtual register operands to the instruction's register class. @@ -121,14 +124,19 @@ void reportGISelWarning(MachineFunction &MF, const TargetPassConfig &TPC, MachineOptimizationRemarkEmitter &MORE, MachineOptimizationRemarkMissed &R); +/// If \p VReg is defined by a G_CONSTANT, return the corresponding value. +Optional getConstantVRegVal(Register VReg, + const MachineRegisterInfo &MRI); + /// If \p VReg is defined by a G_CONSTANT fits in int64_t /// returns it. -Optional getConstantVRegVal(Register VReg, - const MachineRegisterInfo &MRI); +Optional getConstantVRegSExtVal(Register VReg, + const MachineRegisterInfo &MRI); + /// Simple struct used to hold a constant integer value and a virtual /// register. struct ValueAndVReg { - int64_t Value; + APInt Value; Register VReg; }; /// If \p VReg is defined by a statically evaluable chain of @@ -138,10 +146,13 @@ struct ValueAndVReg { /// When \p LookThroughInstrs == false this function behaves like /// getConstantVRegVal. /// When \p HandleFConstants == false the function bails on G_FCONSTANTs. +/// When \p LookThroughAnyExt == true the function treats G_ANYEXT same as +/// G_SEXT. Optional getConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs = true, - bool HandleFConstants = true); + bool HandleFConstants = true, + bool LookThroughAnyExt = false); const ConstantFP* getConstantFPVRegVal(Register VReg, const MachineRegisterInfo &MRI); @@ -151,9 +162,20 @@ const ConstantFP* getConstantFPVRegVal(Register VReg, MachineInstr *getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI); -/// Find the def instruction for \p Reg, folding away any trivial copies. Note -/// it may still return a COPY, if it changes the type. May return nullptr if \p -/// Reg is not a generic virtual register. +/// Simple struct used to hold a Register value and the instruction which +/// defines it. +struct DefinitionAndSourceRegister { + MachineInstr *MI; + Register Reg; +}; + +/// Find the def instruction for \p Reg, and underlying value Register folding +/// away any copies. +Optional +getDefSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI); + +/// Find the def instruction for \p Reg, folding away any trivial copies. May +/// return nullptr if \p Reg is not a generic virtual register. MachineInstr *getDefIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI); @@ -178,6 +200,12 @@ Optional ConstantFoldBinOp(unsigned Opcode, const Register Op1, Optional ConstantFoldExtOp(unsigned Opcode, const Register Op1, uint64_t Imm, const MachineRegisterInfo &MRI); +/// Test if the given value is known to have exactly one bit set. This differs +/// from computeKnownBits in that it doesn't necessarily determine which bit is +/// set. +bool isKnownToBeAPowerOfTwo(Register Val, const MachineRegisterInfo &MRI, + GISelKnownBits *KnownBits = nullptr); + /// Returns true if \p Val can be assumed to never be a NaN. If \p SNaN is true, /// this returns if \p Val can be assumed to never be a signaling NaN. bool isKnownNeverNaN(Register Val, const MachineRegisterInfo &MRI, @@ -190,17 +218,65 @@ inline bool isKnownNeverSNaN(Register Val, const MachineRegisterInfo &MRI) { Align inferAlignFromPtrInfo(MachineFunction &MF, const MachinePointerInfo &MPO); -/// Return the least common multiple type of \p Ty0 and \p Ty1, by changing -/// the number of vector elements or scalar bitwidth. The intent is a -/// G_MERGE_VALUES can be constructed from \p Ty0 elements, and unmerged into -/// \p Ty1. -LLT getLCMType(LLT Ty0, LLT Ty1); +/// Return a virtual register corresponding to the incoming argument register \p +/// PhysReg. This register is expected to have class \p RC, and optional type \p +/// RegTy. This assumes all references to the register will use the same type. +/// +/// If there is an existing live-in argument register, it will be returned. +/// This will also ensure there is a valid copy +Register getFunctionLiveInPhysReg(MachineFunction &MF, const TargetInstrInfo &TII, + MCRegister PhysReg, + const TargetRegisterClass &RC, + LLT RegTy = LLT()); + +/// Return the least common multiple type of \p OrigTy and \p TargetTy, by changing the +/// number of vector elements or scalar bitwidth. The intent is a +/// G_MERGE_VALUES, G_BUILD_VECTOR, or G_CONCAT_VECTORS can be constructed from +/// \p OrigTy elements, and unmerged into \p TargetTy +LLVM_READNONE +LLT getLCMType(LLT OrigTy, LLT TargetTy); -/// Return a type that is greatest common divisor of \p OrigTy and \p -/// TargetTy. This will either change the number of vector elements, or -/// bitwidth of scalars. The intent is the result type can be used as the -/// result of a G_UNMERGE_VALUES from \p OrigTy. +/// Return a type where the total size is the greatest common divisor of \p +/// OrigTy and \p TargetTy. This will try to either change the number of vector +/// elements, or bitwidth of scalars. The intent is the result type can be used +/// as the result of a G_UNMERGE_VALUES from \p OrigTy, and then some +/// combination of G_MERGE_VALUES, G_BUILD_VECTOR and G_CONCAT_VECTORS (possibly +/// with intermediate casts) can re-form \p TargetTy. +/// +/// If these are vectors with different element types, this will try to produce +/// a vector with a compatible total size, but the element type of \p OrigTy. If +/// this can't be satisfied, this will produce a scalar smaller than the +/// original vector elements. +/// +/// In the worst case, this returns LLT::scalar(1) +LLVM_READNONE LLT getGCDType(LLT OrigTy, LLT TargetTy); +/// \returns The splat index of a G_SHUFFLE_VECTOR \p MI when \p MI is a splat. +/// If \p MI is not a splat, returns None. +Optional getSplatIndex(MachineInstr &MI); + +/// Returns a scalar constant of a G_BUILD_VECTOR splat if it exists. +Optional getBuildVectorConstantSplat(const MachineInstr &MI, + const MachineRegisterInfo &MRI); + +/// Return true if the specified instruction is a G_BUILD_VECTOR or +/// G_BUILD_VECTOR_TRUNC where all of the elements are 0 or undef. +bool isBuildVectorAllZeros(const MachineInstr &MI, + const MachineRegisterInfo &MRI); + +/// Return true if the specified instruction is a G_BUILD_VECTOR or +/// G_BUILD_VECTOR_TRUNC where all of the elements are ~0 or undef. +bool isBuildVectorAllOnes(const MachineInstr &MI, + const MachineRegisterInfo &MRI); + +/// Returns true if given the TargetLowering's boolean contents information, +/// the value \p Val contains a true value. +bool isConstTrueVal(const TargetLowering &TLI, int64_t Val, bool IsVector, + bool IsFP); + +/// Returns an integer representing true, as defined by the +/// TargetBooleanContents. +int64_t getICmpTrueVal(const TargetLowering &TLI, bool IsVector, bool IsFP); } // End namespace llvm. #endif diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/ISDOpcodes.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/ISDOpcodes.h index 534f988c5e96..1974e2f842c9 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/ISDOpcodes.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/ISDOpcodes.h @@ -86,7 +86,16 @@ enum NodeType { /// the parent's frame or return address, and so on. FRAMEADDR, RETURNADDR, + + /// ADDROFRETURNADDR - Represents the llvm.addressofreturnaddress intrinsic. + /// This node takes no operand, returns a target-specific pointer to the + /// place in the stack frame where the return address of the current + /// function is stored. ADDROFRETURNADDR, + + /// SPONENTRY - Represents the llvm.sponentry intrinsic. Takes no argument + /// and returns the stack pointer value at the entry of the current + /// function calling this intrinsic. SPONENTRY, /// LOCAL_RECOVER - Represents the llvm.localrecover intrinsic. @@ -274,6 +283,16 @@ enum NodeType { ADDCARRY, SUBCARRY, + /// Carry-using overflow-aware nodes for multiple precision addition and + /// subtraction. These nodes take three operands: The first two are normal lhs + /// and rhs to the add or sub, and the third is a boolean indicating if there + /// is an incoming carry. They produce two results: the normal result of the + /// add or sub, and a boolean that indicates if an overflow occured (*not* + /// flag, because it may be a store to memory, etc.). If the type of the + /// boolean is not i1 then the high bits conform to getBooleanContents. + SADDO_CARRY, + SSUBO_CARRY, + /// RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition. /// These nodes take two operands: the normal LHS and RHS to the add. They /// produce two results: the normal result of the add, and a boolean that @@ -310,6 +329,16 @@ enum NodeType { SSUBSAT, USUBSAT, + /// RESULT = [US]SHLSAT(LHS, RHS) - Perform saturation left shift. The first + /// operand is the value to be shifted, and the second argument is the amount + /// to shift by. Both must be integers of the same bit width (W). If the true + /// value of LHS << RHS exceeds the largest value that can be represented by + /// W bits, the resulting value is this maximum value, Otherwise, if this + /// value is less than the smallest value that can be represented by W bits, + /// the resulting value is this minimum value. + SSHLSAT, + USHLSAT, + /// RESULT = [US]MULFIX(LHS, RHS, SCALE) - Perform fixed point multiplication /// on /// 2 integers with the same width and scale. SCALE represents the scale of @@ -504,7 +533,8 @@ enum NodeType { /// IDX is first scaled by the runtime scaling factor of T. Elements IDX /// through (IDX + num_elements(T) - 1) must be valid VECTOR indices. If this /// condition cannot be determined statically but is false at runtime, then - /// the result vector is undefined. + /// the result vector is undefined. The IDX parameter must be a vector index + /// constant type, which for most targets will be an integer pointer type. /// /// This operation supports extracting a fixed-width vector from a scalable /// vector, but not the other way around. @@ -587,6 +617,7 @@ enum NodeType { CTLZ, CTPOP, BITREVERSE, + PARITY, /// Bit counting operators with an undefined result for zero inputs. CTTZ_ZERO_UNDEF, @@ -703,6 +734,21 @@ enum NodeType { FP_TO_SINT, FP_TO_UINT, + /// FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a + /// signed or unsigned integer type with the bit width given in operand 1 with + /// the following semantics: + /// + /// * If the value is NaN, zero is returned. + /// * If the value is larger/smaller than the largest/smallest integer, + /// the largest/smallest integer is returned (saturation). + /// * Otherwise the result of rounding the value towards zero is returned. + /// + /// The width given in operand 1 must be equal to, or smaller than, the scalar + /// result type width. It may end up being smaller than the result witdh as a + /// result of integer type legalization. + FP_TO_SINT_SAT, + FP_TO_UINT_SAT, + /// X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type /// down to the precision of the destination VT. TRUNC is a flag, which is /// always an integer that is zero or one. If TRUNC is 0, this is a @@ -844,13 +890,18 @@ enum NodeType { /// BRCOND - Conditional branch. The first operand is the chain, the /// second is the condition, the third is the block to branch to if the /// condition is true. If the type of the condition is not i1, then the - /// high bits must conform to getBooleanContents. + /// high bits must conform to getBooleanContents. If the condition is undef, + /// it nondeterministically jumps to the block. + /// TODO: Its semantics w.r.t undef requires further discussion; we need to + /// make it sure that it is consistent with optimizations in MIR & the + /// meaning of IMPLICIT_DEF. See https://reviews.llvm.org/D92015 BRCOND, /// BR_CC - Conditional branch. The behavior is like that of SELECT_CC, in /// that the condition is represented as condition code, and two nodes to /// compare, rather than as a combined SetCC node. The operands in order - /// are chain, cc, lhs, rhs, block to branch to if condition is true. + /// are chain, cc, lhs, rhs, block to branch to if condition is true. If + /// condition is undef, it nondeterministically jumps to the block. BR_CC, /// INLINEASM - Represents an inline asm block. This node always has two @@ -981,6 +1032,9 @@ enum NodeType { /// DEBUGTRAP - Trap intended to get the attention of a debugger. DEBUGTRAP, + /// UBSANTRAP - Trap with an immediate describing the kind of sanitizer failure. + UBSANTRAP, + /// PREFETCH - This corresponds to a prefetch intrinsic. The first operand /// is the chain. The other operands are the address to prefetch, /// read / write specifier, locality specifier and instruction / data cache @@ -1075,6 +1129,10 @@ enum NodeType { /// known nonzero constant. The only operand here is the chain. GET_DYNAMIC_AREA_OFFSET, + /// Pseudo probe for AutoFDO, as a place holder in a basic block to improve + /// the sample counts quality. + PSEUDO_PROBE, + /// VSCALE(IMM) - Returns the runtime scaling factor used to calculate the /// number of elements within a scalable vector. IMM is a constant integer /// multiplier that is applied to the runtime value. @@ -1082,12 +1140,25 @@ enum NodeType { /// Generic reduction nodes. These nodes represent horizontal vector /// reduction operations, producing a scalar result. - /// The STRICT variants perform reductions in sequential order. The first + /// The SEQ variants perform reductions in sequential order. The first /// operand is an initial scalar accumulator value, and the second operand /// is the vector to reduce. - VECREDUCE_STRICT_FADD, - VECREDUCE_STRICT_FMUL, - /// These reductions are non-strict, and have a single vector operand. + /// E.g. RES = VECREDUCE_SEQ_FADD f32 ACC, <4 x f32> SRC_VEC + /// ... is equivalent to + /// RES = (((ACC + SRC_VEC[0]) + SRC_VEC[1]) + SRC_VEC[2]) + SRC_VEC[3] + VECREDUCE_SEQ_FADD, + VECREDUCE_SEQ_FMUL, + + /// These reductions have relaxed evaluation order semantics, and have a + /// single vector operand. The order of evaluation is unspecified. For + /// pow-of-2 vectors, one valid legalizer expansion is to use a tree + /// reduction, i.e.: + /// For RES = VECREDUCE_FADD <8 x f16> SRC_VEC + /// PART_RDX = FADD SRC_VEC[0:3], SRC_VEC[4:7] + /// PART_RDX2 = FADD PART_RDX[0:1], PART_RDX[2:3] + /// RES = FADD PART_RDX2[0], PART_RDX2[1] + /// For non-pow-2 vectors, this can be computed by extracting each element + /// and performing the operation as if it were scalarized. VECREDUCE_FADD, VECREDUCE_FMUL, /// FMIN/FMAX nodes can have flags, for NaN/NoNaN variants. @@ -1106,6 +1177,10 @@ enum NodeType { VECREDUCE_UMAX, VECREDUCE_UMIN, +// Vector Predication +#define BEGIN_REGISTER_VP_SDNODE(VPSDID, ...) VPSDID, +#include "llvm/IR/VPIntrinsics.def" + /// BUILTIN_OP_END - This must be the last enum value in this list. /// The target-specific pre-isel opcode values start here. BUILTIN_OP_END @@ -1122,6 +1197,19 @@ static const int FIRST_TARGET_STRICTFP_OPCODE = BUILTIN_OP_END + 400; /// be used with SelectionDAG::getMemIntrinsicNode. static const int FIRST_TARGET_MEMORY_OPCODE = BUILTIN_OP_END + 500; +/// Get underlying scalar opcode for VECREDUCE opcode. +/// For example ISD::AND for ISD::VECREDUCE_AND. +NodeType getVecReduceBaseOpcode(unsigned VecReduceOpcode); + +/// Whether this is a vector-predicated Opcode. +bool isVPOpcode(unsigned Opcode); + +/// The operand position of the vector mask. +Optional getVPMaskIdx(unsigned Opcode); + +/// The operand position of the explicit vector length parameter. +Optional getVPExplicitVectorLengthIdx(unsigned Opcode); + //===--------------------------------------------------------------------===// /// MemIndexedMode enum - This enum defines the load / store indexed /// addressing modes. @@ -1244,6 +1332,12 @@ inline bool isUnsignedIntSetCC(CondCode Code) { return Code == SETUGT || Code == SETUGE || Code == SETULT || Code == SETULE; } +/// Return true if this is a setcc instruction that performs an equality +/// comparison when used with integer operands. +inline bool isIntEqualitySetCC(CondCode Code) { + return Code == SETEQ || Code == SETNE; +} + /// Return true if the specified condition returns true if the two operands to /// the condition are equal. Note that if one of the two operands is a NaN, /// this value is meaningless. diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/LexicalScopes.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/LexicalScopes.h index bac850d327ef..9617ba80c138 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/LexicalScopes.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/LexicalScopes.h @@ -194,9 +194,6 @@ public: return I != LexicalScopeMap.end() ? &I->second : nullptr; } - /// dump - Print data structures to dbgs(). - void dump() const; - /// getOrCreateAbstractScope - Find or create an abstract lexical scope. LexicalScope *getOrCreateAbstractScope(const DILocalScope *Scope); diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/LiveInterval.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/LiveInterval.h index 0764257125e6..c2b158ac1b7f 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/LiveInterval.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/LiveInterval.h @@ -25,6 +25,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/iterator_range.h" +#include "llvm/CodeGen/Register.h" #include "llvm/CodeGen/SlotIndexes.h" #include "llvm/MC/LaneBitmask.h" #include "llvm/Support/Allocator.h" @@ -597,10 +598,9 @@ namespace llvm { /// @p End. bool isUndefIn(ArrayRef Undefs, SlotIndex Begin, SlotIndex End) const { - return std::any_of(Undefs.begin(), Undefs.end(), - [Begin,End] (SlotIndex Idx) -> bool { - return Begin <= Idx && Idx < End; - }); + return llvm::any_of(Undefs, [Begin, End](SlotIndex Idx) -> bool { + return Begin <= Idx && Idx < End; + }); } /// Flush segment set into the regular segment vector. @@ -704,12 +704,16 @@ namespace llvm { private: SubRange *SubRanges = nullptr; ///< Single linked list of subregister live /// ranges. + const Register Reg; // the register or stack slot of this interval. + float Weight = 0.0; // weight of this interval public: - const unsigned reg; // the register or stack slot of this interval. - float weight; // weight of this interval + Register reg() const { return Reg; } + float weight() const { return Weight; } + void incrementWeight(float Inc) { Weight += Inc; } + void setWeight(float Value) { Weight = Value; } - LiveInterval(unsigned Reg, float Weight) : reg(Reg), weight(Weight) {} + LiveInterval(unsigned Reg, float Weight) : Reg(Reg), Weight(Weight) {} ~LiveInterval() { clearSubRanges(); @@ -731,10 +735,10 @@ namespace llvm { ++*this; return res; } - bool operator!=(const SingleLinkedListIterator &Other) { + bool operator!=(const SingleLinkedListIterator &Other) const { return P != Other.operator->(); } - bool operator==(const SingleLinkedListIterator &Other) { + bool operator==(const SingleLinkedListIterator &Other) const { return P == Other.operator->(); } T &operator*() const { @@ -806,14 +810,10 @@ namespace llvm { unsigned getSize() const; /// isSpillable - Can this interval be spilled? - bool isSpillable() const { - return weight != huge_valf; - } + bool isSpillable() const { return Weight != huge_valf; } /// markNotSpillable - Mark interval as not spillable - void markNotSpillable() { - weight = huge_valf; - } + void markNotSpillable() { Weight = huge_valf; } /// For a given lane mask @p LaneMask, compute indexes at which the /// lane is marked undefined by subregister definitions. @@ -834,7 +834,7 @@ namespace llvm { /// function will be applied to the L0010 and L0008 subranges. /// /// \p Indexes and \p TRI are required to clean up the VNIs that - /// don't defne the related lane masks after they get shrunk. E.g., + /// don't define the related lane masks after they get shrunk. E.g., /// when L000F gets split into L0007 and L0008 maybe only a subset /// of the VNIs that defined L000F defines L0007. /// @@ -870,7 +870,7 @@ namespace llvm { bool operator<(const LiveInterval& other) const { const SlotIndex &thisIndex = beginIndex(); const SlotIndex &otherIndex = other.beginIndex(); - return std::tie(thisIndex, reg) < std::tie(otherIndex, other.reg); + return std::tie(thisIndex, Reg) < std::tie(otherIndex, other.Reg); } void print(raw_ostream &OS) const; diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/LiveIntervalUnion.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/LiveIntervalUnion.h index c555763a4ec2..ad9e06d2bcf0 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/LiveIntervalUnion.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/LiveIntervalUnion.h @@ -104,6 +104,9 @@ public: void verify(LiveVirtRegBitSet& VisitedVRegs); #endif + // Get any virtual register that is assign to this physical unit + LiveInterval *getOneVReg() const; + /// Query interferences between a single live virtual register and a live /// interval union. class Query { diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/LiveIntervals.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/LiveIntervals.h index 945a40829714..fa08166791b0 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/LiveIntervals.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/LiveIntervals.h @@ -114,8 +114,8 @@ class VirtRegMap; LiveInterval &getInterval(Register Reg) { if (hasInterval(Reg)) return *VirtRegIntervals[Reg.id()]; - else - return createAndComputeVirtRegInterval(Reg); + + return createAndComputeVirtRegInterval(Reg); } const LiveInterval &getInterval(Register Reg) const { @@ -142,14 +142,14 @@ class VirtRegMap; } /// Interval removal. - void removeInterval(unsigned Reg) { + void removeInterval(Register Reg) { delete VirtRegIntervals[Reg]; VirtRegIntervals[Reg] = nullptr; } /// Given a register and an instruction, adds a live segment from that /// instruction to the end of its MBB. - LiveInterval::Segment addSegmentToEndOfBlock(unsigned reg, + LiveInterval::Segment addSegmentToEndOfBlock(Register Reg, MachineInstr &startInst); /// After removing some uses of a register, shrink its live range to just @@ -167,7 +167,7 @@ class VirtRegMap; /// the lane mask of the subregister range. /// This may leave the subrange empty which needs to be cleaned up with /// LiveInterval::removeEmptySubranges() afterwards. - void shrinkToUses(LiveInterval::SubRange &SR, unsigned Reg); + void shrinkToUses(LiveInterval::SubRange &SR, Register Reg); /// Extend the live range \p LR to reach all points in \p Indices. The /// points in the \p Indices array must be jointly dominated by the union @@ -256,9 +256,8 @@ class VirtRegMap; return Indexes->getMBBFromIndex(index); } - void insertMBBInMaps(MachineBasicBlock *MBB, - MachineInstr *InsertionPoint = nullptr) { - Indexes->insertMBBInMaps(MBB, InsertionPoint); + void insertMBBInMaps(MachineBasicBlock *MBB) { + Indexes->insertMBBInMaps(MBB); assert(unsigned(MBB->getNumber()) == RegMaskBlocks.size() && "Blocks must be added in order."); RegMaskBlocks.push_back(std::make_pair(RegMaskSlots.size(), 0)); @@ -423,7 +422,7 @@ class VirtRegMap; /// Reg. Subsequent uses should rely on on-demand recomputation. \note This /// method can result in inconsistent liveness tracking if multiple phyical /// registers share a regunit, and should be used cautiously. - void removeAllRegUnitsForPhysReg(unsigned Reg) { + void removeAllRegUnitsForPhysReg(MCRegister Reg) { for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) removeRegUnit(*Units); } @@ -431,7 +430,7 @@ class VirtRegMap; /// Remove value numbers and related live segments starting at position /// \p Pos that are part of any liverange of physical register \p Reg or one /// of its subregisters. - void removePhysRegDefAt(unsigned Reg, SlotIndex Pos); + void removePhysRegDefAt(MCRegister Reg, SlotIndex Pos); /// Remove value number and related live segments of \p LI and its subranges /// that start at position \p Pos. @@ -463,7 +462,7 @@ class VirtRegMap; bool computeDeadValues(LiveInterval &LI, SmallVectorImpl *dead); - static LiveInterval* createInterval(unsigned Reg); + static LiveInterval *createInterval(Register Reg); void printInstrs(raw_ostream &O) const; void dumpInstrs() const; @@ -474,7 +473,7 @@ class VirtRegMap; using ShrinkToUsesWorkList = SmallVector, 16>; void extendSegmentsToUses(LiveRange &Segments, - ShrinkToUsesWorkList &WorkList, unsigned Reg, + ShrinkToUsesWorkList &WorkList, Register Reg, LaneBitmask LaneMask); /// Helper function for repairIntervalsInRange(), walks backwards and @@ -484,7 +483,7 @@ class VirtRegMap; void repairOldRegInRange(MachineBasicBlock::iterator Begin, MachineBasicBlock::iterator End, const SlotIndex endIdx, LiveRange &LR, - unsigned Reg, + Register Reg, LaneBitmask LaneMask = LaneBitmask::getAll()); class HMEditor; diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/LiveRangeEdit.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/LiveRangeEdit.h index 3c4273130ab2..87d48adc7f27 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/LiveRangeEdit.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/LiveRangeEdit.h @@ -56,14 +56,14 @@ public: /// Called when a virtual register is no longer used. Return false to defer /// its deletion from LiveIntervals. - virtual bool LRE_CanEraseVirtReg(unsigned) { return true; } + virtual bool LRE_CanEraseVirtReg(Register) { return true; } /// Called before shrinking the live range of a virtual register. - virtual void LRE_WillShrinkVirtReg(unsigned) {} + virtual void LRE_WillShrinkVirtReg(Register) {} /// Called after cloning a virtual register. /// This is used for new registers representing connected components of Old. - virtual void LRE_DidCloneVirtReg(unsigned New, unsigned Old) {} + virtual void LRE_DidCloneVirtReg(Register New, Register Old) {} }; private: @@ -152,7 +152,7 @@ public: return *Parent; } - Register getReg() const { return getParent().reg; } + Register getReg() const { return getParent().reg(); } /// Iterator for accessing the new registers added by this edit. using iterator = SmallVectorImpl::const_iterator; diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/LiveRegMatrix.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/LiveRegMatrix.h index ab4d44f9a611..fc67bce329ab 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/LiveRegMatrix.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/LiveRegMatrix.h @@ -104,19 +104,19 @@ public: /// If this function returns IK_Free, it is legal to assign(VirtReg, PhysReg). /// When there is more than one kind of interference, the InterferenceKind /// with the highest enum value is returned. - InterferenceKind checkInterference(LiveInterval &VirtReg, unsigned PhysReg); + InterferenceKind checkInterference(LiveInterval &VirtReg, MCRegister PhysReg); /// Check for interference in the segment [Start, End) that may prevent /// assignment to PhysReg. If this function returns true, there is /// interference in the segment [Start, End) of some other interval already /// assigned to PhysReg. If this function returns false, PhysReg is free at /// the segment [Start, End). - bool checkInterference(SlotIndex Start, SlotIndex End, unsigned PhysReg); + bool checkInterference(SlotIndex Start, SlotIndex End, MCRegister PhysReg); /// Assign VirtReg to PhysReg. /// This will mark VirtReg's live range as occupied in the LiveRegMatrix and /// update VirtRegMap. The live range is expected to be available in PhysReg. - void assign(LiveInterval &VirtReg, unsigned PhysReg); + void assign(LiveInterval &VirtReg, MCRegister PhysReg); /// Unassign VirtReg from its PhysReg. /// Assuming that VirtReg was previously assigned to a PhysReg, this undoes @@ -124,7 +124,7 @@ public: void unassign(LiveInterval &VirtReg); /// Returns true if the given \p PhysReg has any live intervals assigned. - bool isPhysRegUsed(unsigned PhysReg) const; + bool isPhysRegUsed(MCRegister PhysReg) const; //===--------------------------------------------------------------------===// // Low-level interface. @@ -136,22 +136,25 @@ public: /// Check for regmask interference only. /// Return true if VirtReg crosses a regmask operand that clobbers PhysReg. /// If PhysReg is null, check if VirtReg crosses any regmask operands. - bool checkRegMaskInterference(LiveInterval &VirtReg, unsigned PhysReg = 0); + bool checkRegMaskInterference(LiveInterval &VirtReg, + MCRegister PhysReg = MCRegister::NoRegister); /// Check for regunit interference only. /// Return true if VirtReg overlaps a fixed assignment of one of PhysRegs's /// register units. - bool checkRegUnitInterference(LiveInterval &VirtReg, unsigned PhysReg); + bool checkRegUnitInterference(LiveInterval &VirtReg, MCRegister PhysReg); /// Query a line of the assigned virtual register matrix directly. /// Use MCRegUnitIterator to enumerate all regunits in the desired PhysReg. /// This returns a reference to an internal Query data structure that is only /// valid until the next query() call. - LiveIntervalUnion::Query &query(const LiveRange &LR, unsigned RegUnit); + LiveIntervalUnion::Query &query(const LiveRange &LR, MCRegister RegUnit); /// Directly access the live interval unions per regunit. /// This returns an array indexed by the regunit number. LiveIntervalUnion *getLiveUnions() { return &Matrix[0]; } + + Register getOneVReg(unsigned PhysReg) const; }; } // end namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/LiveRegUnits.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/LiveRegUnits.h index 1ed091e3bb5e..39a1ec461ef6 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/LiveRegUnits.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/LiveRegUnits.h @@ -15,7 +15,7 @@ #define LLVM_CODEGEN_LIVEREGUNITS_H #include "llvm/ADT/BitVector.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/MachineInstrBundle.h" #include "llvm/CodeGen/TargetRegisterInfo.h" #include "llvm/MC/LaneBitmask.h" #include "llvm/MC/MCRegisterInfo.h" @@ -67,7 +67,6 @@ public: UsedRegUnits.addReg(Reg); } } - return; } /// Initialize and clear the set. diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/LiveVariables.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/LiveVariables.h index efb0fa85a0fe..9b0667bbbeb0 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/LiveVariables.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/LiveVariables.h @@ -105,8 +105,7 @@ public: /// isLiveIn - Is Reg live in to MBB? This means that Reg is live through /// MBB, or it is killed in MBB. If Reg is only used by PHI instructions in /// MBB, it is not considered live in. - bool isLiveIn(const MachineBasicBlock &MBB, - unsigned Reg, + bool isLiveIn(const MachineBasicBlock &MBB, Register Reg, MachineRegisterInfo &MRI); void dump() const; @@ -149,25 +148,25 @@ private: // Intermediate data structures /// HandlePhysRegKill - Add kills of Reg and its sub-registers to the /// uses. Pay special attention to the sub-register uses which may come below /// the last use of the whole register. - bool HandlePhysRegKill(unsigned Reg, MachineInstr *MI); + bool HandlePhysRegKill(Register Reg, MachineInstr *MI); /// HandleRegMask - Call HandlePhysRegKill for all registers clobbered by Mask. void HandleRegMask(const MachineOperand&); - void HandlePhysRegUse(unsigned Reg, MachineInstr &MI); - void HandlePhysRegDef(unsigned Reg, MachineInstr *MI, + void HandlePhysRegUse(Register Reg, MachineInstr &MI); + void HandlePhysRegDef(Register Reg, MachineInstr *MI, SmallVectorImpl &Defs); void UpdatePhysRegDefs(MachineInstr &MI, SmallVectorImpl &Defs); /// FindLastRefOrPartRef - Return the last reference or partial reference of /// the specified register. - MachineInstr *FindLastRefOrPartRef(unsigned Reg); + MachineInstr *FindLastRefOrPartRef(Register Reg); /// FindLastPartialDef - Return the last partial def of the specified /// register. Also returns the sub-registers that're defined by the /// instruction. - MachineInstr *FindLastPartialDef(unsigned Reg, - SmallSet &PartDefRegs); + MachineInstr *FindLastPartialDef(Register Reg, + SmallSet &PartDefRegs); /// analyzePHINodes - Gather information about the PHI nodes in here. In /// particular, we want to map the variable information of a virtual @@ -184,21 +183,21 @@ public: /// RegisterDefIsDead - Return true if the specified instruction defines the /// specified register, but that definition is dead. - bool RegisterDefIsDead(MachineInstr &MI, unsigned Reg) const; + bool RegisterDefIsDead(MachineInstr &MI, Register Reg) const; //===--------------------------------------------------------------------===// // API to update live variable information /// replaceKillInstruction - Update register kill info by replacing a kill /// instruction with a new one. - void replaceKillInstruction(unsigned Reg, MachineInstr &OldMI, + void replaceKillInstruction(Register Reg, MachineInstr &OldMI, MachineInstr &NewMI); /// addVirtualRegisterKilled - Add information about the fact that the /// specified register is killed after being used by the specified /// instruction. If AddIfNotFound is true, add a implicit operand if it's /// not found. - void addVirtualRegisterKilled(unsigned IncomingReg, MachineInstr &MI, + void addVirtualRegisterKilled(Register IncomingReg, MachineInstr &MI, bool AddIfNotFound = false) { if (MI.addRegisterKilled(IncomingReg, TRI, AddIfNotFound)) getVarInfo(IncomingReg).Kills.push_back(&MI); @@ -208,14 +207,14 @@ public: /// register from the live variable information. Returns true if the /// variable was marked as killed by the specified instruction, /// false otherwise. - bool removeVirtualRegisterKilled(unsigned reg, MachineInstr &MI) { - if (!getVarInfo(reg).removeKill(MI)) + bool removeVirtualRegisterKilled(Register Reg, MachineInstr &MI) { + if (!getVarInfo(Reg).removeKill(MI)) return false; bool Removed = false; for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { MachineOperand &MO = MI.getOperand(i); - if (MO.isReg() && MO.isKill() && MO.getReg() == reg) { + if (MO.isReg() && MO.isKill() && MO.getReg() == Reg) { MO.setIsKill(false); Removed = true; break; @@ -234,7 +233,7 @@ public: /// addVirtualRegisterDead - Add information about the fact that the specified /// register is dead after being used by the specified instruction. If /// AddIfNotFound is true, add a implicit operand if it's not found. - void addVirtualRegisterDead(unsigned IncomingReg, MachineInstr &MI, + void addVirtualRegisterDead(Register IncomingReg, MachineInstr &MI, bool AddIfNotFound = false) { if (MI.addRegisterDead(IncomingReg, TRI, AddIfNotFound)) getVarInfo(IncomingReg).Kills.push_back(&MI); @@ -244,14 +243,14 @@ public: /// register from the live variable information. Returns true if the /// variable was marked dead at the specified instruction, false /// otherwise. - bool removeVirtualRegisterDead(unsigned reg, MachineInstr &MI) { - if (!getVarInfo(reg).removeKill(MI)) + bool removeVirtualRegisterDead(Register Reg, MachineInstr &MI) { + if (!getVarInfo(Reg).removeKill(MI)) return false; bool Removed = false; for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { MachineOperand &MO = MI.getOperand(i); - if (MO.isReg() && MO.isDef() && MO.getReg() == reg) { + if (MO.isReg() && MO.isDef() && MO.getReg() == Reg) { MO.setIsDead(false); Removed = true; break; @@ -270,24 +269,25 @@ public: /// getVarInfo - Return the VarInfo structure for the specified VIRTUAL /// register. - VarInfo &getVarInfo(unsigned RegIdx); + VarInfo &getVarInfo(Register Reg); void MarkVirtRegAliveInBlock(VarInfo& VRInfo, MachineBasicBlock* DefBlock, MachineBasicBlock *BB); - void MarkVirtRegAliveInBlock(VarInfo& VRInfo, MachineBasicBlock* DefBlock, + void MarkVirtRegAliveInBlock(VarInfo &VRInfo, MachineBasicBlock *DefBlock, MachineBasicBlock *BB, - std::vector &WorkList); - void HandleVirtRegDef(unsigned reg, MachineInstr &MI); - void HandleVirtRegUse(unsigned reg, MachineBasicBlock *MBB, MachineInstr &MI); + SmallVectorImpl &WorkList); + + void HandleVirtRegDef(Register reg, MachineInstr &MI); + void HandleVirtRegUse(Register reg, MachineBasicBlock *MBB, MachineInstr &MI); - bool isLiveIn(unsigned Reg, const MachineBasicBlock &MBB) { + bool isLiveIn(Register Reg, const MachineBasicBlock &MBB) { return getVarInfo(Reg).isLiveIn(MBB, Reg, *MRI); } /// isLiveOut - Determine if Reg is live out from MBB, when not considering /// PHI nodes. This means that Reg is either killed by a successor block or /// passed through one. - bool isLiveOut(unsigned Reg, const MachineBasicBlock &MBB); + bool isLiveOut(Register Reg, const MachineBasicBlock &MBB); /// addNewBlock - Add a new basic block BB between DomBB and SuccBB. All /// variables that are live out of DomBB and live into SuccBB will be marked @@ -303,10 +303,10 @@ public: std::vector> &LiveInSets); /// isPHIJoin - Return true if Reg is a phi join register. - bool isPHIJoin(unsigned Reg) { return PHIJoins.test(Reg); } + bool isPHIJoin(Register Reg) { return PHIJoins.test(Reg.id()); } /// setPHIJoin - Mark Reg as a phi join register. - void setPHIJoin(unsigned Reg) { PHIJoins.set(Reg); } + void setPHIJoin(Register Reg) { PHIJoins.set(Reg.id()); } }; } // End llvm namespace diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/LowLevelType.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/LowLevelType.h index 6295d86f749c..402fa2ce61e7 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/LowLevelType.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/LowLevelType.h @@ -23,6 +23,7 @@ namespace llvm { class DataLayout; class Type; +struct fltSemantics; /// Construct a low-level type based on an LLVM type. LLT getLLTForType(Type &Ty, const DataLayout &DL); @@ -35,6 +36,9 @@ MVT getMVTForLLT(LLT Ty); /// scalarable vector types, and will assert if used. LLT getLLTForMVT(MVT Ty); +/// Get the appropriate floating point arithmetic semantic based on the bit size +/// of the given scalar LLT. +const llvm::fltSemantics &getFltSemanticForLLT(LLT Ty); } #endif // LLVM_CODEGEN_LOWLEVELTYPE_H diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/MBFIWrapper.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/MBFIWrapper.h index 062431a6f96b..bcbf3eedf59d 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/MBFIWrapper.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/MBFIWrapper.h @@ -28,6 +28,8 @@ class MBFIWrapper { BlockFrequency getBlockFreq(const MachineBasicBlock *MBB) const; void setBlockFreq(const MachineBasicBlock *MBB, BlockFrequency F); + Optional getBlockProfileCount(const MachineBasicBlock *MBB) const; + raw_ostream &printBlockFreq(raw_ostream &OS, const MachineBasicBlock *MBB) const; raw_ostream &printBlockFreq(raw_ostream &OS, diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/MIRFormatter.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/MIRFormatter.h index e57c32c5ae61..9cb92091db50 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/MIRFormatter.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/MIRFormatter.h @@ -14,11 +14,15 @@ #ifndef LLVM_CODEGEN_MIRFORMATTER_H #define LLVM_CODEGEN_MIRFORMATTER_H -#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/ADT/Optional.h" #include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/Support/raw_ostream.h" +#include namespace llvm { +class MachineFunction; +class MachineInstr; struct PerFunctionMIParsingState; struct SlotMapping; diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/MIRYamlMapping.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/MIRYamlMapping.h index c68b073ebb8c..4a7406473b11 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/MIRYamlMapping.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/MIRYamlMapping.h @@ -159,6 +159,22 @@ template <> struct ScalarTraits { static QuotingType mustQuote(StringRef) { return QuotingType::None; } }; +template <> struct ScalarTraits { + static void output(const Align &Alignment, void *, llvm::raw_ostream &OS) { + OS << Alignment.value(); + } + static StringRef input(StringRef Scalar, void *, Align &Alignment) { + unsigned long long N; + if (getAsUnsignedInteger(Scalar, 10, N)) + return "invalid number"; + if (!isPowerOf2_64(N)) + return "must be a power of two"; + Alignment = Align(N); + return StringRef(); + } + static QuotingType mustQuote(StringRef) { return QuotingType::None; } +}; + } // end namespace yaml } // end namespace llvm @@ -331,7 +347,7 @@ struct ScalarEnumerationTraits { static void enumeration(yaml::IO &IO, TargetStackID::Value &ID) { IO.enumCase(ID, "default", TargetStackID::Default); IO.enumCase(ID, "sgpr-spill", TargetStackID::SGPRSpill); - IO.enumCase(ID, "sve-vec", TargetStackID::SVEVector); + IO.enumCase(ID, "scalable-vector", TargetStackID::ScalableVector); IO.enumCase(ID, "noalloc", TargetStackID::NoAlloc); } }; @@ -425,6 +441,36 @@ template <> struct MappingTraits { static const bool flow = true; }; +/// Serializable representation of debug value substitutions. +struct DebugValueSubstitution { + unsigned SrcInst; + unsigned SrcOp; + unsigned DstInst; + unsigned DstOp; + + bool operator==(const DebugValueSubstitution &Other) const { + return std::tie(SrcInst, SrcOp, DstInst, DstOp) == + std::tie(Other.SrcInst, Other.SrcOp, Other.DstInst, Other.DstOp); + } +}; + +template <> struct MappingTraits { + static void mapping(IO &YamlIO, DebugValueSubstitution &Sub) { + YamlIO.mapRequired("srcinst", Sub.SrcInst); + YamlIO.mapRequired("srcop", Sub.SrcOp); + YamlIO.mapRequired("dstinst", Sub.DstInst); + YamlIO.mapRequired("dstop", Sub.DstOp); + } + + static const bool flow = true; +}; +} // namespace yaml +} // namespace llvm + +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::DebugValueSubstitution) + +namespace llvm { +namespace yaml { struct MachineConstantPoolValue { UnsignedValue ID; StringValue Value; @@ -609,6 +655,7 @@ struct MachineFunction { std::vector Constants; /// Constant pool. std::unique_ptr MachineFuncInfo; std::vector CallSitesInfo; + std::vector DebugValueSubstitutions; MachineJumpTable JumpTableInfo; BlockStringValue Body; }; @@ -637,6 +684,8 @@ template <> struct MappingTraits { std::vector()); YamlIO.mapOptional("callSites", MF.CallSitesInfo, std::vector()); + YamlIO.mapOptional("debugValueSubstitutions", MF.DebugValueSubstitutions, + std::vector()); YamlIO.mapOptional("constants", MF.Constants, std::vector()); YamlIO.mapOptional("machineFunctionInfo", MF.MachineFuncInfo); diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineBasicBlock.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineBasicBlock.h index d6cb7211cf70..2bad64c6cc2e 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineBasicBlock.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineBasicBlock.h @@ -40,6 +40,7 @@ class Printable; class SlotIndexes; class StringRef; class raw_ostream; +class LiveIntervals; class TargetRegisterClass; class TargetRegisterInfo; @@ -174,8 +175,9 @@ private: /// is only computed once and is cached. mutable MCSymbol *CachedMCSymbol = nullptr; - /// Used during basic block sections to mark the end of a basic block. - MCSymbol *EndMCSymbol = nullptr; + /// Marks the end of the basic block. Used during basic block sections to + /// calculate the size of the basic block, or the BB section ending with it. + mutable MCSymbol *CachedEndMCSymbol = nullptr; // Intrusive list support MachineBasicBlock() = default; @@ -432,6 +434,9 @@ public: bool hasEHPadSuccessor() const; + /// Returns true if this is the entry block of the function. + bool isEntryBlock() const; + /// Returns true if this is the entry block of an EH scope, i.e., the block /// that used to have a catchpad or cleanuppad instruction in the LLVM IR. bool isEHScopeEntry() const { return IsEHScopeEntry; } @@ -474,6 +479,9 @@ public: /// Sets the section ID for this basic block. void setSectionID(MBBSectionID V) { SectionID = V; } + /// Returns the MCSymbol marking the end of this basic block. + MCSymbol *getEndSymbol() const; + /// Returns true if this block may have an INLINEASM_BR (overestimate, by /// checking if any of the successors are indirect targets of any inlineasm_br /// in the function). @@ -671,6 +679,17 @@ public: return !empty() && back().isEHScopeReturn(); } + /// Split a basic block into 2 pieces at \p SplitPoint. A new block will be + /// inserted after this block, and all instructions after \p SplitInst moved + /// to it (\p SplitInst will be in the original block). If \p LIS is provided, + /// LiveIntervals will be appropriately updated. \return the newly inserted + /// block. + /// + /// If \p UpdateLiveIns is true, this will ensure the live ins list is + /// accurate, including for physreg uses/defs in the original block. + MachineBasicBlock *splitAt(MachineInstr &SplitInst, bool UpdateLiveIns = true, + LiveIntervals *LIS = nullptr); + /// Split the critical edge from this block to the given successor block, and /// return the newly created block, or null if splitting is not possible. /// @@ -872,6 +891,14 @@ public: void print(raw_ostream &OS, ModuleSlotTracker &MST, const SlotIndexes * = nullptr, bool IsStandalone = true) const; + enum PrintNameFlag { + PrintNameIr = (1 << 0), ///< Add IR name where available + PrintNameAttributes = (1 << 1), ///< Print attributes + }; + + void printName(raw_ostream &os, unsigned printNameFlags = PrintNameIr, + ModuleSlotTracker *moduleSlotTracker = nullptr) const; + // Printing method used by LoopInfo. void printAsOperand(raw_ostream &OS, bool PrintType = true) const; diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineBlockFrequencyInfo.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineBlockFrequencyInfo.h index 0f8d69ebd7da..6c442d3d07bd 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineBlockFrequencyInfo.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineBlockFrequencyInfo.h @@ -58,18 +58,33 @@ public: /// information. Please note that initial frequency is equal to 1024. It means /// that we should not rely on the value itself, but only on the comparison to /// the other block frequencies. We do this to avoid using of floating points. - /// + /// For example, to get the frequency of a block relative to the entry block, + /// divide the integral value returned by this function (the + /// BlockFrequency::getFrequency() value) by getEntryFreq(). BlockFrequency getBlockFreq(const MachineBasicBlock *MBB) const; + /// Compute the frequency of the block, relative to the entry block. + /// This API assumes getEntryFreq() is non-zero. + float getBlockFreqRelativeToEntryBlock(const MachineBasicBlock *MBB) const { + return getBlockFreq(MBB).getFrequency() * (1.0f / getEntryFreq()); + } + Optional getBlockProfileCount(const MachineBasicBlock *MBB) const; Optional getProfileCountFromFreq(uint64_t Freq) const; - bool isIrrLoopHeader(const MachineBasicBlock *MBB); + bool isIrrLoopHeader(const MachineBasicBlock *MBB) const; - void setBlockFreq(const MachineBasicBlock *MBB, uint64_t Freq); + /// incrementally calculate block frequencies when we split edges, to avoid + /// full CFG traversal. + void onEdgeSplit(const MachineBasicBlock &NewPredecessor, + const MachineBasicBlock &NewSuccessor, + const MachineBranchProbabilityInfo &MBPI); const MachineFunction *getFunction() const; const MachineBranchProbabilityInfo *getMBPI() const; + + /// Pop up a ghostview window with the current block frequency propagation + /// rendered using dot. void view(const Twine &Name, bool isSimple = true) const; // Print the block frequency Freq to OS using the current functions entry @@ -81,6 +96,8 @@ public: raw_ostream &printBlockFreq(raw_ostream &OS, const MachineBasicBlock *MBB) const; + /// Divide a block's BlockFrequency::getFrequency() value by this value to + /// obtain the entry block - relative frequency of said block. uint64_t getEntryFreq() const; }; diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineCombinerPattern.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineCombinerPattern.h index e9f52fb064e1..ac0cc70744d1 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineCombinerPattern.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineCombinerPattern.h @@ -29,6 +29,11 @@ enum class MachineCombinerPattern { REASSOC_XY_AMM_BMM, REASSOC_XMM_AMM_BMM, + // These are patterns matched by the PowerPC to reassociate FMA and FSUB to + // reduce register pressure. + REASSOC_XY_BCA, + REASSOC_XY_BAC, + // These are multiply-add patterns matched by the AArch64 machine combiner. MULADDW_OP1, MULADDW_OP2, diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineConstantPool.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineConstantPool.h index cfc9ca88c976..a9bc0ce300b2 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineConstantPool.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineConstantPool.h @@ -41,10 +41,10 @@ public: explicit MachineConstantPoolValue(Type *ty) : Ty(ty) {} virtual ~MachineConstantPoolValue() = default; - /// getType - get type of this MachineConstantPoolValue. - /// Type *getType() const { return Ty; } + virtual unsigned getSizeInBytes(const DataLayout &DL) const; + virtual int getExistingMachineCPValue(MachineConstantPool *CP, Align Alignment) = 0; @@ -94,7 +94,7 @@ public: Align getAlign() const { return Alignment; } - Type *getType() const; + unsigned getSizeInBytes(const DataLayout &DL) const; /// This method classifies the entry according to whether or not it may /// generate a relocation entry. This must be conservative, so if it might diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineDominanceFrontier.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineDominanceFrontier.h index f7bbd07a63ab..e3e679608784 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineDominanceFrontier.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineDominanceFrontier.h @@ -14,7 +14,6 @@ #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/Support/GenericDomTree.h" -#include namespace llvm { diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineDominators.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineDominators.h index cf3af4d38223..46bf73cdd7b6 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineDominators.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineDominators.h @@ -23,7 +23,6 @@ #include "llvm/Support/GenericDomTreeConstruction.h" #include #include -#include namespace llvm { diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineFrameInfo.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineFrameInfo.h index 5cd7f9cde674..7f0ec0df57c5 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineFrameInfo.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineFrameInfo.h @@ -14,6 +14,7 @@ #define LLVM_CODEGEN_MACHINEFRAMEINFO_H #include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/Register.h" #include "llvm/Support/Alignment.h" #include "llvm/Support/DataTypes.h" #include @@ -31,7 +32,7 @@ class AllocaInst; /// Callee saved reg can also be saved to a different register rather than /// on the stack by setting DstReg instead of FrameIdx. class CalleeSavedInfo { - unsigned Reg; + Register Reg; union { int FrameIdx; unsigned DstReg; @@ -58,14 +59,14 @@ public: : Reg(R), FrameIdx(FI), Restored(true), SpilledToReg(false) {} // Accessors. - unsigned getReg() const { return Reg; } + Register getReg() const { return Reg; } int getFrameIdx() const { return FrameIdx; } unsigned getDstReg() const { return DstReg; } void setFrameIdx(int FI) { FrameIdx = FI; SpilledToReg = false; } - void setDstReg(unsigned SpillReg) { + void setDstReg(Register SpillReg) { DstReg = SpillReg; SpilledToReg = true; } diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineFunction.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineFunction.h index 809c21dd26fc..e9979c788ce0 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineFunction.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineFunction.h @@ -431,6 +431,39 @@ public: using VariableDbgInfoMapTy = SmallVector; VariableDbgInfoMapTy VariableDbgInfos; + /// A count of how many instructions in the function have had numbers + /// assigned to them. Used for debug value tracking, to determine the + /// next instruction number. + unsigned DebugInstrNumberingCount = 0; + + /// Set value of DebugInstrNumberingCount field. Avoid using this unless + /// you're deserializing this data. + void setDebugInstrNumberingCount(unsigned Num); + + /// Pair of instruction number and operand number. + using DebugInstrOperandPair = std::pair; + + /// Substitution map: from one pair to another. Used to + /// record changes in where a value is defined, so that debug variable + /// locations can find it later. + std::map + DebugValueSubstitutions; + + /// Create a substitution between one value to a different, + /// new value. + void makeDebugValueSubstitution(DebugInstrOperandPair, DebugInstrOperandPair); + + /// Create substitutions for any tracked values in \p Old, to point at + /// \p New. Needed when we re-create an instruction during optimization, + /// which has the same signature (i.e., def operands in the same place) but + /// a modified instruction type, flags, or otherwise. An example: X86 moves + /// are sometimes transformed into equivalent LEAs. + /// If the two instructions are not the same opcode, limit which operands to + /// examine for substitutions to the first N operands by setting + /// \p MaxOperand. + void substituteDebugValuesForInst(const MachineInstr &Old, MachineInstr &New, + unsigned MaxOperand = UINT_MAX); + MachineFunction(Function &F, const LLVMTargetMachine &Target, const TargetSubtargetInfo &STI, unsigned FunctionNum, MachineModuleInfo &MMI); @@ -494,7 +527,8 @@ public: /// Returns true if this function has basic block sections enabled. bool hasBBSections() const { return (BBSectionsType == BasicBlockSection::All || - BBSectionsType == BasicBlockSection::List); + BBSectionsType == BasicBlockSection::List || + BBSectionsType == BasicBlockSection::Preset); } /// Returns true if basic block labels are to be generated for this function. @@ -504,9 +538,6 @@ public: void setBBSectionsType(BasicBlockSection V) { BBSectionsType = V; } - /// Creates basic block Labels for this function. - void createBBLabels(); - /// Assign IsBeginSection IsEndSection fields for basic blocks in this /// function. void assignBeginEndSections(); @@ -769,7 +800,7 @@ public: /// CreateMachineInstr - Allocate a new MachineInstr. Use this instead /// of `new MachineInstr'. MachineInstr *CreateMachineInstr(const MCInstrDesc &MCID, const DebugLoc &DL, - bool NoImp = false); + bool NoImplicit = false); /// Create a new MachineInstr which is a copy of \p Orig, identical in all /// ways except the instruction has no parent, prev, or next. Bundling flags @@ -815,6 +846,14 @@ public: MachineMemOperand *getMachineMemOperand(const MachineMemOperand *MMO, int64_t Offset, uint64_t Size); + /// getMachineMemOperand - Allocate a new MachineMemOperand by copying + /// an existing one, replacing only the MachinePointerInfo and size. + /// MachineMemOperands are owned by the MachineFunction and need not be + /// explicitly deallocated. + MachineMemOperand *getMachineMemOperand(const MachineMemOperand *MMO, + MachinePointerInfo &PtrInfo, + uint64_t Size); + /// Allocate a new MachineMemOperand by copying an existing one, /// replacing only AliasAnalysis information. MachineMemOperands are owned /// by the MachineFunction and need not be explicitly deallocated. @@ -1067,6 +1106,10 @@ public: /// the same callee. void moveCallSiteInfo(const MachineInstr *Old, const MachineInstr *New); + + unsigned getNewDebugInstrNum() { + return ++DebugInstrNumberingCount; + } }; //===--------------------------------------------------------------------===// @@ -1133,6 +1176,11 @@ template <> struct GraphTraits> : } }; +class MachineFunctionAnalysisManager; +void verifyMachineFunction(MachineFunctionAnalysisManager *, + const std::string &Banner, + const MachineFunction &MF); + } // end namespace llvm #endif // LLVM_CODEGEN_MACHINEFUNCTION_H diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineInstr.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineInstr.h index 970d6d7db334..f8d97c2c07a6 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineInstr.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineInstr.h @@ -249,6 +249,10 @@ private: DebugLoc debugLoc; // Source line information. + /// Unique instruction number. Used by DBG_INSTR_REFs to refer to the values + /// defined by this instruction. + unsigned DebugInstrNum; + // Intrusive list support friend struct ilist_traits; friend struct ilist_callback_traits; @@ -280,6 +284,9 @@ public: const MachineBasicBlock* getParent() const { return Parent; } MachineBasicBlock* getParent() { return Parent; } + /// Move the instruction before \p MovePos. + void moveBefore(MachineInstr *MovePos); + /// Return the function that contains the basic block that this instruction /// belongs to. /// @@ -441,6 +448,18 @@ public: /// this DBG_LABEL instruction. const DILabel *getDebugLabel() const; + /// Fetch the instruction number of this MachineInstr. If it does not have + /// one already, a new and unique number will be assigned. + unsigned getDebugInstrNum(); + + /// Examine the instruction number of this MachineInstr. May be zero if + /// it hasn't been assigned a number yet. + unsigned peekDebugInstrNum() const { return DebugInstrNum; } + + /// Set instruction number of this MachineInstr. Avoid using unless you're + /// deserializing this information. + void setDebugInstrNum(unsigned Num) { DebugInstrNum = Num; } + /// Emit an error referring to the source location of this instruction. /// This should only be used for inline assembly that is somehow /// impossible to compile. Other errors should have been handled much @@ -1137,12 +1156,22 @@ public: return getOpcode() == TargetOpcode::CFI_INSTRUCTION; } + bool isPseudoProbe() const { + return getOpcode() == TargetOpcode::PSEUDO_PROBE; + } + // True if the instruction represents a position in the function. bool isPosition() const { return isLabel() || isCFIInstruction(); } bool isDebugValue() const { return getOpcode() == TargetOpcode::DBG_VALUE; } bool isDebugLabel() const { return getOpcode() == TargetOpcode::DBG_LABEL; } - bool isDebugInstr() const { return isDebugValue() || isDebugLabel(); } + bool isDebugRef() const { return getOpcode() == TargetOpcode::DBG_INSTR_REF; } + bool isDebugInstr() const { + return isDebugValue() || isDebugLabel() || isDebugRef(); + } + bool isDebugOrPseudoInstr() const { + return isDebugInstr() || isPseudoProbe(); + } bool isDebugOffsetImm() const { return getDebugOffset().isImm(); } @@ -1235,9 +1264,11 @@ public: case TargetOpcode::EH_LABEL: case TargetOpcode::GC_LABEL: case TargetOpcode::DBG_VALUE: + case TargetOpcode::DBG_INSTR_REF: case TargetOpcode::DBG_LABEL: case TargetOpcode::LIFETIME_START: case TargetOpcode::LIFETIME_END: + case TargetOpcode::PSEUDO_PROBE: return true; } } @@ -1310,7 +1341,8 @@ public: /// Return true if the MachineInstr modifies (fully define or partially /// define) the specified register. /// NOTE: It's ignoring subreg indices on virtual registers. - bool modifiesRegister(Register Reg, const TargetRegisterInfo *TRI) const { + bool modifiesRegister(Register Reg, + const TargetRegisterInfo *TRI = nullptr) const { return findRegisterDefOperandIdx(Reg, false, true, TRI) != -1; } @@ -1761,8 +1793,10 @@ public: void setDebugValueUndef() { assert(isDebugValue() && "Must be a debug value instruction."); for (MachineOperand &MO : debug_operands()) { - if (MO.isReg()) + if (MO.isReg()) { MO.setReg(0); + MO.setSubReg(0); + } } } diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineInstrBuilder.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineInstrBuilder.h index cabb9f1c97c9..115c50175604 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineInstrBuilder.h @@ -40,20 +40,30 @@ class MDNode; namespace RegState { - enum { - Define = 0x2, - Implicit = 0x4, - Kill = 0x8, - Dead = 0x10, - Undef = 0x20, - EarlyClobber = 0x40, - Debug = 0x80, - InternalRead = 0x100, - Renamable = 0x200, - DefineNoRead = Define | Undef, - ImplicitDefine = Implicit | Define, - ImplicitKill = Implicit | Kill - }; +enum { + /// Register definition. + Define = 0x2, + /// Not emitted register (e.g. carry, or temporary result). + Implicit = 0x4, + /// The last use of a register. + Kill = 0x8, + /// Unused definition. + Dead = 0x10, + /// Value of the register doesn't matter. + Undef = 0x20, + /// Register definition happens before uses. + EarlyClobber = 0x40, + /// Register 'use' is for debugging purpose. + Debug = 0x80, + /// Register reads a value that is defined inside the same instruction or + /// bundle. + InternalRead = 0x100, + /// Register that may be renamed. + Renamable = 0x200, + DefineNoRead = Define | Undef, + ImplicitDefine = Implicit | Define, + ImplicitKill = Implicit | Kill +}; } // end namespace RegState @@ -295,6 +305,9 @@ public: case MachineOperand::MO_BlockAddress: return addBlockAddress(Disp.getBlockAddress(), Disp.getOffset() + off, TargetFlags); + case MachineOperand::MO_JumpTableIndex: + assert(off == 0 && "cannot create offset into jump tables"); + return addJumpTableIndex(Disp.getIndex(), TargetFlags); } } diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineJumpTableInfo.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineJumpTableInfo.h index 11781145b378..1d082bd03e5b 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineJumpTableInfo.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineJumpTableInfo.h @@ -106,6 +106,9 @@ public: JumpTables[Idx].MBBs.clear(); } + /// RemoveMBBFromJumpTables - If MBB is present in any jump tables, remove it. + bool RemoveMBBFromJumpTables(MachineBasicBlock *MBB); + /// ReplaceMBBInJumpTables - If Old is the target of any jump tables, update /// the jump tables to branch to New instead. bool ReplaceMBBInJumpTables(MachineBasicBlock *Old, MachineBasicBlock *New); diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineLoopInfo.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineLoopInfo.h index 8a93f91ae54d..c7491d4191de 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineLoopInfo.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineLoopInfo.h @@ -67,6 +67,12 @@ public: /// it returns an unknown location. DebugLoc getStartLoc() const; + /// Returns true if the instruction is loop invariant. + /// I.e., all virtual register operands are defined outside of the loop, + /// physical registers aren't accessed explicitly, and there are no side + /// effects that aren't captured by the operands or other flags. + bool isLoopInvariant(MachineInstr &I) const; + void dump() const; private: diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineLoopUtils.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineLoopUtils.h index 2cb0134ca848..ec0b3529c0d6 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineLoopUtils.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineLoopUtils.h @@ -37,10 +37,6 @@ MachineBasicBlock *PeelSingleBlockLoop(LoopPeelDirection Direction, MachineRegisterInfo &MRI, const TargetInstrInfo *TII); -/// Return true if PhysReg is live outside the loop, i.e. determine if it -/// is live in the loop exit blocks, and false otherwise. -bool isRegLiveInExitBlocks(MachineLoop *Loop, int PhysReg); - } // namespace llvm #endif // LLVM_LIB_CODEGEN_MACHINELOOPUTILS_H diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineModuleInfo.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineModuleInfo.h index 0ee595b5b5ce..fa900affb214 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineModuleInfo.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineModuleInfo.h @@ -54,8 +54,8 @@ class Module; //===----------------------------------------------------------------------===// /// This class can be derived from and used by targets to hold private /// target-specific information for each Module. Objects of type are -/// accessed/created with MMI::getInfo and destroyed when the MachineModuleInfo -/// is destroyed. +/// accessed/created with MachineModuleInfo::getObjFileInfo and destroyed when +/// the MachineModuleInfo is destroyed. /// class MachineModuleInfoImpl { public: @@ -83,6 +83,9 @@ class MachineModuleInfo { /// This is the MCContext used for the entire code generator. MCContext Context; + // This is an external context, that if assigned, will be used instead of the + // internal context. + MCContext *ExternalContext = nullptr; /// This is the LLVM Module being worked on. const Module *TheModule; @@ -149,6 +152,9 @@ class MachineModuleInfo { public: explicit MachineModuleInfo(const LLVMTargetMachine *TM = nullptr); + explicit MachineModuleInfo(const LLVMTargetMachine *TM, + MCContext *ExtContext); + MachineModuleInfo(MachineModuleInfo &&MMII); ~MachineModuleInfo(); @@ -158,8 +164,12 @@ public: const LLVMTargetMachine &getTarget() const { return TM; } - const MCContext &getContext() const { return Context; } - MCContext &getContext() { return Context; } + const MCContext &getContext() const { + return ExternalContext ? *ExternalContext : Context; + } + MCContext &getContext() { + return ExternalContext ? *ExternalContext : Context; + } const Module *getModule() const { return TheModule; } @@ -251,6 +261,12 @@ public: return Personalities; } /// \} + + // MMI owes MCContext. It should never be invalidated. + bool invalidate(Module &, const PreservedAnalyses &, + ModuleAnalysisManager::Invalidator &) { + return false; + } }; // End class MachineModuleInfo class MachineModuleInfoWrapperPass : public ImmutablePass { @@ -260,6 +276,9 @@ public: static char ID; // Pass identification, replacement for typeid explicit MachineModuleInfoWrapperPass(const LLVMTargetMachine *TM = nullptr); + explicit MachineModuleInfoWrapperPass(const LLVMTargetMachine *TM, + MCContext *ExtContext); + // Initialization and Finalization bool doInitialization(Module &) override; bool doFinalization(Module &) override; diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineOperand.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineOperand.h index 0f252137364c..b12351b8a702 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineOperand.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineOperand.h @@ -33,7 +33,6 @@ class MachineRegisterInfo; class MCCFIInstruction; class MDNode; class ModuleSlotTracker; -class TargetMachine; class TargetIntrinsicInfo; class TargetRegisterInfo; class hash_code; @@ -728,12 +727,12 @@ public: /// ChangeToImmediate - Replace this operand with a new immediate operand of /// the specified value. If an operand is known to be an immediate already, /// the setImm method should be used. - void ChangeToImmediate(int64_t ImmVal); + void ChangeToImmediate(int64_t ImmVal, unsigned TargetFlags = 0); /// ChangeToFPImmediate - Replace this operand with a new FP immediate operand /// of the specified value. If an operand is known to be an FP immediate /// already, the setFPImm method should be used. - void ChangeToFPImmediate(const ConstantFP *FPImm); + void ChangeToFPImmediate(const ConstantFP *FPImm, unsigned TargetFlags = 0); /// ChangeToES - Replace this operand with a new external symbol operand. void ChangeToES(const char *SymName, unsigned TargetFlags = 0); @@ -743,10 +742,10 @@ public: unsigned TargetFlags = 0); /// ChangeToMCSymbol - Replace this operand with a new MC symbol operand. - void ChangeToMCSymbol(MCSymbol *Sym); + void ChangeToMCSymbol(MCSymbol *Sym, unsigned TargetFlags = 0); /// Replace this operand with a frame index. - void ChangeToFrameIndex(int Idx); + void ChangeToFrameIndex(int Idx, unsigned TargetFlags = 0); /// Replace this operand with a target index. void ChangeToTargetIndex(unsigned Idx, int64_t Offset, @@ -759,6 +758,11 @@ public: bool isKill = false, bool isDead = false, bool isUndef = false, bool isDebug = false); + /// getTargetIndexName - If this MachineOperand is a TargetIndex that has a + /// name, attempt to get the name. Returns nullptr if the TargetIndex does not + /// have a name. Asserts if MO is not a TargetIndex. + const char *getTargetIndexName() const; + //===--------------------------------------------------------------------===// // Construction methods. //===--------------------------------------------------------------------===// diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineOutliner.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineOutliner.h index 4a1b04ab3e88..a5dbbdb4fdcd 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineOutliner.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineOutliner.h @@ -15,10 +15,11 @@ #ifndef LLVM_MACHINEOUTLINER_H #define LLVM_MACHINEOUTLINER_H +#include "llvm/CodeGen/LivePhysRegs.h" #include "llvm/CodeGen/LiveRegUnits.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/TargetRegisterInfo.h" -#include "llvm/CodeGen/LivePhysRegs.h" namespace llvm { namespace outliner { diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachinePassManager.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachinePassManager.h new file mode 100644 index 000000000000..1489177d9668 --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachinePassManager.h @@ -0,0 +1,256 @@ +//===- PassManager.h --- Pass management for CodeGen ------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This header defines the pass manager interface for codegen. The codegen +// pipeline consists of only machine function passes. There is no container +// relationship between IR module/function and machine function in terms of pass +// manager organization. So there is no need for adaptor classes (for example +// ModuleToMachineFunctionAdaptor). Since invalidation could only happen among +// machine function passes, there is no proxy classes to handle cross-IR-unit +// invalidation. IR analysis results are provided for machine function passes by +// their respective analysis managers such as ModuleAnalysisManager and +// FunctionAnalysisManager. +// +// TODO: Add MachineFunctionProperties support. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEPASSMANAGER_H +#define LLVM_CODEGEN_MACHINEPASSMANAGER_H + +#include "llvm/ADT/FunctionExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/type_traits.h" + +namespace llvm { +class Module; + +extern template class AnalysisManager; + +/// An AnalysisManager that also exposes IR analysis results. +class MachineFunctionAnalysisManager : public AnalysisManager { +public: + using Base = AnalysisManager; + + MachineFunctionAnalysisManager() : Base(false), FAM(nullptr), MAM(nullptr) {} + MachineFunctionAnalysisManager(FunctionAnalysisManager &FAM, + ModuleAnalysisManager &MAM, + bool DebugLogging = false) + : Base(DebugLogging), FAM(&FAM), MAM(&MAM) {} + MachineFunctionAnalysisManager(MachineFunctionAnalysisManager &&) = default; + MachineFunctionAnalysisManager & + operator=(MachineFunctionAnalysisManager &&) = default; + + /// Get the result of an analysis pass for a Function. + /// + /// Runs the analysis if a cached result is not available. + template typename PassT::Result &getResult(Function &F) { + return FAM->getResult(F); + } + + /// Get the cached result of an analysis pass for a Function. + /// + /// This method never runs the analysis. + /// + /// \returns null if there is no cached result. + template + typename PassT::Result *getCachedResult(Function &F) { + return FAM->getCachedResult(F); + } + + /// Get the result of an analysis pass for a Module. + /// + /// Runs the analysis if a cached result is not available. + template typename PassT::Result &getResult(Module &M) { + return MAM->getResult(M); + } + + /// Get the cached result of an analysis pass for a Module. + /// + /// This method never runs the analysis. + /// + /// \returns null if there is no cached result. + template typename PassT::Result *getCachedResult(Module &M) { + return MAM->getCachedResult(M); + } + + /// Get the result of an analysis pass for a MachineFunction. + /// + /// Runs the analysis if a cached result is not available. + using Base::getResult; + + /// Get the cached result of an analysis pass for a MachineFunction. + /// + /// This method never runs the analysis. + /// + /// returns null if there is no cached result. + using Base::getCachedResult; + + // FIXME: Add LoopAnalysisManager or CGSCCAnalysisManager if needed. + FunctionAnalysisManager *FAM; + ModuleAnalysisManager *MAM; +}; + +extern template class PassManager; + +/// MachineFunctionPassManager adds/removes below features to/from the base +/// PassManager template instantiation. +/// +/// - Support passes that implement doInitialization/doFinalization. This is for +/// machine function passes to work on module level constructs. One such pass +/// is AsmPrinter. +/// +/// - Support machine module pass which runs over the module (for example, +/// MachineOutliner). A machine module pass needs to define the method: +/// +/// ```Error run(Module &, MachineFunctionAnalysisManager &)``` +/// +/// FIXME: machine module passes still need to define the usual machine +/// function pass interface, namely, +/// `PreservedAnalyses run(MachineFunction &, +/// MachineFunctionAnalysisManager &)` +/// But this interface wouldn't be executed. It is just a placeholder +/// to satisfy the pass manager type-erased inteface. This +/// special-casing of machine module pass is due to its limited use +/// cases and the unnecessary complexity it may bring to the machine +/// pass manager. +/// +/// - The base class `run` method is replaced by an alternative `run` method. +/// See details below. +/// +/// - Support codegening in the SCC order. Users include interprocedural +/// register allocation (IPRA). +class MachineFunctionPassManager + : public PassManager { + using Base = PassManager; + +public: + MachineFunctionPassManager(bool DebugLogging = false, + bool RequireCodeGenSCCOrder = false, + bool VerifyMachineFunction = false) + : Base(DebugLogging), RequireCodeGenSCCOrder(RequireCodeGenSCCOrder), + VerifyMachineFunction(VerifyMachineFunction) {} + MachineFunctionPassManager(MachineFunctionPassManager &&) = default; + MachineFunctionPassManager & + operator=(MachineFunctionPassManager &&) = default; + + /// Run machine passes for a Module. + /// + /// The intended use is to start the codegen pipeline for a Module. The base + /// class's `run` method is deliberately hidden by this due to the observation + /// that we don't yet have the use cases of compositing two instances of + /// machine pass managers, or compositing machine pass managers with other + /// types of pass managers. + Error run(Module &M, MachineFunctionAnalysisManager &MFAM); + + template void addPass(PassT &&Pass) { + Base::addPass(std::forward(Pass)); + PassConceptT *P = Passes.back().get(); + addDoInitialization(P); + addDoFinalization(P); + + // Add machine module pass. + addRunOnModule(P); + } + +private: + template + using has_init_t = decltype(std::declval().doInitialization( + std::declval(), + std::declval())); + + template + std::enable_if_t::value> + addDoInitialization(PassConceptT *Pass) {} + + template + std::enable_if_t::value> + addDoInitialization(PassConceptT *Pass) { + using PassModelT = + detail::PassModel; + auto *P = static_cast(Pass); + InitializationFuncs.emplace_back( + [=](Module &M, MachineFunctionAnalysisManager &MFAM) { + return P->Pass.doInitialization(M, MFAM); + }); + } + + template + using has_fini_t = decltype(std::declval().doFinalization( + std::declval(), + std::declval())); + + template + std::enable_if_t::value> + addDoFinalization(PassConceptT *Pass) {} + + template + std::enable_if_t::value> + addDoFinalization(PassConceptT *Pass) { + using PassModelT = + detail::PassModel; + auto *P = static_cast(Pass); + FinalizationFuncs.emplace_back( + [=](Module &M, MachineFunctionAnalysisManager &MFAM) { + return P->Pass.doFinalization(M, MFAM); + }); + } + + template + using is_machine_module_pass_t = decltype(std::declval().run( + std::declval(), + std::declval())); + + template + using is_machine_function_pass_t = decltype(std::declval().run( + std::declval(), + std::declval())); + + template + std::enable_if_t::value> + addRunOnModule(PassConceptT *Pass) {} + + template + std::enable_if_t::value> + addRunOnModule(PassConceptT *Pass) { + static_assert(is_detected::value, + "machine module pass needs to define machine function pass " + "api. sorry."); + + using PassModelT = + detail::PassModel; + auto *P = static_cast(Pass); + MachineModulePasses.emplace( + Passes.size() - 1, + [=](Module &M, MachineFunctionAnalysisManager &MFAM) { + return P->Pass.run(M, MFAM); + }); + } + + using FuncTy = Error(Module &, MachineFunctionAnalysisManager &); + SmallVector, 4> InitializationFuncs; + SmallVector, 4> FinalizationFuncs; + + using PassIndex = decltype(Passes)::size_type; + std::map> MachineModulePasses; + + // Run codegen in the SCC order. + bool RequireCodeGenSCCOrder; + + bool VerifyMachineFunction; +}; + +} // end namespace llvm + +#endif // LLVM_CODEGEN_MACHINEPASSMANAGER_H diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachinePassRegistry.def b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachinePassRegistry.def new file mode 100644 index 000000000000..e9eaa5f77000 --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachinePassRegistry.def @@ -0,0 +1,197 @@ +//===- MachinePassRegistry.def - Registry of passes -------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file is used as the registry of passes that are for target-independent +// code generator. +// +//===----------------------------------------------------------------------===// + +// NOTE: NO INCLUDE GUARD DESIRED! + +#ifndef MODULE_ANALYSIS +#define MODULE_ANALYSIS(NAME, PASS_NAME, CONSTRUCTOR) +#endif +MODULE_ANALYSIS("pass-instrumentation", PassInstrumentationAnalysis, (PIC)) +#undef MODULE_ANALYSIS + +#ifndef MODULE_PASS +#define MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR) +#endif +MODULE_PASS("pre-isel-intrinsic-lowering", PreISelIntrinsicLoweringPass, ()) +#undef MODULE_PASS + +#ifndef FUNCTION_ANALYSIS +#define FUNCTION_ANALYSIS(NAME, PASS_NAME, CONSTRUCTOR) +#endif +FUNCTION_ANALYSIS("pass-instrumentation", PassInstrumentationAnalysis, (PIC)) +FUNCTION_ANALYSIS("targetir", TargetIRAnalysis, (std::move(TM.getTargetIRAnalysis()))) +#undef FUNCTION_ANALYSIS + +#ifndef FUNCTION_PASS +#define FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) +#endif +FUNCTION_PASS("mergeicmps", MergeICmpsPass, ()) +FUNCTION_PASS("lower-constant-intrinsics", LowerConstantIntrinsicsPass, ()) +FUNCTION_PASS("unreachableblockelim", UnreachableBlockElimPass, ()) +FUNCTION_PASS("consthoist", ConstantHoistingPass, ()) +FUNCTION_PASS("partially-inline-libcalls", PartiallyInlineLibCallsPass, ()) +FUNCTION_PASS("ee-instrument", EntryExitInstrumenterPass, (false)) +FUNCTION_PASS("post-inline-ee-instrument", EntryExitInstrumenterPass, (true)) +FUNCTION_PASS("expand-reductions", ExpandReductionsPass, ()) +FUNCTION_PASS("lowerinvoke", LowerInvokePass, ()) +FUNCTION_PASS("scalarize-masked-mem-intrin", ScalarizeMaskedMemIntrinPass, ()) +FUNCTION_PASS("verify", VerifierPass, ()) +#undef FUNCTION_PASS + +#ifndef LOOP_PASS +#define LOOP_PASS(NAME, PASS_NAME, CONSTRUCTOR) +#endif +LOOP_PASS("loop-reduce", LoopStrengthReducePass, ()) +#undef LOOP_PASS + +#ifndef MACHINE_MODULE_PASS +#define MACHINE_MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR) +#endif +#undef MACHINE_MODULE_PASS + +#ifndef MACHINE_FUNCTION_ANALYSIS +#define MACHINE_FUNCTION_ANALYSIS(NAME, PASS_NAME, CONSTRUCTOR) +#endif +MACHINE_FUNCTION_ANALYSIS("pass-instrumentation", PassInstrumentationAnalysis, (PIC)) +// LiveVariables currently requires pure SSA form. +// FIXME: Once TwoAddressInstruction pass no longer uses kill flags, +// LiveVariables can be removed completely, and LiveIntervals can be directly +// computed. (We still either need to regenerate kill flags after regalloc, or +// preferably fix the scavenger to not depend on them). +// MACHINE_FUNCTION_ANALYSIS("live-vars", LiveVariablesAnalysis()) + +// MACHINE_FUNCTION_ANALYSIS("live-stacks", LiveStacksPass()) +// MACHINE_FUNCTION_ANALYSIS("slot-indexes", SlotIndexesAnalysis()) +// MACHINE_FUNCTION_ANALYSIS("edge-bundles", EdgeBundlesAnalysis()) +// MACHINE_FUNCTION_ANALYSIS("lazy-machine-bfi", LazyMachineBlockFrequencyInfoAnalysis()) +// MACHINE_FUNCTION_ANALYSIS("machine-bfi", MachineBlockFrequencyInfoAnalysis()) +// MACHINE_FUNCTION_ANALYSIS("machine-loops", MachineLoopInfoAnalysis()) +// MACHINE_FUNCTION_ANALYSIS("machine-dom-frontier", MachineDominanceFrontierAnalysis()) +// MACHINE_FUNCTION_ANALYSIS("machine-dom-tree", MachineDominatorTreeAnalysis()) +// MACHINE_FUNCTION_ANALYSIS("machine-ore", MachineOptimizationRemarkEmitterPassAnalysis()) +// MACHINE_FUNCTION_ANALYSIS("machine-post-dom-tree", MachinePostDominatorTreeAnalysis()) +// MACHINE_FUNCTION_ANALYSIS("machine-region-info", MachineRegionInfoPassAnalysis()) +// MACHINE_FUNCTION_ANALYSIS("machine-trace-metrics", MachineTraceMetricsAnalysis()) +// MACHINE_FUNCTION_ANALYSIS("reaching-def", ReachingDefAnalysisAnalysis()) +// MACHINE_FUNCTION_ANALYSIS("live-reg-matrix", LiveRegMatrixAnalysis()) +// MACHINE_FUNCTION_ANALYSIS("gc-analysis", GCMachineCodeAnalysisPass()) +#undef MACHINE_FUNCTION_ANALYSIS + +#ifndef MACHINE_FUNCTION_PASS +#define MACHINE_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) +#endif +// MACHINE_FUNCTION_PASS("mir-printer", PrintMIRPass, ()) +// MACHINE_FUNCTION_PASS("free-machine-function", FreeMachineFunctionPass, ()) +#undef MACHINE_FUNCTION_PASS + +// After a pass is converted to new pass manager, its entry should be moved from +// dummy table to the normal one. For example, for a machine function pass, +// DUMMY_MACHINE_FUNCTION_PASS to MACHINE_FUNCTION_PASS. + +#ifndef DUMMY_FUNCTION_PASS +#define DUMMY_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) +#endif +DUMMY_FUNCTION_PASS("expandmemcmp", ExpandMemCmpPass, ()) +DUMMY_FUNCTION_PASS("gc-lowering", GCLoweringPass, ()) +DUMMY_FUNCTION_PASS("shadow-stack-gc-lowering", ShadowStackGCLoweringPass, ()) +DUMMY_FUNCTION_PASS("sjljehprepare", SjLjEHPreparePass, ()) +DUMMY_FUNCTION_PASS("dwarfehprepare", DwarfEHPass, ()) +DUMMY_FUNCTION_PASS("winehprepare", WinEHPass, ()) +DUMMY_FUNCTION_PASS("wasmehprepare", WasmEHPass, ()) +DUMMY_FUNCTION_PASS("codegenprepare", CodeGenPreparePass, ()) +DUMMY_FUNCTION_PASS("safe-stack", SafeStackPass, ()) +DUMMY_FUNCTION_PASS("stack-protector", StackProtectorPass, ()) +DUMMY_FUNCTION_PASS("atomic-expand", AtomicExpandPass, ()) +DUMMY_FUNCTION_PASS("interleaved-access", InterleavedAccessPass, ()) +DUMMY_FUNCTION_PASS("indirectbr-expand", IndirectBrExpandPass, ()) +DUMMY_FUNCTION_PASS("cfguard-dispatch", CFGuardDispatchPass, ()) +DUMMY_FUNCTION_PASS("cfguard-check", CFGuardCheckPass, ()) +DUMMY_FUNCTION_PASS("gc-info-printer", GCInfoPrinterPass, ()) +#undef DUMMY_FUNCTION_PASS + +#ifndef DUMMY_MODULE_PASS +#define DUMMY_MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR) +#endif +DUMMY_MODULE_PASS("lower-emutls", LowerEmuTLSPass, ()) +#undef DUMMY_MODULE_PASS + +#ifndef DUMMY_MACHINE_MODULE_PASS +#define DUMMY_MACHINE_MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR) +#endif +DUMMY_MACHINE_MODULE_PASS("machine-outliner", MachineOutlinerPass, ()) +#undef DUMMY_MACHINE_MODULE_PASS + +#ifndef DUMMY_MACHINE_FUNCTION_PASS +#define DUMMY_MACHINE_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) +#endif +DUMMY_MACHINE_FUNCTION_PASS("mir-printer", PrintMIRPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("free-machine-function", FreeMachineFunctionPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("finalize-isel", FinalizeISelPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("localstackalloc", LocalStackSlotPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("shrink-wrap", ShrinkWrapPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("prologepilog", PrologEpilogInserterPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("postrapseudos", ExpandPostRAPseudosPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("implicit-null-checks", ImplicitNullChecksPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("postmisched", PostMachineSchedulerPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("machine-scheduler", MachineSchedulerPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("machine-cp", MachineCopyPropagationPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("post-RA-sched", PostRASchedulerPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("fentry-insert", FEntryInserterPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("xray-instrumentation", XRayInstrumentationPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("patchable-function", PatchableFunctionPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("reg-usage-propagation", RegUsageInfoPropagationPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("reg-usage-collector", RegUsageInfoCollectorPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("funclet-layout", FuncletLayoutPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("stackmap-liveness", StackMapLivenessPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("livedebugvalues", LiveDebugValuesPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("early-tailduplication", EarlyTailDuplicatePass, ()) +DUMMY_MACHINE_FUNCTION_PASS("opt-phis", OptimizePHIsPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("stack-coloring", StackColoringPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("dead-mi-elimination", DeadMachineInstructionElimPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("early-machinelicm", EarlyMachineLICMPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("machinelicm", MachineLICMPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("machine-cse", MachineCSEPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("machine-sink", MachineSinkingPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("postra-machine-sink", PostRAMachineSinkingPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("peephole-opt", PeepholeOptimizerPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("regalloc", RegAllocPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("virtregrewriter", VirtRegRewriterPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("stack-slot-coloring", StackSlotColoringPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("phi-node-elimination", PHIEliminationPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("twoaddressinstruction", TwoAddressInstructionPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("detect-dead-lanes", DetectDeadLanesPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("processimpdefs", ProcessImplicitDefsPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("liveintervals", LiveIntervalsPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("simple-register-coalescing", RegisterCoalescerPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("rename-independent-subregs", RenameIndependentSubregsPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("branch-folder", BranchFolderPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("tailduplication", TailDuplicatePass, ()) +DUMMY_MACHINE_FUNCTION_PASS("block-placement", MachineBlockPlacementPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("block-placement-stats", MachineBlockPlacementStatsPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("early-ifcvt", EarlyIfConverterPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("machine-combiner", MachineCombinerPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("lrshrink", LiveRangeShrinkPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("break-false-deps", BreakFalseDepsPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("cfi-instr-inserter", CFIInstrInserterPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("cfguard-longjmp", CFGuardLongjmpPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("ra-basic", RABasicPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("ra-fast", RAFastPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("ra-greedy", RAGreedyPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("ra-pbqp", RAPBQPPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("legalizer", LegalizerPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("irtranslator", IRTranslatorPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("regbankselect", RegBankSelectPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("instruction-select", InstructionSelectPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("reset-machine-function", ResetMachineFunctionPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("machineverifier", MachineVerifierPass, ()) +#undef DUMMY_MACHINE_FUNCTION_PASS diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachinePipeliner.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachinePipeliner.h index 8b2c27e7b888..f89a453749e8 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachinePipeliner.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachinePipeliner.h @@ -40,8 +40,6 @@ #ifndef LLVM_LIB_CODEGEN_MACHINEPIPELINER_H #define LLVM_LIB_CODEGEN_MACHINEPIPELINER_H -#include "llvm/Analysis/AliasAnalysis.h" - #include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" #include "llvm/CodeGen/RegisterClassInfo.h" @@ -51,6 +49,7 @@ namespace llvm { +class AAResults; class NodeSet; class SMSchedule; @@ -92,15 +91,7 @@ public: bool runOnMachineFunction(MachineFunction &MF) override; - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequired(); - AU.addPreserved(); - AU.addRequired(); - AU.addRequired(); - AU.addRequired(); - AU.addRequired(); - MachineFunctionPass::getAnalysisUsage(AU); - } + void getAnalysisUsage(AnalysisUsage &AU) const override; private: void preprocessPhiNodes(MachineBasicBlock &B); @@ -285,7 +276,7 @@ public: static bool classof(const ScheduleDAGInstrs *DAG) { return true; } private: - void addLoopCarriedDependences(AliasAnalysis *AA); + void addLoopCarriedDependences(AAResults *AA); void updatePhiDependences(); void changeDependences(); unsigned calculateResMII(); @@ -304,7 +295,7 @@ private: void checkValidNodeOrder(const NodeSetType &Circuits) const; bool schedulePipeline(SMSchedule &Schedule); bool computeDelta(MachineInstr &MI, unsigned &Delta); - MachineInstr *findDefInLoop(unsigned Reg); + MachineInstr *findDefInLoop(Register Reg); bool canUseLastOffsetValue(MachineInstr *MI, unsigned &BasePos, unsigned &OffsetPos, unsigned &NewBase, int64_t &NewOffset); diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineRegisterInfo.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineRegisterInfo.h index 35aab5018fa4..57086b4eebd6 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineRegisterInfo.h @@ -442,10 +442,20 @@ public: /// Return true if there is exactly one operand defining the specified /// register. bool hasOneDef(Register RegNo) const { - def_iterator DI = def_begin(RegNo); - if (DI == def_end()) - return false; - return ++DI == def_end(); + return hasSingleElement(def_operands(RegNo)); + } + + /// Returns the defining operand if there is exactly one operand defining the + /// specified register, otherwise nullptr. + MachineOperand *getOneDef(Register Reg) const { + def_iterator DI = def_begin(Reg); + if (DI == def_end()) // No defs. + return nullptr; + + def_iterator OneDef = DI; + if (++DI == def_end()) + return &*OneDef; + return nullptr; // Multiple defs. } /// use_iterator/use_begin/use_end - Walk all uses of the specified register. @@ -498,10 +508,7 @@ public: /// hasOneUse - Return true if there is exactly one instruction using the /// specified register. bool hasOneUse(Register RegNo) const { - use_iterator UI = use_begin(RegNo); - if (UI == use_end()) - return false; - return ++UI == use_end(); + return hasSingleElement(use_operands(RegNo)); } /// use_nodbg_iterator/use_nodbg_begin/use_nodbg_end - Walk all uses of the @@ -612,14 +619,10 @@ public: /// function. Writing to a constant register has no effect. bool isConstantPhysReg(MCRegister PhysReg) const; - /// Returns true if either isConstantPhysReg or TRI->isCallerPreservedPhysReg - /// returns true. This is a utility member function. - bool isCallerPreservedOrConstPhysReg(MCRegister PhysReg) const; - /// Get an iterator over the pressure sets affected by the given physical or /// virtual register. If RegUnit is physical, it must be a register unit (from /// MCRegUnitIterator). - PSetIterator getPressureSets(unsigned RegUnit) const; + PSetIterator getPressureSets(Register RegUnit) const; //===--------------------------------------------------------------------===// // Virtual Register Info @@ -894,7 +897,7 @@ public: /// /// Reserved registers may belong to an allocatable register class, but the /// target has explicitly requested that they are not used. - bool isReserved(Register PhysReg) const { + bool isReserved(MCRegister PhysReg) const { return getReservedRegs().test(PhysReg.id()); } @@ -1174,14 +1177,13 @@ class PSetIterator { public: PSetIterator() = default; - PSetIterator(unsigned RegUnit, const MachineRegisterInfo *MRI) { + PSetIterator(Register RegUnit, const MachineRegisterInfo *MRI) { const TargetRegisterInfo *TRI = MRI->getTargetRegisterInfo(); - if (Register::isVirtualRegister(RegUnit)) { + if (RegUnit.isVirtual()) { const TargetRegisterClass *RC = MRI->getRegClass(RegUnit); PSet = TRI->getRegClassPressureSets(RC); Weight = TRI->getRegClassWeight(RC).RegWeight; - } - else { + } else { PSet = TRI->getRegUnitPressureSets(RegUnit); Weight = TRI->getRegUnitWeight(RegUnit); } @@ -1203,8 +1205,8 @@ public: } }; -inline PSetIterator MachineRegisterInfo:: -getPressureSets(unsigned RegUnit) const { +inline PSetIterator +MachineRegisterInfo::getPressureSets(Register RegUnit) const { return PSetIterator(RegUnit, this); } diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineSSAUpdater.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineSSAUpdater.h index df972e12d461..0af356e376ab 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineSSAUpdater.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineSSAUpdater.h @@ -40,9 +40,6 @@ private: //typedef DenseMap AvailableValsTy; void *AV = nullptr; - /// VR - Current virtual register whose uses are being updated. - Register VR; - /// VRC - Register class of the current virtual register. const TargetRegisterClass *VRC; @@ -65,6 +62,7 @@ public: /// Initialize - Reset this object to get ready for a new set of SSA /// updates. void Initialize(Register V); + void Initialize(const TargetRegisterClass *RC); /// AddAvailableValue - Indicate that a rewritten value is available at the /// end of the specified block with the specified value. diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineStableHash.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineStableHash.h new file mode 100644 index 000000000000..8423b2da1c78 --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineStableHash.h @@ -0,0 +1,30 @@ +//===------------ MachineStableHash.h - MIR Stable Hashing Utilities ------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Stable hashing for MachineInstr and MachineOperand. Useful or getting a +// hash across runs, modules, etc. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINESTABLEHASH_H +#define LLVM_CODEGEN_MACHINESTABLEHASH_H + +#include "llvm/CodeGen/StableHashing.h" + +namespace llvm { +class MachineInstr; +class MachineOperand; + +stable_hash stableHashValue(const MachineOperand &MO); +stable_hash stableHashValue(const MachineInstr &MI, bool HashVRegs = false, + bool HashConstantPoolIndices = false, + bool HashMemOperands = false); + +} // namespace llvm + +#endif diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineTraceMetrics.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineTraceMetrics.h index 025989504177..46b57365e653 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineTraceMetrics.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/MachineTraceMetrics.h @@ -140,13 +140,13 @@ public: /// successors. struct LiveInReg { /// The virtual register required, or a register unit. - unsigned Reg; + Register Reg; /// For virtual registers: Minimum height of the defining instruction. /// For regunits: Height of the highest user in the trace. unsigned Height; - LiveInReg(unsigned Reg, unsigned Height = 0) : Reg(Reg), Height(Height) {} + LiveInReg(Register Reg, unsigned Height = 0) : Reg(Reg), Height(Height) {} }; /// Per-basic block information that relates to a specific trace through the diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/MultiHazardRecognizer.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/MultiHazardRecognizer.h new file mode 100644 index 000000000000..9846045ff014 --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/MultiHazardRecognizer.h @@ -0,0 +1,47 @@ +//=- llvm/CodeGen/MultiHazardRecognizer.h - Scheduling Support ----*- C++ -*-=// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file implements the MultiHazardRecognizer class, which is a wrapper +// for a set of ScheduleHazardRecognizer instances +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MULTIHAZARDRECOGNIZER_H +#define LLVM_CODEGEN_MULTIHAZARDRECOGNIZER_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/ScheduleHazardRecognizer.h" + +namespace llvm { + +class MachineInstr; +class SUnit; + +class MultiHazardRecognizer : public ScheduleHazardRecognizer { + SmallVector, 4> Recognizers; + +public: + MultiHazardRecognizer() = default; + void AddHazardRecognizer(std::unique_ptr &&); + + bool atIssueLimit() const override; + HazardType getHazardType(SUnit *, int Stalls = 0) override; + void Reset() override; + void EmitInstruction(SUnit *) override; + void EmitInstruction(MachineInstr *) override; + unsigned PreEmitNoops(SUnit *) override; + unsigned PreEmitNoops(MachineInstr *) override; + bool ShouldPreferAnother(SUnit *) override; + void AdvanceCycle() override; + void RecedeCycle() override; + void EmitNoop() override; +}; + +} // end namespace llvm + +#endif // LLVM_CODEGEN_MULTIHAZARDRECOGNIZER_H diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/NonRelocatableStringpool.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/NonRelocatableStringpool.h index 56db30ff7d6d..fe07c70d85c5 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/NonRelocatableStringpool.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/NonRelocatableStringpool.h @@ -39,7 +39,7 @@ public: /// Get the offset of string \p S in the string table. This can insert a new /// element or return the offset of a pre-existing one. - uint32_t getStringOffset(StringRef S) { return getEntry(S).getOffset(); } + uint64_t getStringOffset(StringRef S) { return getEntry(S).getOffset(); } /// Get permanent storage for \p S (but do not necessarily emit \p S in the /// output section). A latter call to getStringOffset() with the same string @@ -57,7 +57,7 @@ public: private: MapTy Strings; - uint32_t CurrentEndOffset = 0; + uint64_t CurrentEndOffset = 0; unsigned NumEntries = 0; DwarfStringPoolEntryRef EmptyString; std::function Translator; diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/Passes.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/Passes.h index 9e5b4446c195..676ed2c65eb1 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/Passes.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/Passes.h @@ -44,11 +44,15 @@ namespace llvm { /// the entry block. FunctionPass *createUnreachableBlockEliminationPass(); - /// createBBSectionsPrepare Pass - This pass assigns sections to machine basic - /// blocks and is enabled with -fbasic-block-sections. - /// Buf is a memory buffer that contains the list of functions and basic - /// block ids to selectively enable basic block sections. - MachineFunctionPass *createBBSectionsPreparePass(const MemoryBuffer *Buf); + /// createBasicBlockSections Pass - This pass assigns sections to machine + /// basic blocks and is enabled with -fbasic-block-sections. Buf is a memory + /// buffer that contains the list of functions and basic block ids to + /// selectively enable basic block sections. + MachineFunctionPass *createBasicBlockSectionsPass(const MemoryBuffer *Buf); + + /// createMachineFunctionSplitterPass - This pass splits machine functions + /// using profile information. + MachineFunctionPass *createMachineFunctionSplitterPass(); /// MachineFunctionPrinter pass - This pass prints out the machine function to /// the given stream as a debugging tool. @@ -72,10 +76,6 @@ namespace llvm { /// matching during instruction selection. FunctionPass *createCodeGenPreparePass(); - /// createScalarizeMaskedMemIntrinPass - Replace masked load, store, gather - /// and scatter intrinsics with scalar code when target doesn't support them. - FunctionPass *createScalarizeMaskedMemIntrinPass(); - /// AtomicExpandID -- Lowers atomic operations in terms of either cmpxchg /// load-linked/store-conditional loops. extern char &AtomicExpandID; @@ -387,10 +387,6 @@ namespace llvm { /// createJumpInstrTables - This pass creates jump-instruction tables. ModulePass *createJumpInstrTablesPass(); - /// createForwardControlFlowIntegrityPass - This pass adds control-flow - /// integrity. - ModulePass *createForwardControlFlowIntegrityPass(); - /// InterleavedAccess Pass - This pass identifies and matches interleaved /// memory accesses to target specific intrinsics. /// @@ -471,6 +467,9 @@ namespace llvm { /// Create Hardware Loop pass. \see HardwareLoops.cpp FunctionPass *createHardwareLoopsPass(); + /// This pass inserts pseudo probe annotation for callsite profiling. + FunctionPass *createPseudoProbeInserter(); + /// Create IR Type Promotion pass. \see TypePromotion.cpp FunctionPass *createTypePromotionPass(); @@ -483,9 +482,16 @@ namespace llvm { /// info was generated by another source such as clang. ModulePass *createStripDebugMachineModulePass(bool OnlyDebugified); + /// Creates MIR Check Debug pass. \see MachineCheckDebugify.cpp + ModulePass *createCheckDebugMachineModulePass(); + /// The pass fixups statepoint machine instruction to replace usage of /// caller saved registers with stack slots. extern char &FixupStatepointCallerSavedID; + + /// The pass transform load/store <256 x i32> to AMX load/store intrinsics + /// or split the data to two <128 x i32>. + FunctionPass *createX86LowerAMXTypePass(); } // End llvm namespace #endif diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/RDFGraph.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/RDFGraph.h index 585f43e116f9..00d6ec93d555 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/RDFGraph.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/RDFGraph.h @@ -753,10 +753,6 @@ namespace rdf { NodeAddr getNextRelated(NodeAddr IA, NodeAddr RA) const; - NodeAddr getNextImp(NodeAddr IA, - NodeAddr RA, bool Create); - NodeAddr getNextImp(NodeAddr IA, - NodeAddr RA) const; NodeAddr getNextShadow(NodeAddr IA, NodeAddr RA, bool Create); NodeAddr getNextShadow(NodeAddr IA, diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/RDFLiveness.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/RDFLiveness.h index ea4890271726..d39d3585e7bd 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/RDFLiveness.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/RDFLiveness.h @@ -18,6 +18,8 @@ #include "llvm/MC/LaneBitmask.h" #include #include +#include +#include #include namespace llvm { @@ -28,6 +30,30 @@ class MachineDominatorTree; class MachineRegisterInfo; class TargetRegisterInfo; +} // namespace llvm + +namespace llvm { +namespace rdf { +namespace detail { + +using NodeRef = std::pair; + +} // namespace detail +} // namespace rdf +} // namespace llvm + +namespace std { + +template <> struct hash { + std::size_t operator()(llvm::rdf::detail::NodeRef R) const { + return std::hash{}(R.first) ^ + std::hash{}(R.second.getAsInteger()); + } +}; + +} // namespace std + +namespace llvm { namespace rdf { struct Liveness { @@ -46,10 +72,9 @@ namespace rdf { std::map Map; }; - using NodeRef = std::pair; - using NodeRefSet = std::set; - // RegisterId in RefMap must be normalized. - using RefMap = std::map; + using NodeRef = detail::NodeRef; + using NodeRefSet = std::unordered_set; + using RefMap = std::unordered_map; Liveness(MachineRegisterInfo &mri, const DataFlowGraph &g) : DFG(g), TRI(g.getTRI()), PRI(g.getPRI()), MDT(g.getDT()), @@ -110,15 +135,14 @@ namespace rdf { // Cache of mapping from node ids (for RefNodes) to the containing // basic blocks. Not computing it each time for each node reduces // the liveness calculation time by a large fraction. - using NodeBlockMap = DenseMap; - NodeBlockMap NBMap; + DenseMap NBMap; // Phi information: // // RealUseMap // map: NodeId -> (map: RegisterId -> NodeRefSet) // phi id -> (map: register -> set of reached non-phi uses) - std::map RealUseMap; + DenseMap RealUseMap; // Inverse iterated dominance frontier. std::map> IIDF; diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/RDFRegisters.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/RDFRegisters.h index 4afaf80e4659..c49b4883e1c1 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/RDFRegisters.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/RDFRegisters.h @@ -91,6 +91,11 @@ namespace rdf { bool operator< (const RegisterRef &RR) const { return Reg < RR.Reg || (Reg == RR.Reg && Mask < RR.Mask); } + + size_t hash() const { + return std::hash{}(Reg) ^ + std::hash{}(Mask.getAsInteger()); + } }; @@ -110,8 +115,6 @@ namespace rdf { return RegMasks.get(Register::stackSlot2Index(R)); } - RegisterRef normalize(RegisterRef RR) const; - bool alias(RegisterRef RA, RegisterRef RB) const { if (!isRegMaskId(RA.Reg)) return !isRegMaskId(RB.Reg) ? aliasRR(RA, RB) : aliasRM(RA, RB); @@ -128,6 +131,10 @@ namespace rdf { return MaskInfos[Register::stackSlot2Index(MaskId)].Units; } + const BitVector &getUnitAliases(uint32_t U) const { + return AliasInfos[U].Regs; + } + RegisterRef mapTo(RegisterRef RR, unsigned R) const; const TargetRegisterInfo &getTRI() const { return TRI; } @@ -142,12 +149,16 @@ namespace rdf { struct MaskInfo { BitVector Units; }; + struct AliasInfo { + BitVector Regs; + }; const TargetRegisterInfo &TRI; IndexedSet RegMasks; std::vector RegInfos; std::vector UnitInfos; std::vector MaskInfos; + std::vector AliasInfos; bool aliasRR(RegisterRef RA, RegisterRef RB) const; bool aliasRM(RegisterRef RR, RegisterRef RM) const; @@ -159,10 +170,15 @@ namespace rdf { : Units(pri.getTRI().getNumRegUnits()), PRI(pri) {} RegisterAggr(const RegisterAggr &RG) = default; + unsigned count() const { return Units.count(); } bool empty() const { return Units.none(); } bool hasAliasOf(RegisterRef RR) const; bool hasCoverOf(RegisterRef RR) const; + bool operator==(const RegisterAggr &A) const { + return DenseMapInfo::isEqual(Units, A.Units); + } + static bool isCoverOf(RegisterRef RA, RegisterRef RB, const PhysicalRegisterInfo &PRI) { return RegisterAggr(PRI).insert(RA).hasCoverOf(RB); @@ -179,6 +195,10 @@ namespace rdf { RegisterRef clearIn(RegisterRef RR) const; RegisterRef makeRegRef() const; + size_t hash() const { + return DenseMapInfo::getHashValue(Units); + } + void print(raw_ostream &OS) const; struct rr_iterator { @@ -233,8 +253,27 @@ namespace rdf { }; raw_ostream &operator<< (raw_ostream &OS, const PrintLaneMaskOpt &P); + raw_ostream &operator<< (raw_ostream &OS, const RegisterAggr &A); } // end namespace rdf } // end namespace llvm +namespace std { + template <> struct hash { + size_t operator()(llvm::rdf::RegisterRef A) const { + return A.hash(); + } + }; + template <> struct hash { + size_t operator()(const llvm::rdf::RegisterAggr &A) const { + return A.hash(); + } + }; + template <> struct equal_to { + bool operator()(const llvm::rdf::RegisterAggr &A, + const llvm::rdf::RegisterAggr &B) const { + return A == B; + } + }; +} #endif // LLVM_LIB_TARGET_HEXAGON_RDFREGISTERS_H diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/ReachingDefAnalysis.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/ReachingDefAnalysis.h index a8a436337e07..bcb48de2fe5a 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/ReachingDefAnalysis.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/ReachingDefAnalysis.h @@ -139,23 +139,25 @@ public: /// Provides the instruction id of the closest reaching def instruction of /// PhysReg that reaches MI, relative to the begining of MI's basic block. - int getReachingDef(MachineInstr *MI, int PhysReg) const; + int getReachingDef(MachineInstr *MI, MCRegister PhysReg) const; /// Return whether A and B use the same def of PhysReg. - bool hasSameReachingDef(MachineInstr *A, MachineInstr *B, int PhysReg) const; + bool hasSameReachingDef(MachineInstr *A, MachineInstr *B, + MCRegister PhysReg) const; /// Return whether the reaching def for MI also is live out of its parent /// block. - bool isReachingDefLiveOut(MachineInstr *MI, int PhysReg) const; + bool isReachingDefLiveOut(MachineInstr *MI, MCRegister PhysReg) const; /// Return the local MI that produces the live out value for PhysReg, or /// nullptr for a non-live out or non-local def. MachineInstr *getLocalLiveOutMIDef(MachineBasicBlock *MBB, - int PhysReg) const; + MCRegister PhysReg) const; /// If a single MachineInstr creates the reaching definition, then return it. /// Otherwise return null. - MachineInstr *getUniqueReachingMIDef(MachineInstr *MI, int PhysReg) const; + MachineInstr *getUniqueReachingMIDef(MachineInstr *MI, + MCRegister PhysReg) const; /// If a single MachineInstr creates the reaching definition, for MIs operand /// at Idx, then return it. Otherwise return null. @@ -167,40 +169,45 @@ public: /// Provide whether the register has been defined in the same basic block as, /// and before, MI. - bool hasLocalDefBefore(MachineInstr *MI, int PhysReg) const; + bool hasLocalDefBefore(MachineInstr *MI, MCRegister PhysReg) const; /// Return whether the given register is used after MI, whether it's a local /// use or a live out. - bool isRegUsedAfter(MachineInstr *MI, int PhysReg) const; + bool isRegUsedAfter(MachineInstr *MI, MCRegister PhysReg) const; /// Return whether the given register is defined after MI. - bool isRegDefinedAfter(MachineInstr *MI, int PhysReg) const; + bool isRegDefinedAfter(MachineInstr *MI, MCRegister PhysReg) const; /// Provides the clearance - the number of instructions since the closest /// reaching def instuction of PhysReg that reaches MI. - int getClearance(MachineInstr *MI, MCPhysReg PhysReg) const; + int getClearance(MachineInstr *MI, MCRegister PhysReg) const; /// Provides the uses, in the same block as MI, of register that MI defines. /// This does not consider live-outs. - void getReachingLocalUses(MachineInstr *MI, int PhysReg, + void getReachingLocalUses(MachineInstr *MI, MCRegister PhysReg, InstSet &Uses) const; /// Search MBB for a definition of PhysReg and insert it into Defs. If no /// definition is found, recursively search the predecessor blocks for them. - void getLiveOuts(MachineBasicBlock *MBB, int PhysReg, InstSet &Defs, + void getLiveOuts(MachineBasicBlock *MBB, MCRegister PhysReg, InstSet &Defs, BlockSet &VisitedBBs) const; - void getLiveOuts(MachineBasicBlock *MBB, int PhysReg, InstSet &Defs) const; + void getLiveOuts(MachineBasicBlock *MBB, MCRegister PhysReg, + InstSet &Defs) const; /// For the given block, collect the instructions that use the live-in /// value of the provided register. Return whether the value is still /// live on exit. - bool getLiveInUses(MachineBasicBlock *MBB, int PhysReg, + bool getLiveInUses(MachineBasicBlock *MBB, MCRegister PhysReg, InstSet &Uses) const; /// Collect the users of the value stored in PhysReg, which is defined /// by MI. - void getGlobalUses(MachineInstr *MI, int PhysReg, - InstSet &Uses) const; + void getGlobalUses(MachineInstr *MI, MCRegister PhysReg, InstSet &Uses) const; + + /// Collect all possible definitions of the value stored in PhysReg, which is + /// used by MI. + void getGlobalReachingDefs(MachineInstr *MI, MCRegister PhysReg, + InstSet &Defs) const; /// Return whether From can be moved forwards to just before To. bool isSafeToMoveForwards(MachineInstr *From, MachineInstr *To) const; @@ -224,12 +231,13 @@ public: /// Return whether a MachineInstr could be inserted at MI and safely define /// the given register without affecting the program. - bool isSafeToDefRegAt(MachineInstr *MI, int PhysReg) const; + bool isSafeToDefRegAt(MachineInstr *MI, MCRegister PhysReg) const; /// Return whether a MachineInstr could be inserted at MI and safely define /// the given register without affecting the program, ignoring any effects /// on the provided instructions. - bool isSafeToDefRegAt(MachineInstr *MI, int PhysReg, InstSet &Ignore) const; + bool isSafeToDefRegAt(MachineInstr *MI, MCRegister PhysReg, + InstSet &Ignore) const; private: /// Set up LiveRegs by merging predecessor live-out values. @@ -264,7 +272,8 @@ private: /// Provides the instruction of the closest reaching def instruction of /// PhysReg that reaches MI, relative to the begining of MI's basic block. - MachineInstr *getReachingLocalMIDef(MachineInstr *MI, int PhysReg) const; + MachineInstr *getReachingLocalMIDef(MachineInstr *MI, + MCRegister PhysReg) const; }; } // namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/RegAllocPBQP.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/RegAllocPBQP.h index f7f92248f4ce..1ed55082e32c 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/RegAllocPBQP.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/RegAllocPBQP.h @@ -22,6 +22,8 @@ #include "llvm/CodeGen/PBQP/Math.h" #include "llvm/CodeGen/PBQP/ReductionRules.h" #include "llvm/CodeGen/PBQP/Solution.h" +#include "llvm/CodeGen/Register.h" +#include "llvm/MC/MCRegister.h" #include "llvm/Support/ErrorHandling.h" #include #include @@ -96,13 +98,13 @@ public: AllowedRegVector() = default; AllowedRegVector(AllowedRegVector &&) = default; - AllowedRegVector(const std::vector &OptVec) - : NumOpts(OptVec.size()), Opts(new unsigned[NumOpts]) { + AllowedRegVector(const std::vector &OptVec) + : NumOpts(OptVec.size()), Opts(new MCRegister[NumOpts]) { std::copy(OptVec.begin(), OptVec.end(), Opts.get()); } unsigned size() const { return NumOpts; } - unsigned operator[](size_t I) const { return Opts[I]; } + MCRegister operator[](size_t I) const { return Opts[I]; } bool operator==(const AllowedRegVector &Other) const { if (NumOpts != Other.NumOpts) @@ -116,12 +118,12 @@ public: private: unsigned NumOpts = 0; - std::unique_ptr Opts; + std::unique_ptr Opts; }; inline hash_code hash_value(const AllowedRegVector &OptRegs) { - unsigned *OStart = OptRegs.Opts.get(); - unsigned *OEnd = OptRegs.Opts.get() + OptRegs.NumOpts; + MCRegister *OStart = OptRegs.Opts.get(); + MCRegister *OEnd = OptRegs.Opts.get() + OptRegs.NumOpts; return hash_combine(OptRegs.NumOpts, hash_combine_range(OStart, OEnd)); } @@ -143,11 +145,11 @@ public: LiveIntervals &LIS; MachineBlockFrequencyInfo &MBFI; - void setNodeIdForVReg(unsigned VReg, GraphBase::NodeId NId) { - VRegToNodeId[VReg] = NId; + void setNodeIdForVReg(Register VReg, GraphBase::NodeId NId) { + VRegToNodeId[VReg.id()] = NId; } - GraphBase::NodeId getNodeIdForVReg(unsigned VReg) const { + GraphBase::NodeId getNodeIdForVReg(Register VReg) const { auto VRegItr = VRegToNodeId.find(VReg); if (VRegItr == VRegToNodeId.end()) return GraphBase::invalidNodeId(); @@ -159,7 +161,7 @@ public: } private: - DenseMap VRegToNodeId; + DenseMap VRegToNodeId; AllowedRegVecPool AllowedRegVecs; }; @@ -197,8 +199,8 @@ public: NodeMetadata(NodeMetadata &&) = default; NodeMetadata& operator=(NodeMetadata &&) = default; - void setVReg(unsigned VReg) { this->VReg = VReg; } - unsigned getVReg() const { return VReg; } + void setVReg(Register VReg) { this->VReg = VReg; } + Register getVReg() const { return VReg; } void setAllowedRegs(GraphMetadata::AllowedRegVecRef AllowedRegs) { this->AllowedRegs = std::move(AllowedRegs); @@ -256,7 +258,7 @@ private: unsigned NumOpts = 0; unsigned DeniedOpts = 0; std::unique_ptr OptUnsafeEdges; - unsigned VReg = 0; + Register VReg; GraphMetadata::AllowedRegVecRef AllowedRegs; #ifndef NDEBUG diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/Register.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/Register.h index 054040cd29a1..d7057cfb76e0 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/Register.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/Register.h @@ -40,24 +40,24 @@ public: /// frame index in a variable that normally holds a register. isStackSlot() /// returns true if Reg is in the range used for stack slots. /// - /// Note that isVirtualRegister() and isPhysicalRegister() cannot handle stack - /// slots, so if a variable may contains a stack slot, always check - /// isStackSlot() first. - /// + /// FIXME: remove in favor of member. static bool isStackSlot(unsigned Reg) { return MCRegister::isStackSlot(Reg); } + /// Return true if this is a stack slot. + bool isStack() const { return MCRegister::isStackSlot(Reg); } + /// Compute the frame index from a register value representing a stack slot. - static int stackSlot2Index(unsigned Reg) { - assert(isStackSlot(Reg) && "Not a stack slot"); + static int stackSlot2Index(Register Reg) { + assert(Reg.isStack() && "Not a stack slot"); return int(Reg - MCRegister::FirstStackSlot); } /// Convert a non-negative frame index to a stack slot register value. - static unsigned index2StackSlot(int FI) { + static Register index2StackSlot(int FI) { assert(FI >= 0 && "Cannot hold a negative frame index."); - return FI + MCRegister::FirstStackSlot; + return Register(FI + MCRegister::FirstStackSlot); } /// Return true if the specified register number is in @@ -69,20 +69,19 @@ public: /// Return true if the specified register number is in /// the virtual register namespace. static bool isVirtualRegister(unsigned Reg) { - assert(!isStackSlot(Reg) && "Not a register! Check isStackSlot() first."); - return Reg & MCRegister::VirtualRegFlag; + return Reg & MCRegister::VirtualRegFlag && !isStackSlot(Reg); } /// Convert a virtual register number to a 0-based index. /// The first virtual register in a function will get the index 0. - static unsigned virtReg2Index(unsigned Reg) { + static unsigned virtReg2Index(Register Reg) { assert(isVirtualRegister(Reg) && "Not a virtual register"); return Reg & ~MCRegister::VirtualRegFlag; } /// Convert a 0-based index to a virtual register number. /// This is the inverse operation of VirtReg2IndexFunctor below. - static unsigned index2VirtReg(unsigned Index) { + static Register index2VirtReg(unsigned Index) { assert(Index < (1u << 31) && "Index too large for virtual register range."); return Index | MCRegister::VirtualRegFlag; } @@ -115,6 +114,15 @@ public: return MCRegister(Reg); } + /// Utility to check-convert this value to a MCRegister. The caller is + /// expected to have already validated that this Register is, indeed, + /// physical. + MCRegister asMCReg() const { + assert(Reg == MCRegister::NoRegister || + MCRegister::isPhysicalRegister(Reg)); + return MCRegister(Reg); + } + bool isValid() const { return Reg != MCRegister::NoRegister; } /// Comparisons between register objects diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/RegisterPressure.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/RegisterPressure.h index 92333b859f1b..1deeb4d41511 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/RegisterPressure.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/RegisterPressure.h @@ -37,10 +37,10 @@ class MachineRegisterInfo; class RegisterClassInfo; struct RegisterMaskPair { - unsigned RegUnit; ///< Virtual register or register unit. + Register RegUnit; ///< Virtual register or register unit. LaneBitmask LaneMask; - RegisterMaskPair(unsigned RegUnit, LaneBitmask LaneMask) + RegisterMaskPair(Register RegUnit, LaneBitmask LaneMask) : RegUnit(RegUnit), LaneMask(LaneMask) {} }; @@ -157,7 +157,7 @@ public: const_iterator begin() const { return &PressureChanges[0]; } const_iterator end() const { return &PressureChanges[MaxPSets]; } - void addPressureChange(unsigned RegUnit, bool IsDec, + void addPressureChange(Register RegUnit, bool IsDec, const MachineRegisterInfo *MRI); void dump(const TargetRegisterInfo &TRI) const; @@ -275,24 +275,24 @@ private: RegSet Regs; unsigned NumRegUnits; - unsigned getSparseIndexFromReg(unsigned Reg) const { - if (Register::isVirtualRegister(Reg)) + unsigned getSparseIndexFromReg(Register Reg) const { + if (Reg.isVirtual()) return Register::virtReg2Index(Reg) + NumRegUnits; assert(Reg < NumRegUnits); return Reg; } - unsigned getRegFromSparseIndex(unsigned SparseIndex) const { + Register getRegFromSparseIndex(unsigned SparseIndex) const { if (SparseIndex >= NumRegUnits) - return Register::index2VirtReg(SparseIndex-NumRegUnits); - return SparseIndex; + return Register::index2VirtReg(SparseIndex - NumRegUnits); + return Register(SparseIndex); } public: void clear(); void init(const MachineRegisterInfo &MRI); - LaneBitmask contains(unsigned Reg) const { + LaneBitmask contains(Register Reg) const { unsigned SparseIndex = getSparseIndexFromReg(Reg); RegSet::const_iterator I = Regs.find(SparseIndex); if (I == Regs.end()) @@ -332,7 +332,7 @@ public: template void appendTo(ContainerT &To) const { for (const IndexMaskPair &P : Regs) { - unsigned Reg = getRegFromSparseIndex(P.Index); + Register Reg = getRegFromSparseIndex(P.Index); if (P.LaneMask.any()) To.push_back(RegisterMaskPair(Reg, P.LaneMask)); } @@ -390,7 +390,7 @@ class RegPressureTracker { LiveRegSet LiveRegs; /// Set of vreg defs that start a live range. - SparseSet UntiedDefs; + SparseSet UntiedDefs; /// Live-through pressure. std::vector LiveThruPressure; @@ -532,7 +532,7 @@ public: return getDownwardPressure(MI, PressureResult, MaxPressureResult); } - bool hasUntiedDef(unsigned VirtReg) const { + bool hasUntiedDef(Register VirtReg) const { return UntiedDefs.count(VirtReg); } @@ -548,9 +548,9 @@ protected: /// after the current position. SlotIndex getCurrSlot() const; - void increaseRegPressure(unsigned RegUnit, LaneBitmask PreviousMask, + void increaseRegPressure(Register RegUnit, LaneBitmask PreviousMask, LaneBitmask NewMask); - void decreaseRegPressure(unsigned RegUnit, LaneBitmask PreviousMask, + void decreaseRegPressure(Register RegUnit, LaneBitmask PreviousMask, LaneBitmask NewMask); void bumpDeadDefs(ArrayRef DeadDefs); @@ -561,9 +561,9 @@ protected: void discoverLiveInOrOut(RegisterMaskPair Pair, SmallVectorImpl &LiveInOrOut); - LaneBitmask getLastUsedLanes(unsigned RegUnit, SlotIndex Pos) const; - LaneBitmask getLiveLanesAt(unsigned RegUnit, SlotIndex Pos) const; - LaneBitmask getLiveThroughAt(unsigned RegUnit, SlotIndex Pos) const; + LaneBitmask getLastUsedLanes(Register RegUnit, SlotIndex Pos) const; + LaneBitmask getLiveLanesAt(Register RegUnit, SlotIndex Pos) const; + LaneBitmask getLiveThroughAt(Register RegUnit, SlotIndex Pos) const; }; void dumpRegSetPressure(ArrayRef SetPressure, diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/RegisterScavenging.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/RegisterScavenging.h index 5b5a80a67e7f..4f48ea2dc8e8 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/RegisterScavenging.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/RegisterScavenging.h @@ -89,15 +89,6 @@ public: while (MBBI != I) forward(); } - /// Invert the behavior of forward() on the current instruction (undo the - /// changes to the available registers made by forward()). - void unprocess(); - - /// Unprocess instructions until you reach the provided iterator. - void unprocess(MachineBasicBlock::iterator I) { - while (MBBI != I) unprocess(); - } - /// Update internal register state and move MBB iterator backwards. /// Contrary to unprocess() this method gives precise results even in the /// absence of kill flags. @@ -203,10 +194,10 @@ private: void determineKillsAndDefs(); /// Add all Reg Units that Reg contains to BV. - void addRegUnits(BitVector &BV, Register Reg); + void addRegUnits(BitVector &BV, MCRegister Reg); /// Remove all Reg Units that \p Reg contains from \p BV. - void removeRegUnits(BitVector &BV, Register Reg); + void removeRegUnits(BitVector &BV, MCRegister Reg); /// Return the candidate register that is unused for the longest after /// StartMI. UseMI is set to the instruction where the search stopped. diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/ResourcePriorityQueue.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/ResourcePriorityQueue.h index b38cd4924174..bd63dd875621 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/ResourcePriorityQueue.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/ResourcePriorityQueue.h @@ -107,7 +107,6 @@ namespace llvm { /// InitNumRegDefsLeft - Determine the # of regs defined by this node. /// void initNumRegDefsLeft(SUnit *SU); - void updateNumRegDefsLeft(SUnit *SU); int regPressureDelta(SUnit *SU, bool RawPressure = false); int rawRegPressureDelta (SUnit *SU, unsigned RCId); diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/RuntimeLibcalls.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/RuntimeLibcalls.h index f71f39e5bf03..86e24cab76f6 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/RuntimeLibcalls.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/RuntimeLibcalls.h @@ -15,6 +15,7 @@ #define LLVM_CODEGEN_RUNTIMELIBCALLS_H #include "llvm/CodeGen/ValueTypes.h" +#include "llvm/Support/AtomicOrdering.h" namespace llvm { namespace RTLIB { @@ -60,6 +61,10 @@ namespace RTLIB { /// UNKNOWN_LIBCALL if there is none. Libcall getSYNC(unsigned Opc, MVT VT); + /// Return the outline atomics value for the given opcode, atomic ordering + /// and type, or UNKNOWN_LIBCALL if there is none. + Libcall getOUTLINE_ATOMIC(unsigned Opc, AtomicOrdering Order, MVT VT); + /// getMEMCPY_ELEMENT_UNORDERED_ATOMIC - Return /// MEMCPY_ELEMENT_UNORDERED_ATOMIC_* value for the given element size or /// UNKNOW_LIBCALL if there is none. diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h index 1eb9b9f322ba..50b186de2b05 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h @@ -268,6 +268,11 @@ namespace llvm { return SU->SchedClass; } + /// IsReachable - Checks if SU is reachable from TargetSU. + bool IsReachable(SUnit *SU, SUnit *TargetSU) { + return Topo.IsReachable(SU, TargetSU); + } + /// Returns an iterator to the top of the current scheduling region. MachineBasicBlock::iterator begin() const { return RegionBegin; } @@ -362,16 +367,6 @@ namespace llvm { void addVRegDefDeps(SUnit *SU, unsigned OperIdx); void addVRegUseDeps(SUnit *SU, unsigned OperIdx); - /// Initializes register live-range state for updating kills. - /// PostRA helper for rewriting kill flags. - void startBlockForKills(MachineBasicBlock *BB); - - /// Toggles a register operand kill flag. - /// - /// Other adjustments may be made to the instruction if necessary. Return - /// true if the operand has been deleted, false if not. - void toggleKillFlag(MachineInstr &MI, MachineOperand &MO); - /// Returns a mask for which lanes get read/written by the given (register) /// machine operand. LaneBitmask getLaneMaskForMO(const MachineOperand &MO) const; @@ -393,10 +388,7 @@ namespace llvm { /// Returns an existing SUnit for this MI, or nullptr. inline SUnit *ScheduleDAGInstrs::getSUnit(MachineInstr *MI) const { - DenseMap::const_iterator I = MISUnitMap.find(MI); - if (I == MISUnitMap.end()) - return nullptr; - return I->second; + return MISUnitMap.lookup(MI); } } // end namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/ScheduleHazardRecognizer.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/ScheduleHazardRecognizer.h index 37590f496ca2..9f1101b658d0 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/ScheduleHazardRecognizer.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/ScheduleHazardRecognizer.h @@ -57,7 +57,7 @@ public: /// other instruction is available, issue it first. /// * NoopHazard: issuing this instruction would break the program. If /// some other instruction can be issued, do so, otherwise issue a noop. - virtual HazardType getHazardType(SUnit *m, int Stalls = 0) { + virtual HazardType getHazardType(SUnit *, int Stalls = 0) { return NoHazard; } @@ -114,6 +114,14 @@ public: // Default implementation: count it as a cycle. AdvanceCycle(); } + + /// EmitNoops - This callback is invoked when noops were added to the + /// instruction stream. + virtual void EmitNoops(unsigned Quantity) { + // Default implementation: count it as a cycle. + for (unsigned i = 0; i < Quantity; ++i) + EmitNoop(); + } }; } // end namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/SelectionDAG.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/SelectionDAG.h index f26ab6f287a0..aeb488dd6c83 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/SelectionDAG.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/SelectionDAG.h @@ -27,7 +27,6 @@ #include "llvm/ADT/iterator.h" #include "llvm/ADT/iterator_range.h" #include "llvm/CodeGen/DAGCombine.h" -#include "llvm/CodeGen/FunctionLoweringInfo.h" #include "llvm/CodeGen/ISDOpcodes.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineMemOperand.h" @@ -64,6 +63,7 @@ class ConstantFP; class ConstantInt; class DataLayout; struct fltSemantics; +class FunctionLoweringInfo; class GlobalValue; struct KnownBits; class LegacyDivergenceAnalysis; @@ -331,6 +331,29 @@ public: virtual void anchor(); }; + /// Help to insert SDNodeFlags automatically in transforming. Use + /// RAII to save and resume flags in current scope. + class FlagInserter { + SelectionDAG &DAG; + SDNodeFlags Flags; + FlagInserter *LastInserter; + + public: + FlagInserter(SelectionDAG &SDAG, SDNodeFlags Flags) + : DAG(SDAG), Flags(Flags), + LastInserter(SDAG.getFlagInserter()) { + SDAG.setFlagInserter(this); + } + FlagInserter(SelectionDAG &SDAG, SDNode *N) + : FlagInserter(SDAG, N->getFlags()) {} + + FlagInserter(const FlagInserter &) = delete; + FlagInserter &operator=(const FlagInserter &) = delete; + ~FlagInserter() { DAG.setFlagInserter(LastInserter); } + + const SDNodeFlags getFlags() const { return Flags; } + }; + /// When true, additional steps are taken to /// ensure that getConstant() and similar functions return DAG nodes that /// have legal types. This is important after type legalization since @@ -433,6 +456,9 @@ public: ProfileSummaryInfo *getPSI() const { return PSI; } BlockFrequencyInfo *getBFI() const { return BFI; } + FlagInserter *getFlagInserter() { return Inserter; } + void setFlagInserter(FlagInserter *FI) { Inserter = FI; } + /// Just dump dot graph to a user-provided path and title. /// This doesn't open the dot viewer program and /// helps visualization when outside debugging session. @@ -695,9 +721,7 @@ public: // When generating a branch to a BB, we don't in general know enough // to provide debug info for the BB at that time, so keep this one around. SDValue getBasicBlock(MachineBasicBlock *MBB); - SDValue getBasicBlock(MachineBasicBlock *MBB, SDLoc dl); SDValue getExternalSymbol(const char *Sym, EVT VT); - SDValue getExternalSymbol(const char *Sym, const SDLoc &dl, EVT VT); SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags = 0); SDValue getMCSymbol(MCSymbol *Sym, EVT VT); @@ -870,7 +894,7 @@ public: /// Returns sum of the base pointer and offset. /// Unlike getObjectPtrOffset this does not set NoUnsignedWrap by default. - SDValue getMemBasePlusOffset(SDValue Base, int64_t Offset, const SDLoc &DL, + SDValue getMemBasePlusOffset(SDValue Base, TypeSize Offset, const SDLoc &DL, const SDNodeFlags Flags = SDNodeFlags()); SDValue getMemBasePlusOffset(SDValue Base, SDValue Offset, const SDLoc &DL, const SDNodeFlags Flags = SDNodeFlags()); @@ -878,7 +902,7 @@ public: /// Create an add instruction with appropriate flags when used for /// addressing some offset of an object. i.e. if a load is split into multiple /// components, create an add nuw from the base pointer to the offset. - SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, int64_t Offset) { + SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, TypeSize Offset) { SDNodeFlags Flags; Flags.setNoUnsignedWrap(true); return getMemBasePlusOffset(Ptr, Offset, SL, Flags); @@ -945,21 +969,31 @@ public: SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef Ops); SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, - ArrayRef Ops, const SDNodeFlags Flags = SDNodeFlags()); + ArrayRef Ops, const SDNodeFlags Flags); SDValue getNode(unsigned Opcode, const SDLoc &DL, ArrayRef ResultTys, ArrayRef Ops); SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList, - ArrayRef Ops, const SDNodeFlags Flags = SDNodeFlags()); + ArrayRef Ops, const SDNodeFlags Flags); + + // Use flags from current flag inserter. + SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, + ArrayRef Ops); + SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList, + ArrayRef Ops); + SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue Operand); + SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N1, + SDValue N2); + SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N1, + SDValue N2, SDValue N3); // Specialize based on number of operands. SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT); SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue Operand, - const SDNodeFlags Flags = SDNodeFlags()); + const SDNodeFlags Flags); SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N1, - SDValue N2, const SDNodeFlags Flags = SDNodeFlags()); + SDValue N2, const SDNodeFlags Flags); SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N1, - SDValue N2, SDValue N3, - const SDNodeFlags Flags = SDNodeFlags()); + SDValue N2, SDValue N3, const SDNodeFlags Flags); SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N1, SDValue N2, SDValue N3, SDValue N4); SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N1, @@ -1169,6 +1203,12 @@ public: SDValue getLifetimeNode(bool IsStart, const SDLoc &dl, SDValue Chain, int FrameIndex, int64_t Size, int64_t Offset = -1); + /// Creates a PseudoProbeSDNode with function GUID `Guid` and + /// the index of the block `Index` it is probing, as well as the attributes + /// `attr` of the probe. + SDValue getPseudoProbeNode(const SDLoc &Dl, SDValue Chain, uint64_t Guid, + uint64_t Index, uint32_t Attr); + /// Create a MERGE_VALUES node from the given operands. SDValue getMergeValues(ArrayRef Ops, const SDLoc &dl); @@ -1178,14 +1218,15 @@ public: /// This function will set the MOLoad flag on MMOFlags, but you can set it if /// you want. The MOStore flag must not be set. SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, - MachinePointerInfo PtrInfo, MaybeAlign Alignment, + MachinePointerInfo PtrInfo, + MaybeAlign Alignment = MaybeAlign(), MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone, const AAMDNodes &AAInfo = AAMDNodes(), const MDNode *Ranges = nullptr); /// FIXME: Remove once transition to Align is over. inline SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, - MachinePointerInfo PtrInfo, unsigned Alignment = 0, + MachinePointerInfo PtrInfo, unsigned Alignment, MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone, const AAMDNodes &AAInfo = AAMDNodes(), const MDNode *Ranges = nullptr) { @@ -1197,14 +1238,14 @@ public: SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, - MaybeAlign Alignment, + MaybeAlign Alignment = MaybeAlign(), MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone, const AAMDNodes &AAInfo = AAMDNodes()); /// FIXME: Remove once transition to Align is over. inline SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, - unsigned Alignment = 0, + unsigned Alignment, MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone, const AAMDNodes &AAInfo = AAMDNodes()) { return getExtLoad(ExtType, dl, VT, Chain, Ptr, PtrInfo, MemVT, @@ -1221,13 +1262,12 @@ public: MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone, const AAMDNodes &AAInfo = AAMDNodes(), const MDNode *Ranges = nullptr); - inline SDValue - getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT, - const SDLoc &dl, SDValue Chain, SDValue Ptr, SDValue Offset, - MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment, - MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone, - const AAMDNodes &AAInfo = AAMDNodes(), - const MDNode *Ranges = nullptr) { + inline SDValue getLoad( + ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT, const SDLoc &dl, + SDValue Chain, SDValue Ptr, SDValue Offset, MachinePointerInfo PtrInfo, + EVT MemVT, MaybeAlign Alignment = MaybeAlign(), + MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone, + const AAMDNodes &AAInfo = AAMDNodes(), const MDNode *Ranges = nullptr) { // Ensures that codegen never sees a None Alignment. return getLoad(AM, ExtType, VT, dl, Chain, Ptr, Offset, PtrInfo, MemVT, Alignment.getValueOr(getEVTAlign(MemVT)), MMOFlags, AAInfo, @@ -1237,7 +1277,7 @@ public: inline SDValue getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, SDValue Offset, - MachinePointerInfo PtrInfo, EVT MemVT, unsigned Alignment = 0, + MachinePointerInfo PtrInfo, EVT MemVT, unsigned Alignment, MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone, const AAMDNodes &AAInfo = AAMDNodes(), const MDNode *Ranges = nullptr) { @@ -1260,7 +1300,7 @@ public: const AAMDNodes &AAInfo = AAMDNodes()); inline SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, - MachinePointerInfo PtrInfo, MaybeAlign Alignment, + MachinePointerInfo PtrInfo, MaybeAlign Alignment = MaybeAlign(), MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone, const AAMDNodes &AAInfo = AAMDNodes()) { return getStore(Chain, dl, Val, Ptr, PtrInfo, @@ -1270,7 +1310,7 @@ public: /// FIXME: Remove once transition to Align is over. inline SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, - MachinePointerInfo PtrInfo, unsigned Alignment = 0, + MachinePointerInfo PtrInfo, unsigned Alignment, MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone, const AAMDNodes &AAInfo = AAMDNodes()) { return getStore(Chain, dl, Val, Ptr, PtrInfo, MaybeAlign(Alignment), @@ -1285,7 +1325,8 @@ public: const AAMDNodes &AAInfo = AAMDNodes()); inline SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, - MachinePointerInfo PtrInfo, EVT SVT, MaybeAlign Alignment, + MachinePointerInfo PtrInfo, EVT SVT, + MaybeAlign Alignment = MaybeAlign(), MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone, const AAMDNodes &AAInfo = AAMDNodes()) { return getTruncStore(Chain, dl, Val, Ptr, PtrInfo, SVT, @@ -1295,7 +1336,7 @@ public: /// FIXME: Remove once transition to Align is over. inline SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, - MachinePointerInfo PtrInfo, EVT SVT, unsigned Alignment = 0, + MachinePointerInfo PtrInfo, EVT SVT, unsigned Alignment, MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone, const AAMDNodes &AAInfo = AAMDNodes()) { return getTruncStore(Chain, dl, Val, Ptr, PtrInfo, SVT, @@ -1321,10 +1362,11 @@ public: ISD::MemIndexedMode AM); SDValue getMaskedGather(SDVTList VTs, EVT VT, const SDLoc &dl, ArrayRef Ops, MachineMemOperand *MMO, - ISD::MemIndexType IndexType); + ISD::MemIndexType IndexType, ISD::LoadExtType ExtTy); SDValue getMaskedScatter(SDVTList VTs, EVT VT, const SDLoc &dl, ArrayRef Ops, MachineMemOperand *MMO, - ISD::MemIndexType IndexType); + ISD::MemIndexType IndexType, + bool IsTruncating = false); /// Construct a node to track a Value* through the backend. SDValue getSrcValue(const Value *v); @@ -1389,6 +1431,9 @@ public: void setNodeMemRefs(MachineSDNode *N, ArrayRef NewMemRefs); + // Calculate divergence of node \p N based on its operands. + bool calculateDivergence(SDNode *N); + // Propagates the change in divergence to users void updateDivergence(SDNode * N); @@ -1409,8 +1454,6 @@ public: EVT VT2, ArrayRef Ops); SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT1, EVT VT2, EVT VT3, ArrayRef Ops); - SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, - EVT VT2, SDValue Op1); SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT1, EVT VT2, SDValue Op1, SDValue Op2); SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, SDVTList VTs, @@ -1468,8 +1511,13 @@ public: SDValue Operand, SDValue Subreg); /// Get the specified node if it's already available, or else return NULL. - SDNode *getNodeIfExists(unsigned Opcode, SDVTList VTList, ArrayRef Ops, - const SDNodeFlags Flags = SDNodeFlags()); + SDNode *getNodeIfExists(unsigned Opcode, SDVTList VTList, + ArrayRef Ops, const SDNodeFlags Flags); + SDNode *getNodeIfExists(unsigned Opcode, SDVTList VTList, + ArrayRef Ops); + + /// Check if a node exists without modifying its flags. + bool doesNodeExist(unsigned Opcode, SDVTList VTList, ArrayRef Ops); /// Creates a SDDbgValue node. SDDbgValue *getDbgValue(DIVariable *Var, DIExpression *Expr, SDNode *N, @@ -1543,7 +1591,14 @@ public: /// chain to the token factor. This ensures that the new memory node will have /// the same relative memory dependency position as the old load. Returns the /// new merged load chain. - SDValue makeEquivalentMemoryOrdering(LoadSDNode *Old, SDValue New); + SDValue makeEquivalentMemoryOrdering(SDValue OldChain, SDValue NewMemOpChain); + + /// If an existing load has uses of its chain, create a token factor node with + /// that chain and the new memory node's chain and update users of the old + /// chain to the token factor. This ensures that the new memory node will have + /// the same relative memory dependency position as the old load. Returns the + /// new merged load chain. + SDValue makeEquivalentMemoryOrdering(LoadSDNode *OldLoad, SDValue NewMemOp); /// Topological-sort the AllNodes list and a /// assign a unique node id for each node in the DAG based on their @@ -1781,7 +1836,8 @@ public: /// for \p DemandedElts. /// /// NOTE: The function will return true for a demanded splat of UNDEF values. - bool isSplatValue(SDValue V, const APInt &DemandedElts, APInt &UndefElts); + bool isSplatValue(SDValue V, const APInt &DemandedElts, APInt &UndefElts, + unsigned Depth = 0); /// Test whether \p V has a splatted value. bool isSplatValue(SDValue V, bool AllowUndefs = false); @@ -1903,14 +1959,14 @@ public: } /// Test whether the given value is a constant int or similar node. - SDNode *isConstantIntBuildVectorOrConstantInt(SDValue N); + SDNode *isConstantIntBuildVectorOrConstantInt(SDValue N) const; /// Test whether the given value is a constant FP or similar node. - SDNode *isConstantFPBuildVectorOrConstantFP(SDValue N); + SDNode *isConstantFPBuildVectorOrConstantFP(SDValue N) const ; /// \returns true if \p N is any kind of constant or build_vector of /// constants, int or float. If a vector, it may not necessarily be a splat. - inline bool isConstantValueOfAnyType(SDValue N) { + inline bool isConstantValueOfAnyType(SDValue N) const { return isConstantIntBuildVectorOrConstantInt(N) || isConstantFPBuildVectorOrConstantFP(N); } @@ -1958,6 +2014,10 @@ public: bool shouldOptForSize() const; + /// Get the (commutative) neutral element for the given opcode, if it exists. + SDValue getNeutralElement(unsigned Opcode, const SDLoc &DL, EVT VT, + SDNodeFlags Flags); + private: void InsertNode(SDNode *N); bool RemoveNodeFromCSEMaps(SDNode *N); @@ -1998,6 +2058,8 @@ private: std::map, SDNode *> TargetExternalSymbols; DenseMap MCSymbols; + + FlagInserter *Inserter = nullptr; }; template <> struct GraphTraits : public GraphTraits { diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/SelectionDAGISel.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/SelectionDAGISel.h index 3bfbf3765e4f..84bb11edd715 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/SelectionDAGISel.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/SelectionDAGISel.h @@ -323,8 +323,6 @@ private: SDNode *MorphNode(SDNode *Node, unsigned TargetOpc, SDVTList VTList, ArrayRef Ops, unsigned EmitNodeInfo); - SDNode *MutateStrictFPToFP(SDNode *Node, unsigned NewOpc); - /// Prepares the landing pad to take incoming values or do other EH /// personality specific tasks. Returns true if the block should be /// instruction selected, false if no code should be emitted for it. diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/SelectionDAGNodes.h index 7c2b49087edd..000e383b71eb 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/SelectionDAGNodes.h @@ -85,29 +85,42 @@ namespace ISD { /// Node predicates - /// If N is a BUILD_VECTOR node whose elements are all the same constant or - /// undefined, return true and return the constant value in \p SplatValue. - bool isConstantSplatVector(const SDNode *N, APInt &SplatValue); - - /// Return true if the specified node is a BUILD_VECTOR where all of the - /// elements are ~0 or undef. - bool isBuildVectorAllOnes(const SDNode *N); - - /// Return true if the specified node is a BUILD_VECTOR where all of the - /// elements are 0 or undef. - bool isBuildVectorAllZeros(const SDNode *N); - - /// Return true if the specified node is a BUILD_VECTOR node of all - /// ConstantSDNode or undef. - bool isBuildVectorOfConstantSDNodes(const SDNode *N); - - /// Return true if the specified node is a BUILD_VECTOR node of all - /// ConstantFPSDNode or undef. - bool isBuildVectorOfConstantFPSDNodes(const SDNode *N); - - /// Return true if the node has at least one operand and all operands of the - /// specified node are ISD::UNDEF. - bool allOperandsUndef(const SDNode *N); +/// If N is a BUILD_VECTOR or SPLAT_VECTOR node whose elements are all the +/// same constant or undefined, return true and return the constant value in +/// \p SplatValue. +bool isConstantSplatVector(const SDNode *N, APInt &SplatValue); + +/// Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where +/// all of the elements are ~0 or undef. If \p BuildVectorOnly is set to +/// true, it only checks BUILD_VECTOR. +bool isConstantSplatVectorAllOnes(const SDNode *N, + bool BuildVectorOnly = false); + +/// Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where +/// all of the elements are 0 or undef. If \p BuildVectorOnly is set to true, it +/// only checks BUILD_VECTOR. +bool isConstantSplatVectorAllZeros(const SDNode *N, + bool BuildVectorOnly = false); + +/// Return true if the specified node is a BUILD_VECTOR where all of the +/// elements are ~0 or undef. +bool isBuildVectorAllOnes(const SDNode *N); + +/// Return true if the specified node is a BUILD_VECTOR where all of the +/// elements are 0 or undef. +bool isBuildVectorAllZeros(const SDNode *N); + +/// Return true if the specified node is a BUILD_VECTOR node of all +/// ConstantSDNode or undef. +bool isBuildVectorOfConstantSDNodes(const SDNode *N); + +/// Return true if the specified node is a BUILD_VECTOR node of all +/// ConstantFPSDNode or undef. +bool isBuildVectorOfConstantFPSDNodes(const SDNode *N); + +/// Return true if the node has at least one operand and all operands of the +/// specified node are ISD::UNDEF. +bool allOperandsUndef(const SDNode *N); } // end namespace ISD @@ -180,8 +193,8 @@ public: return getValueType().getSizeInBits(); } - TypeSize getScalarValueSizeInBits() const { - return getValueType().getScalarType().getSizeInBits(); + uint64_t getScalarValueSizeInBits() const { + return getValueType().getScalarType().getFixedSizeInBits(); } // Forwarding methods - These forward to the corresponding methods in SDNode. @@ -357,11 +370,6 @@ template<> struct simplify_type { /// the backend. struct SDNodeFlags { private: - // This bit is used to determine if the flags are in a defined state. - // Flag bits can only be masked out during intersection if the masking flags - // are defined. - bool AnyDefined : 1; - bool NoUnsignedWrap : 1; bool NoSignedWrap : 1; bool Exact : 1; @@ -383,9 +391,8 @@ private: public: /// Default constructor turns off all optimization flags. SDNodeFlags() - : AnyDefined(false), NoUnsignedWrap(false), NoSignedWrap(false), - Exact(false), NoNaNs(false), NoInfs(false), - NoSignedZeros(false), AllowReciprocal(false), + : NoUnsignedWrap(false), NoSignedWrap(false), Exact(false), NoNaNs(false), + NoInfs(false), NoSignedZeros(false), AllowReciprocal(false), AllowContract(false), ApproximateFuncs(false), AllowReassociation(false), NoFPExcept(false) {} @@ -400,56 +407,18 @@ public: setAllowReassociation(FPMO.hasAllowReassoc()); } - /// Sets the state of the flags to the defined state. - void setDefined() { AnyDefined = true; } - /// Returns true if the flags are in a defined state. - bool isDefined() const { return AnyDefined; } - // These are mutators for each flag. - void setNoUnsignedWrap(bool b) { - setDefined(); - NoUnsignedWrap = b; - } - void setNoSignedWrap(bool b) { - setDefined(); - NoSignedWrap = b; - } - void setExact(bool b) { - setDefined(); - Exact = b; - } - void setNoNaNs(bool b) { - setDefined(); - NoNaNs = b; - } - void setNoInfs(bool b) { - setDefined(); - NoInfs = b; - } - void setNoSignedZeros(bool b) { - setDefined(); - NoSignedZeros = b; - } - void setAllowReciprocal(bool b) { - setDefined(); - AllowReciprocal = b; - } - void setAllowContract(bool b) { - setDefined(); - AllowContract = b; - } - void setApproximateFuncs(bool b) { - setDefined(); - ApproximateFuncs = b; - } - void setAllowReassociation(bool b) { - setDefined(); - AllowReassociation = b; - } - void setNoFPExcept(bool b) { - setDefined(); - NoFPExcept = b; - } + void setNoUnsignedWrap(bool b) { NoUnsignedWrap = b; } + void setNoSignedWrap(bool b) { NoSignedWrap = b; } + void setExact(bool b) { Exact = b; } + void setNoNaNs(bool b) { NoNaNs = b; } + void setNoInfs(bool b) { NoInfs = b; } + void setNoSignedZeros(bool b) { NoSignedZeros = b; } + void setAllowReciprocal(bool b) { AllowReciprocal = b; } + void setAllowContract(bool b) { AllowContract = b; } + void setApproximateFuncs(bool b) { ApproximateFuncs = b; } + void setAllowReassociation(bool b) { AllowReassociation = b; } + void setNoFPExcept(bool b) { NoFPExcept = b; } // These are accessors for each flag. bool hasNoUnsignedWrap() const { return NoUnsignedWrap; } @@ -464,11 +433,9 @@ public: bool hasAllowReassociation() const { return AllowReassociation; } bool hasNoFPExcept() const { return NoFPExcept; } - /// Clear any flags in this flag set that aren't also set in Flags. - /// If the given Flags are undefined then don't do anything. + /// Clear any flags in this flag set that aren't also set in Flags. All + /// flags will be cleared if Flags are undefined. void intersectWith(const SDNodeFlags Flags) { - if (!Flags.isDefined()) - return; NoUnsignedWrap &= Flags.NoUnsignedWrap; NoSignedWrap &= Flags.NoSignedWrap; Exact &= Flags.Exact; @@ -559,6 +526,7 @@ BEGIN_TWO_BYTE_PACK() class LoadSDNodeBitfields { friend class LoadSDNode; friend class MaskedLoadSDNode; + friend class MaskedGatherSDNode; uint16_t : NumLSBaseSDNodeBits; @@ -569,6 +537,7 @@ BEGIN_TWO_BYTE_PACK() class StoreSDNodeBitfields { friend class StoreSDNode; friend class MaskedStoreSDNode; + friend class MaskedScatterSDNode; uint16_t : NumLSBaseSDNodeBits; @@ -720,9 +689,7 @@ public: bool use_empty() const { return UseList == nullptr; } /// Return true if there is exactly one use of this node. - bool hasOneUse() const { - return !use_empty() && std::next(use_begin()) == use_end(); - } + bool hasOneUse() const { return hasSingleElement(uses()); } /// Return the number of uses of this node. This method takes /// time proportional to the number of uses. @@ -1379,8 +1346,18 @@ public: } const SDValue &getChain() const { return getOperand(0); } + const SDValue &getBasePtr() const { - return getOperand(getOpcode() == ISD::STORE ? 2 : 1); + switch (getOpcode()) { + case ISD::STORE: + case ISD::MSTORE: + return getOperand(2); + case ISD::MGATHER: + case ISD::MSCATTER: + return getOperand(3); + default: + return getOperand(1); + } } // Methods to support isa and dyn_cast @@ -1784,6 +1761,32 @@ public: } }; +/// This SDNode is used for PSEUDO_PROBE values, which are the function guid and +/// the index of the basic block being probed. A pseudo probe serves as a place +/// holder and will be removed at the end of compilation. It does not have any +/// operand because we do not want the instruction selection to deal with any. +class PseudoProbeSDNode : public SDNode { + friend class SelectionDAG; + uint64_t Guid; + uint64_t Index; + uint32_t Attributes; + + PseudoProbeSDNode(unsigned Opcode, unsigned Order, const DebugLoc &Dl, + SDVTList VTs, uint64_t Guid, uint64_t Index, uint32_t Attr) + : SDNode(Opcode, Order, Dl, VTs), Guid(Guid), Index(Index), + Attributes(Attr) {} + +public: + uint64_t getGuid() const { return Guid; } + uint64_t getIndex() const { return Index; } + uint32_t getAttributes() const { return Attributes; } + + // Methods to support isa and dyn_cast + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::PSEUDO_PROBE; + } +}; + class JumpTableSDNode : public SDNode { friend class SelectionDAG; @@ -1944,6 +1947,33 @@ public: /// the vector width and set the bits where elements are undef. SDValue getSplatValue(BitVector *UndefElements = nullptr) const; + /// Find the shortest repeating sequence of values in the build vector. + /// + /// e.g. { u, X, u, X, u, u, X, u } -> { X } + /// { X, Y, u, Y, u, u, X, u } -> { X, Y } + /// + /// Currently this must be a power-of-2 build vector. + /// The DemandedElts mask indicates the elements that must be present, + /// undemanded elements in Sequence may be null (SDValue()). If passed a + /// non-null UndefElements bitvector, it will resize it to match the original + /// vector width and set the bits where elements are undef. If result is + /// false, Sequence will be empty. + bool getRepeatedSequence(const APInt &DemandedElts, + SmallVectorImpl &Sequence, + BitVector *UndefElements = nullptr) const; + + /// Find the shortest repeating sequence of values in the build vector. + /// + /// e.g. { u, X, u, X, u, u, X, u } -> { X } + /// { X, Y, u, Y, u, u, X, u } -> { X, Y } + /// + /// Currently this must be a power-of-2 build vector. + /// If passed a non-null UndefElements bitvector, it will resize it to match + /// the original vector width and set the bits where elements are undef. + /// If result is false, Sequence will be empty. + bool getRepeatedSequence(SmallVectorImpl &Sequence, + BitVector *UndefElements = nullptr) const; + /// Returns the demanded splatted constant or null if this is not a constant /// splat. /// @@ -2292,9 +2322,6 @@ public: // MaskedLoadSDNode (Chain, ptr, offset, mask, passthru) // MaskedStoreSDNode (Chain, data, ptr, offset, mask) // Mask is a vector of i1 elements - const SDValue &getBasePtr() const { - return getOperand(getOpcode() == ISD::MLOAD ? 1 : 2); - } const SDValue &getOffset() const { return getOperand(getOpcode() == ISD::MLOAD ? 2 : 3); } @@ -2402,6 +2429,9 @@ public: ISD::MemIndexType getIndexType() const { return static_cast(LSBaseSDNodeBits.AddressingMode); } + void setIndexType(ISD::MemIndexType IndexType) { + LSBaseSDNodeBits.AddressingMode = IndexType; + } bool isIndexScaled() const { return (getIndexType() == ISD::SIGNED_SCALED) || (getIndexType() == ISD::UNSIGNED_SCALED); @@ -2434,12 +2464,18 @@ public: MaskedGatherSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs, EVT MemVT, MachineMemOperand *MMO, - ISD::MemIndexType IndexType) + ISD::MemIndexType IndexType, ISD::LoadExtType ETy) : MaskedGatherScatterSDNode(ISD::MGATHER, Order, dl, VTs, MemVT, MMO, - IndexType) {} + IndexType) { + LoadSDNodeBits.ExtTy = ETy; + } const SDValue &getPassThru() const { return getOperand(1); } + ISD::LoadExtType getExtensionType() const { + return ISD::LoadExtType(LoadSDNodeBits.ExtTy); + } + static bool classof(const SDNode *N) { return N->getOpcode() == ISD::MGATHER; } @@ -2453,9 +2489,16 @@ public: MaskedScatterSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs, EVT MemVT, MachineMemOperand *MMO, - ISD::MemIndexType IndexType) + ISD::MemIndexType IndexType, bool IsTrunc) : MaskedGatherScatterSDNode(ISD::MSCATTER, Order, dl, VTs, MemVT, MMO, - IndexType) {} + IndexType) { + StoreSDNodeBits.IsTruncating = IsTrunc; + } + + /// Return true if the op does a truncation before store. + /// For integers this is the same as doing a TRUNCATE and storing the result. + /// For floats, it is the same as doing an FP_ROUND and storing the result. + bool isTruncatingStore() const { return StoreSDNodeBits.IsTruncating; } const SDValue &getValue() const { return getOperand(1); } @@ -2605,7 +2648,8 @@ template <> struct GraphTraits { /// with 4 and 8 byte pointer alignment, respectively. using LargestSDNode = AlignedCharArrayUnion; + GlobalAddressSDNode, + PseudoProbeSDNode>; /// The SDNode class with the greatest alignment requirement. using MostAlignedSDNode = GlobalAddressSDNode; diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/SelectionDAGTargetInfo.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/SelectionDAGTargetInfo.h index 014523f1af6a..78f6fc6656fa 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/SelectionDAGTargetInfo.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/SelectionDAGTargetInfo.h @@ -85,7 +85,7 @@ public: return SDValue(); } - /// Emit target-specific code that performs a memcmp, in cases where that is + /// Emit target-specific code that performs a memcmp/bcmp, in cases where that is /// faster than a libcall. The first returned SDValue is the result of the /// memcmp and the second is the chain. Both SDValues can be null if a normal /// libcall should be used. diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/SlotIndexes.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/SlotIndexes.h index 19eab7ae5e35..b2133de93ea2 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/SlotIndexes.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/SlotIndexes.h @@ -604,38 +604,27 @@ class raw_ostream; } /// Add the given MachineBasicBlock into the maps. - /// If \p InsertionPoint is specified then the block will be placed - /// before the given machine instr, otherwise it will be placed - /// before the next block in MachineFunction insertion order. - void insertMBBInMaps(MachineBasicBlock *mbb, - MachineInstr *InsertionPoint = nullptr) { - MachineFunction::iterator nextMBB = - std::next(MachineFunction::iterator(mbb)); - - IndexListEntry *startEntry = nullptr; - IndexListEntry *endEntry = nullptr; - IndexList::iterator newItr; - if (InsertionPoint) { - startEntry = createEntry(nullptr, 0); - endEntry = getInstructionIndex(*InsertionPoint).listEntry(); - newItr = indexList.insert(endEntry->getIterator(), startEntry); - } else if (nextMBB == mbb->getParent()->end()) { - startEntry = &indexList.back(); - endEntry = createEntry(nullptr, 0); - newItr = indexList.insertAfter(startEntry->getIterator(), endEntry); - } else { - startEntry = createEntry(nullptr, 0); - endEntry = getMBBStartIdx(&*nextMBB).listEntry(); - newItr = indexList.insert(endEntry->getIterator(), startEntry); - } + /// If it contains any instructions then they must already be in the maps. + /// This is used after a block has been split by moving some suffix of its + /// instructions into a newly created block. + void insertMBBInMaps(MachineBasicBlock *mbb) { + assert(mbb != &mbb->getParent()->front() && + "Can't insert a new block at the beginning of a function."); + auto prevMBB = std::prev(MachineFunction::iterator(mbb)); + + // Create a new entry to be used for the start of mbb and the end of + // prevMBB. + IndexListEntry *startEntry = createEntry(nullptr, 0); + IndexListEntry *endEntry = getMBBEndIdx(&*prevMBB).listEntry(); + IndexListEntry *insEntry = + mbb->empty() ? endEntry + : getInstructionIndex(mbb->front()).listEntry(); + IndexList::iterator newItr = + indexList.insert(insEntry->getIterator(), startEntry); SlotIndex startIdx(startEntry, SlotIndex::Slot_Block); SlotIndex endIdx(endEntry, SlotIndex::Slot_Block); - MachineFunction::iterator prevMBB(mbb); - assert(prevMBB != mbb->getParent()->end() && - "Can't insert a new block at the beginning of a function."); - --prevMBB; MBBRanges[prevMBB->getNumber()].second = startIdx; assert(unsigned(mbb->getNumber()) == MBBRanges.size() && diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/StableHashing.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/StableHashing.h new file mode 100644 index 000000000000..caf27e152e78 --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/StableHashing.h @@ -0,0 +1,112 @@ +//===- llvm/CodeGen/StableHashing.h - Utilities for stable hashing * C++ *-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file provides types and functions for computing and combining stable +// hashes. Stable hashes can be useful for hashing across different modules, +// processes, or compiler runs. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_STABLEHASHING_H +#define LLVM_CODEGEN_STABLEHASHING_H + +#include "llvm/ADT/StringRef.h" + +namespace llvm { + +/// An opaque object representing a stable hash code. It can be serialized, +/// deserialized, and is stable across processes and executions. +using stable_hash = uint64_t; + +// Implementation details +namespace hashing { +namespace detail { + +// Stable hashes are based on the 64-bit FNV-1 hash: +// https://en.wikipedia.org/wiki/Fowler-Noll-Vo_hash_function + +const uint64_t FNV_PRIME_64 = 1099511628211u; +const uint64_t FNV_OFFSET_64 = 14695981039346656037u; + +inline void stable_hash_append(stable_hash &Hash, const char Value) { + Hash = Hash ^ (Value & 0xFF); + Hash = Hash * FNV_PRIME_64; +} + +inline void stable_hash_append(stable_hash &Hash, stable_hash Value) { + for (unsigned I = 0; I < 8; ++I) { + stable_hash_append(Hash, static_cast(Value)); + Value >>= 8; + } +} + +} // namespace detail +} // namespace hashing + +inline stable_hash stable_hash_combine(stable_hash A, stable_hash B) { + stable_hash Hash = hashing::detail::FNV_OFFSET_64; + hashing::detail::stable_hash_append(Hash, A); + hashing::detail::stable_hash_append(Hash, B); + return Hash; +} + +inline stable_hash stable_hash_combine(stable_hash A, stable_hash B, + stable_hash C) { + stable_hash Hash = hashing::detail::FNV_OFFSET_64; + hashing::detail::stable_hash_append(Hash, A); + hashing::detail::stable_hash_append(Hash, B); + hashing::detail::stable_hash_append(Hash, C); + return Hash; +} + +inline stable_hash stable_hash_combine(stable_hash A, stable_hash B, + stable_hash C, stable_hash D) { + stable_hash Hash = hashing::detail::FNV_OFFSET_64; + hashing::detail::stable_hash_append(Hash, A); + hashing::detail::stable_hash_append(Hash, B); + hashing::detail::stable_hash_append(Hash, C); + hashing::detail::stable_hash_append(Hash, D); + return Hash; +} + +/// Compute a stable_hash for a sequence of values. +/// +/// This hashes a sequence of values. It produces the same stable_hash as +/// 'stable_hash_combine(a, b, c, ...)', but can run over arbitrary sized +/// sequences and is significantly faster given pointers and types which +/// can be hashed as a sequence of bytes. +template +stable_hash stable_hash_combine_range(InputIteratorT First, + InputIteratorT Last) { + stable_hash Hash = hashing::detail::FNV_OFFSET_64; + for (auto I = First; I != Last; ++I) + hashing::detail::stable_hash_append(Hash, *I); + return Hash; +} + +inline stable_hash stable_hash_combine_array(const stable_hash *P, size_t C) { + stable_hash Hash = hashing::detail::FNV_OFFSET_64; + for (size_t I = 0; I < C; ++I) + hashing::detail::stable_hash_append(Hash, P[I]); + return Hash; +} + +inline stable_hash stable_hash_combine_string(const StringRef &S) { + return stable_hash_combine_range(S.begin(), S.end()); +} + +inline stable_hash stable_hash_combine_string(const char *C) { + stable_hash Hash = hashing::detail::FNV_OFFSET_64; + while (*C) + hashing::detail::stable_hash_append(Hash, *(C++)); + return Hash; +} + +} // namespace llvm + +#endif diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/StackMaps.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/StackMaps.h index e33ee226e41a..928d7cc6cc04 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/StackMaps.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/StackMaps.h @@ -148,9 +148,13 @@ public: /// , , /// , , /// , , [deopt args...], -/// -/// Note that the last two sets of arguments are not currently length -/// prefixed. +/// , , [gc pointer args...], +/// , , [gc allocas args...], +/// , , [base/derived pairs] +/// base/derived pairs in gc map are logical indices into +/// section. +/// All gc pointers assigned to VRegs produce new value (in form of MI Def +/// operand) and are tied to it. class StatepointOpers { // TODO:: we should change the STATEPOINT representation so that CC and // Flags should be part of meta operands, with args and deopt operands, and @@ -166,21 +170,23 @@ class StatepointOpers { enum { CCOffset = 1, FlagsOffset = 3, NumDeoptOperandsOffset = 5 }; public: - explicit StatepointOpers(const MachineInstr *MI) : MI(MI) {} + explicit StatepointOpers(const MachineInstr *MI) : MI(MI) { + NumDefs = MI->getNumDefs(); + } /// Get index of statepoint ID operand. - unsigned getIDPos() const { return IDPos; } + unsigned getIDPos() const { return NumDefs + IDPos; } /// Get index of Num Patch Bytes operand. - unsigned getNBytesPos() const { return NBytesPos; } + unsigned getNBytesPos() const { return NumDefs + NBytesPos; } /// Get index of Num Call Arguments operand. - unsigned getNCallArgsPos() const { return NCallArgsPos; } + unsigned getNCallArgsPos() const { return NumDefs + NCallArgsPos; } /// Get starting index of non call related arguments /// (calling convention, statepoint flags, vm state and gc state). unsigned getVarIdx() const { - return MI->getOperand(NCallArgsPos).getImm() + MetaEnd; + return MI->getOperand(NumDefs + NCallArgsPos).getImm() + MetaEnd + NumDefs; } /// Get index of Calling Convention operand. @@ -195,16 +201,16 @@ public: } /// Return the ID for the given statepoint. - uint64_t getID() const { return MI->getOperand(IDPos).getImm(); } + uint64_t getID() const { return MI->getOperand(NumDefs + IDPos).getImm(); } /// Return the number of patchable bytes the given statepoint should emit. uint32_t getNumPatchBytes() const { - return MI->getOperand(NBytesPos).getImm(); + return MI->getOperand(NumDefs + NBytesPos).getImm(); } /// Return the target of the underlying call. const MachineOperand &getCallTarget() const { - return MI->getOperand(CallTargetPos); + return MI->getOperand(NumDefs + CallTargetPos); } /// Return the calling convention. @@ -215,8 +221,31 @@ public: /// Return the statepoint flags. uint64_t getFlags() const { return MI->getOperand(getFlagsIdx()).getImm(); } + uint64_t getNumDeoptArgs() const { + return MI->getOperand(getNumDeoptArgsIdx()).getImm(); + } + + /// Get index of number of gc map entries. + unsigned getNumGcMapEntriesIdx(); + + /// Get index of number of gc allocas. + unsigned getNumAllocaIdx(); + + /// Get index of number of GC pointers. + unsigned getNumGCPtrIdx(); + + /// Get index of first GC pointer operand of -1 if there are none. + int getFirstGCPtrIdx(); + + /// Get vector of base/derived pairs from statepoint. + /// Elements are indices into GC Pointer operand list (logical). + /// Returns number of elements in GCMap. + unsigned + getGCPointerMap(SmallVectorImpl> &GCMap); + private: const MachineInstr *MI; + unsigned NumDefs; }; class StackMaps { @@ -258,6 +287,10 @@ public: StackMaps(AsmPrinter &AP); + /// Get index of next meta operand. + /// Similar to parseOperand, but does not actually parses operand meaning. + static unsigned getNextMetaArgIdx(const MachineInstr *MI, unsigned CurIdx); + void reset() { CSInfos.clear(); ConstPool.clear(); @@ -330,6 +363,13 @@ private: MachineInstr::const_mop_iterator MOE, LocationVec &Locs, LiveOutVec &LiveOuts) const; + /// Specialized parser of statepoint operands. + /// They do not directly correspond to StackMap record entries. + void parseStatepointOpers(const MachineInstr &MI, + MachineInstr::const_mop_iterator MOI, + MachineInstr::const_mop_iterator MOE, + LocationVec &Locations, LiveOutVec &LiveOuts); + /// Create a live-out register record for the given register @p Reg. LiveOutReg createLiveOutReg(unsigned Reg, const TargetRegisterInfo *TRI) const; diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/SwitchLoweringUtils.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/SwitchLoweringUtils.h index 4d6afa617d3a..51f1d7d6fd21 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/SwitchLoweringUtils.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/SwitchLoweringUtils.h @@ -10,16 +10,21 @@ #define LLVM_CODEGEN_SWITCHLOWERINGUTILS_H #include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/ISDOpcodes.h" #include "llvm/CodeGen/SelectionDAGNodes.h" -#include "llvm/CodeGen/TargetLowering.h" -#include "llvm/IR/Constants.h" +#include "llvm/IR/InstrTypes.h" #include "llvm/Support/BranchProbability.h" +#include namespace llvm { +class BlockFrequencyInfo; +class ConstantInt; class FunctionLoweringInfo; class MachineBasicBlock; -class BlockFrequencyInfo; +class ProfileSummaryInfo; +class TargetLowering; +class TargetMachine; namespace SwitchCG { diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetCallingConv.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetCallingConv.h index 347d7ff40404..df974b499851 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetCallingConv.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetCallingConv.h @@ -31,6 +31,7 @@ namespace ISD { unsigned IsInReg : 1; ///< Passed in register unsigned IsSRet : 1; ///< Hidden struct-ret ptr unsigned IsByVal : 1; ///< Struct passed by value + unsigned IsByRef : 1; ///< Passed in memory unsigned IsNest : 1; ///< Nested fn static chain unsigned IsReturned : 1; ///< Always returned unsigned IsSplit : 1; @@ -43,25 +44,31 @@ namespace ISD { unsigned IsHva : 1; ///< HVA field for unsigned IsHvaStart : 1; ///< HVA structure start unsigned IsSecArgPass : 1; ///< Second argument - unsigned ByValAlign : 4; ///< Log 2 of byval alignment + unsigned ByValOrByRefAlign : 4; ///< Log 2 of byval/byref alignment unsigned OrigAlign : 5; ///< Log 2 of original alignment unsigned IsInConsecutiveRegsLast : 1; unsigned IsInConsecutiveRegs : 1; unsigned IsCopyElisionCandidate : 1; ///< Argument copy elision candidate unsigned IsPointer : 1; - unsigned ByValSize; ///< Byval struct size + unsigned ByValOrByRefSize; ///< Byval or byref struct size unsigned PointerAddrSpace; ///< Address space of pointer argument + /// Set the alignment used by byref or byval parameters. + void setAlignImpl(Align A) { + ByValOrByRefAlign = encode(A); + assert(getNonZeroByValAlign() == A && "bitfield overflow"); + } + public: ArgFlagsTy() - : IsZExt(0), IsSExt(0), IsInReg(0), IsSRet(0), IsByVal(0), IsNest(0), - IsReturned(0), IsSplit(0), IsInAlloca(0), IsPreallocated(0), + : IsZExt(0), IsSExt(0), IsInReg(0), IsSRet(0), IsByVal(0), IsByRef(0), + IsNest(0), IsReturned(0), IsSplit(0), IsInAlloca(0), IsPreallocated(0), IsSplitEnd(0), IsSwiftSelf(0), IsSwiftError(0), IsCFGuardTarget(0), - IsHva(0), IsHvaStart(0), IsSecArgPass(0), ByValAlign(0), OrigAlign(0), - IsInConsecutiveRegsLast(0), IsInConsecutiveRegs(0), - IsCopyElisionCandidate(0), IsPointer(0), ByValSize(0), + IsHva(0), IsHvaStart(0), IsSecArgPass(0), ByValOrByRefAlign(0), + OrigAlign(0), IsInConsecutiveRegsLast(0), IsInConsecutiveRegs(0), + IsCopyElisionCandidate(0), IsPointer(0), ByValOrByRefSize(0), PointerAddrSpace(0) { static_assert(sizeof(*this) == 3 * sizeof(unsigned), "flags are too big"); } @@ -81,6 +88,9 @@ namespace ISD { bool isByVal() const { return IsByVal; } void setByVal() { IsByVal = 1; } + bool isByRef() const { return IsByRef; } + void setByRef() { IsByRef = 1; } + bool isInAlloca() const { return IsInAlloca; } void setInAlloca() { IsInAlloca = 1; } @@ -112,10 +122,12 @@ namespace ISD { void setReturned() { IsReturned = 1; } bool isInConsecutiveRegs() const { return IsInConsecutiveRegs; } - void setInConsecutiveRegs() { IsInConsecutiveRegs = 1; } + void setInConsecutiveRegs(bool Flag = true) { IsInConsecutiveRegs = Flag; } bool isInConsecutiveRegsLast() const { return IsInConsecutiveRegsLast; } - void setInConsecutiveRegsLast() { IsInConsecutiveRegsLast = 1; } + void setInConsecutiveRegsLast(bool Flag = true) { + IsInConsecutiveRegsLast = Flag; + } bool isSplit() const { return IsSplit; } void setSplit() { IsSplit = 1; } @@ -131,17 +143,22 @@ namespace ISD { LLVM_ATTRIBUTE_DEPRECATED(unsigned getByValAlign() const, "Use getNonZeroByValAlign() instead") { - MaybeAlign A = decodeMaybeAlign(ByValAlign); + MaybeAlign A = decodeMaybeAlign(ByValOrByRefAlign); return A ? A->value() : 0; } Align getNonZeroByValAlign() const { - MaybeAlign A = decodeMaybeAlign(ByValAlign); + MaybeAlign A = decodeMaybeAlign(ByValOrByRefAlign); assert(A && "ByValAlign must be defined"); return *A; } void setByValAlign(Align A) { - ByValAlign = encode(A); - assert(getNonZeroByValAlign() == A && "bitfield overflow"); + assert(isByVal() && !isByRef()); + setAlignImpl(A); + } + + void setByRefAlign(Align A) { + assert(!isByVal() && isByRef()); + setAlignImpl(A); } LLVM_ATTRIBUTE_DEPRECATED(unsigned getOrigAlign() const, @@ -157,8 +174,23 @@ namespace ISD { assert(getNonZeroOrigAlign() == A && "bitfield overflow"); } - unsigned getByValSize() const { return ByValSize; } - void setByValSize(unsigned S) { ByValSize = S; } + unsigned getByValSize() const { + assert(isByVal() && !isByRef()); + return ByValOrByRefSize; + } + void setByValSize(unsigned S) { + assert(isByVal() && !isByRef()); + ByValOrByRefSize = S; + } + + unsigned getByRefSize() const { + assert(!isByVal() && isByRef()); + return ByValOrByRefSize; + } + void setByRefSize(unsigned S) { + assert(!isByVal() && isByRef()); + ByValOrByRefSize = S; + } unsigned getPointerAddrSpace() const { return PointerAddrSpace; } void setPointerAddrSpace(unsigned AS) { PointerAddrSpace = AS; } diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetFrameLowering.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetFrameLowering.h index d6580430daf7..792452f6e81d 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetFrameLowering.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetFrameLowering.h @@ -14,6 +14,7 @@ #define LLVM_CODEGEN_TARGETFRAMELOWERING_H #include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/Support/TypeSize.h" #include namespace llvm { @@ -26,7 +27,7 @@ namespace TargetStackID { enum Value { Default = 0, SGPRSpill = 1, - SVEVector = 2, + ScalableVector = 2, NoAlloc = 255 }; } @@ -297,8 +298,8 @@ public: /// getFrameIndexReference - This method should return the base register /// and offset used to reference a frame index location. The offset is /// returned directly, and the base register is returned via FrameReg. - virtual int getFrameIndexReference(const MachineFunction &MF, int FI, - Register &FrameReg) const; + virtual StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, + Register &FrameReg) const; /// Same as \c getFrameIndexReference, except that the stack pointer (as /// opposed to the frame pointer) will be the preferred value for \p @@ -306,9 +307,10 @@ public: /// use offsets from RSP. If \p IgnoreSPUpdates is true, the returned /// offset is only guaranteed to be valid with respect to the value of SP at /// the end of the prologue. - virtual int getFrameIndexReferencePreferSP(const MachineFunction &MF, int FI, - Register &FrameReg, - bool IgnoreSPUpdates) const { + virtual StackOffset + getFrameIndexReferencePreferSP(const MachineFunction &MF, int FI, + Register &FrameReg, + bool IgnoreSPUpdates) const { // Always safe to dispatch to getFrameIndexReference. return getFrameIndexReference(MF, FI, FrameReg); } @@ -316,8 +318,8 @@ public: /// getNonLocalFrameIndexReference - This method returns the offset used to /// reference a frame index location. The offset can be from either FP/BP/SP /// based on which base register is returned by llvm.localaddress. - virtual int getNonLocalFrameIndexReference(const MachineFunction &MF, - int FI) const { + virtual StackOffset getNonLocalFrameIndexReference(const MachineFunction &MF, + int FI) const { // By default, dispatch to getFrameIndexReference. Interested targets can // override this. Register FrameReg; diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetInstrInfo.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetInstrInfo.h index b3b2fa218627..36afdefd27b2 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetInstrInfo.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetInstrInfo.h @@ -25,6 +25,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineOutliner.h" +#include "llvm/CodeGen/RegisterClassInfo.h" #include "llvm/CodeGen/VirtRegMap.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/Support/BranchProbability.h" @@ -80,6 +81,15 @@ struct RegImmPair { RegImmPair(Register Reg, int64_t Imm) : Reg(Reg), Imm(Imm) {} }; +/// Used to describe addressing mode similar to ExtAddrMode in CodeGenPrepare. +/// It holds the register values, the scale value and the displacement. +struct ExtAddrMode { + Register BaseReg; + Register ScaledReg; + int64_t Scale; + int64_t Displacement; +}; + //--------------------------------------------------------------------------- /// /// TargetInstrInfo - Interface to description of machine instruction set @@ -339,6 +349,12 @@ public: unsigned &Size, unsigned &Offset, const MachineFunction &MF) const; + /// Return true if the given instruction is terminator that is unspillable, + /// according to isUnspillableTerminatorImpl. + bool isUnspillableTerminator(const MachineInstr *MI) const { + return MI->isTerminator() && isUnspillableTerminatorImpl(MI); + } + /// Returns the size in bytes of the specified MachineInstr, or ~0U /// when this function is not implemented by a target. virtual unsigned getInstSizeInBytes(const MachineInstr &MI) const { @@ -724,7 +740,7 @@ public: return nullptr; } - /// Analyze the loop code, return true if it cannot be understoo. Upon + /// Analyze the loop code, return true if it cannot be understood. Upon /// success, this function returns false and returns information about the /// induction variable and compare instruction used at the end. virtual bool analyzeLoop(MachineLoop &L, MachineInstr *&IndVarInst, @@ -771,7 +787,7 @@ public: /// Second variant of isProfitableToIfCvt. This one /// checks for the case where two basic blocks from true and false path - /// of a if-then-else (diamond) are predicated on mutally exclusive + /// of a if-then-else (diamond) are predicated on mutually exclusive /// predicates, where the probability of the true path being taken is given /// by Probability, and Confidence is a measure of our confidence that it /// will be properly predicted. @@ -945,6 +961,17 @@ protected: return None; } + /// Return true if the given terminator MI is not expected to spill. This + /// sets the live interval as not spillable and adjusts phi node lowering to + /// not introduce copies after the terminator. Use with care, these are + /// currently used for hardware loop intrinsics in very controlled situations, + /// created prior to registry allocation in loops that only have single phi + /// users for the terminators value. They may run out of registers if not used + /// carefully. + virtual bool isUnspillableTerminatorImpl(const MachineInstr *MI) const { + return false; + } + public: /// If the specific machine instruction is a instruction that moves/copies /// value from one register to another register return destination and source @@ -968,6 +995,15 @@ public: return None; } + /// Returns true if MI is an instruction that defines Reg to have a constant + /// value and the value is recorded in ImmVal. The ImmVal is a result that + /// should be interpreted as modulo size of Reg. + virtual bool getConstValDefinedInReg(const MachineInstr &MI, + const Register Reg, + int64_t &ImmVal) const { + return false; + } + /// Store the specified register of the given register class to the specified /// stack frame index. The store instruction is to be added to the given /// machine basic block before the specified machine instruction. If isKill @@ -1041,9 +1077,23 @@ public: /// faster sequence. /// \param Root - Instruction that could be combined with one of its operands /// \param Patterns - Vector of possible combination patterns - virtual bool getMachineCombinerPatterns( - MachineInstr &Root, - SmallVectorImpl &Patterns) const; + virtual bool + getMachineCombinerPatterns(MachineInstr &Root, + SmallVectorImpl &Patterns, + bool DoRegPressureReduce) const; + + /// Return true if target supports reassociation of instructions in machine + /// combiner pass to reduce register pressure for a given BB. + virtual bool + shouldReduceRegisterPressure(MachineBasicBlock *MBB, + RegisterClassInfo *RegClassInfo) const { + return false; + } + + /// Fix up the placeholder we may add in genAlternativeCodeSequence(). + virtual void + finalizeInsInstrs(MachineInstr &Root, MachineCombinerPattern &P, + SmallVectorImpl &InsInstrs) const {} /// Return true when a code sequence can improve throughput. It /// should be called only for instructions in loops. @@ -1248,10 +1298,11 @@ public: bool &OffsetIsScalable, const TargetRegisterInfo *TRI) const; - /// Get the base operands and byte offset of an instruction that reads/writes - /// memory. + /// Get zero or more base operands and the byte offset of an instruction that + /// reads/writes memory. Note that there may be zero base operands if the + /// instruction accesses a constant address. /// It returns false if MI does not read/write memory. - /// It returns false if no base operands and offset was found. + /// It returns false if base operands and offset could not be determined. /// It is not guaranteed to always recognize base operands and offsets in all /// cases. virtual bool getMemOperandsWithOffsetWidth( @@ -1270,6 +1321,27 @@ public: return false; } + /// Target dependent implementation to get the values constituting the address + /// MachineInstr that is accessing memory. These values are returned as a + /// struct ExtAddrMode which contains all relevant information to make up the + /// address. + virtual Optional + getAddrModeFromMemoryOp(const MachineInstr &MemI, + const TargetRegisterInfo *TRI) const { + return None; + } + + /// Returns true if MI's Def is NullValueReg, and the MI + /// does not change the Zero value. i.e. cases such as rax = shr rax, X where + /// NullValueReg = rax. Note that if the NullValueReg is non-zero, this + /// function can return true even if becomes zero. Specifically cases such as + /// NullValueReg = shl NullValueReg, 63. + virtual bool preservesZeroValueInReg(const MachineInstr *MI, + const Register NullValueReg, + const TargetRegisterInfo *TRI) const { + return false; + } + /// If the instruction is an increment of a constant value, return the amount. virtual bool getIncrementValue(const MachineInstr &MI, int &Value) const { return false; @@ -1304,6 +1376,11 @@ public: virtual void insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const; + /// Insert noops into the instruction stream at the specified point. + virtual void insertNoops(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned Quantity) const; + /// Return the noop instruction to use for a noop. virtual void getNoop(MCInst &NopInst) const; @@ -1355,8 +1432,13 @@ public: /// If the specified instruction defines any predicate /// or condition code register(s) used for predication, returns true as well /// as the definition predicate(s) by reference. - virtual bool DefinesPredicate(MachineInstr &MI, - std::vector &Pred) const { + /// SkipDead should be set to false at any point that dead + /// predicate instructions should be considered as being defined. + /// A dead predicate instruction is one that is guaranteed to be removed + /// after a call to PredicateInstruction. + virtual bool ClobbersPredicate(MachineInstr &MI, + std::vector &Pred, + bool SkipDead) const { return false; } @@ -1442,7 +1524,7 @@ public: /// the machine instruction generated due to folding. virtual MachineInstr *optimizeLoadInstr(MachineInstr &MI, const MachineRegisterInfo *MRI, - unsigned &FoldAsLoadDefReg, + Register &FoldAsLoadDefReg, MachineInstr *&DefMI) const { return nullptr; } @@ -1627,7 +1709,7 @@ public: /// This hook works similarly to getPartialRegUpdateClearance, except that it /// does not take an operand index. Instead sets \p OpNum to the index of the /// unused register. - virtual unsigned getUndefRegClearance(const MachineInstr &MI, unsigned &OpNum, + virtual unsigned getUndefRegClearance(const MachineInstr &MI, unsigned OpNum, const TargetRegisterInfo *TRI) const { // The default implementation returns 0 for no undef register dependency. return 0; @@ -1688,6 +1770,21 @@ public: return 5; } + /// Return the maximal number of alias checks on memory operands. For + /// instructions with more than one memory operands, the alias check on a + /// single MachineInstr pair has quadratic overhead and results in + /// unacceptable performance in the worst case. The limit here is to clamp + /// that maximal checks performed. Usually, that's the product of memory + /// operand numbers from that pair of MachineInstr to be checked. For + /// instance, with two MachineInstrs with 4 and 5 memory operands + /// correspondingly, a total of 20 checks are required. With this limit set to + /// 16, their alias check is skipped. We choose to limit the product instead + /// of the individual instruction as targets may have special MachineInstrs + /// with a considerably high number of memory operands, such as `ldm` in ARM. + /// Setting this limit per MachineInstr would result in either too high + /// overhead or too rigid restriction. + virtual unsigned getMemOperandAACheckLimit() const { return 16; } + /// Return an array that contains the ids of the target indices (used for the /// TargetIndex machine operand) and their names. /// diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetLowering.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetLowering.h index 06f2b3ca38ea..40115fbd2f15 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetLowering.h @@ -278,6 +278,7 @@ public: bool IsSRet : 1; bool IsNest : 1; bool IsByVal : 1; + bool IsByRef : 1; bool IsInAlloca : 1; bool IsPreallocated : 1; bool IsReturned : 1; @@ -290,7 +291,7 @@ public: ArgListEntry() : IsSExt(false), IsZExt(false), IsInReg(false), IsSRet(false), - IsNest(false), IsByVal(false), IsInAlloca(false), + IsNest(false), IsByVal(false), IsByRef(false), IsInAlloca(false), IsPreallocated(false), IsReturned(false), IsSwiftSelf(false), IsSwiftError(false), IsCFGuardTarget(false) {} @@ -374,6 +375,13 @@ public: EVT getShiftAmountTy(EVT LHSTy, const DataLayout &DL, bool LegalTypes = true) const; + /// Return the preferred type to use for a shift opcode, given the shifted + /// amount type is \p ShiftValueTy. + LLVM_READONLY + virtual LLT getPreferredShiftAmountTy(LLT ShiftValueTy) const { + return ShiftValueTy; + } + /// Returns the type to be used for the index operand of: /// ISD::INSERT_VECTOR_ELT, ISD::EXTRACT_VECTOR_ELT, /// ISD::INSERT_SUBVECTOR, and ISD::EXTRACT_SUBVECTOR @@ -419,7 +427,7 @@ public: virtual TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(MVT VT) const { // The default action for one element vectors is to scalarize - if (VT.getVectorElementCount() == 1) + if (VT.getVectorElementCount().isScalar()) return TypeScalarizeVector; // The default action for an odd-width vector is to widen. if (!VT.isPow2VectorType()) @@ -597,6 +605,12 @@ public: return false; } + /// Return the maximum number of "x & (x - 1)" operations that can be done + /// instead of deferring to a custom CTPOP. + virtual unsigned getCustomCtpopCost(EVT VT, ISD::CondCode Cond) const { + return 1; + } + /// Return true if instruction generated for equality comparison is folded /// with instruction generated for signed comparison. virtual bool isEqualityCmpFoldedWithSignedCmp() const { return true; } @@ -1085,8 +1099,13 @@ public: /// Return true if the specified operation is legal on this target or can be /// made legal with custom lowering. This is used to help guide high-level - /// lowering decisions. - bool isOperationLegalOrCustom(unsigned Op, EVT VT) const { + /// lowering decisions. LegalOnly is an optional convenience for code paths + /// traversed pre and post legalisation. + bool isOperationLegalOrCustom(unsigned Op, EVT VT, + bool LegalOnly = false) const { + if (LegalOnly) + return isOperationLegal(Op, VT); + return (VT == MVT::Other || isTypeLegal(VT)) && (getOperationAction(Op, VT) == Legal || getOperationAction(Op, VT) == Custom); @@ -1094,8 +1113,13 @@ public: /// Return true if the specified operation is legal on this target or can be /// made legal using promotion. This is used to help guide high-level lowering - /// decisions. - bool isOperationLegalOrPromote(unsigned Op, EVT VT) const { + /// decisions. LegalOnly is an optional convenience for code paths traversed + /// pre and post legalisation. + bool isOperationLegalOrPromote(unsigned Op, EVT VT, + bool LegalOnly = false) const { + if (LegalOnly) + return isOperationLegal(Op, VT); + return (VT == MVT::Other || isTypeLegal(VT)) && (getOperationAction(Op, VT) == Legal || getOperationAction(Op, VT) == Promote); @@ -1103,8 +1127,13 @@ public: /// Return true if the specified operation is legal on this target or can be /// made legal with custom lowering or using promotion. This is used to help - /// guide high-level lowering decisions. - bool isOperationLegalOrCustomOrPromote(unsigned Op, EVT VT) const { + /// guide high-level lowering decisions. LegalOnly is an optional convenience + /// for code paths traversed pre and post legalisation. + bool isOperationLegalOrCustomOrPromote(unsigned Op, EVT VT, + bool LegalOnly = false) const { + if (LegalOnly) + return isOperationLegal(Op, VT); + return (VT == MVT::Other || isTypeLegal(VT)) && (getOperationAction(Op, VT) == Legal || getOperationAction(Op, VT) == Custom || @@ -1289,6 +1318,10 @@ public: getIndexedMaskedStoreAction(IdxMode, VT.getSimpleVT()) == Custom); } + // Returns true if VT is a legal index type for masked gathers/scatters + // on this target + virtual bool shouldRemoveExtendFromGSIndex(EVT VT) const { return false; } + /// Return how the condition code should be treated: either it is legal, needs /// to be expanded to some other code sequence, or the target has a custom /// expander for it. @@ -1625,6 +1658,11 @@ public: const MachineMemOperand &MMO, bool *Fast = nullptr) const; + /// LLT handling variant. + bool allowsMemoryAccess(LLVMContext &Context, const DataLayout &DL, LLT Ty, + const MachineMemOperand &MMO, + bool *Fast = nullptr) const; + /// Returns the target specific optimal type for load and store operations as /// a result of memset, memcpy, and memmove lowering. /// It returns EVT::Other if the type should be determined using generic @@ -1663,13 +1701,9 @@ public: virtual bool isJumpTableRelative() const; - /// Return true if a mulh[s|u] node for a specific type is cheaper than - /// a multiply followed by a shift. This is false by default. - virtual bool isMulhCheaperThanMulShift(EVT Type) const { return false; } - /// If a physical register, this specifies the register that /// llvm.savestack/llvm.restorestack should save and restore. - unsigned getStackPointerRegisterToSaveRestore() const { + Register getStackPointerRegisterToSaveRestore() const { return StackPointerRegisterToSaveRestore; } @@ -1758,17 +1792,10 @@ public: return ""; } - /// Returns true if a cast between SrcAS and DestAS is a noop. - virtual bool isNoopAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const { - return false; - } - /// Returns true if a cast from SrcAS to DestAS is "cheap", such that e.g. we /// are happy to sink it into basic blocks. A cast may be free, but not /// necessarily a no-op. e.g. a free truncate from a 64-bit to 32-bit pointer. - virtual bool isFreeAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const { - return isNoopAddrSpaceCast(SrcAS, DestAS); - } + virtual bool isFreeAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const; /// Return true if the pointer arguments to CI should be aligned by aligning /// the object whose address is being passed. If so then MinSize is set to the @@ -2758,6 +2785,10 @@ public: return false; } + /// Does this target require the clearing of high-order bits in a register + /// passed to the fp16 to fp conversion library function. + virtual bool shouldKeepZExtForFP16Conv() const { return false; } + //===--------------------------------------------------------------------===// // Runtime Library hooks // @@ -3090,16 +3121,6 @@ protected: MachineBasicBlock *emitPatchPoint(MachineInstr &MI, MachineBasicBlock *MBB) const; - /// Replace/modify the XRay custom event operands with target-dependent - /// details. - MachineBasicBlock *emitXRayCustomEvent(MachineInstr &MI, - MachineBasicBlock *MBB) const; - - /// Replace/modify the XRay typed event operands with target-dependent - /// details. - MachineBasicBlock *emitXRayTypedEvent(MachineInstr &MI, - MachineBasicBlock *MBB) const; - bool IsStrictFPEnabled; }; @@ -4188,7 +4209,7 @@ public: // Lower custom output constraints. If invalid, return SDValue(). virtual SDValue LowerAsmOutputForConstraint(SDValue &Chain, SDValue &Flag, - SDLoc DL, + const SDLoc &DL, const AsmOperandInfo &OpInfo, SelectionDAG &DAG) const; @@ -4255,6 +4276,20 @@ public: return SDValue(); } + /// Return a target-dependent comparison result if the input operand is + /// suitable for use with a square root estimate calculation. For example, the + /// comparison may check if the operand is NAN, INF, zero, normal, etc. The + /// result should be used as the condition operand for a select or branch. + virtual SDValue getSqrtInputTest(SDValue Operand, SelectionDAG &DAG, + const DenormalMode &Mode) const; + + /// Return a target-dependent result if the input operand is not suitable for + /// use with a square root estimate calculation. + virtual SDValue getSqrtResultForDenormInput(SDValue Operand, + SelectionDAG &DAG) const { + return DAG.getConstantFP(0.0, SDLoc(Operand), Operand.getValueType()); + } + //===--------------------------------------------------------------------===// // Legalization utility functions // @@ -4269,7 +4304,7 @@ public: /// \param RL Low bits of the RHS of the MUL. See LL for meaning /// \param RH High bits of the RHS of the MUL. See LL for meaning. /// \returns true if the node has been expanded, false if it has not - bool expandMUL_LOHI(unsigned Opcode, EVT VT, SDLoc dl, SDValue LHS, + bool expandMUL_LOHI(unsigned Opcode, EVT VT, const SDLoc &dl, SDValue LHS, SDValue RHS, SmallVectorImpl &Result, EVT HiLoVT, SelectionDAG &DAG, MulExpansionKind Kind, SDValue LL = SDValue(), SDValue LH = SDValue(), @@ -4297,9 +4332,12 @@ public: /// Expand rotations. /// \param N Node to expand + /// \param AllowVectorOps expand vector rotate, this should only be performed + /// if the legalization is happening outside of LegalizeVectorOps /// \param Result output after conversion /// \returns True, if the expansion was successful, false otherwise - bool expandROT(SDNode *N, SDValue &Result, SelectionDAG &DAG) const; + bool expandROT(SDNode *N, bool AllowVectorOps, SDValue &Result, + SelectionDAG &DAG) const; /// Expand float(f32) to SINT(i64) conversion /// \param N Node to expand @@ -4326,6 +4364,11 @@ public: /// Expand fminnum/fmaxnum into fminnum_ieee/fmaxnum_ieee with quieted inputs. SDValue expandFMINNUM_FMAXNUM(SDNode *N, SelectionDAG &DAG) const; + /// Expand FP_TO_[US]INT_SAT into FP_TO_[US]INT and selects or min/max. + /// \param N Node to expand + /// \returns The expansion result + SDValue expandFP_TO_INT_SAT(SDNode *N, SelectionDAG &DAG) const; + /// Expand CTPOP nodes. Expands vector/scalar CTPOP nodes, /// vector nodes can only succeed if all operations are legal/custom. /// \param N Node to expand @@ -4352,8 +4395,10 @@ public: /// (ABS x) -> (XOR (ADD x, (SRA x, type_size)), (SRA x, type_size)) /// \param N Node to expand /// \param Result output after conversion + /// \param IsNegative indicate negated abs /// \returns True, if the expansion was successful, false otherwise - bool expandABS(SDNode *N, SDValue &Result, SelectionDAG &DAG) const; + bool expandABS(SDNode *N, SDValue &Result, SelectionDAG &DAG, + bool IsNegative = false) const; /// Turn load of vector type into a load of the individual elements. /// \param LD load to expand @@ -4393,10 +4438,18 @@ public: SDValue getVectorElementPointer(SelectionDAG &DAG, SDValue VecPtr, EVT VecVT, SDValue Index) const; + /// Method for building the DAG expansion of ISD::[US][MIN|MAX]. This + /// method accepts integers as its arguments. + SDValue expandIntMINMAX(SDNode *Node, SelectionDAG &DAG) const; + /// Method for building the DAG expansion of ISD::[US][ADD|SUB]SAT. This /// method accepts integers as its arguments. SDValue expandAddSubSat(SDNode *Node, SelectionDAG &DAG) const; + /// Method for building the DAG expansion of ISD::[US]SHLSAT. This + /// method accepts integers as its arguments. + SDValue expandShlSat(SDNode *Node, SelectionDAG &DAG) const; + /// Method for building the DAG expansion of ISD::[U|S]MULFIX[SAT]. This /// method accepts integers as its arguments. SDValue expandFixedPointMul(SDNode *Node, SelectionDAG &DAG) const; @@ -4428,6 +4481,9 @@ public: /// only the first Count elements of the vector are used. SDValue expandVecReduce(SDNode *Node, SelectionDAG &DAG) const; + /// Expand a VECREDUCE_SEQ_* into an explicit ordered calculation. + SDValue expandVecReduceSeq(SDNode *Node, SelectionDAG &DAG) const; + /// Expand an SREM or UREM using SDIV/UDIV or SDIVREM/UDIVREM, if legal. /// Returns true if the expansion was successful. bool expandREM(SDNode *Node, SDValue &Result, SelectionDAG &DAG) const; @@ -4482,6 +4538,10 @@ public: // combiner can fold the new nodes. SDValue lowerCmpEqZeroToCtlzSrl(SDValue Op, SelectionDAG &DAG) const; + /// Give targets the chance to reduce the number of distinct addresing modes. + ISD::MemIndexType getCanonicalIndexType(ISD::MemIndexType IndexType, + EVT MemVT, SDValue Offsets) const; + private: SDValue foldSetCCWithAnd(EVT VT, SDValue N0, SDValue N1, ISD::CondCode Cond, const SDLoc &DL, DAGCombinerInfo &DCI) const; diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index 6e2c0973e354..31e08b7d1e63 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -21,6 +21,7 @@ namespace llvm { class GlobalValue; class MachineModuleInfo; +class MachineFunction; class MCContext; class MCExpr; class MCSection; @@ -35,10 +36,9 @@ class TargetLoweringObjectFileELF : public TargetLoweringObjectFile { protected: MCSymbolRefExpr::VariantKind PLTRelativeVariantKind = MCSymbolRefExpr::VK_None; - const TargetMachine *TM = nullptr; public: - TargetLoweringObjectFileELF() = default; + TargetLoweringObjectFileELF(); ~TargetLoweringObjectFileELF() override = default; void Initialize(MCContext &Ctx, const TargetMachine &TM) override; @@ -63,6 +63,8 @@ public: MCSection *getSectionForJumpTable(const Function &F, const TargetMachine &TM) const override; + MCSection *getSectionForLSDA(const Function &F, + const TargetMachine &TM) const override; MCSection * getSectionForMachineBasicBlock(const Function &F, @@ -95,6 +97,9 @@ public: const GlobalValue *RHS, const TargetMachine &TM) const override; + const MCExpr *lowerDSOLocalEquivalent(const DSOLocalEquivalent *Equiv, + const TargetMachine &TM) const override; + MCSection *getSectionForCommandLines() const override; }; @@ -143,6 +148,7 @@ public: class TargetLoweringObjectFileCOFF : public TargetLoweringObjectFile { mutable unsigned NextUniqueID = 0; + const TargetMachine *TM = nullptr; public: ~TargetLoweringObjectFileCOFF() override = default; @@ -168,12 +174,6 @@ public: MCSection *getStaticDtorSection(unsigned Priority, const MCSymbol *KeySym) const override; - void emitLinkerFlagsForGlobal(raw_ostream &OS, - const GlobalValue *GV) const override; - - void emitLinkerFlagsForUsed(raw_ostream &OS, - const GlobalValue *GV) const override; - const MCExpr *lowerRelativeReference(const GlobalValue *LHS, const GlobalValue *RHS, const TargetMachine &TM) const override; @@ -183,6 +183,9 @@ public: MCSection *getSectionForConstant(const DataLayout &DL, SectionKind Kind, const Constant *C, Align &Alignment) const override; + +private: + void emitLinkerDirectives(MCStreamer &Streamer, Module &M) const; }; class TargetLoweringObjectFileWasm : public TargetLoweringObjectFile { @@ -217,6 +220,10 @@ public: TargetLoweringObjectFileXCOFF() = default; ~TargetLoweringObjectFileXCOFF() override = default; + static bool ShouldEmitEHBlock(const MachineFunction *MF); + + static MCSymbol *getEHInfoTableSymbol(const MachineFunction *MF); + void Initialize(MCContext &Ctx, const TargetMachine &TM) override; bool shouldPutJumpTableInFunctionSection(bool UsesLabelDifference, @@ -246,12 +253,13 @@ public: const Constant *C, Align &Alignment) const override; - static XCOFF::StorageClass getStorageClassForGlobal(const GlobalObject *GO); + static XCOFF::StorageClass getStorageClassForGlobal(const GlobalValue *GV); MCSection * getSectionForFunctionDescriptor(const Function *F, const TargetMachine &TM) const override; - MCSection *getSectionForTOCEntry(const MCSymbol *Sym) const override; + MCSection *getSectionForTOCEntry(const MCSymbol *Sym, + const TargetMachine &TM) const override; /// For external functions, this will always return a function descriptor /// csect. @@ -263,7 +271,7 @@ public: MCSymbol *getTargetSymbol(const GlobalValue *GV, const TargetMachine &TM) const override; - MCSymbol *getFunctionEntryPointSymbol(const Function *F, + MCSymbol *getFunctionEntryPointSymbol(const GlobalValue *Func, const TargetMachine &TM) const override; }; diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetPassConfig.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetPassConfig.h index a18c8b16bf1c..b4787710379f 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetPassConfig.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetPassConfig.h @@ -25,6 +25,7 @@ struct MachineSchedContext; class PassConfigImpl; class ScheduleDAGInstrs; class CSEConfigBase; +class PassInstrumentationCallbacks; // The old pass manager infrastructure is hidden in a legacy namespace now. namespace legacy { @@ -187,7 +188,7 @@ public: /// Insert InsertedPassID pass after TargetPassID pass. void insertPass(AnalysisID TargetPassID, IdentifyingPassPtr InsertedPassID, - bool VerifyAfter = true, bool PrintAfter = true); + bool VerifyAfter = true); /// Allow the target to enable a specific standard pass by default. void enablePass(AnalysisID PassID) { substitutePass(PassID, PassID); } @@ -313,14 +314,17 @@ public: /// Add a pass to remove debug info from the MIR. void addStripDebugPass(); + /// Add a pass to check synthesized debug info for MIR. + void addCheckDebugPass(); + /// Add standard passes before a pass that's about to be added. For example, /// the DebugifyMachineModulePass if it is enabled. void addMachinePrePasses(bool AllowDebugify = true); /// Add standard passes after a pass that has just been added. For example, /// the MachineVerifier if it is enabled. - void addMachinePostPasses(const std::string &Banner, bool AllowPrint = true, - bool AllowVerify = true, bool AllowStrip = true); + void addMachinePostPasses(const std::string &Banner, bool AllowVerify = true, + bool AllowStrip = true); /// Check whether or not GlobalISel should abort on error. /// When this is disabled, GlobalISel will fall back on SDISel instead of @@ -441,32 +445,30 @@ protected: /// Add a CodeGen pass at this point in the pipeline after checking overrides. /// Return the pass that was added, or zero if no pass was added. - /// @p printAfter if true and adding a machine function pass add an extra - /// machine printer pass afterwards /// @p verifyAfter if true and adding a machine function pass add an extra /// machine verification pass afterwards. - AnalysisID addPass(AnalysisID PassID, bool verifyAfter = true, - bool printAfter = true); + AnalysisID addPass(AnalysisID PassID, bool verifyAfter = true); /// Add a pass to the PassManager if that pass is supposed to be run, as /// determined by the StartAfter and StopAfter options. Takes ownership of the /// pass. - /// @p printAfter if true and adding a machine function pass add an extra - /// machine printer pass afterwards /// @p verifyAfter if true and adding a machine function pass add an extra /// machine verification pass afterwards. - void addPass(Pass *P, bool verifyAfter = true, bool printAfter = true); + void addPass(Pass *P, bool verifyAfter = true); /// addMachinePasses helper to create the target-selected or overriden /// regalloc pass. virtual FunctionPass *createRegAllocPass(bool Optimized); - /// Add core register alloator passes which do the actual register assignment + /// Add core register allocator passes which do the actual register assignment /// and rewriting. \returns true if any passes were added. - virtual bool addRegAssignmentFast(); - virtual bool addRegAssignmentOptimized(); + virtual bool addRegAssignAndRewriteFast(); + virtual bool addRegAssignAndRewriteOptimized(); }; +void registerCodeGenCallback(PassInstrumentationCallbacks &PIC, + LLVMTargetMachine &); + } // end namespace llvm #endif // LLVM_CODEGEN_TARGETPASSCONFIG_H diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetRegisterInfo.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetRegisterInfo.h index d921c4c9028b..8790e2f09eb6 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetRegisterInfo.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetRegisterInfo.h @@ -34,6 +34,7 @@ namespace llvm { class BitVector; +class DIExpression; class LiveRegMatrix; class MachineFunction; class MachineInstr; @@ -87,22 +88,21 @@ public: /// Return true if the specified register is included in this register class. /// This does not include virtual registers. - bool contains(unsigned Reg) const { + bool contains(Register Reg) const { /// FIXME: Historically this function has returned false when given vregs /// but it should probably only receive physical registers - if (!Register::isPhysicalRegister(Reg)) + if (!Reg.isPhysical()) return false; - return MC->contains(Reg); + return MC->contains(Reg.asMCReg()); } /// Return true if both registers are in this class. - bool contains(unsigned Reg1, unsigned Reg2) const { + bool contains(Register Reg1, Register Reg2) const { /// FIXME: Historically this function has returned false when given a vregs /// but it should probably only receive physical registers - if (!Register::isPhysicalRegister(Reg1) || - !Register::isPhysicalRegister(Reg2)) + if (!Reg1.isPhysical() || !Reg2.isPhysical()) return false; - return MC->contains(Reg1, Reg2); + return MC->contains(Reg1.asMCReg(), Reg2.asMCReg()); } /// Return the cost of copying a value between two registers in this class. @@ -386,12 +386,12 @@ public: /// The registers may be virtual registers. bool regsOverlap(Register regA, Register regB) const { if (regA == regB) return true; - if (regA.isVirtual() || regB.isVirtual()) + if (!regA.isPhysical() || !regB.isPhysical()) return false; // Regunits are numerically ordered. Find a common unit. - MCRegUnitIterator RUA(regA, this); - MCRegUnitIterator RUB(regB, this); + MCRegUnitIterator RUA(regA.asMCReg(), this); + MCRegUnitIterator RUB(regB.asMCReg(), this); do { if (*RUA == *RUB) return true; if (*RUA < *RUB) ++RUA; @@ -401,9 +401,9 @@ public: } /// Returns true if Reg contains RegUnit. - bool hasRegUnit(MCRegister Reg, unsigned RegUnit) const { + bool hasRegUnit(MCRegister Reg, Register RegUnit) const { for (MCRegUnitIterator Units(Reg, this); Units.isValid(); ++Units) - if (*Units == RegUnit) + if (Register(*Units) == RegUnit) return true; return false; } @@ -415,6 +415,16 @@ public: virtual Register lookThruCopyLike(Register SrcReg, const MachineRegisterInfo *MRI) const; + /// Find the original SrcReg unless it is the target of a copy-like operation, + /// in which case we chain backwards through all such operations to the + /// ultimate source register. If a physical register is encountered, we stop + /// the search. + /// Return the original SrcReg if all the definitions in the chain only have + /// one user and not a physical register. + virtual Register + lookThruSingleUseCopyChain(Register SrcReg, + const MachineRegisterInfo *MRI) const; + /// Return a null-terminated list of all of the callee-saved registers on /// this target. The register should be in the order of desired callee-save /// stack frame offset. The first register is closest to the incoming stack @@ -449,6 +459,13 @@ public: return nullptr; } + /// Return a register mask for the registers preserved by the unwinder, + /// or nullptr if no custom mask is needed. + virtual const uint32_t * + getCustomEHPadPreservedMask(const MachineFunction &MF) const { + return nullptr; + } + /// Return a register mask that clobbers everything. virtual const uint32_t *getNoPreservedMask() const { llvm_unreachable("target does not provide no preserved mask"); @@ -894,11 +911,11 @@ public: return false; } - /// Insert defining instruction(s) for BaseReg to be a pointer to FrameIdx - /// before insertion point I. - virtual void materializeFrameBaseRegister(MachineBasicBlock *MBB, - Register BaseReg, int FrameIdx, - int64_t Offset) const { + /// Insert defining instruction(s) for a pointer to FrameIdx before + /// insertion point I. Return materialized frame pointer. + virtual Register materializeFrameBaseRegister(MachineBasicBlock *MBB, + int FrameIdx, + int64_t Offset) const { llvm_unreachable("materializeFrameBaseRegister does not exist on this " "target"); } @@ -917,6 +934,15 @@ public: llvm_unreachable("isFrameOffsetLegal does not exist on this target"); } + /// Gets the DWARF expression opcodes for \p Offset. + virtual void getOffsetOpcodes(const StackOffset &Offset, + SmallVectorImpl &Ops) const; + + /// Prepends a DWARF expression for \p Offset to DIExpression \p Expr. + DIExpression * + prependOffsetExpression(const DIExpression *Expr, unsigned PrependFlags, + const StackOffset &Offset) const; + /// Spill the register so it can be used by the register scavenger. /// Return true if the register was spilled, false otherwise. /// If this function does not spill the register, the scavenger @@ -970,6 +996,36 @@ public: virtual bool shouldRegionSplitForVirtReg(const MachineFunction &MF, const LiveInterval &VirtReg) const; + /// Last chance recoloring has a high compile time cost especially for + /// targets with a lot of registers. + /// This method is used to decide whether or not \p VirtReg should + /// go through this expensive heuristic. + /// When this target hook is hit, by returning false, there is a high + /// chance that the register allocation will fail altogether (usually with + /// "ran out of registers"). + /// That said, this error usually points to another problem in the + /// optimization pipeline. + virtual bool + shouldUseLastChanceRecoloringForVirtReg(const MachineFunction &MF, + const LiveInterval &VirtReg) const { + return true; + } + + /// Deferred spilling delays the spill insertion of a virtual register + /// after every other allocation. By deferring the spilling, it is + /// sometimes possible to eliminate that spilling altogether because + /// something else could have been eliminated, thus leaving some space + /// for the virtual register. + /// However, this comes with a compile time impact because it adds one + /// more stage to the greedy register allocator. + /// This method is used to decide whether \p VirtReg should use the deferred + /// spilling stage instead of being spilled right away. + virtual bool + shouldUseDeferredSpillingForVirtReg(const MachineFunction &MF, + const LiveInterval &VirtReg) const { + return false; + } + //===--------------------------------------------------------------------===// /// Debug information queries. @@ -994,7 +1050,7 @@ public: /// Returns the physical register number of sub-register "Index" /// for physical register RegNo. Return zero if the sub-register does not /// exist. - inline Register getSubReg(MCRegister Reg, unsigned Idx) const { + inline MCRegister getSubReg(MCRegister Reg, unsigned Idx) const { return static_cast(this)->getSubReg(Reg, Idx); } }; @@ -1146,8 +1202,8 @@ public: // This is useful when building IndexedMaps keyed on virtual registers struct VirtReg2IndexFunctor { - using argument_type = unsigned; - unsigned operator()(unsigned Reg) const { + using argument_type = Register; + unsigned operator()(Register Reg) const { return Register::virtReg2Index(Reg); } }; diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h index e0dfd9c8bbc5..3fac2f688dd8 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h @@ -58,8 +58,8 @@ class Triple; /// class TargetSubtargetInfo : public MCSubtargetInfo { protected: // Can only create subclasses... - TargetSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS, - ArrayRef PF, + TargetSubtargetInfo(const Triple &TT, StringRef CPU, StringRef TuneCPU, + StringRef FS, ArrayRef PF, ArrayRef PD, const MCWriteProcResEntry *WPR, const MCWriteLatencyEntry *WL, diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/TileShapeInfo.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/TileShapeInfo.h new file mode 100644 index 000000000000..031d23555b7e --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/TileShapeInfo.h @@ -0,0 +1,97 @@ +//===- llvm/CodeGen/TileShapeInfo.h - ---------------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +/// \file Shape utility for AMX. +/// AMX hardware requires to config the shape of tile data register before use. +/// The 2D shape includes row and column. In AMX intrinsics interface the shape +/// is passed as 1st and 2nd parameter and they are lowered as the 1st and 2nd +/// machine operand of AMX pseudo instructions. ShapeT class is to facilitate +/// tile config and register allocator. The row and column are machine operand +/// of AMX pseudo instructions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_TILESHAPEINFO_H +#define LLVM_CODEGEN_TILESHAPEINFO_H + +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineOperand.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Register.h" +#include + +namespace llvm { + +class ShapeT { +public: + ShapeT(MachineOperand *Row, MachineOperand *Col, + const MachineRegisterInfo *MRI = nullptr) + : Row(Row), Col(Col) { + if (MRI) + deduceImm(MRI); + } + ShapeT() + : Row(nullptr), Col(nullptr), RowImm(InvalidImmShape), + ColImm(InvalidImmShape) {} + bool operator==(const ShapeT &Shape) { + MachineOperand *R = Shape.Row; + MachineOperand *C = Shape.Col; + if (!R || !C) + return false; + if (!Row || !Col) + return false; + if (Row->getReg() == R->getReg() && Col->getReg() == C->getReg()) + return true; + if ((RowImm != InvalidImmShape) && (ColImm != InvalidImmShape)) + return RowImm == Shape.getRowImm() && ColImm == Shape.getColImm(); + return false; + } + + bool operator!=(const ShapeT &Shape) { return !(*this == Shape); } + + MachineOperand *getRow() const { return Row; } + + MachineOperand *getCol() const { return Col; } + + int64_t getRowImm() const { return RowImm; } + + int64_t getColImm() const { return ColImm; } + + bool isValid() { return (Row != nullptr) && (Col != nullptr); } + + void deduceImm(const MachineRegisterInfo *MRI) { + // All def must be the same value, otherwise it is invalid MIs. + // Find the immediate. + // TODO copy propagation. + auto GetImm = [&](Register Reg) { + int64_t Imm = InvalidImmShape; + for (const MachineOperand &DefMO : MRI->def_operands(Reg)) { + const auto *MI = DefMO.getParent(); + if (MI->isMoveImmediate()) { + Imm = MI->getOperand(1).getImm(); + break; + } + } + return Imm; + }; + RowImm = GetImm(Row->getReg()); + ColImm = GetImm(Col->getReg()); + } + +private: + static constexpr int64_t InvalidImmShape = -1; + MachineOperand *Row; + MachineOperand *Col; + int64_t RowImm; + int64_t ColImm; +}; + +} // namespace llvm + +#endif diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/ValueTypes.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/ValueTypes.h index db8161caf7d2..888b83d6f736 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/ValueTypes.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/ValueTypes.h @@ -92,26 +92,17 @@ namespace llvm { /// with the element type converted to an integer type with the same /// bitwidth. EVT changeVectorElementTypeToInteger() const { - if (!isSimple()) - return changeExtendedVectorElementTypeToInteger(); - MVT EltTy = getSimpleVT().getVectorElementType(); - unsigned BitWidth = EltTy.getSizeInBits(); - MVT IntTy = MVT::getIntegerVT(BitWidth); - MVT VecTy = MVT::getVectorVT(IntTy, getVectorElementCount()); - assert(VecTy.SimpleTy != MVT::INVALID_SIMPLE_VALUE_TYPE && - "Simple vector VT not representable by simple integer vector VT!"); - return VecTy; + if (isSimple()) + return getSimpleVT().changeVectorElementTypeToInteger(); + return changeExtendedVectorElementTypeToInteger(); } /// Return a VT for a vector type whose attributes match ourselves /// with the exception of the element type that is chosen by the caller. EVT changeVectorElementType(EVT EltVT) const { - if (!isSimple()) - return changeExtendedVectorElementType(EltVT); - MVT VecTy = MVT::getVectorVT(EltVT.V, getVectorElementCount()); - assert(VecTy.SimpleTy != MVT::INVALID_SIMPLE_VALUE_TYPE && - "Simple vector VT not representable by simple integer vector VT!"); - return VecTy; + if (isSimple() && EltVT.isSimple()) + return getSimpleVT().changeVectorElementType(EltVT.getSimpleVT()); + return changeExtendedVectorElementType(EltVT); } /// Return the type converted to an equivalently sized integer or vector @@ -122,8 +113,7 @@ namespace llvm { return changeVectorElementTypeToInteger(); if (isSimple()) - return MVT::getIntegerVT(getSizeInBits()); - + return getSimpleVT().changeTypeToInteger(); return changeExtendedTypeToInteger(); } @@ -214,9 +204,7 @@ namespace llvm { } /// Return true if the bit size is a multiple of 8. - bool isByteSized() const { - return getSizeInBits().isByteSized(); - } + bool isByteSized() const { return getSizeInBits().isKnownMultipleOf(8); } /// Return true if the size is a power-of-two number of bytes. bool isRound() const { @@ -232,28 +220,58 @@ namespace llvm { return getSizeInBits() == VT.getSizeInBits(); } + /// Return true if we know at compile time this has more bits than VT. + bool knownBitsGT(EVT VT) const { + return TypeSize::isKnownGT(getSizeInBits(), VT.getSizeInBits()); + } + + /// Return true if we know at compile time this has more than or the same + /// bits as VT. + bool knownBitsGE(EVT VT) const { + return TypeSize::isKnownGE(getSizeInBits(), VT.getSizeInBits()); + } + + /// Return true if we know at compile time this has fewer bits than VT. + bool knownBitsLT(EVT VT) const { + return TypeSize::isKnownLT(getSizeInBits(), VT.getSizeInBits()); + } + + /// Return true if we know at compile time this has fewer than or the same + /// bits as VT. + bool knownBitsLE(EVT VT) const { + return TypeSize::isKnownLE(getSizeInBits(), VT.getSizeInBits()); + } + /// Return true if this has more bits than VT. bool bitsGT(EVT VT) const { if (EVT::operator==(VT)) return false; - return getSizeInBits() > VT.getSizeInBits(); + assert(isScalableVector() == VT.isScalableVector() && + "Comparison between scalable and fixed types"); + return knownBitsGT(VT); } /// Return true if this has no less bits than VT. bool bitsGE(EVT VT) const { if (EVT::operator==(VT)) return true; - return getSizeInBits() >= VT.getSizeInBits(); + assert(isScalableVector() == VT.isScalableVector() && + "Comparison between scalable and fixed types"); + return knownBitsGE(VT); } /// Return true if this has less bits than VT. bool bitsLT(EVT VT) const { if (EVT::operator==(VT)) return false; - return getSizeInBits() < VT.getSizeInBits(); + assert(isScalableVector() == VT.isScalableVector() && + "Comparison between scalable and fixed types"); + return knownBitsLT(VT); } /// Return true if this has no more bits than VT. bool bitsLE(EVT VT) const { if (EVT::operator==(VT)) return true; - return getSizeInBits() <= VT.getSizeInBits(); + assert(isScalableVector() == VT.isScalableVector() && + "Comparison between scalable and fixed types"); + return knownBitsLE(VT); } /// Return the SimpleValueType held in the specified simple EVT. @@ -285,7 +303,7 @@ namespace llvm { if (isScalableVector()) WithColor::warning() << "Possible incorrect use of EVT::getVectorNumElements() for " - "scalable vector. Scalable flag may be dropped, use" + "scalable vector. Scalable flag may be dropped, use " "EVT::getVectorElementCount() instead\n"; #endif if (isSimple()) @@ -304,7 +322,7 @@ namespace llvm { /// Given a vector type, return the minimum number of elements it contains. unsigned getVectorMinNumElements() const { - return getVectorElementCount().Min; + return getVectorElementCount().getKnownMinValue(); } /// Return the size of the specified value type in bits. @@ -318,8 +336,14 @@ namespace llvm { return getExtendedSizeInBits(); } - TypeSize getScalarSizeInBits() const { - return getScalarType().getSizeInBits(); + /// Return the size of the specified fixed width value type in bits. The + /// function will assert if the type is scalable. + uint64_t getFixedSizeInBits() const { + return getSizeInBits().getFixedSize(); + } + + uint64_t getScalarSizeInBits() const { + return getScalarType().getSizeInBits().getFixedSize(); } /// Return the number of bytes overwritten by a store of the specified value @@ -383,8 +407,17 @@ namespace llvm { EVT getHalfNumVectorElementsVT(LLVMContext &Context) const { EVT EltVT = getVectorElementType(); auto EltCnt = getVectorElementCount(); - assert(!(EltCnt.Min & 1) && "Splitting vector, but not in half!"); - return EVT::getVectorVT(Context, EltVT, EltCnt / 2); + assert(EltCnt.isKnownEven() && "Splitting vector, but not in half!"); + return EVT::getVectorVT(Context, EltVT, EltCnt.divideCoefficientBy(2)); + } + + // Return a VT for a vector type with the same element type but + // double the number of elements. The type returned may be an + // extended type. + EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const { + EVT EltVT = getVectorElementType(); + auto EltCnt = getVectorElementCount(); + return EVT::getVectorVT(Context, EltVT, EltCnt * 2); } /// Returns true if the given vector is a power of 2. @@ -398,7 +431,8 @@ namespace llvm { EVT getPow2VectorType(LLVMContext &Context) const { if (!isPow2VectorType()) { ElementCount NElts = getVectorElementCount(); - NElts.Min = 1 << Log2_32_Ceil(NElts.Min); + unsigned NewMinCount = 1 << Log2_32_Ceil(NElts.getKnownMinValue()); + NElts = ElementCount::get(NewMinCount, NElts.isScalable()); return EVT::getVectorVT(Context, getVectorElementType(), NElts); } else { diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/ValueTypes.td b/contrib/llvm-project/llvm/include/llvm/CodeGen/ValueTypes.td index c5eb87cf1d34..d13d0a7772e9 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/ValueTypes.td +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/ValueTypes.td @@ -87,107 +87,116 @@ def v4i64 : ValueType<256, 60>; // 4 x i64 vector value def v8i64 : ValueType<512, 61>; // 8 x i64 vector value def v16i64 : ValueType<1024,62>; // 16 x i64 vector value def v32i64 : ValueType<2048,63>; // 32 x i64 vector value +def v64i64 : ValueType<4096,64>; // 64 x i64 vector value +def v128i64: ValueType<8192,65>; // 128 x i64 vector value +def v256i64: ValueType<16384,66>; // 256 x i64 vector value + +def v1i128 : ValueType<128, 67>; // 1 x i128 vector value + +def v2f16 : ValueType<32 , 68>; // 2 x f16 vector value +def v3f16 : ValueType<48 , 69>; // 3 x f16 vector value +def v4f16 : ValueType<64 , 70>; // 4 x f16 vector value +def v8f16 : ValueType<128, 71>; // 8 x f16 vector value +def v16f16 : ValueType<256, 72>; // 16 x f16 vector value +def v32f16 : ValueType<512, 73>; // 32 x f16 vector value +def v64f16 : ValueType<1024, 74>; // 64 x f16 vector value +def v128f16 : ValueType<2048, 75>; // 128 x f16 vector value +def v2bf16 : ValueType<32 , 76>; // 2 x bf16 vector value +def v3bf16 : ValueType<48 , 77>; // 3 x bf16 vector value +def v4bf16 : ValueType<64 , 78>; // 4 x bf16 vector value +def v8bf16 : ValueType<128, 79>; // 8 x bf16 vector value +def v16bf16 : ValueType<256, 80>; // 16 x bf16 vector value +def v32bf16 : ValueType<512, 81>; // 32 x bf16 vector value +def v64bf16 : ValueType<1024, 82>; // 64 x bf16 vector value +def v128bf16 : ValueType<2048, 83>; // 128 x bf16 vector value +def v1f32 : ValueType<32 , 84>; // 1 x f32 vector value +def v2f32 : ValueType<64 , 85>; // 2 x f32 vector value +def v3f32 : ValueType<96 , 86>; // 3 x f32 vector value +def v4f32 : ValueType<128, 87>; // 4 x f32 vector value +def v5f32 : ValueType<160, 88>; // 5 x f32 vector value +def v8f32 : ValueType<256, 89>; // 8 x f32 vector value +def v16f32 : ValueType<512, 90>; // 16 x f32 vector value +def v32f32 : ValueType<1024, 91>; // 32 x f32 vector value +def v64f32 : ValueType<2048, 92>; // 64 x f32 vector value +def v128f32 : ValueType<4096, 93>; // 128 x f32 vector value +def v256f32 : ValueType<8182, 94>; // 256 x f32 vector value +def v512f32 : ValueType<16384, 95>; // 512 x f32 vector value +def v1024f32 : ValueType<32768, 96>; // 1024 x f32 vector value +def v2048f32 : ValueType<65536, 97>; // 2048 x f32 vector value +def v1f64 : ValueType<64, 98>; // 1 x f64 vector value +def v2f64 : ValueType<128, 99>; // 2 x f64 vector value +def v4f64 : ValueType<256, 100>; // 4 x f64 vector value +def v8f64 : ValueType<512, 101>; // 8 x f64 vector value +def v16f64 : ValueType<1024, 102>; // 16 x f64 vector value +def v32f64 : ValueType<2048, 103>; // 32 x f64 vector value +def v64f64 : ValueType<4096, 104>; // 64 x f64 vector value +def v128f64 : ValueType<8192, 105>; // 128 x f64 vector value +def v256f64 : ValueType<16384, 106>; // 256 x f64 vector value + +def nxv1i1 : ValueType<1, 107>; // n x 1 x i1 vector value +def nxv2i1 : ValueType<2, 108>; // n x 2 x i1 vector value +def nxv4i1 : ValueType<4, 109>; // n x 4 x i1 vector value +def nxv8i1 : ValueType<8, 110>; // n x 8 x i1 vector value +def nxv16i1 : ValueType<16, 111>; // n x 16 x i1 vector value +def nxv32i1 : ValueType<32, 112>; // n x 32 x i1 vector value +def nxv64i1 : ValueType<64,113>; // n x 64 x i1 vector value + +def nxv1i8 : ValueType<8, 114>; // n x 1 x i8 vector value +def nxv2i8 : ValueType<16, 115>; // n x 2 x i8 vector value +def nxv4i8 : ValueType<32, 116>; // n x 4 x i8 vector value +def nxv8i8 : ValueType<64, 117>; // n x 8 x i8 vector value +def nxv16i8 : ValueType<128, 118>; // n x 16 x i8 vector value +def nxv32i8 : ValueType<256, 119>; // n x 32 x i8 vector value +def nxv64i8 : ValueType<512, 120>; // n x 64 x i8 vector value + +def nxv1i16 : ValueType<16, 121>; // n x 1 x i16 vector value +def nxv2i16 : ValueType<32, 122>; // n x 2 x i16 vector value +def nxv4i16 : ValueType<64, 123>; // n x 4 x i16 vector value +def nxv8i16 : ValueType<128, 124>; // n x 8 x i16 vector value +def nxv16i16: ValueType<256, 125>; // n x 16 x i16 vector value +def nxv32i16: ValueType<512, 126>; // n x 32 x i16 vector value + +def nxv1i32 : ValueType<32, 127>; // n x 1 x i32 vector value +def nxv2i32 : ValueType<64, 128>; // n x 2 x i32 vector value +def nxv4i32 : ValueType<128, 129>; // n x 4 x i32 vector value +def nxv8i32 : ValueType<256, 130>; // n x 8 x i32 vector value +def nxv16i32: ValueType<512, 131>; // n x 16 x i32 vector value +def nxv32i32: ValueType<1024,132>; // n x 32 x i32 vector value + +def nxv1i64 : ValueType<64, 133>; // n x 1 x i64 vector value +def nxv2i64 : ValueType<128, 134>; // n x 2 x i64 vector value +def nxv4i64 : ValueType<256, 135>; // n x 4 x i64 vector value +def nxv8i64 : ValueType<512, 136>; // n x 8 x i64 vector value +def nxv16i64: ValueType<1024,137>; // n x 16 x i64 vector value +def nxv32i64: ValueType<2048,138>; // n x 32 x i64 vector value + +def nxv1f16 : ValueType<32, 139>; // n x 1 x f16 vector value +def nxv2f16 : ValueType<32 , 140>; // n x 2 x f16 vector value +def nxv4f16 : ValueType<64 , 141>; // n x 4 x f16 vector value +def nxv8f16 : ValueType<128, 142>; // n x 8 x f16 vector value +def nxv16f16 : ValueType<256,143>; // n x 16 x f16 vector value +def nxv32f16 : ValueType<512,144>; // n x 32 x f16 vector value +def nxv2bf16 : ValueType<32 , 145>; // n x 2 x bf16 vector value +def nxv4bf16 : ValueType<64 , 146>; // n x 4 x bf16 vector value +def nxv8bf16 : ValueType<128, 147>; // n x 8 x bf16 vector value +def nxv1f32 : ValueType<32 , 148>; // n x 1 x f32 vector value +def nxv2f32 : ValueType<64 , 149>; // n x 2 x f32 vector value +def nxv4f32 : ValueType<128, 150>; // n x 4 x f32 vector value +def nxv8f32 : ValueType<256, 151>; // n x 8 x f32 vector value +def nxv16f32 : ValueType<512, 152>; // n x 16 x f32 vector value +def nxv1f64 : ValueType<64, 153>; // n x 1 x f64 vector value +def nxv2f64 : ValueType<128, 154>; // n x 2 x f64 vector value +def nxv4f64 : ValueType<256, 155>; // n x 4 x f64 vector value +def nxv8f64 : ValueType<512, 156>; // n x 8 x f64 vector value + +def x86mmx : ValueType<64 , 157>; // X86 MMX value +def FlagVT : ValueType<0 , 158>; // Pre-RA sched glue +def isVoid : ValueType<0 , 159>; // Produces no value +def untyped: ValueType<8 , 160>; // Produces an untyped value +def funcref : ValueType<0 , 161>; // WebAssembly's funcref type +def externref : ValueType<0 , 162>; // WebAssembly's externref type +def x86amx : ValueType<8192, 163>; // X86 AMX value -def v1i128 : ValueType<128, 64>; // 1 x i128 vector value - -def v2f16 : ValueType<32 , 65>; // 2 x f16 vector value -def v3f16 : ValueType<48 , 66>; // 3 x f16 vector value -def v4f16 : ValueType<64 , 67>; // 4 x f16 vector value -def v8f16 : ValueType<128, 68>; // 8 x f16 vector value -def v16f16 : ValueType<256, 69>; // 16 x f16 vector value -def v32f16 : ValueType<512, 70>; // 32 x f16 vector value -def v64f16 : ValueType<1024, 71>; // 64 x f16 vector value -def v128f16 : ValueType<2048, 72>; // 128 x f16 vector value -def v2bf16 : ValueType<32 , 73>; // 2 x bf16 vector value -def v3bf16 : ValueType<48 , 74>; // 3 x bf16 vector value -def v4bf16 : ValueType<64 , 75>; // 4 x bf16 vector value -def v8bf16 : ValueType<128, 76>; // 8 x bf16 vector value -def v16bf16 : ValueType<256, 77>; // 16 x bf16 vector value -def v32bf16 : ValueType<512, 78>; // 32 x bf16 vector value -def v64bf16 : ValueType<1024, 79>; // 64 x bf16 vector value -def v128bf16 : ValueType<2048, 80>; // 128 x bf16 vector value -def v1f32 : ValueType<32 , 81>; // 1 x f32 vector value -def v2f32 : ValueType<64 , 82>; // 2 x f32 vector value -def v3f32 : ValueType<96 , 83>; // 3 x f32 vector value -def v4f32 : ValueType<128, 84>; // 4 x f32 vector value -def v5f32 : ValueType<160, 85>; // 5 x f32 vector value -def v8f32 : ValueType<256, 86>; // 8 x f32 vector value -def v16f32 : ValueType<512, 87>; // 16 x f32 vector value -def v32f32 : ValueType<1024, 88>; // 32 x f32 vector value -def v64f32 : ValueType<2048, 89>; // 64 x f32 vector value -def v128f32 : ValueType<4096, 90>; // 128 x f32 vector value -def v256f32 : ValueType<8182, 91>; // 256 x f32 vector value -def v512f32 : ValueType<16384, 92>; // 512 x f32 vector value -def v1024f32 : ValueType<32768, 93>; // 1024 x f32 vector value -def v2048f32 : ValueType<65536, 94>; // 2048 x f32 vector value -def v1f64 : ValueType<64, 95>; // 1 x f64 vector value -def v2f64 : ValueType<128, 96>; // 2 x f64 vector value -def v4f64 : ValueType<256, 97>; // 4 x f64 vector value -def v8f64 : ValueType<512, 98>; // 8 x f64 vector value -def v16f64 : ValueType<1024, 99>; // 16 x f64 vector value -def v32f64 : ValueType<2048, 100>; // 32 x f64 vector value - -def nxv1i1 : ValueType<1, 101>; // n x 1 x i1 vector value -def nxv2i1 : ValueType<2, 102>; // n x 2 x i1 vector value -def nxv4i1 : ValueType<4, 103>; // n x 4 x i1 vector value -def nxv8i1 : ValueType<8, 104>; // n x 8 x i1 vector value -def nxv16i1 : ValueType<16, 105>; // n x 16 x i1 vector value -def nxv32i1 : ValueType<32, 106>; // n x 32 x i1 vector value -def nxv64i1 : ValueType<64,107>; // n x 64 x i1 vector value - -def nxv1i8 : ValueType<8, 108>; // n x 1 x i8 vector value -def nxv2i8 : ValueType<16, 109>; // n x 2 x i8 vector value -def nxv4i8 : ValueType<32, 110>; // n x 4 x i8 vector value -def nxv8i8 : ValueType<64, 111>; // n x 8 x i8 vector value -def nxv16i8 : ValueType<128, 112>; // n x 16 x i8 vector value -def nxv32i8 : ValueType<256, 113>; // n x 32 x i8 vector value -def nxv64i8 : ValueType<512, 114>; // n x 64 x i8 vector value - -def nxv1i16 : ValueType<16, 115>; // n x 1 x i16 vector value -def nxv2i16 : ValueType<32, 116>; // n x 2 x i16 vector value -def nxv4i16 : ValueType<64, 117>; // n x 4 x i16 vector value -def nxv8i16 : ValueType<128, 118>; // n x 8 x i16 vector value -def nxv16i16: ValueType<256, 119>; // n x 16 x i16 vector value -def nxv32i16: ValueType<512, 120>; // n x 32 x i16 vector value - -def nxv1i32 : ValueType<32, 121>; // n x 1 x i32 vector value -def nxv2i32 : ValueType<64, 122>; // n x 2 x i32 vector value -def nxv4i32 : ValueType<128, 123>; // n x 4 x i32 vector value -def nxv8i32 : ValueType<256, 124>; // n x 8 x i32 vector value -def nxv16i32: ValueType<512, 125>; // n x 16 x i32 vector value -def nxv32i32: ValueType<1024,126>; // n x 32 x i32 vector value - -def nxv1i64 : ValueType<64, 127>; // n x 1 x i64 vector value -def nxv2i64 : ValueType<128, 128>; // n x 2 x i64 vector value -def nxv4i64 : ValueType<256, 129>; // n x 4 x i64 vector value -def nxv8i64 : ValueType<512, 130>; // n x 8 x i64 vector value -def nxv16i64: ValueType<1024,131>; // n x 16 x i64 vector value -def nxv32i64: ValueType<2048,132>; // n x 32 x i64 vector value - -def nxv1f16 : ValueType<32, 133>; // n x 1 x f16 vector value -def nxv2f16 : ValueType<32 , 134>; // n x 2 x f16 vector value -def nxv4f16 : ValueType<64 , 135>; // n x 4 x f16 vector value -def nxv8f16 : ValueType<128, 136>; // n x 8 x f16 vector value -def nxv16f16 : ValueType<256,137>; // n x 16 x f16 vector value -def nxv32f16 : ValueType<512,138>; // n x 32 x f16 vector value -def nxv2bf16 : ValueType<32 , 139>; // n x 2 x bf16 vector value -def nxv4bf16 : ValueType<64 , 140>; // n x 4 x bf16 vector value -def nxv8bf16 : ValueType<128, 141>; // n x 8 x bf16 vector value -def nxv1f32 : ValueType<32 , 142>; // n x 1 x f32 vector value -def nxv2f32 : ValueType<64 , 143>; // n x 2 x f32 vector value -def nxv4f32 : ValueType<128, 144>; // n x 4 x f32 vector value -def nxv8f32 : ValueType<256, 145>; // n x 8 x f32 vector value -def nxv16f32 : ValueType<512, 146>; // n x 16 x f32 vector value -def nxv1f64 : ValueType<64, 147>; // n x 1 x f64 vector value -def nxv2f64 : ValueType<128, 148>; // n x 2 x f64 vector value -def nxv4f64 : ValueType<256, 149>; // n x 4 x f64 vector value -def nxv8f64 : ValueType<512, 150>; // n x 8 x f64 vector value - -def x86mmx : ValueType<64 , 151>; // X86 MMX value -def FlagVT : ValueType<0 , 152>; // Pre-RA sched glue -def isVoid : ValueType<0 , 153>; // Produces no value -def untyped: ValueType<8 , 154>; // Produces an untyped value -def exnref : ValueType<0 , 155>; // WebAssembly's exnref type def token : ValueType<0 , 248>; // TokenTy def MetadataVT: ValueType<0, 249>; // Metadata diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/VirtRegMap.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/VirtRegMap.h index 823154318eb7..deef4b90279a 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/VirtRegMap.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/VirtRegMap.h @@ -19,6 +19,7 @@ #include "llvm/ADT/IndexedMap.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/TargetRegisterInfo.h" +#include "llvm/CodeGen/TileShapeInfo.h" #include "llvm/Pass.h" #include @@ -60,6 +61,10 @@ class TargetInstrInfo; /// mapping. IndexedMap Virt2SplitMap; + /// Virt2ShapeMap - For X86 AMX register whose register is bound shape + /// information. + DenseMap Virt2ShapeMap; + /// createSpillSlot - Allocate a spill slot for RC from MFI. unsigned createSpillSlot(const TargetRegisterClass *RC); @@ -98,15 +103,30 @@ class TargetInstrInfo; /// returns the physical register mapped to the specified /// virtual register - Register getPhys(Register virtReg) const { + MCRegister getPhys(Register virtReg) const { assert(virtReg.isVirtual()); - return Virt2PhysMap[virtReg.id()]; + return MCRegister::from(Virt2PhysMap[virtReg.id()]); } /// creates a mapping for the specified virtual register to /// the specified physical register void assignVirt2Phys(Register virtReg, MCPhysReg physReg); + bool isShapeMapEmpty() const { return Virt2ShapeMap.empty(); } + + bool hasShape(Register virtReg) const { + return getShape(virtReg).isValid(); + } + + ShapeT getShape(Register virtReg) const { + assert(virtReg.isVirtual()); + return Virt2ShapeMap.lookup(virtReg); + } + + void assignVirt2Shape(Register virtReg, ShapeT shape) { + Virt2ShapeMap[virtReg.id()] = shape; + } + /// clears the specified virtual register's, physical /// register mapping void clearVirt(Register virtReg) { @@ -131,12 +151,15 @@ class TargetInstrInfo; bool hasKnownPreference(Register VirtReg); /// records virtReg is a split live interval from SReg. - void setIsSplitFromReg(Register virtReg, unsigned SReg) { + void setIsSplitFromReg(Register virtReg, Register SReg) { Virt2SplitMap[virtReg.id()] = SReg; + if (hasShape(SReg)) { + Virt2ShapeMap[virtReg.id()] = getShape(SReg); + } } /// returns the live interval virtReg is split from. - unsigned getPreSplitReg(Register virtReg) const { + Register getPreSplitReg(Register virtReg) const { return Virt2SplitMap[virtReg.id()]; } @@ -144,8 +167,8 @@ class TargetInstrInfo; /// from through splitting. /// A register that was not created by splitting is its own original. /// This operation is idempotent. - unsigned getOriginal(unsigned VirtReg) const { - unsigned Orig = getPreSplitReg(VirtReg); + Register getOriginal(Register VirtReg) const { + Register Orig = getPreSplitReg(VirtReg); return Orig ? Orig : VirtReg; } diff --git a/contrib/llvm-project/llvm/include/llvm/CodeGen/WasmEHFuncInfo.h b/contrib/llvm-project/llvm/include/llvm/CodeGen/WasmEHFuncInfo.h index 41f8856f31f2..54e8c40a9e72 100644 --- a/contrib/llvm-project/llvm/include/llvm/CodeGen/WasmEHFuncInfo.h +++ b/contrib/llvm-project/llvm/include/llvm/CodeGen/WasmEHFuncInfo.h @@ -22,7 +22,9 @@ class BasicBlock; class Function; class MachineBasicBlock; +namespace WebAssembly { enum EventTag { CPP_EXCEPTION = 0, C_LONGJMP = 1 }; +} using BBOrMBB = PointerUnion; diff --git a/contrib/llvm-project/llvm/include/llvm/DWARFLinker/DWARFLinker.h b/contrib/llvm-project/llvm/include/llvm/DWARFLinker/DWARFLinker.h index be3c5ebcadae..7281966fc608 100644 --- a/contrib/llvm-project/llvm/include/llvm/DWARFLinker/DWARFLinker.h +++ b/contrib/llvm-project/llvm/include/llvm/DWARFLinker/DWARFLinker.h @@ -64,14 +64,17 @@ public: /// section. Reset current relocation pointer if neccessary. virtual bool hasValidRelocs(bool ResetRelocsPtr = true) = 0; - /// Checks that there is a relocation against .debug_info - /// table between \p StartOffset and \p NextOffset. - /// - /// This function must be called with offsets in strictly ascending - /// order because it never looks back at relocations it already 'went past'. - /// \returns true and sets Info.InDebugMap if it is the case. - virtual bool hasValidRelocationAt(uint64_t StartOffset, uint64_t EndOffset, - CompileUnit::DIEInfo &Info) = 0; + /// Checks that the specified DIE has a DW_AT_Location attribute + /// that references into a live code section. This function + /// must be called with DIE offsets in strictly ascending order. + virtual bool hasLiveMemoryLocation(const DWARFDie &DIE, + CompileUnit::DIEInfo &Info) = 0; + + /// Checks that the specified DIE has a DW_AT_Low_pc attribute + /// that references into a live code section. This function + /// must be called with DIE offsets in strictly ascending order. + virtual bool hasLiveAddressRange(const DWARFDie &DIE, + CompileUnit::DIEInfo &Info) = 0; /// Apply the valid relocations to the buffer \p Data, taking into /// account that Data is at \p BaseOffset in the debug_info section. @@ -82,6 +85,9 @@ public: virtual bool applyValidRelocs(MutableArrayRef Data, uint64_t BaseOffset, bool IsLittleEndian) = 0; + /// Relocate the given address offset if a valid relocation exists. + virtual llvm::Expected relocateIndexedAddr(uint64_t Offset) = 0; + /// Returns all valid functions address ranges(i.e., those ranges /// which points to sections with code). virtual RangesTy &getValidAddressRanges() = 0; @@ -180,7 +186,8 @@ public: /// /// As a side effect, this also switches the current Dwarf version /// of the MC layer to the one of U.getOrigUnit(). - virtual void emitCompileUnitHeader(CompileUnit &Unit) = 0; + virtual void emitCompileUnitHeader(CompileUnit &Unit, + unsigned DwarfVersion) = 0; /// Recursively emit the DIE tree rooted at \p Die. virtual void emitDIE(DIE &Die) = 0; @@ -202,9 +209,9 @@ using UnitListTy = std::vector>; /// this class represents DWARF information for source file /// and it`s address map. -class DwarfFile { +class DWARFFile { public: - DwarfFile(StringRef Name, DWARFContext *Dwarf, AddressesMap *Addresses, + DWARFFile(StringRef Name, DWARFContext *Dwarf, AddressesMap *Addresses, const std::vector &Warnings) : FileName(Name), Dwarf(Dwarf), Addresses(Addresses), Warnings(Warnings) { } @@ -222,7 +229,7 @@ public: typedef std::function messageHandler; -typedef std::function(StringRef ContainerName, +typedef std::function(StringRef ContainerName, StringRef Path)> objFileLoader; typedef std::map swiftInterfacesMap; @@ -249,7 +256,7 @@ public: : TheDwarfEmitter(Emitter), DwarfLinkerClientID(ClientID) {} /// Add object file to be linked. - void addObjectFile(DwarfFile &File); + void addObjectFile(DWARFFile &File); /// Link debug info for added objFiles. Object /// files are linked all together. @@ -353,36 +360,38 @@ private: /// of work needs to be performed when processing the current item. The flags /// and info fields are optional based on the type. struct WorklistItem { - WorklistItemType Type; DWARFDie Die; + WorklistItemType Type; CompileUnit &CU; unsigned Flags; - unsigned AncestorIdx = 0; - CompileUnit::DIEInfo *OtherInfo = nullptr; + union { + const unsigned AncestorIdx; + CompileUnit::DIEInfo *OtherInfo; + }; WorklistItem(DWARFDie Die, CompileUnit &CU, unsigned Flags, WorklistItemType T = WorklistItemType::LookForDIEsToKeep) - : Type(T), Die(Die), CU(CU), Flags(Flags) {} + : Die(Die), Type(T), CU(CU), Flags(Flags), AncestorIdx(0) {} WorklistItem(DWARFDie Die, CompileUnit &CU, WorklistItemType T, CompileUnit::DIEInfo *OtherInfo = nullptr) - : Type(T), Die(Die), CU(CU), OtherInfo(OtherInfo) {} + : Die(Die), Type(T), CU(CU), Flags(0), OtherInfo(OtherInfo) {} WorklistItem(unsigned AncestorIdx, CompileUnit &CU, unsigned Flags) - : Type(WorklistItemType::LookForParentDIEsToKeep), CU(CU), Flags(Flags), - AncestorIdx(AncestorIdx) {} + : Die(), Type(WorklistItemType::LookForParentDIEsToKeep), CU(CU), + Flags(Flags), AncestorIdx(AncestorIdx) {} }; /// returns true if we need to translate strings. bool needToTranslateStrings() { return StringsTranslator != nullptr; } - void reportWarning(const Twine &Warning, const DwarfFile &File, + void reportWarning(const Twine &Warning, const DWARFFile &File, const DWARFDie *DIE = nullptr) const { if (Options.WarningHandler != nullptr) Options.WarningHandler(Warning, File.FileName, DIE); } - void reportError(const Twine &Warning, const DwarfFile &File, + void reportError(const Twine &Warning, const DWARFFile &File, const DWARFDie *DIE = nullptr) const { if (Options.ErrorHandler != nullptr) Options.ErrorHandler(Warning, File.FileName, DIE); @@ -398,18 +407,18 @@ private: void updateAccelKind(DWARFContext &Dwarf); /// Emit warnings as Dwarf compile units to leave a trail after linking. - bool emitPaperTrailWarnings(const DwarfFile &File, + bool emitPaperTrailWarnings(const DWARFFile &File, OffsetsStringPool &StringPool); void copyInvariantDebugSection(DWARFContext &Dwarf); /// Keeps track of data associated with one object during linking. struct LinkContext { - DwarfFile &File; + DWARFFile &File; UnitListTy CompileUnits; bool Skip = false; - LinkContext(DwarfFile &File) : File(File) {} + LinkContext(DWARFFile &File) : File(File) {} /// Clear part of the context that's no longer needed when we're done with /// the debug object. @@ -438,7 +447,7 @@ private: /// kept. All DIEs referenced though attributes should be kept. void lookForRefDIEsToKeep(const DWARFDie &Die, CompileUnit &CU, unsigned Flags, const UnitListTy &Units, - const DwarfFile &File, + const DWARFFile &File, SmallVectorImpl &Worklist); /// \defgroup FindRootDIEs Find DIEs corresponding to Address map entries. @@ -450,7 +459,7 @@ private: /// The return value indicates whether the DIE is incomplete. void lookForDIEsToKeep(AddressesMap &RelocMgr, RangesTy &Ranges, const UnitListTy &Units, const DWARFDie &DIE, - const DwarfFile &File, CompileUnit &CU, + const DWARFFile &File, CompileUnit &CU, unsigned Flags); /// If this compile unit is really a skeleton CU that points to a @@ -460,9 +469,8 @@ private: /// pointing to the module, and a DW_AT_gnu_dwo_id with the module /// hash. bool registerModuleReference(DWARFDie CUDie, const DWARFUnit &Unit, - const DwarfFile &File, + const DWARFFile &File, OffsetsStringPool &OffsetsStringPool, - UniquingStringPool &UniquingStringPoolStringPool, DeclContextTree &ODRContexts, uint64_t ModulesEndOffset, unsigned &UnitID, bool IsLittleEndian, unsigned Indent = 0, @@ -473,9 +481,8 @@ private: /// to Units. Error loadClangModule(DWARFDie CUDie, StringRef FilePath, StringRef ModuleName, uint64_t DwoId, - const DwarfFile &File, + const DWARFFile &File, OffsetsStringPool &OffsetsStringPool, - UniquingStringPool &UniquingStringPool, DeclContextTree &ODRContexts, uint64_t ModulesEndOffset, unsigned &UnitID, bool IsLittleEndian, unsigned Indent = 0, bool Quiet = false); @@ -484,22 +491,21 @@ private: void keepDIEAndDependencies(AddressesMap &RelocMgr, RangesTy &Ranges, const UnitListTy &Units, const DWARFDie &DIE, CompileUnit::DIEInfo &MyInfo, - const DwarfFile &File, CompileUnit &CU, + const DWARFFile &File, CompileUnit &CU, bool UseODR); unsigned shouldKeepDIE(AddressesMap &RelocMgr, RangesTy &Ranges, - const DWARFDie &DIE, const DwarfFile &File, + const DWARFDie &DIE, const DWARFFile &File, CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo, unsigned Flags); /// Check if a variable describing DIE should be kept. /// \returns updated TraversalFlags. unsigned shouldKeepVariableDIE(AddressesMap &RelocMgr, const DWARFDie &DIE, - CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo, unsigned Flags); unsigned shouldKeepSubprogramDIE(AddressesMap &RelocMgr, RangesTy &Ranges, - const DWARFDie &DIE, const DwarfFile &File, + const DWARFDie &DIE, const DWARFFile &File, CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo, unsigned Flags); @@ -508,7 +514,7 @@ private: /// RefValue. The resulting DIE might be in another CompileUnit which is /// stored into \p ReferencedCU. \returns null if resolving fails for any /// reason. - DWARFDie resolveDIEReference(const DwarfFile &File, const UnitListTy &Units, + DWARFDie resolveDIEReference(const DWARFFile &File, const UnitListTy &Units, const DWARFFormValue &RefValue, const DWARFDie &DIE, CompileUnit *&RefCU); @@ -523,7 +529,7 @@ private: class DIECloner { DWARFLinker &Linker; DwarfEmitter *Emitter; - DwarfFile &ObjFile; + DWARFFile &ObjFile; /// Allocator used for all the DIEValue objects. BumpPtrAllocator &DIEAlloc; @@ -533,7 +539,7 @@ private: bool Update; public: - DIECloner(DWARFLinker &Linker, DwarfEmitter *Emitter, DwarfFile &ObjFile, + DIECloner(DWARFLinker &Linker, DwarfEmitter *Emitter, DWARFFile &ObjFile, BumpPtrAllocator &DIEAlloc, std::vector> &CompileUnits, bool Update) @@ -551,7 +557,7 @@ private: /// applied to the entry point of the function to get the linked address. /// \param Die the output DIE to use, pass NULL to create one. /// \returns the root of the cloned tree or null if nothing was selected. - DIE *cloneDIE(const DWARFDie &InputDIE, const DwarfFile &File, + DIE *cloneDIE(const DWARFDie &InputDIE, const DWARFFile &File, CompileUnit &U, OffsetsStringPool &StringPool, int64_t PCOffset, uint32_t OutOffset, unsigned Flags, bool IsLittleEndian, DIE *Die = nullptr); @@ -560,7 +566,7 @@ private: /// chose to keep above. If there are no valid relocs, then there's /// nothing to clone/emit. uint64_t cloneAllCompileUnits(DWARFContext &DwarfContext, - const DwarfFile &File, + const DWARFFile &File, OffsetsStringPool &StringPool, bool IsLittleEndian); @@ -606,7 +612,7 @@ private: /// Helper for cloneDIE. unsigned cloneAttribute(DIE &Die, const DWARFDie &InputDIE, - const DwarfFile &File, CompileUnit &U, + const DWARFFile &File, CompileUnit &U, OffsetsStringPool &StringPool, const DWARFFormValue &Val, const AttributeSpec AttrSpec, unsigned AttrSize, @@ -627,18 +633,18 @@ private: AttributeSpec AttrSpec, unsigned AttrSize, const DWARFFormValue &Val, - const DwarfFile &File, + const DWARFFile &File, CompileUnit &Unit); /// Clone a DWARF expression that may be referencing another DIE. void cloneExpression(DataExtractor &Data, DWARFExpression Expression, - const DwarfFile &File, CompileUnit &Unit, + const DWARFFile &File, CompileUnit &Unit, SmallVectorImpl &OutputBuffer); /// Clone an attribute referencing another DIE and add /// it to \p Die. /// \returns the size of the new attribute. - unsigned cloneBlockAttribute(DIE &Die, const DwarfFile &File, + unsigned cloneBlockAttribute(DIE &Die, const DWARFFile &File, CompileUnit &Unit, AttributeSpec AttrSpec, const DWARFFormValue &Val, unsigned AttrSize, bool IsLittleEndian); @@ -654,7 +660,7 @@ private: /// Clone a scalar attribute and add it to \p Die. /// \returns the size of the new attribute. unsigned cloneScalarAttribute(DIE &Die, const DWARFDie &InputDIE, - const DwarfFile &File, CompileUnit &U, + const DWARFFile &File, CompileUnit &U, AttributeSpec AttrSpec, const DWARFFormValue &Val, unsigned AttrSize, AttributesInfo &Info); @@ -670,7 +676,7 @@ private: void copyAbbrev(const DWARFAbbreviationDeclaration &Abbrev, bool hasODR); uint32_t hashFullyQualifiedName(DWARFDie DIE, CompileUnit &U, - const DwarfFile &File, + const DWARFFile &File, int RecurseDepth = 0); /// Helper for cloneDIE. @@ -685,7 +691,7 @@ private: /// Compute and emit debug_ranges section for \p Unit, and /// patch the attributes referencing it. void patchRangesForUnit(const CompileUnit &Unit, DWARFContext &Dwarf, - const DwarfFile &File) const; + const DWARFFile &File) const; /// Generate and emit the DW_AT_ranges attribute for a compile_unit if it had /// one. @@ -695,7 +701,7 @@ private: /// parts according to the linked function ranges and emit the result in the /// debug_line section. void patchLineTableForUnit(CompileUnit &Unit, DWARFContext &OrigDwarf, - const DwarfFile &File); + const DWARFFile &File); /// Emit the accelerator entries for \p Unit. void emitAcceleratorEntriesForUnit(CompileUnit &Unit); @@ -703,7 +709,7 @@ private: void emitAppleAcceleratorEntriesForUnit(CompileUnit &Unit); /// Patch the frame info for an object file and emit it. - void patchFrameInfoForObject(const DwarfFile &, RangesTy &Ranges, + void patchFrameInfoForObject(const DWARFFile &, RangesTy &Ranges, DWARFContext &, unsigned AddressSize); /// FoldingSet that uniques the abbreviations. diff --git a/contrib/llvm-project/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h b/contrib/llvm-project/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h index 944e7e3501c9..a6310bcb5df1 100644 --- a/contrib/llvm-project/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h +++ b/contrib/llvm-project/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h @@ -101,10 +101,7 @@ public: unsigned getUniqueID() const { return ID; } - void createOutputDIE() { - NewUnit.emplace(OrigUnit.getVersion(), OrigUnit.getAddressByteSize(), - OrigUnit.getUnitDIE().getTag()); - } + void createOutputDIE() { NewUnit.emplace(OrigUnit.getUnitDIE().getTag()); } DIE *getOutputUnitDIE() const { if (NewUnit) @@ -123,6 +120,11 @@ public: DIEInfo &getInfo(unsigned Idx) { return Info[Idx]; } const DIEInfo &getInfo(unsigned Idx) const { return Info[Idx]; } + DIEInfo &getInfo(const DWARFDie &Die) { + unsigned Idx = getOrigUnit().getDIEIndex(Die); + return Info[Idx]; + } + uint64_t getStartOffset() const { return StartOffset; } uint64_t getNextUnitOffset() const { return NextUnitOffset; } void setStartOffset(uint64_t DebugInfoSize) { StartOffset = DebugInfoSize; } @@ -157,7 +159,7 @@ public: /// Compute the end offset for this unit. Must be called after the CU's DIEs /// have been cloned. \returns the next unit offset (which is also the /// current debug_info section size). - uint64_t computeNextUnitOffset(); + uint64_t computeNextUnitOffset(uint16_t DwarfVersion); /// Keep track of a forward reference to DIE \p Die in \p RefUnit by \p /// Attr. The attribute should be fixed up later to point to the absolute @@ -235,21 +237,6 @@ public: const std::vector &getNamespaces() const { return Namespaces; } const std::vector &getObjC() const { return ObjC; } - /// Get the full path for file \a FileNum in the line table - StringRef getResolvedPath(unsigned FileNum) { - if (FileNum >= ResolvedPaths.size()) - return StringRef(); - return ResolvedPaths[FileNum]; - } - - /// Set the fully resolved path for the line-table's file \a FileNum - /// to \a Path. - void setResolvedPath(unsigned FileNum, StringRef Path) { - if (ResolvedPaths.size() <= FileNum) - ResolvedPaths.resize(FileNum + 1); - ResolvedPaths[FileNum] = Path; - } - MCSymbol *getLabelBegin() { return LabelBegin; } void setLabelBegin(MCSymbol *S) { LabelBegin = S; } @@ -308,12 +295,6 @@ private: std::vector ObjC; /// @} - /// Cached resolved paths from the line table. - /// Note, the StringRefs here point in to the intern (uniquing) string pool. - /// This means that a StringRef returned here doesn't need to then be uniqued - /// for the purposes of getting a unique address for each string. - std::vector ResolvedPaths; - /// Is this unit subject to the ODR rule? bool HasODR; diff --git a/contrib/llvm-project/llvm/include/llvm/DWARFLinker/DWARFLinkerDeclContext.h b/contrib/llvm-project/llvm/include/llvm/DWARFLinker/DWARFLinkerDeclContext.h index e59e15f00a7e..d2274488e85f 100644 --- a/contrib/llvm-project/llvm/include/llvm/DWARFLinker/DWARFLinkerDeclContext.h +++ b/contrib/llvm-project/llvm/include/llvm/DWARFLinker/DWARFLinkerDeclContext.h @@ -15,6 +15,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/CodeGen/NonRelocatableStringpool.h" #include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" @@ -31,16 +32,18 @@ class CachedPathResolver { public: /// Resolve a path by calling realpath and cache its result. The returned /// StringRef is interned in the given \p StringPool. - StringRef resolve(std::string Path, NonRelocatableStringpool &StringPool) { + StringRef resolve(const std::string &Path, + NonRelocatableStringpool &StringPool) { StringRef FileName = sys::path::filename(Path); - SmallString<256> ParentPath = sys::path::parent_path(Path); + StringRef ParentPath = sys::path::parent_path(Path); // If the ParentPath has not yet been resolved, resolve and cache it for // future look-ups. if (!ResolvedPaths.count(ParentPath)) { SmallString<256> RealPath; sys::fs::real_path(ParentPath, RealPath); - ResolvedPaths.insert({ParentPath, StringRef(RealPath).str()}); + ResolvedPaths.insert( + {ParentPath, std::string(RealPath.c_str(), RealPath.size())}); } // Join the file name again with the resolved path. @@ -95,7 +98,6 @@ public: void setDefinedInClangModule(bool Val) { DefinedInClangModule = Val; } uint16_t getTag() const { return Tag; } - StringRef getName() const { return Name; } private: friend DeclMapInfo; @@ -129,10 +131,10 @@ public: /// /// FIXME: The invalid bit along the return value is to emulate some /// dsymutil-classic functionality. - PointerIntPair - getChildDeclContext(DeclContext &Context, const DWARFDie &DIE, - CompileUnit &Unit, UniquingStringPool &StringPool, - bool InClangModule); + PointerIntPair getChildDeclContext(DeclContext &Context, + const DWARFDie &DIE, + CompileUnit &Unit, + bool InClangModule); DeclContext &getRoot() { return Root; } @@ -141,8 +143,19 @@ private: DeclContext Root; DeclContext::Map Contexts; - /// Cache resolved paths from the line table. + /// Cached resolved paths from the line table. + /// The key is . + using ResolvedPathsMap = DenseMap, StringRef>; + ResolvedPathsMap ResolvedPaths; + + /// Helper that resolves and caches fragments of file paths. CachedPathResolver PathResolver; + + /// String pool keeping real path bodies. + NonRelocatableStringpool StringPool; + + StringRef getResolvedPath(CompileUnit &CU, unsigned FileNum, + const DWARFDebugLine::LineTable &LineTable); }; /// Info type for the DenseMap storing the DeclContext pointers. diff --git a/contrib/llvm-project/llvm/include/llvm/DWARFLinker/DWARFStreamer.h b/contrib/llvm-project/llvm/include/llvm/DWARFLinker/DWARFStreamer.h index de58f5dedf24..7b0851159252 100644 --- a/contrib/llvm-project/llvm/include/llvm/DWARFLinker/DWARFStreamer.h +++ b/contrib/llvm-project/llvm/include/llvm/DWARFLinker/DWARFStreamer.h @@ -64,7 +64,7 @@ public: /// /// As a side effect, this also switches the current Dwarf version /// of the MC layer to the one of U.getOrigUnit(). - void emitCompileUnitHeader(CompileUnit &Unit) override; + void emitCompileUnitHeader(CompileUnit &Unit, unsigned DwarfVersion) override; /// Recursively emit the DIE tree rooted at \p Die. void emitDIE(DIE &Die) override; diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h index 784c47e3bf5d..bb29ef5f2ce8 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h @@ -11,9 +11,9 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Optional.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/CodeViewError.h" #include "llvm/DebugInfo/CodeView/RecordSerialization.h" -#include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/BinaryStreamRef.h" #include "llvm/Support/Endian.h" @@ -61,12 +61,9 @@ public: ArrayRef RecordData; }; -template struct RemappedRecord { - explicit RemappedRecord(const CVRecord &R) : OriginalRecord(R) {} - - CVRecord OriginalRecord; - SmallVector, 8> Mappings; -}; +// There are two kinds of codeview records: type and symbol records. +using CVType = CVRecord; +using CVSymbol = CVRecord; template Error forEachCodeViewRecord(ArrayRef StreamBuffer, Func F) { @@ -126,6 +123,12 @@ struct VarStreamArrayExtractor> { } }; +namespace codeview { +using CVSymbolArray = VarStreamArray; +using CVTypeArray = VarStreamArray; +using CVTypeRange = iterator_range; +} // namespace codeview + } // end namespace llvm #endif // LLVM_DEBUGINFO_CODEVIEW_RECORDITERATOR_H diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h index 1615ff41df12..82ef8c173bee 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h @@ -10,9 +10,6 @@ #define LLVM_DEBUGINFO_CODEVIEW_CVSYMBOLVISITOR_H #include "llvm/DebugInfo/CodeView/CVRecord.h" -#include "llvm/DebugInfo/CodeView/CodeView.h" -#include "llvm/DebugInfo/CodeView/SymbolRecord.h" -#include "llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h" #include "llvm/Support/ErrorOr.h" namespace llvm { diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h index f26e80ebe2a9..d851dea0a27f 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h @@ -15,7 +15,8 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/DebugInfo/CodeView/CodeViewError.h" -#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/GUID.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/BinaryStreamWriter.h" #include "llvm/Support/Error.h" diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def index ed5c143818e6..48ea7e52c172 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def @@ -15,6 +15,7 @@ #endif #if !defined(CV_REGISTERS_ALL) && !defined(CV_REGISTERS_X86) && \ + !defined(CV_REGISTERS_ARM) && \ !defined(CV_REGISTERS_ARM64) #error Need include at least one register set. #endif @@ -393,13 +394,46 @@ CV_REGISTER(ARM_PC, 25) // Status register -CV_REGISTER(ARM_CPSR, 25) +CV_REGISTER(ARM_CPSR, 26) // ARM VFPv1 registers CV_REGISTER(ARM_FPSCR, 40) CV_REGISTER(ARM_FPEXC, 41) +CV_REGISTER(ARM_FS0, 50) +CV_REGISTER(ARM_FS1, 51) +CV_REGISTER(ARM_FS2, 52) +CV_REGISTER(ARM_FS3, 53) +CV_REGISTER(ARM_FS4, 54) +CV_REGISTER(ARM_FS5, 55) +CV_REGISTER(ARM_FS6, 56) +CV_REGISTER(ARM_FS7, 57) +CV_REGISTER(ARM_FS8, 58) +CV_REGISTER(ARM_FS9, 59) +CV_REGISTER(ARM_FS10, 60) +CV_REGISTER(ARM_FS11, 61) +CV_REGISTER(ARM_FS12, 62) +CV_REGISTER(ARM_FS13, 63) +CV_REGISTER(ARM_FS14, 64) +CV_REGISTER(ARM_FS15, 65) +CV_REGISTER(ARM_FS16, 66) +CV_REGISTER(ARM_FS17, 67) +CV_REGISTER(ARM_FS18, 68) +CV_REGISTER(ARM_FS19, 69) +CV_REGISTER(ARM_FS20, 70) +CV_REGISTER(ARM_FS21, 71) +CV_REGISTER(ARM_FS22, 72) +CV_REGISTER(ARM_FS23, 73) +CV_REGISTER(ARM_FS24, 74) +CV_REGISTER(ARM_FS25, 75) +CV_REGISTER(ARM_FS26, 76) +CV_REGISTER(ARM_FS27, 77) +CV_REGISTER(ARM_FS28, 78) +CV_REGISTER(ARM_FS29, 79) +CV_REGISTER(ARM_FS30, 80) +CV_REGISTER(ARM_FS31, 81) + // ARM VFPv3/NEON registers CV_REGISTER(ARM_FS32, 200) diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h index 720b1b49581f..624a623e75b8 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h @@ -10,10 +10,8 @@ #define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENTVISITOR_H #include "llvm/DebugInfo/CodeView/CodeView.h" -#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" #include "llvm/DebugInfo/CodeView/StringsAndChecksums.h" #include "llvm/Support/Error.h" -#include namespace llvm { @@ -30,7 +28,6 @@ class DebugStringTableSubsectionRef; class DebugSymbolRVASubsectionRef; class DebugSymbolsSubsectionRef; class DebugUnknownSubsectionRef; -class StringsAndChecksumsRef; class DebugSubsectionVisitor { public: diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h index 784fc59484b9..51b8523ed969 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h @@ -9,8 +9,8 @@ #ifndef LLVM_DEBUGINFO_CODEVIEW_DEBUGSYMBOLSSUBSECTION_H #define LLVM_DEBUGINFO_CODEVIEW_DEBUGSYMBOLSSUBSECTION_H +#include "llvm/DebugInfo/CodeView/CVRecord.h" #include "llvm/DebugInfo/CodeView/DebugSubsection.h" -#include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/Support/Error.h" namespace llvm { diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h index 35eeef5a327e..ddbb4e3c5e6c 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h @@ -14,7 +14,6 @@ #include "llvm/ADT/StringRef.h" #include "llvm/DebugInfo/CodeView/TypeCollection.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" -#include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/BinaryStreamArray.h" #include "llvm/Support/Error.h" diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/RecordName.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/RecordName.h index cc09db8933bd..8e06be9e41e8 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/RecordName.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/RecordName.h @@ -9,7 +9,6 @@ #ifndef LLVM_DEBUGINFO_CODEVIEW_RECORDNAME_H #define LLVM_DEBUGINFO_CODEVIEW_RECORDNAME_H -#include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/CodeView/TypeCollection.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h index d832a48b1265..aaeffb2446ad 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h @@ -11,8 +11,8 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringSet.h" +#include "llvm/DebugInfo/CodeView/CVRecord.h" #include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h" -#include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" namespace llvm { diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h index 4383534b0db2..c37f6b4d5fa7 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h @@ -1003,9 +1003,6 @@ public: uint32_t RecordOffset = 0; }; -using CVSymbol = CVRecord; -using CVSymbolArray = VarStreamArray; - Expected readSymbolFromStream(BinaryStreamRef Stream, uint32_t Offset); diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/SymbolRecordHelpers.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/SymbolRecordHelpers.h index 57dbc56c0769..71bc70dde6ed 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/SymbolRecordHelpers.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/SymbolRecordHelpers.h @@ -9,7 +9,8 @@ #ifndef LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORDHELPERS_H #define LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORDHELPERS_H -#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/CodeView/CVRecord.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" namespace llvm { namespace codeview { diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/TypeCollection.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/TypeCollection.h index 102d68c3fb2a..bde5a8b3ab2f 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/TypeCollection.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/TypeCollection.h @@ -10,9 +10,8 @@ #define LLVM_DEBUGINFO_CODEVIEW_TYPECOLLECTION_H #include "llvm/ADT/StringRef.h" - +#include "llvm/DebugInfo/CodeView/CVRecord.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" -#include "llvm/DebugInfo/CodeView/TypeRecord.h" namespace llvm { namespace codeview { diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/TypeHashing.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/TypeHashing.h index b0a16cccbff3..9f34d026b1ba 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/TypeHashing.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/TypeHashing.h @@ -86,6 +86,16 @@ struct GloballyHashedType { bool empty() const { return *(const uint64_t*)Hash.data() == 0; } + friend inline bool operator==(const GloballyHashedType &L, + const GloballyHashedType &R) { + return L.Hash == R.Hash; + } + + friend inline bool operator!=(const GloballyHashedType &L, + const GloballyHashedType &R) { + return !(L.Hash == R.Hash); + } + /// Given a sequence of bytes representing a record, compute a global hash for /// this record. Due to the nature of global hashes incorporating the hashes /// of referenced records, this function requires a list of types and ids @@ -161,15 +171,10 @@ struct GloballyHashedType { return Hashes; } }; -#if defined(_MSC_VER) -// is_trivially_copyable is not available in older versions of libc++, but it is -// available in all supported versions of MSVC, so at least this gives us some -// coverage. static_assert(std::is_trivially_copyable::value, "GloballyHashedType must be trivially copyable so that we can " "reinterpret_cast arrays of hash data to arrays of " "GloballyHashedType"); -#endif } // namespace codeview template <> struct DenseMapInfo { @@ -206,7 +211,7 @@ template <> struct DenseMapInfo { static bool isEqual(codeview::GloballyHashedType LHS, codeview::GloballyHashedType RHS) { - return LHS.Hash == RHS.Hash; + return LHS == RHS; } }; diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/TypeIndex.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/TypeIndex.h index b9e2562bfc2b..bdc6cf46509b 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/TypeIndex.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/TypeIndex.h @@ -116,13 +116,22 @@ public: uint32_t toArrayIndex() const { assert(!isSimple()); - return getIndex() - FirstNonSimpleIndex; + return (getIndex() & ~DecoratedItemIdMask) - FirstNonSimpleIndex; } static TypeIndex fromArrayIndex(uint32_t Index) { return TypeIndex(Index + FirstNonSimpleIndex); } + static TypeIndex fromDecoratedArrayIndex(bool IsItem, uint32_t Index) { + return TypeIndex((Index + FirstNonSimpleIndex) | + (IsItem ? DecoratedItemIdMask : 0)); + } + + TypeIndex removeDecoration() { + return TypeIndex(Index & ~DecoratedItemIdMask); + } + SimpleTypeKind getSimpleKind() const { assert(isSimple()); return static_cast(Index & SimpleKindMask); diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h index 469768787274..f4f5835d8b57 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h @@ -10,8 +10,8 @@ #define LLVM_DEBUGINFO_CODEVIEW_TYPEINDEXDISCOVERY_H #include "llvm/ADT/SmallVector.h" -#include "llvm/DebugInfo/CodeView/SymbolRecord.h" -#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/CVRecord.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/Support/Error.h" namespace llvm { diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h index 35f5c0561138..3b6d1b0b1a70 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h @@ -14,7 +14,6 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/iterator_range.h" #include "llvm/DebugInfo/CodeView/CVRecord.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/GUID.h" @@ -32,15 +31,10 @@ using support::little32_t; using support::ulittle16_t; using support::ulittle32_t; -using CVType = CVRecord; -using RemappedType = RemappedRecord; - struct CVMemberRecord { TypeLeafKind Kind; ArrayRef Data; }; -using CVTypeArray = VarStreamArray; -using CVTypeRange = iterator_range; /// Equvalent to CV_fldattr_t in cvinfo.h. struct MemberAttributes { @@ -703,7 +697,7 @@ public: : TypeRecord(TypeRecordKind::VFTable), CompleteClass(CompleteClass), OverriddenVFTable(OverriddenVFTable), VFPtrOffset(VFPtrOffset) { MethodNames.push_back(Name); - MethodNames.insert(MethodNames.end(), Methods.begin(), Methods.end()); + llvm::append_range(MethodNames, Methods); } TypeIndex getCompleteClass() const { return CompleteClass; } diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/TypeRecordHelpers.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/TypeRecordHelpers.h index 19492b93681c..041f5214967c 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/TypeRecordHelpers.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/TypeRecordHelpers.h @@ -9,7 +9,8 @@ #ifndef LLVM_DEBUGINFO_CODEVIEW_TYPERECORDHELPERS_H #define LLVM_DEBUGINFO_CODEVIEW_TYPERECORDHELPERS_H -#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/CVRecord.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" namespace llvm { namespace codeview { diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h index d0506cce8176..04d7c7b0420a 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h @@ -11,7 +11,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/CVRecord.h" #include "llvm/Support/Error.h" namespace llvm { diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/DIContext.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/DIContext.h index 661d30d04c94..ae78fe912188 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/DIContext.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/DIContext.h @@ -35,6 +35,7 @@ struct DILineInfo { static constexpr const char *const Addr2LineBadString = "??"; std::string FileName; std::string FunctionName; + std::string StartFileName; Optional Source; uint32_t Line = 0; uint32_t Column = 0; @@ -43,12 +44,15 @@ struct DILineInfo { // DWARF-specific. uint32_t Discriminator = 0; - DILineInfo() : FileName(BadString), FunctionName(BadString) {} + DILineInfo() + : FileName(BadString), FunctionName(BadString), StartFileName(BadString) { + } bool operator==(const DILineInfo &RHS) const { return Line == RHS.Line && Column == RHS.Column && FileName == RHS.FileName && FunctionName == RHS.FunctionName && - StartLine == RHS.StartLine && Discriminator == RHS.Discriminator; + StartFileName == RHS.StartFileName && StartLine == RHS.StartLine && + Discriminator == RHS.Discriminator; } bool operator!=(const DILineInfo &RHS) const { @@ -56,10 +60,10 @@ struct DILineInfo { } bool operator<(const DILineInfo &RHS) const { - return std::tie(FileName, FunctionName, Line, Column, StartLine, - Discriminator) < - std::tie(RHS.FileName, RHS.FunctionName, RHS.Line, RHS.Column, - RHS.StartLine, RHS.Discriminator); + return std::tie(FileName, FunctionName, StartFileName, Line, Column, + StartLine, Discriminator) < + std::tie(RHS.FileName, RHS.FunctionName, RHS.StartFileName, RHS.Line, + RHS.Column, RHS.StartLine, RHS.Discriminator); } explicit operator bool() const { return *this != DILineInfo(); } @@ -72,6 +76,8 @@ struct DILineInfo { OS << "function '" << FunctionName << "', "; OS << "line " << Line << ", "; OS << "column " << Column << ", "; + if (StartFileName != BadString) + OS << "start file '" << StartFileName << "', "; OS << "start line " << StartLine << '\n'; } }; diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h index 39ae53c4e7fe..cf4c827b9267 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h @@ -111,6 +111,16 @@ public: return AttributeSpecs[idx].Attr; } + bool getAttrIsImplicitConstByIndex(uint32_t idx) const { + assert(idx < AttributeSpecs.size()); + return AttributeSpecs[idx].isImplicitConst(); + } + + int64_t getAttrImplicitConstValueByIndex(uint32_t idx) const { + assert(idx < AttributeSpecs.size()); + return AttributeSpecs[idx].getImplicitConstValue(); + } + /// Get the index of the specified attribute. /// /// Searches the this abbreviation declaration for the index of the specified diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h index 97903a96b3fc..7d88e1447dca 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -146,6 +146,7 @@ public: bool verify(raw_ostream &OS, DIDumpOptions DumpOpts = {}) override; using unit_iterator_range = DWARFUnitVector::iterator_range; + using compile_unit_range = DWARFUnitVector::compile_unit_range; /// Get units from .debug_info in this context. unit_iterator_range info_section_units() { @@ -163,10 +164,12 @@ public: } /// Get compile units in this context. - unit_iterator_range compile_units() { return info_section_units(); } + compile_unit_range compile_units() { + return make_filter_range(info_section_units(), isCompileUnit); + } - /// Get type units in this context. - unit_iterator_range type_units() { return types_section_units(); } + // If you want type_units(), it'll need to be a concat iterator of a filter of + // TUs in info_section + all the (all type) units in types_section /// Get all normal compile/type units in this context. unit_iterator_range normal_units() { @@ -189,10 +192,13 @@ public: } /// Get compile units in the DWO context. - unit_iterator_range dwo_compile_units() { return dwo_info_section_units(); } + compile_unit_range dwo_compile_units() { + return make_filter_range(dwo_info_section_units(), isCompileUnit); + } - /// Get type units in the DWO context. - unit_iterator_range dwo_type_units() { return dwo_types_section_units(); } + // If you want dwo_type_units(), it'll need to be a concat iterator of a + // filter of TUs in dwo_info_section + all the (all type) units in + // dwo_types_section. /// Get all units in the DWO context. unit_iterator_range dwo_units() { diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugAddr.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugAddr.h index 32844ffd570f..69e67866946c 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugAddr.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugAddr.h @@ -74,6 +74,24 @@ public: /// Return the full length of this table, including the length field. /// Return None if the length cannot be identified reliably. Optional getFullLength() const; + + /// Return the DWARF format of this table. + dwarf::DwarfFormat getFormat() const { return Format; } + + /// Return the length of this table. + uint64_t getLength() const { return Length; } + + /// Return the version of this table. + uint16_t getVersion() const { return Version; } + + /// Return the address size of this table. + uint8_t getAddressSize() const { return AddrSize; } + + /// Return the segment selector size of this table. + uint8_t getSegmentSelectorSize() const { return SegSize; } + + /// Return the parsed addresses of this table. + ArrayRef getAddressEntries() const { return Addrs; } }; } // end namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h index 0681a2e33a50..3d5852ee1518 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h @@ -60,7 +60,8 @@ public: DWARFDebugArangeSet() { clear(); } void clear(); - Error extract(DWARFDataExtractor data, uint64_t *offset_ptr); + Error extract(DWARFDataExtractor data, uint64_t *offset_ptr, + function_ref WarningHandler); void dump(raw_ostream &OS) const; uint64_t getCompileUnitDIEOffset() const { return HeaderData.CuOffset; } diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h index 233b55cc55c1..af87811f5d7d 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h @@ -71,8 +71,8 @@ public: /// where a problem occurred in case an error is returned. Error parse(DWARFDataExtractor Data, uint64_t *Offset, uint64_t EndOffset); - void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, - unsigned IndentLevel = 1) const; + void dump(raw_ostream &OS, DIDumpOptions DumpOpts, const MCRegisterInfo *MRI, + bool IsEH, unsigned IndentLevel = 1) const; private: std::vector Instructions; @@ -121,7 +121,8 @@ private: static ArrayRef getOperandTypes(); /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand. - void printOperand(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, + void printOperand(raw_ostream &OS, DIDumpOptions DumpOpts, + const MCRegisterInfo *MRI, bool IsEH, const Instruction &Instr, unsigned OperandIdx, uint64_t Operand) const; }; @@ -146,8 +147,8 @@ public: CFIProgram &cfis() { return CFIs; } /// Dump the instructions in this CFI fragment - virtual void dump(raw_ostream &OS, const MCRegisterInfo *MRI, - bool IsEH) const = 0; + virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts, + const MCRegisterInfo *MRI, bool IsEH) const = 0; protected: const FrameKind Kind; @@ -201,7 +202,7 @@ public: uint32_t getLSDAPointerEncoding() const { return LSDAPointerEncoding; } - void dump(raw_ostream &OS, const MCRegisterInfo *MRI, + void dump(raw_ostream &OS, DIDumpOptions DumpOpts, const MCRegisterInfo *MRI, bool IsEH) const override; private: @@ -242,7 +243,7 @@ public: uint64_t getAddressRange() const { return AddressRange; } Optional getLSDAAddress() const { return LSDAAddress; } - void dump(raw_ostream &OS, const MCRegisterInfo *MRI, + void dump(raw_ostream &OS, DIDumpOptions DumpOpts, const MCRegisterInfo *MRI, bool IsEH) const override; static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_FDE; } @@ -285,7 +286,7 @@ public: ~DWARFDebugFrame(); /// Dump the section data into the given stream. - void dump(raw_ostream &OS, const MCRegisterInfo *MRI, + void dump(raw_ostream &OS, DIDumpOptions DumpOpts, const MCRegisterInfo *MRI, Optional Offset) const; /// Parse the section from raw data. \p Data is assumed to contain the whole diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h index fe46d613aedd..bc6c67ae6c5d 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h @@ -121,6 +121,8 @@ public: bool hasFileAtIndex(uint64_t FileIndex) const; + Optional getLastValidFileIndex() const; + bool getFileNameByIndex(uint64_t FileIndex, StringRef CompDir, DILineInfoSpecifier::FileLineInfoKind Kind, @@ -251,6 +253,10 @@ public: return Prologue.hasFileAtIndex(FileIndex); } + Optional getLastValidFileIndex() const { + return Prologue.getLastValidFileIndex(); + } + /// Extracts filename by its index in filename table in prologue. /// In Dwarf 4, the files are 1-indexed and the current compilation file /// name is not represented in the list. In DWARF v5, the files are @@ -309,12 +315,10 @@ public: /// Helper to allow for parsing of an entire .debug_line section in sequence. class SectionParser { public: - using cu_range = DWARFUnitVector::iterator_range; - using tu_range = DWARFUnitVector::iterator_range; using LineToUnitMap = std::map; - SectionParser(DWARFDataExtractor &Data, const DWARFContext &C, cu_range CUs, - tu_range TUs); + SectionParser(DWARFDataExtractor &Data, const DWARFContext &C, + DWARFUnitVector::iterator_range Units); /// Get the next line table from the section. Report any issues via the /// handlers. diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h index 3b141304f85f..dbc11c51a789 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h @@ -72,6 +72,8 @@ public: std::function(uint32_t)> LookupAddr, function_ref)> Callback) const; + const DWARFDataExtractor &getData() { return Data; } + protected: DWARFDataExtractor Data; diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h index 4d463d8fe6f5..f1768a1ddab5 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h @@ -96,6 +96,9 @@ class DWARFDebugMacro { MacroHeader Header; SmallVector Macros; uint64_t Offset; + + /// Whether or not this is a .debug_macro section. + bool IsDebugMacro; }; /// A list of all the macro entries in the debug_macinfo section. @@ -107,7 +110,7 @@ public: /// Print the macro list found within the debug_macinfo/debug_macro section. void dump(raw_ostream &OS) const; - Error parseMacro(DWARFUnitVector::iterator_range Units, + Error parseMacro(DWARFUnitVector::compile_unit_range Units, DataExtractor StringExtractor, DWARFDataExtractor MacroData) { return parseImpl(Units, StringExtractor, MacroData, /*IsMacro=*/true); @@ -123,7 +126,7 @@ public: private: /// Parse the debug_macinfo/debug_macro section accessible via the 'MacroData' /// parameter. - Error parseImpl(Optional Units, + Error parseImpl(Optional Units, Optional StringExtractor, DWARFDataExtractor Data, bool IsMacro); }; diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h index 88e5432851d6..4d28bdcde2e4 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h @@ -34,7 +34,7 @@ struct RangeListEntry : public DWARFListEntryBase { uint64_t Value0; uint64_t Value1; - Error extract(DWARFDataExtractor Data, uint64_t End, uint64_t *OffsetPtr); + Error extract(DWARFDataExtractor Data, uint64_t *OffsetPtr); void dump(raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength, uint64_t &CurrentBase, DIDumpOptions DumpOpts, llvm::function_ref(uint32_t)> @@ -48,6 +48,7 @@ public: /// Build a DWARFAddressRangesVector from a rangelist. DWARFAddressRangesVector getAbsoluteRanges(Optional BaseAddr, + uint8_t AddressByteSize, function_ref(uint32_t)> LookupPooledAddress) const; diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h index 05a6056e8e21..0f76d7f1b31c 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h @@ -262,6 +262,7 @@ public: /// for this subprogram by resolving DW_AT_sepcification or /// DW_AT_abstract_origin references if necessary. uint64_t getDeclLine() const; + std::string getDeclFile(DILineInfoSpecifier::FileLineInfoKind Kind) const; /// Retrieves values of DW_AT_call_file, DW_AT_call_line and DW_AT_call_column /// from DIE (or zeroes if they are missing). This function looks for @@ -381,11 +382,6 @@ inline bool operator==(const DWARFDie::iterator &LHS, return LHS.Die == RHS.Die; } -inline bool operator!=(const DWARFDie::iterator &LHS, - const DWARFDie::iterator &RHS) { - return !(LHS == RHS); -} - // These inline functions must follow the DWARFDie::iterator definition above // as they use functions from that class. inline DWARFDie::iterator DWARFDie::begin() const { diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h index edfa68d49a60..447ad66b9352 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h @@ -10,10 +10,11 @@ #define LLVM_DEBUGINFO_DWARFEXPRESSION_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/iterator.h" #include "llvm/ADT/iterator_range.h" -#include "llvm/ADT/Optional.h" #include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/DebugInfo/DIContext.h" #include "llvm/Support/DataExtractor.h" namespace llvm { @@ -93,8 +94,9 @@ public: bool extract(DataExtractor Data, uint8_t AddressSize, uint64_t Offset, Optional Format); bool isError() { return Error; } - bool print(raw_ostream &OS, const DWARFExpression *Expr, - const MCRegisterInfo *RegInfo, DWARFUnit *U, bool isEH); + bool print(raw_ostream &OS, DIDumpOptions DumpOpts, + const DWARFExpression *Expr, const MCRegisterInfo *RegInfo, + DWARFUnit *U, bool isEH); bool verify(DWARFUnit *U); }; @@ -143,7 +145,8 @@ public: iterator begin() const { return iterator(this, 0); } iterator end() const { return iterator(this, Data.getData().size()); } - void print(raw_ostream &OS, const MCRegisterInfo *RegInfo, DWARFUnit *U, + void print(raw_ostream &OS, DIDumpOptions DumpOpts, + const MCRegisterInfo *RegInfo, DWARFUnit *U, bool IsEH = false) const; /// Print the expression in a format intended to be compact and useful to a @@ -164,10 +167,5 @@ inline bool operator==(const DWARFExpression::iterator &LHS, const DWARFExpression::iterator &RHS) { return LHS.Expr == RHS.Expr && LHS.Offset == RHS.Offset; } - -inline bool operator!=(const DWARFExpression::iterator &LHS, - const DWARFExpression::iterator &RHS) { - return !(LHS == RHS); -} } #endif diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h index 3f1be4e5a592..1342e645934c 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h @@ -82,6 +82,9 @@ public: void dump(raw_ostream &OS, DIDumpOptions DumpOpts = DIDumpOptions()) const; void dumpSectionedAddress(raw_ostream &OS, DIDumpOptions DumpOpts, object::SectionedAddress SA) const; + void dumpAddress(raw_ostream &OS, uint64_t Address) const; + static void dumpAddress(raw_ostream &OS, uint8_t AddressSize, + uint64_t Address); static void dumpAddressSection(const DWARFObject &Obj, raw_ostream &OS, DIDumpOptions DumpOpts, uint64_t SectionIndex); diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h index 496fdb2477f9..8f58b4e6458e 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h @@ -46,7 +46,7 @@ public: const ListEntries &getEntries() const { return Entries; } bool empty() const { return Entries.empty(); } void clear() { Entries.clear(); } - Error extract(DWARFDataExtractor Data, uint64_t HeaderOffset, uint64_t End, + Error extract(DWARFDataExtractor Data, uint64_t HeaderOffset, uint64_t *OffsetPtr, StringRef SectionName, StringRef ListStringName); }; @@ -72,10 +72,6 @@ class DWARFListTableHeader { }; Header HeaderData; - /// The offset table, which contains offsets to the individual list entries. - /// It is used by forms such as DW_FORM_rnglistx. - /// FIXME: Generate the table and use the appropriate forms. - std::vector Offsets; /// The table's format, either DWARF32 or DWARF64. dwarf::DwarfFormat Format; /// The offset at which the header (and hence the table) is located within @@ -93,7 +89,6 @@ public: void clear() { HeaderData = {}; - Offsets.clear(); } uint64_t getHeaderOffset() const { return HeaderOffset; } uint8_t getAddrSize() const { return HeaderData.AddrSize; } @@ -115,11 +110,23 @@ public: llvm_unreachable("Invalid DWARF format (expected DWARF32 or DWARF64"); } - void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) const; - Optional getOffsetEntry(uint32_t Index) const { - if (Index < Offsets.size()) - return Offsets[Index]; - return None; + void dump(DataExtractor Data, raw_ostream &OS, + DIDumpOptions DumpOpts = {}) const; + Optional getOffsetEntry(DataExtractor Data, uint32_t Index) const { + if (Index > HeaderData.OffsetEntryCount) + return None; + + return getOffsetEntry(Data, getHeaderOffset() + getHeaderSize(Format), Format, Index); + } + + static Optional getOffsetEntry(DataExtractor Data, + uint64_t OffsetTableOffset, + dwarf::DwarfFormat Format, + uint32_t Index) { + uint8_t OffsetByteSize = Format == dwarf::DWARF64 ? 8 : 4; + uint64_t Offset = OffsetTableOffset + OffsetByteSize * Index; + auto R = Data.getUnsigned(&Offset, OffsetByteSize); + return R; } /// Extract the table header and the array of offsets. @@ -169,14 +176,14 @@ public: uint8_t getAddrSize() const { return Header.getAddrSize(); } dwarf::DwarfFormat getFormat() const { return Header.getFormat(); } - void dump(raw_ostream &OS, + void dump(DWARFDataExtractor Data, raw_ostream &OS, llvm::function_ref(uint32_t)> LookupPooledAddress, DIDumpOptions DumpOpts = {}) const; /// Return the contents of the offset entry designated by a given index. - Optional getOffsetEntry(uint32_t Index) const { - return Header.getOffsetEntry(Index); + Optional getOffsetEntry(DataExtractor Data, uint32_t Index) const { + return Header.getOffsetEntry(Data, Index); } /// Return the size of the table header including the length but not including /// the offsets. This is dependent on the table format, which is unambiguously @@ -196,18 +203,18 @@ Error DWARFListTableBase::extract(DWARFDataExtractor Data, return E; Data.setAddressSize(Header.getAddrSize()); - uint64_t End = getHeaderOffset() + Header.length(); - while (*OffsetPtr < End) { + Data = DWARFDataExtractor(Data, getHeaderOffset() + Header.length()); + while (Data.isValidOffset(*OffsetPtr)) { DWARFListType CurrentList; uint64_t Off = *OffsetPtr; - if (Error E = CurrentList.extract(Data, getHeaderOffset(), End, OffsetPtr, + if (Error E = CurrentList.extract(Data, getHeaderOffset(), OffsetPtr, Header.getSectionName(), Header.getListTypeString())) return E; ListMap[Off] = CurrentList; } - assert(*OffsetPtr == End && + assert(*OffsetPtr == Data.size() && "mismatch between expected length of table and length " "of extracted data"); return Error::success(); @@ -215,18 +222,18 @@ Error DWARFListTableBase::extract(DWARFDataExtractor Data, template Error DWARFListType::extract(DWARFDataExtractor Data, - uint64_t HeaderOffset, uint64_t End, + uint64_t HeaderOffset, uint64_t *OffsetPtr, StringRef SectionName, StringRef ListTypeString) { - if (*OffsetPtr < HeaderOffset || *OffsetPtr >= End) + if (*OffsetPtr < HeaderOffset || *OffsetPtr >= Data.size()) return createStringError(errc::invalid_argument, "invalid %s list offset 0x%" PRIx64, ListTypeString.data(), *OffsetPtr); Entries.clear(); - while (*OffsetPtr < End) { + while (Data.isValidOffset(*OffsetPtr)) { ListEntryType Entry; - if (Error E = Entry.extract(Data, End, OffsetPtr)) + if (Error E = Entry.extract(Data, OffsetPtr)) return E; Entries.push_back(Entry); if (Entry.isSentinel()) @@ -240,11 +247,11 @@ Error DWARFListType::extract(DWARFDataExtractor Data, template void DWARFListTableBase::dump( - raw_ostream &OS, + DWARFDataExtractor Data, raw_ostream &OS, llvm::function_ref(uint32_t)> LookupPooledAddress, DIDumpOptions DumpOpts) const { - Header.dump(OS, DumpOpts); + Header.dump(Data, OS, DumpOpts); OS << HeaderString << "\n"; // Determine the length of the longest encoding string we have in the table, @@ -269,19 +276,14 @@ template Expected DWARFListTableBase::findList(DWARFDataExtractor Data, uint64_t Offset) { - auto Entry = ListMap.find(Offset); - if (Entry != ListMap.end()) - return Entry->second; - // Extract the list from the section and enter it into the list map. DWARFListType List; - uint64_t End = getHeaderOffset() + Header.length(); - uint64_t StartingOffset = Offset; + if (Header.length()) + Data = DWARFDataExtractor(Data, getHeaderOffset() + Header.length()); if (Error E = - List.extract(Data, getHeaderOffset(), End, &Offset, + List.extract(Data, Header.length() ? getHeaderOffset() : 0, &Offset, Header.getSectionName(), Header.getListTypeString())) return std::move(E); - ListMap[StartingOffset] = List; return List; } diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h index 5b3b46626059..369cbdc28c2e 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -113,6 +113,8 @@ public: const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context, DWARFSectionKind Kind); +bool isCompileUnit(const std::unique_ptr &U); + /// Describe a collection of units. Intended to hold all units either from /// .debug_info and .debug_types, or from .debug_info.dwo and .debug_types.dwo. class DWARFUnitVector final : public SmallVector, 1> { @@ -127,6 +129,9 @@ public: using iterator = typename UnitVector::iterator; using iterator_range = llvm::iterator_range; + using compile_unit_range = + decltype(make_filter_range(std::declval(), isCompileUnit)); + DWARFUnit *getUnitForOffset(uint64_t Offset) const; DWARFUnit *getUnitForIndexEntry(const DWARFUnitIndex::Entry &E); @@ -204,7 +209,6 @@ class DWARFUnit { const DWARFDebugAbbrev *Abbrev; const DWARFSection *RangeSection; uint64_t RangeSectionBase; - const DWARFSection *LocSection; uint64_t LocSectionBase; /// Location table of this unit. @@ -223,10 +227,6 @@ class DWARFUnit { /// offsets table (DWARF v5). Optional StringOffsetsTableContribution; - /// A table of range lists (DWARF v5 and later). - Optional RngListTable; - Optional LoclistTableHeader; - mutable const DWARFAbbreviationDeclarationSet *Abbrevs; llvm::Optional BaseAddr; /// The compile unit debug information entry items. @@ -294,6 +294,7 @@ public: dwarf::DwarfFormat getFormat() const { return Header.getFormat(); } uint8_t getUnitType() const { return Header.getUnitType(); } bool isTypeUnit() const { return Header.isTypeUnit(); } + uint64_t getAbbrOffset() const { return Header.getAbbrOffset(); } uint64_t getNextUnitOffset() const { return Header.getNextUnitOffset(); } const DWARFSection &getLineSection() const { return LineSection; } StringRef getStringSection() const { return StringSection; } @@ -313,10 +314,6 @@ public: RangeSection = RS; RangeSectionBase = Base; } - void setLocSection(const DWARFSection *LS, uint64_t Base) { - LocSection = LS; - LocSectionBase = Base; - } uint64_t getLocSectionBase() const { return LocSectionBase; @@ -411,21 +408,10 @@ public: /// Return a rangelist's offset based on an index. The index designates /// an entry in the rangelist table's offset array and is supplied by /// DW_FORM_rnglistx. - Optional getRnglistOffset(uint32_t Index) { - if (!RngListTable) - return None; - if (Optional Off = RngListTable->getOffsetEntry(Index)) - return *Off + RangeSectionBase; - return None; - } + Optional getRnglistOffset(uint32_t Index); + + Optional getLoclistOffset(uint32_t Index); - Optional getLoclistOffset(uint32_t Index) { - if (!LoclistTableHeader) - return None; - if (Optional Off = LoclistTableHeader->getOffsetEntry(Index)) - return *Off + getLocSectionBase(); - return None; - } Expected collectAddressRanges(); Expected @@ -480,7 +466,6 @@ public: /// The unit needs to have its DIEs extracted for this method to work. DWARFDie getDIEForOffset(uint64_t Offset) { extractDIEsIfNeeded(false); - assert(!DieArray.empty()); auto It = llvm::partition_point(DieArray, [=](const DWARFDebugInfoEntry &DIE) { return DIE.getOffset() < Offset; @@ -529,6 +514,10 @@ private: bool parseDWO(); }; +inline bool isCompileUnit(const std::unique_ptr &U) { + return !U->isTypeUnit(); +} + } // end namespace llvm #endif // LLVM_DEBUGINFO_DWARF_DWARFUNIT_H diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h index 22b1d722fc89..18d889f5cadb 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h @@ -12,25 +12,22 @@ #include "llvm/ADT/Optional.h" #include "llvm/DebugInfo/DIContext.h" #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h" -#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" - #include #include #include namespace llvm { class raw_ostream; +struct DWARFAddressRange; struct DWARFAttribute; class DWARFContext; -class DWARFDie; -class DWARFUnit; -class DWARFCompileUnit; class DWARFDataExtractor; class DWARFDebugAbbrev; class DataExtractor; struct DWARFSection; +class DWARFUnit; /// A class that verifies DWARF debug information given a DWARF Context. class DWARFVerifier { diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/MSF/MappedBlockStream.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/MSF/MappedBlockStream.h index 593d781b990e..473c89e8106f 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/MSF/MappedBlockStream.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/MSF/MappedBlockStream.h @@ -24,8 +24,6 @@ namespace llvm { namespace msf { -struct MSFLayout; - /// MappedBlockStream represents data stored in an MSF file into chunks of a /// particular size (called the Block Size), and whose chunks may not be /// necessarily contiguous. The arrangement of these chunks MSF the file diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h index beaaef0c5a6c..82b63d729454 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h @@ -34,6 +34,34 @@ struct MSFLayout; } namespace pdb { +// Represents merged or unmerged symbols. Merged symbols can be written to the +// output file as is, but unmerged symbols must be rewritten first. In either +// case, the size must be known up front. +struct SymbolListWrapper { + explicit SymbolListWrapper(ArrayRef Syms) + : SymPtr(const_cast(Syms.data())), SymSize(Syms.size()), + NeedsToBeMerged(false) {} + explicit SymbolListWrapper(void *SymSrc, uint32_t Length) + : SymPtr(SymSrc), SymSize(Length), NeedsToBeMerged(true) {} + + ArrayRef asArray() const { + return ArrayRef(static_cast(SymPtr), SymSize); + } + + uint32_t size() const { return SymSize; } + + void *SymPtr = nullptr; + uint32_t SymSize = 0; + bool NeedsToBeMerged = false; +}; + +/// Represents a string table reference at some offset in the module symbol +/// stream. +struct StringTableFixup { + uint32_t StrTabOffset = 0; + uint32_t SymOffsetOfReference = 0; +}; + class DbiModuleDescriptorBuilder { friend class DbiStreamBuilder; @@ -48,10 +76,28 @@ public: void setPdbFilePathNI(uint32_t NI); void setObjFileName(StringRef Name); + + // Callback to merge one source of unmerged symbols. + using MergeSymbolsCallback = Error (*)(void *Ctx, void *Symbols, + BinaryStreamWriter &Writer); + + void setMergeSymbolsCallback(void *Ctx, MergeSymbolsCallback Callback) { + MergeSymsCtx = Ctx; + MergeSymsCallback = Callback; + } + + void setStringTableFixups(std::vector &&Fixups) { + StringTableFixups = std::move(Fixups); + } + void setFirstSectionContrib(const SectionContrib &SC); void addSymbol(codeview::CVSymbol Symbol); void addSymbolsInBulk(ArrayRef BulkSymbols); + // Add symbols of known size which will be merged (rewritten) when committing + // the PDB to disk. + void addUnmergedSymbols(void *SymSrc, uint32_t SymLength); + void addDebugSubsection(std::shared_ptr Subsection); @@ -77,8 +123,14 @@ public: void finalize(); Error finalizeMsfLayout(); - Error commit(BinaryStreamWriter &ModiWriter, const msf::MSFLayout &MsfLayout, - WritableBinaryStreamRef MsfBuffer); + /// Commit the DBI descriptor to the DBI stream. + Error commit(BinaryStreamWriter &ModiWriter); + + /// Commit the accumulated symbols to the module symbol stream. Safe to call + /// in parallel on different DbiModuleDescriptorBuilder objects. Only modifies + /// the pre-allocated stream in question. + Error commitSymbolStream(const msf::MSFLayout &MsfLayout, + WritableBinaryStreamRef MsfBuffer); private: uint32_t calculateC13DebugInfoSize() const; @@ -91,7 +143,12 @@ private: std::string ModuleName; std::string ObjFileName; std::vector SourceFiles; - std::vector> Symbols; + std::vector Symbols; + + void *MergeSymsCtx = nullptr; + MergeSymbolsCallback MergeSymsCallback = nullptr; + + std::vector StringTableFixups; std::vector C13Builders; diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h new file mode 100644 index 000000000000..480b3fb11419 --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h @@ -0,0 +1,41 @@ +//==- NativeEnumSymbols.h - Native Symbols Enumerator impl -------*- C++ -*-==// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMSYMBOLS_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMSYMBOLS_H + +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" + +#include + +namespace llvm { +namespace pdb { + +class NativeSession; + +class NativeEnumSymbols : public IPDBEnumChildren { +public: + NativeEnumSymbols(NativeSession &Session, std::vector Symbols); + + uint32_t getChildCount() const override; + std::unique_ptr getChildAtIndex(uint32_t Index) const override; + std::unique_ptr getNext() override; + void reset() override; + +private: + std::vector Symbols; + uint32_t Index; + NativeSession &Session; +}; + +} // namespace pdb +} // namespace llvm + +#endif diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h index 4adf89f0d69a..b219055d2153 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h @@ -20,7 +20,7 @@ namespace pdb { class NativeFunctionSymbol : public NativeRawSymbol { public: NativeFunctionSymbol(NativeSession &Session, SymIndexId Id, - const codeview::ProcSym &Sym); + const codeview::ProcSym &Sym, uint32_t RecordOffset); ~NativeFunctionSymbol() override; @@ -30,13 +30,15 @@ public: uint32_t getAddressOffset() const override; uint32_t getAddressSection() const override; std::string getName() const override; - PDB_SymType getSymTag() const override; uint64_t getLength() const override; uint32_t getRelativeVirtualAddress() const override; uint64_t getVirtualAddress() const override; + std::unique_ptr + findInlineFramesByVA(uint64_t VA) const override; protected: const codeview::ProcSym Sym; + uint32_t RecordOffset = 0; }; } // namespace pdb diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h new file mode 100644 index 000000000000..2f6aba038ae8 --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h @@ -0,0 +1,46 @@ +//===- NativeInlineSiteSymbol.h - info about inline sites -------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVEINLINESITESYMBOL_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEINLINESITESYMBOL_H + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" + +namespace llvm { +namespace pdb { + +class NativeInlineSiteSymbol : public NativeRawSymbol { +public: + NativeInlineSiteSymbol(NativeSession &Session, SymIndexId Id, + const codeview::InlineSiteSym &Sym, + uint64_t ParentAddr); + + ~NativeInlineSiteSymbol() override; + + void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const override; + + std::string getName() const override; + std::unique_ptr + findInlineeLinesByVA(uint64_t VA, uint32_t Length) const override; + +private: + const codeview::InlineSiteSym Sym; + uint64_t ParentAddr; + + void getLineOffset(uint32_t OffsetInFunc, uint32_t &LineOffset, + uint32_t &FileOffset) const; +}; + +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVEINLINESITESYMBOL_H diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/NativeLineNumber.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/NativeLineNumber.h index a7ce82c70b08..5dedc70f11ba 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/NativeLineNumber.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/NativeLineNumber.h @@ -22,7 +22,7 @@ public: const codeview::LineInfo Line, uint32_t ColumnNumber, uint32_t Length, uint32_t Section, uint32_t Offset, - uint32_t SrcFileId); + uint32_t SrcFileId, uint32_t CompilandId); uint32_t getLineNumber() const override; uint32_t getLineNumberEnd() const override; @@ -45,6 +45,7 @@ private: uint32_t Offset; uint32_t Length; uint32_t SrcFileId; + uint32_t CompilandId; }; } // namespace pdb } // namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/NativePublicSymbol.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/NativePublicSymbol.h index 0a1451530f18..9f410e27f4cb 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/NativePublicSymbol.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/NativePublicSymbol.h @@ -30,7 +30,6 @@ public: uint32_t getAddressOffset() const override; uint32_t getAddressSection() const override; std::string getName() const override; - PDB_SymType getSymTag() const override; uint32_t getRelativeVirtualAddress() const override; uint64_t getVirtualAddress() const override; diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h index 342e63599e66..5f8fc587e546 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h @@ -110,9 +110,14 @@ public: const SymbolCache &getSymbolCache() const { return Cache; } uint32_t getRVAFromSectOffset(uint32_t Section, uint32_t Offset) const; uint64_t getVAFromSectOffset(uint32_t Section, uint32_t Offset) const; + bool moduleIndexForVA(uint64_t VA, uint16_t &ModuleIndex) const; + bool moduleIndexForSectOffset(uint32_t Sect, uint32_t Offset, + uint16_t &ModuleIndex) const; + Expected getModuleDebugStream(uint32_t Index) const; private: void initializeExeSymbol(); + void parseSectionContribs(); std::unique_ptr Pdb; std::unique_ptr Allocator; @@ -120,6 +125,12 @@ private: SymbolCache Cache; SymIndexId ExeSymbol = 0; uint64_t LoadAddress = 0; + + /// Map from virtual address to module index. + using IMap = + IntervalMap>; + IMap::Allocator IMapAllocator; + IMap AddrToModuleIndex; }; } // namespace pdb } // namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h index 90fd19a7a2fb..1ff6ca173b2b 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h @@ -37,40 +37,40 @@ class SymbolCache { /// an Id. Id allocation is an implementation, with the only guarantee /// being that once an Id is allocated, the symbol can be assumed to be /// cached. - std::vector> Cache; + mutable std::vector> Cache; /// For type records from the TPI stream which have been paresd and cached, /// stores a mapping to SymIndexId of the cached symbol. - DenseMap TypeIndexToSymbolId; + mutable DenseMap TypeIndexToSymbolId; /// For field list members which have been parsed and cached, stores a mapping /// from (IndexOfClass, MemberIndex) to the corresponding SymIndexId of the /// cached symbol. - DenseMap, SymIndexId> + mutable DenseMap, SymIndexId> FieldListMembersToSymbolId; /// List of SymIndexIds for each compiland, indexed by compiland index as they /// appear in the PDB file. - std::vector Compilands; + mutable std::vector Compilands; /// List of source files, indexed by unique source file index. mutable std::vector> SourceFiles; + + /// Map from string table offset to source file Id. mutable DenseMap FileNameOffsetToId; /// Map from global symbol offset to SymIndexId. - DenseMap GlobalOffsetToSymbolId; - - /// Map from segment and code offset to SymIndexId. - DenseMap, SymIndexId> AddressToFunctionSymId; - DenseMap, SymIndexId> AddressToPublicSymId; + mutable DenseMap GlobalOffsetToSymbolId; - /// Map from virtual address to module index. - using IMap = - IntervalMap>; - IMap::Allocator IMapAllocator; - IMap AddrToModuleIndex; + /// Map from segment and code offset to function symbols. + mutable DenseMap, SymIndexId> AddressToSymbolId; + /// Map from segment and code offset to public symbols. + mutable DenseMap, SymIndexId> + AddressToPublicSymId; - Expected getModuleDebugStream(uint32_t Index) const; + /// Map from module index and symbol table offset to SymIndexId. + mutable DenseMap, SymIndexId> + SymTabOffsetToSymbolId; struct LineTableEntry { uint64_t Addr; @@ -83,7 +83,7 @@ class SymbolCache { std::vector findLineTable(uint16_t Modi) const; mutable DenseMap> LineTable; - SymIndexId createSymbolPlaceholder() { + SymIndexId createSymbolPlaceholder() const { SymIndexId Id = Cache.size(); Cache.push_back(nullptr); return Id; @@ -91,7 +91,7 @@ class SymbolCache { template SymIndexId createSymbolForType(codeview::TypeIndex TI, codeview::CVType CVT, - Args &&... ConstructorArgs) { + Args &&...ConstructorArgs) const { CVRecordT Record; if (auto EC = codeview::TypeDeserializer::deserializeAs(CVT, Record)) { @@ -104,10 +104,10 @@ class SymbolCache { } SymIndexId createSymbolForModifiedType(codeview::TypeIndex ModifierTI, - codeview::CVType CVT); + codeview::CVType CVT) const; SymIndexId createSimpleType(codeview::TypeIndex TI, - codeview::ModifierOptions Mods); + codeview::ModifierOptions Mods) const; std::unique_ptr findFunctionSymbolBySectOffset(uint32_t Sect, uint32_t Offset); @@ -118,7 +118,7 @@ public: SymbolCache(NativeSession &Session, DbiStream *Dbi); template - SymIndexId createSymbol(Args &&... ConstructorArgs) { + SymIndexId createSymbol(Args &&...ConstructorArgs) const { SymIndexId Id = Cache.size(); // Initial construction must not access the cache, since it must be done @@ -145,7 +145,7 @@ public: std::unique_ptr createGlobalsEnumerator(codeview::SymbolKind Kind); - SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI); + SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI) const; template SymIndexId getOrCreateFieldListMember(codeview::TypeIndex FieldListTI, @@ -163,6 +163,9 @@ public: } SymIndexId getOrCreateGlobalSymbolByOffset(uint32_t Offset); + SymIndexId getOrCreateInlineSymbol(codeview::InlineSiteSym Sym, + uint64_t ParentAddr, uint16_t Modi, + uint32_t RecordOffset) const; std::unique_ptr findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, PDB_SymType Type); @@ -185,9 +188,6 @@ public: std::unique_ptr getSourceFileById(SymIndexId FileId) const; SymIndexId getOrCreateSourceFile(const codeview::FileChecksumEntry &Checksum) const; - - void parseSectionContribs(); - Optional getModuleIndexForAddr(uint64_t Addr) const; }; } // namespace pdb diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/TpiStream.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/TpiStream.h index 1b7fd2d54cb2..70288868ca21 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/TpiStream.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/TpiStream.h @@ -9,7 +9,7 @@ #ifndef LLVM_DEBUGINFO_PDB_RAW_PDBTPISTREAM_H #define LLVM_DEBUGINFO_PDB_RAW_PDBTPISTREAM_H -#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/CVRecord.h" #include "llvm/DebugInfo/PDB/Native/HashTable.h" #include "llvm/DebugInfo/PDB/Native/RawConstants.h" #include "llvm/DebugInfo/PDB/Native/RawTypes.h" diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h index 72d98e9c2c4d..9ef2ee6a9307 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h @@ -54,16 +54,20 @@ public: void setVersionHeader(PdbRaw_TpiVer Version); void addTypeRecord(ArrayRef Type, Optional Hash); + void addTypeRecords(ArrayRef Types, ArrayRef Sizes, + ArrayRef Hashes); Error finalizeMsfLayout(); - uint32_t getRecordCount() const { return TypeRecords.size(); } + uint32_t getRecordCount() const { return TypeRecordCount; } Error commit(const msf::MSFLayout &Layout, WritableBinaryStreamRef Buffer); uint32_t calculateSerializedLength(); private: + void updateTypeIndexOffsets(ArrayRef Sizes); + uint32_t calculateHashBufferSize() const; uint32_t calculateIndexOffsetSize() const; Error finalize(); @@ -71,10 +75,11 @@ private: msf::MSFBuilder &Msf; BumpPtrAllocator &Allocator; + uint32_t TypeRecordCount = 0; size_t TypeRecordBytes = 0; PdbRaw_TpiVer VerHeader = PdbRaw_TpiVer::PdbTpiV80; - std::vector> TypeRecords; + std::vector> TypeRecBuffers; std::vector TypeHashes; std::vector TypeIndexOffsets; uint32_t HashStreamIndex = kInvalidStreamIndex; diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/PDBExtras.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/PDBExtras.h index 45aba013e7c8..802d18a069ee 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/PDBExtras.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/PDBExtras.h @@ -9,16 +9,15 @@ #ifndef LLVM_DEBUGINFO_PDB_PDBEXTRAS_H #define LLVM_DEBUGINFO_PDB_PDBEXTRAS_H +#include "llvm/ADT/StringRef.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/PDB/PDBTypes.h" #include "llvm/Support/raw_ostream.h" - +#include #include namespace llvm { -class raw_ostream; - namespace pdb { using TagStats = std::unordered_map; @@ -51,7 +50,6 @@ void dumpSymbolField(raw_ostream &OS, StringRef Name, T Value, int Indent) { OS << Name << ": " << Value; } - } // end namespace pdb } // end namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h index 2982146f960c..24cf1e459f92 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h @@ -42,7 +42,6 @@ class StringRef; class raw_ostream; namespace pdb { -class IPDBRawSymbol; class IPDBSession; #define DECLARE_PDB_SYMBOL_CONCRETE_TYPE(TagValue) \ @@ -141,7 +140,14 @@ public: StringRef Name, PDB_NameSearchFlags Flags, uint32_t RVA) const; + std::unique_ptr findInlineFramesByVA(uint64_t VA) const; std::unique_ptr findInlineFramesByRVA(uint32_t RVA) const; + std::unique_ptr + findInlineeLinesByVA(uint64_t VA, uint32_t Length) const; + std::unique_ptr + findInlineeLinesByRVA(uint32_t RVA, uint32_t Length) const; + + std::string getName() const; const IPDBRawSymbol &getRawSymbol() const { return *RawSymbol; } IPDBRawSymbol &getRawSymbol() { return *RawSymbol; } diff --git a/contrib/llvm-project/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h b/contrib/llvm-project/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h index 085e4bb4ccb8..1c8fa11660af 100644 --- a/contrib/llvm-project/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h +++ b/contrib/llvm-project/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h @@ -43,7 +43,7 @@ public: bool Demangle = true; bool RelativeAddresses = false; bool UntagAddresses = false; - bool UseNativePDBReader = false; + bool UseDIA = false; std::string DefaultArch; std::vector DsymHints; std::string FallbackDebugPath; diff --git a/contrib/llvm-project/llvm/include/llvm/Demangle/ItaniumDemangle.h b/contrib/llvm-project/llvm/include/llvm/Demangle/ItaniumDemangle.h index 6ab873218386..e5fca98f9271 100644 --- a/contrib/llvm-project/llvm/include/llvm/Demangle/ItaniumDemangle.h +++ b/contrib/llvm-project/llvm/include/llvm/Demangle/ItaniumDemangle.h @@ -82,6 +82,7 @@ X(PostfixExpr) \ X(ConditionalExpr) \ X(MemberExpr) \ + X(SubobjectExpr) \ X(EnclosingExpr) \ X(CastExpr) \ X(SizeofParamPackExpr) \ @@ -91,10 +92,10 @@ X(PrefixExpr) \ X(FunctionParam) \ X(ConversionExpr) \ + X(PointerToMemberConversionExpr) \ X(InitListExpr) \ X(FoldExpr) \ X(ThrowExpr) \ - X(UUIDOfExpr) \ X(BoolExpr) \ X(StringLiteral) \ X(LambdaExpr) \ @@ -1656,6 +1657,40 @@ public: } }; +class SubobjectExpr : public Node { + const Node *Type; + const Node *SubExpr; + StringView Offset; + NodeArray UnionSelectors; + bool OnePastTheEnd; + +public: + SubobjectExpr(const Node *Type_, const Node *SubExpr_, StringView Offset_, + NodeArray UnionSelectors_, bool OnePastTheEnd_) + : Node(KSubobjectExpr), Type(Type_), SubExpr(SubExpr_), Offset(Offset_), + UnionSelectors(UnionSelectors_), OnePastTheEnd(OnePastTheEnd_) {} + + template void match(Fn F) const { + F(Type, SubExpr, Offset, UnionSelectors, OnePastTheEnd); + } + + void printLeft(OutputStream &S) const override { + SubExpr->print(S); + S += ".<"; + Type->print(S); + S += " at offset "; + if (Offset.empty()) { + S += "0"; + } else if (Offset[0] == 'n') { + S += "-"; + S += Offset.dropFront(); + } else { + S += Offset; + } + S += ">"; + } +}; + class EnclosingExpr : public Node { const StringView Prefix; const Node *Infix; @@ -1843,6 +1878,28 @@ public: } }; +class PointerToMemberConversionExpr : public Node { + const Node *Type; + const Node *SubExpr; + StringView Offset; + +public: + PointerToMemberConversionExpr(const Node *Type_, const Node *SubExpr_, + StringView Offset_) + : Node(KPointerToMemberConversionExpr), Type(Type_), SubExpr(SubExpr_), + Offset(Offset_) {} + + template void match(Fn F) const { F(Type, SubExpr, Offset); } + + void printLeft(OutputStream &S) const override { + S += "("; + Type->print(S); + S += ")("; + SubExpr->print(S); + S += ")"; + } +}; + class InitListExpr : public Node { const Node *Ty; NodeArray Inits; @@ -1977,21 +2034,6 @@ public: } }; -// MSVC __uuidof extension, generated by clang in -fms-extensions mode. -class UUIDOfExpr : public Node { - Node *Operand; -public: - UUIDOfExpr(Node *Operand_) : Node(KUUIDOfExpr), Operand(Operand_) {} - - template void match(Fn F) const { F(Operand); } - - void printLeft(OutputStream &S) const override { - S << "__uuidof("; - Operand->print(S); - S << ")"; - } -}; - class BoolExpr : public Node { bool Value; @@ -2313,9 +2355,9 @@ template struct AbstractManglingParser { TemplateParamList Params; public: - ScopedTemplateParamList(AbstractManglingParser *Parser) - : Parser(Parser), - OldNumTemplateParamLists(Parser->TemplateParams.size()) { + ScopedTemplateParamList(AbstractManglingParser *TheParser) + : Parser(TheParser), + OldNumTemplateParamLists(TheParser->TemplateParams.size()) { Parser->TemplateParams.push_back(&Params); } ~ScopedTemplateParamList() { @@ -2437,6 +2479,8 @@ template struct AbstractManglingParser { Node *parseConversionExpr(); Node *parseBracedExpr(); Node *parseFoldExpr(); + Node *parsePointerToMemberConversionExpr(); + Node *parseSubobjectExpr(); /// Parse the production. Node *parseType(); @@ -4404,6 +4448,50 @@ Node *AbstractManglingParser::parseFoldExpr() { return make(IsLeftFold, OperatorName, Pack, Init); } +// ::= mc [] E +// +// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47 +template +Node *AbstractManglingParser::parsePointerToMemberConversionExpr() { + Node *Ty = getDerived().parseType(); + if (!Ty) + return nullptr; + Node *Expr = getDerived().parseExpr(); + if (!Expr) + return nullptr; + StringView Offset = getDerived().parseNumber(true); + if (!consumeIf('E')) + return nullptr; + return make(Ty, Expr, Offset); +} + +// ::= so [] * [p] E +// ::= _ [] +// +// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47 +template +Node *AbstractManglingParser::parseSubobjectExpr() { + Node *Ty = getDerived().parseType(); + if (!Ty) + return nullptr; + Node *Expr = getDerived().parseExpr(); + if (!Expr) + return nullptr; + StringView Offset = getDerived().parseNumber(true); + size_t SelectorsBegin = Names.size(); + while (consumeIf('_')) { + Node *Selector = make(parseNumber()); + if (!Selector) + return nullptr; + Names.push_back(Selector); + } + bool OnePastTheEnd = consumeIf('p'); + if (!consumeIf('E')) + return nullptr; + return make( + Ty, Expr, Offset, popTrailingNodeArray(SelectorsBegin), OnePastTheEnd); +} + // ::= // ::= // ::= @@ -4661,6 +4749,9 @@ Node *AbstractManglingParser::parseExpr() { return nullptr; case 'm': switch (First[1]) { + case 'c': + First += 2; + return parsePointerToMemberConversionExpr(); case 'i': First += 2; return getDerived().parseBinaryExpr("-"); @@ -4808,6 +4899,9 @@ Node *AbstractManglingParser::parseExpr() { return Ex; return make("static_cast", T, Ex); } + case 'o': + First += 2; + return parseSubobjectExpr(); case 'p': { First += 2; Node *Child = getDerived().parseExpr(); @@ -4903,6 +4997,43 @@ Node *AbstractManglingParser::parseExpr() { } } return nullptr; + case 'u': { + ++First; + Node *Name = getDerived().parseSourceName(/*NameState=*/nullptr); + if (!Name) + return nullptr; + // Special case legacy __uuidof mangling. The 't' and 'z' appear where the + // standard encoding expects a , and would be otherwise be + // interpreted as node 'short' or 'ellipsis'. However, neither + // __uuidof(short) nor __uuidof(...) can actually appear, so there is no + // actual conflict here. + if (Name->getBaseName() == "__uuidof") { + if (numLeft() < 2) + return nullptr; + if (*First == 't') { + ++First; + Node *Ty = getDerived().parseType(); + if (!Ty) + return nullptr; + return make(Name, makeNodeArray(&Ty, &Ty + 1)); + } + if (*First == 'z') { + ++First; + Node *Ex = getDerived().parseExpr(); + if (!Ex) + return nullptr; + return make(Name, makeNodeArray(&Ex, &Ex + 1)); + } + } + size_t ExprsBegin = Names.size(); + while (!consumeIf('E')) { + Node *E = getDerived().parseTemplateArg(); + if (E == nullptr) + return E; + Names.push_back(E); + } + return make(Name, popTrailingNodeArray(ExprsBegin)); + } case '1': case '2': case '3': @@ -4914,21 +5045,6 @@ Node *AbstractManglingParser::parseExpr() { case '9': return getDerived().parseUnresolvedName(); } - - if (consumeIf("u8__uuidoft")) { - Node *Ty = getDerived().parseType(); - if (!Ty) - return nullptr; - return make(Ty); - } - - if (consumeIf("u8__uuidofz")) { - Node *Ex = getDerived().parseExpr(); - if (!Ex) - return nullptr; - return make(Ex); - } - return nullptr; } @@ -4975,6 +5091,16 @@ Node *AbstractManglingParser::parseSpecialName() { switch (look()) { case 'T': switch (look(1)) { + // TA # template parameter object + // + // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/63 + case 'A': { + First += 2; + Node *Arg = getDerived().parseTemplateArg(); + if (Arg == nullptr) + return nullptr; + return make("template parameter object for ", Arg); + } // TV # virtual table case 'V': { First += 2; @@ -5103,7 +5229,7 @@ Node *AbstractManglingParser::parseEncoding() { decltype(TemplateParams) OldParams; public: - SaveTemplateParams(AbstractManglingParser *Parser) : Parser(Parser) { + SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) { OldParams = std::move(Parser->TemplateParams); Parser->TemplateParams.clear(); } @@ -5203,7 +5329,12 @@ struct FloatData #else static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms #endif - static const size_t max_demangled_size = 40; + // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes. + // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits. + // Negatives are one character longer than positives. + // `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the + // same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128. + static const size_t max_demangled_size = 42; static constexpr const char *spec = "%LaL"; }; diff --git a/contrib/llvm-project/llvm/include/llvm/Demangle/Utility.h b/contrib/llvm-project/llvm/include/llvm/Demangle/Utility.h index 04e1936ebbe7..846a5f0818e7 100644 --- a/contrib/llvm-project/llvm/include/llvm/Demangle/Utility.h +++ b/contrib/llvm-project/llvm/include/llvm/Demangle/Utility.h @@ -52,7 +52,7 @@ class OutputStream { char *TempPtr = std::end(Temp); while (N) { - *--TempPtr = '0' + char(N % 10); + *--TempPtr = char('0' + N % 10); N /= 10; } diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h index 2562da7cf60b..2e386518f0bf 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -142,11 +142,6 @@ protected: std::shared_ptr SR, std::unique_ptr TM); - static ExecutionEngine *(*OrcMCJITReplacementCtor)( - std::string *ErrorStr, std::shared_ptr MM, - std::shared_ptr SR, - std::unique_ptr TM); - static ExecutionEngine *(*InterpCtor)(std::unique_ptr M, std::string *ErrorStr); @@ -552,7 +547,6 @@ private: std::string MCPU; SmallVector MAttrs; bool VerifyModules; - bool UseOrcMCJITReplacement; bool EmulatedTLS = true; public: @@ -648,17 +642,6 @@ public: return *this; } - // Use OrcMCJITReplacement instead of MCJIT. Off by default. - LLVM_ATTRIBUTE_DEPRECATED( - inline void setUseOrcMCJITReplacement(bool UseOrcMCJITReplacement), - "ORCv1 utilities (including OrcMCJITReplacement) are deprecated. Please " - "use ORCv2/LLJIT instead (see docs/ORCv2.rst)"); - - void setUseOrcMCJITReplacement(ORCv1DeprecationAcknowledgement, - bool UseOrcMCJITReplacement) { - this->UseOrcMCJITReplacement = UseOrcMCJITReplacement; - } - void setEmulatedTLS(bool EmulatedTLS) { this->EmulatedTLS = EmulatedTLS; } @@ -679,10 +662,6 @@ public: ExecutionEngine *create(TargetMachine *TM); }; -void EngineBuilder::setUseOrcMCJITReplacement(bool UseOrcMCJITReplacement) { - this->UseOrcMCJITReplacement = UseOrcMCJITReplacement; -} - // Create wrappers for C Binding types (see CBindingWrapping.h). DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ExecutionEngine, LLVMExecutionEngineRef) diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITEventListener.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITEventListener.h index 606b6f7cc128..4eefd993de2b 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITEventListener.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITEventListener.h @@ -20,7 +20,6 @@ #include "llvm/IR/DebugLoc.h" #include "llvm/Support/CBindingWrapping.h" #include -#include namespace llvm { diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h index 72687682f606..ec78d9db40b6 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h @@ -21,14 +21,6 @@ namespace llvm { namespace jitlink { -/// Registers all FDEs in the given eh-frame section with the current process. -Error registerEHFrameSection(const void *EHFrameSectionAddr, - size_t EHFrameSectionSize); - -/// Deregisters all FDEs in the given eh-frame section with the current process. -Error deregisterEHFrameSection(const void *EHFrameSectionAddr, - size_t EHFrameSectionSize); - /// Supports registration/deregistration of EH-frames in a target process. class EHFrameRegistrar { public: @@ -42,32 +34,11 @@ public: /// Registers / Deregisters EH-frames in the current process. class InProcessEHFrameRegistrar final : public EHFrameRegistrar { public: - /// Get a reference to the InProcessEHFrameRegistrar singleton. - static InProcessEHFrameRegistrar &getInstance(); - - InProcessEHFrameRegistrar(const InProcessEHFrameRegistrar &) = delete; - InProcessEHFrameRegistrar & - operator=(const InProcessEHFrameRegistrar &) = delete; - - InProcessEHFrameRegistrar(InProcessEHFrameRegistrar &&) = delete; - InProcessEHFrameRegistrar &operator=(InProcessEHFrameRegistrar &&) = delete; - Error registerEHFrames(JITTargetAddress EHFrameSectionAddr, - size_t EHFrameSectionSize) override { - return registerEHFrameSection( - jitTargetAddressToPointer(EHFrameSectionAddr), - EHFrameSectionSize); - } + size_t EHFrameSectionSize) override; Error deregisterEHFrames(JITTargetAddress EHFrameSectionAddr, - size_t EHFrameSectionSize) override { - return deregisterEHFrameSection( - jitTargetAddressToPointer(EHFrameSectionAddr), - EHFrameSectionSize); - } - -private: - InProcessEHFrameRegistrar(); + size_t EHFrameSectionSize) override; }; using StoreFrameRangeFunction = diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/ELF.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/ELF.h index 9f6ea5271f4b..8912f3a2db45 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/ELF.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/ELF.h @@ -19,11 +19,20 @@ namespace llvm { namespace jitlink { -/// jit-link the given ObjBuffer, which must be a ELF object file. +/// Create a LinkGraph from an ELF relocatable object. +/// +/// Note: The graph does not take ownership of the underlying buffer, nor copy +/// its contents. The caller is responsible for ensuring that the object buffer +/// outlives the graph. +Expected> +createLinkGraphFromELFObject(MemoryBufferRef ObjectBuffer); + +/// Link the given graph. /// /// Uses conservative defaults for GOT and stub handling based on the target /// platform. -void jitLink_ELF(std::unique_ptr Ctx); +void link_ELF(std::unique_ptr G, + std::unique_ptr Ctx); } // end namespace jitlink } // end namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/ELF_x86_64.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/ELF_x86_64.h index 7860088f3569..1423b0c30b2a 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/ELF_x86_64.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/ELF_x86_64.h @@ -44,8 +44,20 @@ enum ELFX86RelocationKind : Edge::Kind { } // end namespace ELF_x86_64_Edges +/// Create a LinkGraph from an ELF/x86-64 relocatable object. +/// +/// Note: The graph does not take ownership of the underlying buffer, nor copy +/// its contents. The caller is responsible for ensuring that the object buffer +/// outlives the graph. +Expected> +createLinkGraphFromELFObject_x86_64(MemoryBufferRef ObjectBuffer); + /// jit-link the given object buffer, which must be a ELF x86-64 object file. -void jitLink_ELF_x86_64(std::unique_ptr Ctx); +void link_ELF_x86_64(std::unique_ptr G, + std::unique_ptr Ctx); + +/// Return the string name of the given ELF x86-64 edge kind. +StringRef getELFX86RelocationKindName(Edge::Kind R); } // end namespace jitlink } // end namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h index 76f9dea4160f..e8c0e28b83aa 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h @@ -395,6 +395,10 @@ public: return Name; } + /// Rename this symbol. The client is responsible for updating scope and + /// linkage if this name-change requires it. + void setName(StringRef Name) { this->Name = Name; } + /// Returns true if this Symbol has content (potentially) defined within this /// object file (i.e. is anything but an external or absolute symbol). bool isDefined() const { @@ -782,21 +786,48 @@ public: Section::const_block_iterator, const Block *, getSectionConstBlocks>; - LinkGraph(std::string Name, unsigned PointerSize, + LinkGraph(std::string Name, const Triple &TT, unsigned PointerSize, support::endianness Endianness) - : Name(std::move(Name)), PointerSize(PointerSize), + : Name(std::move(Name)), TT(TT), PointerSize(PointerSize), Endianness(Endianness) {} /// Returns the name of this graph (usually the name of the original /// underlying MemoryBuffer). const std::string &getName() { return Name; } + /// Returns the target triple for this Graph. + const Triple &getTargetTriple() const { return TT; } + /// Returns the pointer size for use in this graph. unsigned getPointerSize() const { return PointerSize; } /// Returns the endianness of content in this graph. support::endianness getEndianness() const { return Endianness; } + /// Allocate a copy of the given string using the LinkGraph's allocator. + /// This can be useful when renaming symbols or adding new content to the + /// graph. + StringRef allocateString(StringRef Source) { + auto *AllocatedBuffer = Allocator.Allocate(Source.size()); + llvm::copy(Source, AllocatedBuffer); + return StringRef(AllocatedBuffer, Source.size()); + } + + /// Allocate a copy of the given string using the LinkGraph's allocator. + /// This can be useful when renaming symbols or adding new content to the + /// graph. + /// + /// Note: This Twine-based overload requires an extra string copy and an + /// extra heap allocation for large strings. The StringRef overload should + /// be preferred where possible. + StringRef allocateString(Twine Source) { + SmallString<256> TmpBuffer; + auto SourceStr = Source.toStringRef(TmpBuffer); + auto *AllocatedBuffer = Allocator.Allocate(SourceStr.size()); + llvm::copy(SourceStr, AllocatedBuffer); + return StringRef(AllocatedBuffer, SourceStr.size()); + } + /// Create a section with the given name, protection flags, and alignment. Section &createSection(StringRef Name, sys::Memory::ProtectionFlags Prot) { std::unique_ptr
Sec(new Section(Name, Prot, Sections.size())); @@ -959,7 +990,7 @@ public: Section &Sec = Sym.getBlock().getSection(); Sec.removeSymbol(Sym); } - Sym.makeExternal(createAddressable(false)); + Sym.makeExternal(createAddressable(0, false)); ExternalSymbols.insert(&Sym); } @@ -1019,6 +1050,7 @@ private: BumpPtrAllocator Allocator; std::string Name; + Triple TT; unsigned PointerSize; support::endianness Endianness; SectionList Sections; @@ -1191,15 +1223,31 @@ struct PassConfiguration { /// Notable use cases: Building GOT, stub, and TLV symbols. LinkGraphPassList PostPrunePasses; + /// Post-allocation passes. + /// + /// These passes are called on the graph after memory has been allocated and + /// defined nodes have been assigned their final addresses, but before the + /// context has been notified of these addresses. At this point externals + /// have not been resolved, and symbol content has not yet been copied into + /// working memory. + /// + /// Notable use cases: Setting up data structures associated with addresses + /// of defined symbols (e.g. a mapping of __dso_handle to JITDylib* for the + /// JIT runtime) -- using a PostAllocationPass for this ensures that the + /// data structures are in-place before any query for resolved symbols + /// can complete. + LinkGraphPassList PostAllocationPasses; + /// Pre-fixup passes. /// /// These passes are called on the graph after memory has been allocated, - /// content copied into working memory, and nodes have been assigned their - /// final addresses. + /// content copied into working memory, and all nodes (including externals) + /// have been assigned their final addresses, but before any fixups have been + /// applied. /// /// Notable use cases: Late link-time optimizations like GOT and stub /// elimination. - LinkGraphPassList PostAllocationPasses; + LinkGraphPassList PreFixupPasses; /// Post-fixup passes. /// @@ -1255,16 +1303,18 @@ class JITLinkContext { public: using LookupMap = DenseMap; + /// Create a JITLinkContext. + JITLinkContext(const JITLinkDylib *JD) : JD(JD) {} + /// Destroy a JITLinkContext. virtual ~JITLinkContext(); + /// Return the JITLinkDylib that this link is targeting, if any. + const JITLinkDylib *getJITLinkDylib() const { return JD; } + /// Return the MemoryManager to be used for this link. virtual JITLinkMemoryManager &getMemoryManager() = 0; - /// Returns a StringRef for the object buffer. - /// This method can not be called once takeObjectBuffer has been called. - virtual MemoryBufferRef getObjectBuffer() const = 0; - /// Notify this context that linking failed. /// Called by JITLink if linking cannot be completed. virtual void notifyFailed(Error Err) = 0; @@ -1279,7 +1329,11 @@ public: /// their final memory locations in the target process. At this point the /// LinkGraph can be inspected to build a symbol table, however the block /// content will not generally have been copied to the target location yet. - virtual void notifyResolved(LinkGraph &G) = 0; + /// + /// If the client detects an error in the LinkGraph state (e.g. unexpected or + /// missing symbols) they may return an error here. The error will be + /// propagated to notifyFailed and the linker will bail out. + virtual Error notifyResolved(LinkGraph &G) = 0; /// Called by JITLink to notify the context that the object has been /// finalized (i.e. emitted to memory and memory permissions set). If all of @@ -1305,16 +1359,25 @@ public: /// Called by JITLink to modify the pass pipeline prior to linking. /// The default version performs no modification. virtual Error modifyPassConfig(const Triple &TT, PassConfiguration &Config); + +private: + const JITLinkDylib *JD = nullptr; }; /// Marks all symbols in a graph live. This can be used as a default, /// conservative mark-live implementation. Error markAllSymbolsLive(LinkGraph &G); -/// Basic JITLink implementation. +/// Create a LinkGraph from the given object buffer. /// -/// This function will use sensible defaults for GOT and Stub handling. -void jitLink(std::unique_ptr Ctx); +/// Note: The graph does not take ownership of the underlying buffer, nor copy +/// its contents. The caller is responsible for ensuring that the object buffer +/// outlives the graph. +Expected> +createLinkGraphFromObject(MemoryBufferRef ObjectBuffer); + +/// Link the given graph. +void link(std::unique_ptr G, std::unique_ptr Ctx); } // end namespace jitlink } // end namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/JITLinkDylib.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/JITLinkDylib.h new file mode 100644 index 000000000000..2aa88cb50074 --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/JITLinkDylib.h @@ -0,0 +1,24 @@ +//===-- JITLinkDylib.h - JITLink Dylib type ---------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Defines the JITLinkDylib API. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_JITLINK_JITLINKDYLIB_H +#define LLVM_EXECUTIONENGINE_JITLINK_JITLINKDYLIB_H + +namespace llvm { +namespace jitlink { + +class JITLinkDylib {}; + +} // end namespace jitlink +} // end namespace llvm + +#endif // LLVM_EXECUTIONENGINE_JITLINK_JITLINKDYLIB_H diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h index 0c8514a60a50..cee7d6b09c48 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h @@ -14,10 +14,11 @@ #define LLVM_EXECUTIONENGINE_JITLINK_JITLINKMEMORYMANAGER_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ExecutionEngine/JITLink/JITLinkDylib.h" #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/Support/Error.h" -#include "llvm/Support/Memory.h" #include "llvm/Support/MSVCErrorWorkarounds.h" +#include "llvm/Support/Memory.h" #include #include @@ -93,18 +94,28 @@ public: virtual ~JITLinkMemoryManager(); /// Create an Allocation object. + /// + /// The JD argument represents the target JITLinkDylib, and can be used by + /// JITLinkMemoryManager implementers to manage per-dylib allocation pools + /// (e.g. one pre-reserved address space slab per dylib to ensure that all + /// allocations for the dylib are within a certain range). The JD argument + /// may be null (representing an allocation not associated with any + /// JITDylib. + /// + /// The request argument describes the segment sizes and permisssions being + /// requested. virtual Expected> - allocate(const SegmentsRequestMap &Request) = 0; + allocate(const JITLinkDylib *JD, const SegmentsRequestMap &Request) = 0; }; /// A JITLinkMemoryManager that allocates in-process memory. class InProcessMemoryManager : public JITLinkMemoryManager { public: Expected> - allocate(const SegmentsRequestMap &Request) override; + allocate(const JITLinkDylib *JD, const SegmentsRequestMap &Request) override; }; } // end namespace jitlink } // end namespace llvm -#endif // LLVM_EXECUTIONENGINE_JITLINK_JITLINK_H +#endif // LLVM_EXECUTIONENGINE_JITLINK_JITLINKMEMORYMANAGER_H diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/MachO.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/MachO.h index 7facb657a51c..b8432c4d26c6 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/MachO.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/MachO.h @@ -18,11 +18,20 @@ namespace llvm { namespace jitlink { +/// Create a LinkGraph from a MachO relocatable object. +/// +/// Note: The graph does not take ownership of the underlying buffer, nor copy +/// its contents. The caller is responsible for ensuring that the object buffer +/// outlives the graph. +Expected> +createLinkGraphFromMachOObject(MemoryBufferRef ObjectBuffer); + /// jit-link the given ObjBuffer, which must be a MachO object file. /// /// Uses conservative defaults for GOT and stub handling based on the target /// platform. -void jitLink_MachO(std::unique_ptr Ctx); +void link_MachO(std::unique_ptr G, + std::unique_ptr Ctx); } // end namespace jitlink } // end namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/MachO_arm64.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/MachO_arm64.h index d70b545fff86..c6aed2b60eac 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/MachO_arm64.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/MachO_arm64.h @@ -40,6 +40,14 @@ enum MachOARM64RelocationKind : Edge::Kind { } // namespace MachO_arm64_Edges +/// Create a LinkGraph from a MachO/arm64 relocatable object. +/// +/// Note: The graph does not take ownership of the underlying buffer, nor copy +/// its contents. The caller is responsible for ensuring that the object buffer +/// outlives the graph. +Expected> +createLinkGraphFromMachOObject_arm64(MemoryBufferRef ObjectBuffer); + /// jit-link the given object buffer, which must be a MachO arm64 object file. /// /// If PrePrunePasses is empty then a default mark-live pass will be inserted @@ -49,7 +57,8 @@ enum MachOARM64RelocationKind : Edge::Kind { /// If PostPrunePasses is empty then a default GOT-and-stubs insertion pass will /// be inserted. If PostPrunePasses is not empty then the caller is responsible /// for including a pass to insert GOT and stub edges. -void jitLink_MachO_arm64(std::unique_ptr Ctx); +void link_MachO_arm64(std::unique_ptr G, + std::unique_ptr Ctx); /// Return the string name of the given MachO arm64 edge kind. StringRef getMachOARM64RelocationKindName(Edge::Kind R); diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/MachO_x86_64.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/MachO_x86_64.h index 27fcdf4fa990..66c53d8c8291 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/MachO_x86_64.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/MachO_x86_64.h @@ -45,7 +45,15 @@ enum MachOX86RelocationKind : Edge::Kind { } // namespace MachO_x86_64_Edges -/// jit-link the given object buffer, which must be a MachO x86-64 object file. +/// Create a LinkGraph from a MachO/x86-64 relocatable object. +/// +/// Note: The graph does not take ownership of the underlying buffer, nor copy +/// its contents. The caller is responsible for ensuring that the object buffer +/// outlives the graph. +Expected> +createLinkGraphFromMachOObject_x86_64(MemoryBufferRef ObjectBuffer); + +/// jit-link the given LinkGraph. /// /// If PrePrunePasses is empty then a default mark-live pass will be inserted /// that will mark all exported atoms live. If PrePrunePasses is not empty, the @@ -54,7 +62,8 @@ enum MachOX86RelocationKind : Edge::Kind { /// If PostPrunePasses is empty then a default GOT-and-stubs insertion pass will /// be inserted. If PostPrunePasses is not empty then the caller is responsible /// for including a pass to insert GOT and stub edges. -void jitLink_MachO_x86_64(std::unique_ptr Ctx); +void link_MachO_x86_64(std::unique_ptr G, + std::unique_ptr Ctx); /// Return the string name of the given MachO x86-64 edge kind. StringRef getMachOX86RelocationKindName(Edge::Kind R); diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITSymbol.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITSymbol.h index 6f0030a18f47..9bbdd21f77de 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITSymbol.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITSymbol.h @@ -429,7 +429,7 @@ public: virtual JITSymbol findSymbol(const std::string &Name) = 0; private: - virtual void anchor(); + void anchor() override; }; } // end namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h index 9ecc0464dec1..91b12fd2277a 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h @@ -20,12 +20,10 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" -#include "llvm/ExecutionEngine/Orc/LambdaResolver.h" #include "llvm/ExecutionEngine/Orc/Layer.h" #include "llvm/ExecutionEngine/Orc/LazyReexports.h" -#include "llvm/ExecutionEngine/Orc/Legacy.h" -#include "llvm/ExecutionEngine/Orc/OrcError.h" #include "llvm/ExecutionEngine/Orc/Speculation.h" +#include "llvm/ExecutionEngine/Orc/Shared/OrcError.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/Constant.h" @@ -96,7 +94,8 @@ public: /// Emits the given module. This should not be called by clients: it will be /// called by the JIT when a definition added via the add method is requested. - void emit(MaterializationResponsibility R, ThreadSafeModule TSM) override; + void emit(std::unique_ptr R, + ThreadSafeModule TSM) override; private: struct PerDylibResources { @@ -120,7 +119,8 @@ private: void expandPartition(GlobalValueSet &Partition); - void emitPartition(MaterializationResponsibility R, ThreadSafeModule TSM, + void emitPartition(std::unique_ptr R, + ThreadSafeModule TSM, IRMaterializationUnit::SymbolNameToDefinitionMap Defs); mutable std::mutex CODLayerMutex; @@ -134,635 +134,6 @@ private: ImplSymbolMap *AliaseeImpls = nullptr; }; -/// Compile-on-demand layer. -/// -/// When a module is added to this layer a stub is created for each of its -/// function definitions. The stubs and other global values are immediately -/// added to the layer below. When a stub is called it triggers the extraction -/// of the function body from the original module. The extracted body is then -/// compiled and executed. -template -class LegacyCompileOnDemandLayer { -private: - template - class LambdaMaterializer final : public ValueMaterializer { - public: - LambdaMaterializer(MaterializerFtor M) : M(std::move(M)) {} - - Value *materialize(Value *V) final { return M(V); } - - private: - MaterializerFtor M; - }; - - template - LambdaMaterializer - createLambdaMaterializer(MaterializerFtor M) { - return LambdaMaterializer(std::move(M)); - } - - // Provide type-erasure for the Modules and MemoryManagers. - template - class ResourceOwner { - public: - ResourceOwner() = default; - ResourceOwner(const ResourceOwner &) = delete; - ResourceOwner &operator=(const ResourceOwner &) = delete; - virtual ~ResourceOwner() = default; - - virtual ResourceT& getResource() const = 0; - }; - - template - class ResourceOwnerImpl : public ResourceOwner { - public: - ResourceOwnerImpl(ResourcePtrT ResourcePtr) - : ResourcePtr(std::move(ResourcePtr)) {} - - ResourceT& getResource() const override { return *ResourcePtr; } - - private: - ResourcePtrT ResourcePtr; - }; - - template - std::unique_ptr> - wrapOwnership(ResourcePtrT ResourcePtr) { - using RO = ResourceOwnerImpl; - return std::make_unique(std::move(ResourcePtr)); - } - - struct LogicalDylib { - struct SourceModuleEntry { - std::unique_ptr SourceMod; - std::set StubsToClone; - }; - - using SourceModulesList = std::vector; - using SourceModuleHandle = typename SourceModulesList::size_type; - - LogicalDylib() = default; - - LogicalDylib(VModuleKey K, std::shared_ptr BackingResolver, - std::unique_ptr StubsMgr) - : K(std::move(K)), BackingResolver(std::move(BackingResolver)), - StubsMgr(std::move(StubsMgr)) {} - - SourceModuleHandle addSourceModule(std::unique_ptr M) { - SourceModuleHandle H = SourceModules.size(); - SourceModules.push_back(SourceModuleEntry()); - SourceModules.back().SourceMod = std::move(M); - return H; - } - - Module& getSourceModule(SourceModuleHandle H) { - return *SourceModules[H].SourceMod; - } - - std::set& getStubsToClone(SourceModuleHandle H) { - return SourceModules[H].StubsToClone; - } - - JITSymbol findSymbol(BaseLayerT &BaseLayer, const std::string &Name, - bool ExportedSymbolsOnly) { - if (auto Sym = StubsMgr->findStub(Name, ExportedSymbolsOnly)) - return Sym; - for (auto BLK : BaseLayerVModuleKeys) - if (auto Sym = BaseLayer.findSymbolIn(BLK, Name, ExportedSymbolsOnly)) - return Sym; - else if (auto Err = Sym.takeError()) - return std::move(Err); - return nullptr; - } - - Error removeModulesFromBaseLayer(BaseLayerT &BaseLayer) { - for (auto &BLK : BaseLayerVModuleKeys) - if (auto Err = BaseLayer.removeModule(BLK)) - return Err; - return Error::success(); - } - - VModuleKey K; - std::shared_ptr BackingResolver; - std::unique_ptr StubsMgr; - SymbolLinkagePromoter PromoteSymbols; - SourceModulesList SourceModules; - std::vector BaseLayerVModuleKeys; - }; - -public: - - /// Module partitioning functor. - using PartitioningFtor = std::function(Function&)>; - - /// Builder for IndirectStubsManagers. - using IndirectStubsManagerBuilderT = - std::function()>; - - using SymbolResolverGetter = - std::function(VModuleKey K)>; - - using SymbolResolverSetter = - std::function R)>; - - /// Construct a compile-on-demand layer instance. - LLVM_ATTRIBUTE_DEPRECATED( - LegacyCompileOnDemandLayer( - ExecutionSession &ES, BaseLayerT &BaseLayer, - SymbolResolverGetter GetSymbolResolver, - SymbolResolverSetter SetSymbolResolver, PartitioningFtor Partition, - CompileCallbackMgrT &CallbackMgr, - IndirectStubsManagerBuilderT CreateIndirectStubsManager, - bool CloneStubsIntoPartitions = true), - "ORCv1 layers (layers with the 'Legacy' prefix) are deprecated. Please " - "use " - "the ORCv2 LegacyCompileOnDemandLayer instead"); - - /// Legacy layer constructor with deprecation acknowledgement. - LegacyCompileOnDemandLayer( - ORCv1DeprecationAcknowledgement, ExecutionSession &ES, - BaseLayerT &BaseLayer, SymbolResolverGetter GetSymbolResolver, - SymbolResolverSetter SetSymbolResolver, PartitioningFtor Partition, - CompileCallbackMgrT &CallbackMgr, - IndirectStubsManagerBuilderT CreateIndirectStubsManager, - bool CloneStubsIntoPartitions = true) - : ES(ES), BaseLayer(BaseLayer), - GetSymbolResolver(std::move(GetSymbolResolver)), - SetSymbolResolver(std::move(SetSymbolResolver)), - Partition(std::move(Partition)), CompileCallbackMgr(CallbackMgr), - CreateIndirectStubsManager(std::move(CreateIndirectStubsManager)), - CloneStubsIntoPartitions(CloneStubsIntoPartitions) {} - - ~LegacyCompileOnDemandLayer() { - // FIXME: Report error on log. - while (!LogicalDylibs.empty()) - consumeError(removeModule(LogicalDylibs.begin()->first)); - } - - /// Add a module to the compile-on-demand layer. - Error addModule(VModuleKey K, std::unique_ptr M) { - - assert(!LogicalDylibs.count(K) && "VModuleKey K already in use"); - auto I = LogicalDylibs.insert( - LogicalDylibs.end(), - std::make_pair(K, LogicalDylib(K, GetSymbolResolver(K), - CreateIndirectStubsManager()))); - - return addLogicalModule(I->second, std::move(M)); - } - - /// Add extra modules to an existing logical module. - Error addExtraModule(VModuleKey K, std::unique_ptr M) { - return addLogicalModule(LogicalDylibs[K], std::move(M)); - } - - /// Remove the module represented by the given key. - /// - /// This will remove all modules in the layers below that were derived from - /// the module represented by K. - Error removeModule(VModuleKey K) { - auto I = LogicalDylibs.find(K); - assert(I != LogicalDylibs.end() && "VModuleKey K not valid here"); - auto Err = I->second.removeModulesFromBaseLayer(BaseLayer); - LogicalDylibs.erase(I); - return Err; - } - - /// Search for the given named symbol. - /// @param Name The name of the symbol to search for. - /// @param ExportedSymbolsOnly If true, search only for exported symbols. - /// @return A handle for the given named symbol, if it exists. - JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) { - for (auto &KV : LogicalDylibs) { - if (auto Sym = KV.second.StubsMgr->findStub(Name, ExportedSymbolsOnly)) - return Sym; - if (auto Sym = - findSymbolIn(KV.first, std::string(Name), ExportedSymbolsOnly)) - return Sym; - else if (auto Err = Sym.takeError()) - return std::move(Err); - } - return BaseLayer.findSymbol(std::string(Name), ExportedSymbolsOnly); - } - - /// Get the address of a symbol provided by this layer, or some layer - /// below this one. - JITSymbol findSymbolIn(VModuleKey K, const std::string &Name, - bool ExportedSymbolsOnly) { - assert(LogicalDylibs.count(K) && "VModuleKey K is not valid here"); - return LogicalDylibs[K].findSymbol(BaseLayer, Name, ExportedSymbolsOnly); - } - - /// Update the stub for the given function to point at FnBodyAddr. - /// This can be used to support re-optimization. - /// @return true if the function exists and the stub is updated, false - /// otherwise. - // - // FIXME: We should track and free associated resources (unused compile - // callbacks, uncompiled IR, and no-longer-needed/reachable function - // implementations). - Error updatePointer(std::string FuncName, JITTargetAddress FnBodyAddr) { - //Find out which logical dylib contains our symbol - auto LDI = LogicalDylibs.begin(); - for (auto LDE = LogicalDylibs.end(); LDI != LDE; ++LDI) { - if (auto LMResources = - LDI->getLogicalModuleResourcesForSymbol(FuncName, false)) { - Module &SrcM = LMResources->SourceModule->getResource(); - std::string CalledFnName = mangle(FuncName, SrcM.getDataLayout()); - if (auto Err = LMResources->StubsMgr->updatePointer(CalledFnName, - FnBodyAddr)) - return Err; - return Error::success(); - } - } - return make_error(FuncName); - } - -private: - Error addLogicalModule(LogicalDylib &LD, std::unique_ptr SrcMPtr) { - - // Rename anonymous globals and promote linkage to ensure that everything - // will resolve properly after we partition SrcM. - LD.PromoteSymbols(*SrcMPtr); - - // Create a logical module handle for SrcM within the logical dylib. - Module &SrcM = *SrcMPtr; - auto LMId = LD.addSourceModule(std::move(SrcMPtr)); - - // Create stub functions. - const DataLayout &DL = SrcM.getDataLayout(); - - typename IndirectStubsMgrT::StubInitsMap StubInits; - for (auto &F : SrcM) { - // Skip declarations. - if (F.isDeclaration()) - continue; - - // Skip weak functions for which we already have definitions. - auto MangledName = mangle(F.getName(), DL); - if (F.hasWeakLinkage() || F.hasLinkOnceLinkage()) { - if (auto Sym = LD.findSymbol(BaseLayer, MangledName, false)) - continue; - else if (auto Err = Sym.takeError()) - return Err; - } - - // Record all functions defined by this module. - if (CloneStubsIntoPartitions) - LD.getStubsToClone(LMId).insert(&F); - - // Create a callback, associate it with the stub for the function, - // and set the compile action to compile the partition containing the - // function. - auto CompileAction = [this, &LD, LMId, &F]() -> JITTargetAddress { - if (auto FnImplAddrOrErr = this->extractAndCompile(LD, LMId, F)) - return *FnImplAddrOrErr; - else { - // FIXME: Report error, return to 'abort' or something similar. - consumeError(FnImplAddrOrErr.takeError()); - return 0; - } - }; - if (auto CCAddr = - CompileCallbackMgr.getCompileCallback(std::move(CompileAction))) - StubInits[MangledName] = - std::make_pair(*CCAddr, JITSymbolFlags::fromGlobalValue(F)); - else - return CCAddr.takeError(); - } - - if (auto Err = LD.StubsMgr->createStubs(StubInits)) - return Err; - - // If this module doesn't contain any globals, aliases, or module flags then - // we can bail out early and avoid the overhead of creating and managing an - // empty globals module. - if (SrcM.global_empty() && SrcM.alias_empty() && - !SrcM.getModuleFlagsMetadata()) - return Error::success(); - - // Create the GlobalValues module. - auto GVsM = std::make_unique((SrcM.getName() + ".globals").str(), - SrcM.getContext()); - GVsM->setDataLayout(DL); - - ValueToValueMapTy VMap; - - // Clone global variable decls. - for (auto &GV : SrcM.globals()) - if (!GV.isDeclaration() && !VMap.count(&GV)) - cloneGlobalVariableDecl(*GVsM, GV, &VMap); - - // And the aliases. - for (auto &A : SrcM.aliases()) - if (!VMap.count(&A)) - cloneGlobalAliasDecl(*GVsM, A, VMap); - - // Clone the module flags. - cloneModuleFlagsMetadata(*GVsM, SrcM, VMap); - - // Now we need to clone the GV and alias initializers. - - // Initializers may refer to functions declared (but not defined) in this - // module. Build a materializer to clone decls on demand. - auto Materializer = createLambdaMaterializer( - [&LD, &GVsM](Value *V) -> Value* { - if (auto *F = dyn_cast(V)) { - // Decls in the original module just get cloned. - if (F->isDeclaration()) - return cloneFunctionDecl(*GVsM, *F); - - // Definitions in the original module (which we have emitted stubs - // for at this point) get turned into a constant alias to the stub - // instead. - const DataLayout &DL = GVsM->getDataLayout(); - std::string FName = mangle(F->getName(), DL); - unsigned PtrBitWidth = DL.getPointerTypeSizeInBits(F->getType()); - JITTargetAddress StubAddr = - LD.StubsMgr->findStub(FName, false).getAddress(); - - ConstantInt *StubAddrCI = - ConstantInt::get(GVsM->getContext(), APInt(PtrBitWidth, StubAddr)); - Constant *Init = ConstantExpr::getCast(Instruction::IntToPtr, - StubAddrCI, F->getType()); - return GlobalAlias::create(F->getFunctionType(), - F->getType()->getAddressSpace(), - F->getLinkage(), F->getName(), - Init, GVsM.get()); - } - // else.... - return nullptr; - }); - - // Clone the global variable initializers. - for (auto &GV : SrcM.globals()) - if (!GV.isDeclaration()) - moveGlobalVariableInitializer(GV, VMap, &Materializer); - - // Clone the global alias initializers. - for (auto &A : SrcM.aliases()) { - auto *NewA = cast(VMap[&A]); - assert(NewA && "Alias not cloned?"); - Value *Init = MapValue(A.getAliasee(), VMap, RF_None, nullptr, - &Materializer); - NewA->setAliasee(cast(Init)); - } - - // Build a resolver for the globals module and add it to the base layer. - auto LegacyLookup = [this, &LD](StringRef Name) -> JITSymbol { - if (auto Sym = LD.StubsMgr->findStub(Name, false)) - return Sym; - - if (auto Sym = LD.findSymbol(BaseLayer, std::string(Name), false)) - return Sym; - else if (auto Err = Sym.takeError()) - return std::move(Err); - - return nullptr; - }; - - auto GVsResolver = createSymbolResolver( - [&LD, LegacyLookup](const SymbolNameSet &Symbols) { - auto RS = getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup); - - if (!RS) { - logAllUnhandledErrors( - RS.takeError(), errs(), - "CODLayer/GVsResolver responsibility set lookup failed: "); - return SymbolNameSet(); - } - - if (RS->size() == Symbols.size()) - return *RS; - - SymbolNameSet NotFoundViaLegacyLookup; - for (auto &S : Symbols) - if (!RS->count(S)) - NotFoundViaLegacyLookup.insert(S); - auto RS2 = - LD.BackingResolver->getResponsibilitySet(NotFoundViaLegacyLookup); - - for (auto &S : RS2) - (*RS).insert(S); - - return *RS; - }, - [this, &LD, - LegacyLookup](std::shared_ptr Query, - SymbolNameSet Symbols) { - auto NotFoundViaLegacyLookup = - lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup); - return LD.BackingResolver->lookup(Query, NotFoundViaLegacyLookup); - }); - - SetSymbolResolver(LD.K, std::move(GVsResolver)); - - if (auto Err = BaseLayer.addModule(LD.K, std::move(GVsM))) - return Err; - - LD.BaseLayerVModuleKeys.push_back(LD.K); - - return Error::success(); - } - - static std::string mangle(StringRef Name, const DataLayout &DL) { - std::string MangledName; - { - raw_string_ostream MangledNameStream(MangledName); - Mangler::getNameWithPrefix(MangledNameStream, Name, DL); - } - return MangledName; - } - - Expected - extractAndCompile(LogicalDylib &LD, - typename LogicalDylib::SourceModuleHandle LMId, - Function &F) { - Module &SrcM = LD.getSourceModule(LMId); - - // If F is a declaration we must already have compiled it. - if (F.isDeclaration()) - return 0; - - // Grab the name of the function being called here. - std::string CalledFnName = mangle(F.getName(), SrcM.getDataLayout()); - - JITTargetAddress CalledAddr = 0; - auto Part = Partition(F); - if (auto PartKeyOrErr = emitPartition(LD, LMId, Part)) { - auto &PartKey = *PartKeyOrErr; - for (auto *SubF : Part) { - std::string FnName = mangle(SubF->getName(), SrcM.getDataLayout()); - if (auto FnBodySym = BaseLayer.findSymbolIn(PartKey, FnName, false)) { - if (auto FnBodyAddrOrErr = FnBodySym.getAddress()) { - JITTargetAddress FnBodyAddr = *FnBodyAddrOrErr; - - // If this is the function we're calling record the address so we can - // return it from this function. - if (SubF == &F) - CalledAddr = FnBodyAddr; - - // Update the function body pointer for the stub. - if (auto EC = LD.StubsMgr->updatePointer(FnName, FnBodyAddr)) - return 0; - - } else - return FnBodyAddrOrErr.takeError(); - } else if (auto Err = FnBodySym.takeError()) - return std::move(Err); - else - llvm_unreachable("Function not emitted for partition"); - } - - LD.BaseLayerVModuleKeys.push_back(PartKey); - } else - return PartKeyOrErr.takeError(); - - return CalledAddr; - } - - template - Expected - emitPartition(LogicalDylib &LD, - typename LogicalDylib::SourceModuleHandle LMId, - const PartitionT &Part) { - Module &SrcM = LD.getSourceModule(LMId); - - // Create the module. - std::string NewName(SrcM.getName()); - for (auto *F : Part) { - NewName += "."; - NewName += F->getName(); - } - - auto M = std::make_unique(NewName, SrcM.getContext()); - M->setDataLayout(SrcM.getDataLayout()); - ValueToValueMapTy VMap; - - auto Materializer = createLambdaMaterializer([&LD, &LMId, - &M](Value *V) -> Value * { - if (auto *GV = dyn_cast(V)) - return cloneGlobalVariableDecl(*M, *GV); - - if (auto *F = dyn_cast(V)) { - // Check whether we want to clone an available_externally definition. - if (!LD.getStubsToClone(LMId).count(F)) - return cloneFunctionDecl(*M, *F); - - // Ok - we want an inlinable stub. For that to work we need a decl - // for the stub pointer. - auto *StubPtr = createImplPointer(*F->getType(), *M, - F->getName() + "$stub_ptr", nullptr); - auto *ClonedF = cloneFunctionDecl(*M, *F); - makeStub(*ClonedF, *StubPtr); - ClonedF->setLinkage(GlobalValue::AvailableExternallyLinkage); - ClonedF->addFnAttr(Attribute::AlwaysInline); - return ClonedF; - } - - if (auto *A = dyn_cast(V)) { - auto *Ty = A->getValueType(); - if (Ty->isFunctionTy()) - return Function::Create(cast(Ty), - GlobalValue::ExternalLinkage, A->getName(), - M.get()); - - return new GlobalVariable(*M, Ty, false, GlobalValue::ExternalLinkage, - nullptr, A->getName(), nullptr, - GlobalValue::NotThreadLocal, - A->getType()->getAddressSpace()); - } - - return nullptr; - }); - - // Create decls in the new module. - for (auto *F : Part) - cloneFunctionDecl(*M, *F, &VMap); - - // Move the function bodies. - for (auto *F : Part) - moveFunctionBody(*F, VMap, &Materializer); - - auto K = ES.allocateVModule(); - - auto LegacyLookup = [this, &LD](StringRef Name) -> JITSymbol { - return LD.findSymbol(BaseLayer, std::string(Name), false); - }; - - // Create memory manager and symbol resolver. - auto Resolver = createSymbolResolver( - [&LD, LegacyLookup](const SymbolNameSet &Symbols) { - auto RS = getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup); - if (!RS) { - logAllUnhandledErrors( - RS.takeError(), errs(), - "CODLayer/SubResolver responsibility set lookup failed: "); - return SymbolNameSet(); - } - - if (RS->size() == Symbols.size()) - return *RS; - - SymbolNameSet NotFoundViaLegacyLookup; - for (auto &S : Symbols) - if (!RS->count(S)) - NotFoundViaLegacyLookup.insert(S); - - auto RS2 = - LD.BackingResolver->getResponsibilitySet(NotFoundViaLegacyLookup); - - for (auto &S : RS2) - (*RS).insert(S); - - return *RS; - }, - [this, &LD, LegacyLookup](std::shared_ptr Q, - SymbolNameSet Symbols) { - auto NotFoundViaLegacyLookup = - lookupWithLegacyFn(ES, *Q, Symbols, LegacyLookup); - return LD.BackingResolver->lookup(Q, - std::move(NotFoundViaLegacyLookup)); - }); - SetSymbolResolver(K, std::move(Resolver)); - - if (auto Err = BaseLayer.addModule(std::move(K), std::move(M))) - return std::move(Err); - - return K; - } - - ExecutionSession &ES; - BaseLayerT &BaseLayer; - SymbolResolverGetter GetSymbolResolver; - SymbolResolverSetter SetSymbolResolver; - PartitioningFtor Partition; - CompileCallbackMgrT &CompileCallbackMgr; - IndirectStubsManagerBuilderT CreateIndirectStubsManager; - - std::map LogicalDylibs; - bool CloneStubsIntoPartitions; -}; - -template -LegacyCompileOnDemandLayer:: - LegacyCompileOnDemandLayer( - ExecutionSession &ES, BaseLayerT &BaseLayer, - SymbolResolverGetter GetSymbolResolver, - SymbolResolverSetter SetSymbolResolver, PartitioningFtor Partition, - CompileCallbackMgrT &CallbackMgr, - IndirectStubsManagerBuilderT CreateIndirectStubsManager, - bool CloneStubsIntoPartitions) - : ES(ES), BaseLayer(BaseLayer), - GetSymbolResolver(std::move(GetSymbolResolver)), - SetSymbolResolver(std::move(SetSymbolResolver)), - Partition(std::move(Partition)), CompileCallbackMgr(CallbackMgr), - CreateIndirectStubsManager(std::move(CreateIndirectStubsManager)), - CloneStubsIntoPartitions(CloneStubsIntoPartitions) {} - } // end namespace orc } // end namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h index 8376d163d57a..c7ba57228ab7 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h @@ -28,8 +28,6 @@ class TargetMachine; namespace orc { -class JITTargetMachineBuilder; - IRSymbolMapper::ManglingOptions irManglingOptionsFromTargetOptions(const TargetOptions &Opts); diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Core.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Core.h index a117acefd2d3..4a4b58ed32e3 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Core.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Core.h @@ -16,11 +16,14 @@ #include "llvm/ADT/BitmaskEnum.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/FunctionExtras.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ExecutionEngine/JITLink/JITLinkDylib.h" #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/ExecutionEngine/Orc/SymbolStringPool.h" #include "llvm/ExecutionEngine/OrcV1Deprecation.h" #include "llvm/Support/Debug.h" +#include #include #include @@ -33,11 +36,67 @@ class ExecutionSession; class MaterializationUnit; class MaterializationResponsibility; class JITDylib; +class ResourceTracker; +class InProgressLookupState; + enum class SymbolState : uint8_t; -/// VModuleKey provides a unique identifier (allocated and managed by -/// ExecutionSessions) for a module added to the JIT. -using VModuleKey = uint64_t; +using ResourceTrackerSP = IntrusiveRefCntPtr; +using JITDylibSP = IntrusiveRefCntPtr; + +using ResourceKey = uintptr_t; + +/// API to remove / transfer ownership of JIT resources. +class ResourceTracker : public ThreadSafeRefCountedBase { +private: + friend class ExecutionSession; + friend class JITDylib; + friend class MaterializationResponsibility; + +public: + ResourceTracker(const ResourceTracker &) = delete; + ResourceTracker &operator=(const ResourceTracker &) = delete; + ResourceTracker(ResourceTracker &&) = delete; + ResourceTracker &operator=(ResourceTracker &&) = delete; + + ~ResourceTracker(); + + /// Return the JITDylib targeted by this tracker. + JITDylib &getJITDylib() const { + return *reinterpret_cast(JDAndFlag.load() & + ~static_cast(1)); + } + + /// Remove all resources associated with this key. + Error remove(); + + /// Transfer all resources associated with this key to the given + /// tracker, which must target the same JITDylib as this one. + void transferTo(ResourceTracker &DstRT); + + /// Return true if this tracker has become defunct. + bool isDefunct() const { return JDAndFlag.load() & 0x1; } + + /// Returns the key associated with this tracker. + /// This method should not be used except for debug logging: there is no + /// guarantee that the returned value will remain valid. + ResourceKey getKeyUnsafe() const { return reinterpret_cast(this); } + +private: + ResourceTracker(JITDylibSP JD); + + void makeDefunct(); + + std::atomic_uintptr_t JDAndFlag; +}; + +/// Listens for ResourceTracker operations. +class ResourceManager { +public: + virtual ~ResourceManager(); + virtual Error handleRemoveResources(ResourceKey K) = 0; + virtual void handleTransferResources(ResourceKey DstK, ResourceKey SrcK) = 0; +}; /// A set of symbol names (represented by SymbolStringPtrs for // efficiency). @@ -158,9 +217,19 @@ public: /// Add an element to the set. The client is responsible for checking that /// duplicates are not added. - void add(SymbolStringPtr Name, - SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) { + SymbolLookupSet & + add(SymbolStringPtr Name, + SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) { Symbols.push_back(std::make_pair(std::move(Name), Flags)); + return *this; + } + + /// Quickly append one lookup set to another. + SymbolLookupSet &append(SymbolLookupSet Other) { + Symbols.reserve(Symbols.size() + Other.size()); + for (auto &KV : Other) + Symbols.push_back(std::move(KV)); + return *this; } bool empty() const { return Symbols.empty(); } @@ -287,7 +356,7 @@ public: for (UnderlyingVector::size_type I = 1; I != Symbols.size(); ++I) if (Symbols[I].first == Symbols[I - 1].first) return true; - return true; + return false; } #endif @@ -318,6 +387,18 @@ using RegisterDependenciesFunction = /// are no dependants to register with. extern RegisterDependenciesFunction NoDependenciesToRegister; +class ResourceTrackerDefunct : public ErrorInfo { +public: + static char ID; + + ResourceTrackerDefunct(ResourceTrackerSP RT); + std::error_code convertToErrorCode() const override; + void log(raw_ostream &OS) const override; + +private: + ResourceTrackerSP RT; +}; + /// Used to notify a JITDylib that the given set of symbols failed to /// materialize. class FailedToMaterialize : public ErrorInfo { @@ -408,9 +489,10 @@ private: /// emit symbols, or abandon materialization by notifying any unmaterialized /// symbols of an error. class MaterializationResponsibility { - friend class MaterializationUnit; + friend class ExecutionSession; + public: - MaterializationResponsibility(MaterializationResponsibility &&) = default; + MaterializationResponsibility(MaterializationResponsibility &&) = delete; MaterializationResponsibility & operator=(MaterializationResponsibility &&) = delete; @@ -419,12 +501,15 @@ public: /// emitted or notified of an error. ~MaterializationResponsibility(); + /// Returns the ResourceTracker for this instance. + template Error withResourceKeyDo(Func &&F) const; + /// Returns the target JITDylib that these symbols are being materialized /// into. JITDylib &getTargetJITDylib() const { return *JD; } - /// Returns the VModuleKey for this instance. - VModuleKey getVModuleKey() const { return K; } + /// Returns the ExecutionSession for this instance. + ExecutionSession &getExecutionSession(); /// Returns the symbol flags map for this responsibility instance. /// Note: The returned flags may have transient flags (Lazy, Materializing) @@ -509,13 +594,13 @@ public: /// materializers to break up work based on run-time information (e.g. /// by introspecting which symbols have actually been looked up and /// materializing only those). - void replace(std::unique_ptr MU); + Error replace(std::unique_ptr MU); /// Delegates responsibility for the given symbols to the returned /// materialization responsibility. Useful for breaking up work between /// threads, or different kinds of materialization processes. - MaterializationResponsibility delegate(const SymbolNameSet &Symbols, - VModuleKey NewKey = VModuleKey()); + Expected> + delegate(const SymbolNameSet &Symbols); void addDependencies(const SymbolStringPtr &Name, const SymbolDependenceMap &Dependencies); @@ -526,19 +611,17 @@ public: private: /// Create a MaterializationResponsibility for the given JITDylib and /// initial symbols. - MaterializationResponsibility(std::shared_ptr JD, - SymbolFlagsMap SymbolFlags, - SymbolStringPtr InitSymbol, VModuleKey K) + MaterializationResponsibility(JITDylibSP JD, SymbolFlagsMap SymbolFlags, + SymbolStringPtr InitSymbol) : JD(std::move(JD)), SymbolFlags(std::move(SymbolFlags)), - InitSymbol(std::move(InitSymbol)), K(std::move(K)) { - assert(this->JD && "Cannot initialize with null JD"); + InitSymbol(std::move(InitSymbol)) { + assert(this->JD && "Cannot initialize with null JITDylib"); assert(!this->SymbolFlags.empty() && "Materializing nothing?"); } - std::shared_ptr JD; + JITDylibSP JD; SymbolFlagsMap SymbolFlags; SymbolStringPtr InitSymbol; - VModuleKey K; }; /// A MaterializationUnit represents a set of symbol definitions that can @@ -555,9 +638,9 @@ class MaterializationUnit { public: MaterializationUnit(SymbolFlagsMap InitalSymbolFlags, - SymbolStringPtr InitSymbol, VModuleKey K) + SymbolStringPtr InitSymbol) : SymbolFlags(std::move(InitalSymbolFlags)), - InitSymbol(std::move(InitSymbol)), K(std::move(K)) { + InitSymbol(std::move(InitSymbol)) { assert((!this->InitSymbol || this->SymbolFlags.count(this->InitSymbol)) && "If set, InitSymbol should appear in InitialSymbolFlags map"); } @@ -577,7 +660,8 @@ public: /// Implementations of this method should materialize all symbols /// in the materialzation unit, except for those that have been /// previously discarded. - virtual void materialize(MaterializationResponsibility R) = 0; + virtual void + materialize(std::unique_ptr R) = 0; /// Called by JITDylibs to notify MaterializationUnits that the given symbol /// has been overridden. @@ -589,17 +673,10 @@ public: protected: SymbolFlagsMap SymbolFlags; SymbolStringPtr InitSymbol; - VModuleKey K; private: virtual void anchor(); - MaterializationResponsibility - createMaterializationResponsibility(std::shared_ptr JD) { - return MaterializationResponsibility(std::move(JD), std::move(SymbolFlags), - std::move(InitSymbol), K); - } - /// Implementations of this method should discard the given symbol /// from the source (e.g. if the source is an LLVM IR Module and the /// symbol is a function, delete the function body or mark it available @@ -607,21 +684,18 @@ private: virtual void discard(const JITDylib &JD, const SymbolStringPtr &Name) = 0; }; -using MaterializationUnitList = - std::vector>; - /// A MaterializationUnit implementation for pre-existing absolute symbols. /// /// All symbols will be resolved and marked ready as soon as the unit is /// materialized. class AbsoluteSymbolsMaterializationUnit : public MaterializationUnit { public: - AbsoluteSymbolsMaterializationUnit(SymbolMap Symbols, VModuleKey K); + AbsoluteSymbolsMaterializationUnit(SymbolMap Symbols); StringRef getName() const override; private: - void materialize(MaterializationResponsibility R) override; + void materialize(std::unique_ptr R) override; void discard(const JITDylib &JD, const SymbolStringPtr &Name) override; static SymbolFlagsMap extractFlags(const SymbolMap &Symbols); @@ -639,9 +713,9 @@ private: /// \endcode /// inline std::unique_ptr -absoluteSymbols(SymbolMap Symbols, VModuleKey K = VModuleKey()) { +absoluteSymbols(SymbolMap Symbols) { return std::make_unique( - std::move(Symbols), std::move(K)); + std::move(Symbols)); } /// A materialization unit for symbol aliases. Allows existing symbols to be @@ -658,12 +732,12 @@ public: /// resolved. ReExportsMaterializationUnit(JITDylib *SourceJD, JITDylibLookupFlags SourceJDLookupFlags, - SymbolAliasMap Aliases, VModuleKey K); + SymbolAliasMap Aliases); StringRef getName() const override; private: - void materialize(MaterializationResponsibility R) override; + void materialize(std::unique_ptr R) override; void discard(const JITDylib &JD, const SymbolStringPtr &Name) override; static SymbolFlagsMap extractFlags(const SymbolAliasMap &Aliases); @@ -684,10 +758,9 @@ private: /// return Err; /// \endcode inline std::unique_ptr -symbolAliases(SymbolAliasMap Aliases, VModuleKey K = VModuleKey()) { +symbolAliases(SymbolAliasMap Aliases) { return std::make_unique( - nullptr, JITDylibLookupFlags::MatchAllSymbols, std::move(Aliases), - std::move(K)); + nullptr, JITDylibLookupFlags::MatchAllSymbols, std::move(Aliases)); } /// Create a materialization unit for re-exporting symbols from another JITDylib @@ -696,10 +769,9 @@ symbolAliases(SymbolAliasMap Aliases, VModuleKey K = VModuleKey()) { inline std::unique_ptr reexports(JITDylib &SourceJD, SymbolAliasMap Aliases, JITDylibLookupFlags SourceJDLookupFlags = - JITDylibLookupFlags::MatchExportedSymbolsOnly, - VModuleKey K = VModuleKey()) { + JITDylibLookupFlags::MatchExportedSymbolsOnly) { return std::make_unique( - &SourceJD, SourceJDLookupFlags, std::move(Aliases), std::move(K)); + &SourceJD, SourceJDLookupFlags, std::move(Aliases)); } /// Build a SymbolAliasMap for the common case where you want to re-export @@ -723,8 +795,10 @@ enum class SymbolState : uint8_t { /// makes a callback when all symbols are available. class AsynchronousSymbolQuery { friend class ExecutionSession; + friend class InProgressFullLookupState; friend class JITDylib; friend class JITSymbolResolverAdapter; + friend class MaterializationResponsibility; public: /// Create a query for the given symbols. The NotifyComplete @@ -757,8 +831,6 @@ private: void dropSymbol(const SymbolStringPtr &Name); - bool canStillFail(); - void handleFailed(Error Err); void detach(); @@ -770,34 +842,62 @@ private: SymbolState RequiredState; }; +/// Wraps state for a lookup-in-progress. +/// DefinitionGenerators can optionally take ownership of a LookupState object +/// to suspend a lookup-in-progress while they search for definitions. +class LookupState { + friend class OrcV2CAPIHelper; + friend class ExecutionSession; + +public: + LookupState(); + LookupState(LookupState &&); + LookupState &operator=(LookupState &&); + ~LookupState(); + + /// Continue the lookup. This can be called by DefinitionGenerators + /// to re-start a captured query-application operation. + void continueLookup(Error Err); + +private: + LookupState(std::unique_ptr IPLS); + + // For C API. + void reset(InProgressLookupState *IPLS); + + std::unique_ptr IPLS; +}; + +/// Definition generators can be attached to JITDylibs to generate new +/// definitions for otherwise unresolved symbols during lookup. +class DefinitionGenerator { +public: + virtual ~DefinitionGenerator(); + + /// DefinitionGenerators should override this method to insert new + /// definitions into the parent JITDylib. K specifies the kind of this + /// lookup. JD specifies the target JITDylib being searched, and + /// JDLookupFlags specifies whether the search should match against + /// hidden symbols. Finally, Symbols describes the set of unresolved + /// symbols and their associated lookup flags. + virtual Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD, + JITDylibLookupFlags JDLookupFlags, + const SymbolLookupSet &LookupSet) = 0; +}; + /// A symbol table that supports asynchoronous symbol queries. /// /// Represents a virtual shared object. Instances can not be copied or moved, so /// their addresses may be used as keys for resource management. /// JITDylib state changes must be made via an ExecutionSession to guarantee /// that they are synchronized with respect to other JITDylib operations. -class JITDylib : public std::enable_shared_from_this { +class JITDylib : public ThreadSafeRefCountedBase, + public jitlink::JITLinkDylib { friend class AsynchronousSymbolQuery; friend class ExecutionSession; friend class Platform; friend class MaterializationResponsibility; public: - /// Definition generators can be attached to JITDylibs to generate new - /// definitions for otherwise unresolved symbols during lookup. - class DefinitionGenerator { - public: - virtual ~DefinitionGenerator(); - - /// DefinitionGenerators should override this method to insert new - /// definitions into the parent JITDylib. K specifies the kind of this - /// lookup. JD specifies the target JITDylib being searched, and - /// JDLookupFlags specifies whether the search should match against - /// hidden symbols. Finally, Symbols describes the set of unresolved - /// symbols and their associated lookup flags. - virtual Error tryToGenerate(LookupKind K, JITDylib &JD, - JITDylibLookupFlags JDLookupFlags, - const SymbolLookupSet &LookupSet) = 0; - }; using AsynchronousSymbolQuerySet = std::set>; @@ -813,6 +913,21 @@ public: /// Get a reference to the ExecutionSession for this JITDylib. ExecutionSession &getExecutionSession() const { return ES; } + /// Calls remove on all trackers currently associated with this JITDylib. + /// Does not run static deinits. + /// + /// Note that removal happens outside the session lock, so new code may be + /// added concurrently while the clear is underway, and the newly added + /// code will *not* be cleared. Adding new code concurrently with a clear + /// is usually a bug and should be avoided. + Error clear(); + + /// Get the default resource tracker for this JITDylib. + ResourceTrackerSP getDefaultResourceTracker(); + + /// Create a resource tracker for this JITDylib. + ResourceTrackerSP createResourceTracker(); + /// Adds a definition generator to this JITDylib and returns a referenece to /// it. /// @@ -873,10 +988,13 @@ public: /// Define all symbols provided by the materialization unit to be part of this /// JITDylib. /// + /// If RT is not specified then the default resource tracker will be used. + /// /// This overload always takes ownership of the MaterializationUnit. If any /// errors occur, the MaterializationUnit consumed. template - Error define(std::unique_ptr &&MU); + Error define(std::unique_ptr &&MU, + ResourceTrackerSP RT = nullptr); /// Define all symbols provided by the materialization unit to be part of this /// JITDylib. @@ -886,7 +1004,8 @@ public: /// may allow the caller to modify the MaterializationUnit to correct the /// issue, then re-call define. template - Error define(std::unique_ptr &MU); + Error define(std::unique_ptr &MU, + ResourceTrackerSP RT = nullptr); /// Tries to remove the given symbols. /// @@ -900,41 +1019,47 @@ public: /// left unmodified (no symbols are removed). Error remove(const SymbolNameSet &Names); - /// Search the given JITDylib for the symbols in Symbols. If found, store - /// the flags for each symbol in Flags. If any required symbols are not found - /// then an error will be returned. - Expected lookupFlags(LookupKind K, - JITDylibLookupFlags JDLookupFlags, - SymbolLookupSet LookupSet); - /// Dump current JITDylib state to OS. void dump(raw_ostream &OS); - /// FIXME: Remove this when we remove the old ORC layers. - /// Search the given JITDylibs in order for the symbols in Symbols. Results - /// (once they become available) will be returned via the given Query. - /// - /// If any symbol is not found then the unresolved symbols will be returned, - /// and the query will not be applied. The Query is not failed and can be - /// re-used in a subsequent lookup once the symbols have been added, or - /// manually failed. - Expected - legacyLookup(std::shared_ptr Q, SymbolNameSet Names); + /// Returns the given JITDylibs and all of their transitive dependencies in + /// DFS order (based on linkage relationships). Each JITDylib will appear + /// only once. + static std::vector getDFSLinkOrder(ArrayRef JDs); + + /// Returns the given JITDylibs and all of their transitive dependensies in + /// reverse DFS order (based on linkage relationships). Each JITDylib will + /// appear only once. + static std::vector + getReverseDFSLinkOrder(ArrayRef JDs); + + /// Return this JITDylib and its transitive dependencies in DFS order + /// based on linkage relationships. + std::vector getDFSLinkOrder(); + + /// Rteurn this JITDylib and its transitive dependencies in reverse DFS order + /// based on linkage relationships. + std::vector getReverseDFSLinkOrder(); private: using AsynchronousSymbolQueryList = std::vector>; struct UnmaterializedInfo { - UnmaterializedInfo(std::unique_ptr MU) - : MU(std::move(MU)) {} + UnmaterializedInfo(std::unique_ptr MU, + ResourceTracker *RT) + : MU(std::move(MU)), RT(RT) {} std::unique_ptr MU; + ResourceTracker *RT; }; using UnmaterializedInfosMap = DenseMap>; + using UnmaterializedInfosList = + std::vector>; + struct MaterializingInfo { SymbolDependenceMap Dependants; SymbolDependenceMap UnemittedDependencies; @@ -1001,25 +1126,16 @@ private: JITDylib(ExecutionSession &ES, std::string Name); - Error defineImpl(MaterializationUnit &MU); - - void lookupFlagsImpl(SymbolFlagsMap &Result, LookupKind K, - JITDylibLookupFlags JDLookupFlags, - SymbolLookupSet &Unresolved); + ResourceTrackerSP getTracker(MaterializationResponsibility &MR); + std::pair> + removeTracker(ResourceTracker &RT); - Error lodgeQuery(MaterializationUnitList &MUs, - std::shared_ptr &Q, LookupKind K, - JITDylibLookupFlags JDLookupFlags, - SymbolLookupSet &Unresolved); + void transferTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT); - Error lodgeQueryImpl(MaterializationUnitList &MUs, - std::shared_ptr &Q, - LookupKind K, JITDylibLookupFlags JDLookupFlags, - SymbolLookupSet &Unresolved); + Error defineImpl(MaterializationUnit &MU); - bool lookupImpl(std::shared_ptr &Q, - std::vector> &MUs, - SymbolLookupSet &Unresolved); + void installMaterializationUnit(std::unique_ptr MU, + ResourceTracker &RT); void detachQueryHelper(AsynchronousSymbolQuery &Q, const SymbolNameSet &QuerySymbols); @@ -1030,29 +1146,45 @@ private: Expected defineMaterializing(SymbolFlagsMap SymbolFlags); - void replace(std::unique_ptr MU); + Error replace(MaterializationResponsibility &FromMR, + std::unique_ptr MU); + + Expected> + delegate(MaterializationResponsibility &FromMR, SymbolFlagsMap SymbolFlags, + SymbolStringPtr InitSymbol); SymbolNameSet getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) const; void addDependencies(const SymbolStringPtr &Name, const SymbolDependenceMap &Dependants); - Error resolve(const SymbolMap &Resolved); + Error resolve(MaterializationResponsibility &MR, const SymbolMap &Resolved); + + Error emit(MaterializationResponsibility &MR, const SymbolFlagsMap &Emitted); - Error emit(const SymbolFlagsMap &Emitted); + void unlinkMaterializationResponsibility(MaterializationResponsibility &MR); using FailedSymbolsWorklist = std::vector>; - static void notifyFailed(FailedSymbolsWorklist FailedSymbols); + + static std::pair> + failSymbols(FailedSymbolsWorklist); ExecutionSession &ES; std::string JITDylibName; + std::mutex GeneratorsMutex; bool Open = true; SymbolTable Symbols; UnmaterializedInfosMap UnmaterializedInfos; MaterializingInfosMap MaterializingInfos; - std::vector> DefGenerators; + std::vector> DefGenerators; JITDylibSearchOrder LinkOrder; + ResourceTrackerSP DefaultTracker; + + // Map trackers to sets of symbols tracked. + DenseMap TrackerSymbols; + DenseMap MRTrackers; }; /// Platforms set up standard symbols and mediate interactions between dynamic @@ -1071,11 +1203,12 @@ public: /// This method will be called under the ExecutionSession lock each time a /// MaterializationUnit is added to a JITDylib. - virtual Error notifyAdding(JITDylib &JD, const MaterializationUnit &MU) = 0; + virtual Error notifyAdding(ResourceTracker &RT, + const MaterializationUnit &MU) = 0; /// This method will be called under the ExecutionSession lock when a - /// VModuleKey is removed. - virtual Error notifyRemoving(JITDylib &JD, VModuleKey K) = 0; + /// ResourceTracker is removed. + virtual Error notifyRemoving(ResourceTracker &RT) = 0; /// A utility function for looking up initializer symbols. Performs a blocking /// lookup for the given symbols in each of the given JITDylibs. @@ -1086,8 +1219,12 @@ public: /// An ExecutionSession represents a running JIT program. class ExecutionSession { - // FIXME: Remove this when we remove the old ORC layers. + friend class InProgressLookupFlagsState; + friend class InProgressFullLookupState; friend class JITDylib; + friend class LookupState; + friend class MaterializationResponsibility; + friend class ResourceTracker; public: /// For reporting errors. @@ -1096,13 +1233,16 @@ public: /// For dispatching MaterializationUnit::materialize calls. using DispatchMaterializationFunction = std::function MU, - MaterializationResponsibility MR)>; + std::unique_ptr MR)>; /// Construct an ExecutionSession. /// /// SymbolStringPools may be shared between ExecutionSessions. ExecutionSession(std::shared_ptr SSP = nullptr); + /// End the session. Closes all JITDylibs. + Error endSession(); + /// Add a symbol name to the SymbolStringPool and return a pointer to it. SymbolStringPtr intern(StringRef SymName) { return SSP->intern(SymName); } @@ -1122,6 +1262,14 @@ public: return F(); } + /// Register the given ResourceManager with this ExecutionSession. + /// Managers will be notified of events in reverse order of registration. + void registerResourceManager(ResourceManager &RM); + + /// Deregister the given ResourceManager with this ExecutionSession. + /// Manager must have been previously registered. + void deregisterResourceManager(ResourceManager &RM); + /// Return a pointer to the "name" JITDylib. /// Ownership of JITDylib remains within Execution Session JITDylib *getJITDylibByName(StringRef Name); @@ -1147,17 +1295,6 @@ public: /// If no Platform is attached this call is equivalent to createBareJITDylib. Expected createJITDylib(std::string Name); - /// Allocate a module key for a new module to add to the JIT. - VModuleKey allocateVModule() { - return runSessionLocked([this]() { return ++LastKey; }); - } - - /// Return a module key to the ExecutionSession so that it can be - /// re-used. This should only be done once all resources associated - /// with the original key have been released. - void releaseVModule(VModuleKey Key) { /* FIXME: Recycle keys */ - } - /// Set the error reporter function. ExecutionSession &setErrorReporter(ErrorReporter ReportError) { this->ReportError = std::move(ReportError); @@ -1176,19 +1313,18 @@ public: return *this; } - void legacyFailQuery(AsynchronousSymbolQuery &Q, Error Err); + /// Search the given JITDylibs to find the flags associated with each of the + /// given symbols. + void lookupFlags(LookupKind K, JITDylibSearchOrder SearchOrder, + SymbolLookupSet Symbols, + unique_function)> OnComplete); - using LegacyAsyncLookupFunction = std::function Q, SymbolNameSet Names)>; - - /// A legacy lookup function for JITSymbolResolverAdapter. - /// Do not use -- this will be removed soon. - Expected - legacyLookup(LegacyAsyncLookupFunction AsyncLookup, SymbolNameSet Names, - SymbolState RequiredState, - RegisterDependenciesFunction RegisterDependencies); + /// Blocking version of lookupFlags. + Expected lookupFlags(LookupKind K, + JITDylibSearchOrder SearchOrder, + SymbolLookupSet Symbols); - /// Search the given JITDylib list for the given symbols. + /// Search the given JITDylibs for the given symbols. /// /// SearchOrder lists the JITDylibs to search. For each dylib, the associated /// boolean indicates whether the search should match against non-exported @@ -1248,10 +1384,11 @@ public: SymbolState RequiredState = SymbolState::Ready); /// Materialize the given unit. - void dispatchMaterialization(std::unique_ptr MU, - MaterializationResponsibility MR) { + void + dispatchMaterialization(std::unique_ptr MU, + std::unique_ptr MR) { assert(MU && "MU must be non-null"); - DEBUG_WITH_TYPE("orc", dumpDispatchInfo(MR.getTargetJITDylib(), *MU)); + DEBUG_WITH_TYPE("orc", dumpDispatchInfo(MR->getTargetJITDylib(), *MU)); DispatchMaterialization(std::move(MU), std::move(MR)); } @@ -1263,41 +1400,124 @@ private: logAllUnhandledErrors(std::move(Err), errs(), "JIT session error: "); } - static void - materializeOnCurrentThread(std::unique_ptr MU, - MaterializationResponsibility MR) { + static void materializeOnCurrentThread( + std::unique_ptr MU, + std::unique_ptr MR) { MU->materialize(std::move(MR)); } - void runOutstandingMUs(); + void dispatchOutstandingMUs(); + + static std::unique_ptr + createMaterializationResponsibility(ResourceTracker &RT, + SymbolFlagsMap Symbols, + SymbolStringPtr InitSymbol) { + auto &JD = RT.getJITDylib(); + std::unique_ptr MR( + new MaterializationResponsibility(&JD, std::move(Symbols), + std::move(InitSymbol))); + JD.MRTrackers[MR.get()] = &RT; + return MR; + } + + Error removeResourceTracker(ResourceTracker &RT); + void transferResourceTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT); + void destroyResourceTracker(ResourceTracker &RT); + + // State machine functions for query application.. + + /// IL_updateCandidatesFor is called to remove already-defined symbols that + /// match a given query from the set of candidate symbols to generate + /// definitions for (no need to generate a definition if one already exists). + Error IL_updateCandidatesFor(JITDylib &JD, JITDylibLookupFlags JDLookupFlags, + SymbolLookupSet &Candidates, + SymbolLookupSet *NonCandidates); + + /// OL_applyQueryPhase1 is an optionally re-startable loop for triggering + /// definition generation. It is called when a lookup is performed, and again + /// each time that LookupState::continueLookup is called. + void OL_applyQueryPhase1(std::unique_ptr IPLS, + Error Err); + + /// OL_completeLookup is run once phase 1 successfully completes for a lookup + /// call. It attempts to attach the symbol to all symbol table entries and + /// collect all MaterializationUnits to dispatch. If this method fails then + /// all MaterializationUnits will be left un-materialized. + void OL_completeLookup(std::unique_ptr IPLS, + std::shared_ptr Q, + RegisterDependenciesFunction RegisterDependencies); + + /// OL_completeLookupFlags is run once phase 1 successfully completes for a + /// lookupFlags call. + void OL_completeLookupFlags( + std::unique_ptr IPLS, + unique_function)> OnComplete); + + // State machine functions for MaterializationResponsibility. + void OL_destroyMaterializationResponsibility( + MaterializationResponsibility &MR); + SymbolNameSet OL_getRequestedSymbols(const MaterializationResponsibility &MR); + Error OL_notifyResolved(MaterializationResponsibility &MR, + const SymbolMap &Symbols); + Error OL_notifyEmitted(MaterializationResponsibility &MR); + Error OL_defineMaterializing(MaterializationResponsibility &MR, + SymbolFlagsMap SymbolFlags); + void OL_notifyFailed(MaterializationResponsibility &MR); + Error OL_replace(MaterializationResponsibility &MR, + std::unique_ptr MU); + Expected> + OL_delegate(MaterializationResponsibility &MR, const SymbolNameSet &Symbols); + void OL_addDependencies(MaterializationResponsibility &MR, + const SymbolStringPtr &Name, + const SymbolDependenceMap &Dependencies); + void OL_addDependenciesForAll(MaterializationResponsibility &MR, + const SymbolDependenceMap &Dependencies); #ifndef NDEBUG void dumpDispatchInfo(JITDylib &JD, MaterializationUnit &MU); #endif // NDEBUG mutable std::recursive_mutex SessionMutex; + bool SessionOpen = true; std::shared_ptr SSP; std::unique_ptr P; - VModuleKey LastKey = 0; ErrorReporter ReportError = logErrorsToStdErr; DispatchMaterializationFunction DispatchMaterialization = materializeOnCurrentThread; - std::vector> JDs; + std::vector ResourceManagers; + + std::vector JDs; // FIXME: Remove this (and runOutstandingMUs) once the linking layer works // with callbacks from asynchronous queries. mutable std::recursive_mutex OutstandingMUsMutex; std::vector, - MaterializationResponsibility>> + std::unique_ptr>> OutstandingMUs; }; +inline ExecutionSession &MaterializationResponsibility::getExecutionSession() { + return JD->getExecutionSession(); +} + +template +Error MaterializationResponsibility::withResourceKeyDo(Func &&F) const { + return JD->getExecutionSession().runSessionLocked([&]() -> Error { + auto I = JD->MRTrackers.find(this); + assert(I != JD->MRTrackers.end() && "No tracker for this MR"); + if (I->second->isDefunct()) + return make_error(I->second); + F(I->second->getKeyUnsafe()); + return Error::success(); + }); +} + template GeneratorT &JITDylib::addGenerator(std::unique_ptr DefGenerator) { auto &G = *DefGenerator; - ES.runSessionLocked( - [&]() { DefGenerators.push_back(std::move(DefGenerator)); }); + std::lock_guard Lock(GeneratorsMutex); + DefGenerators.push_back(std::move(DefGenerator)); return G; } @@ -1308,7 +1528,8 @@ auto JITDylib::withLinkOrderDo(Func &&F) } template -Error JITDylib::define(std::unique_ptr &&MU) { +Error JITDylib::define(std::unique_ptr &&MU, + ResourceTrackerSP RT) { assert(MU && "Can not define with a null MU"); if (MU->getSymbols().empty()) { @@ -1320,29 +1541,36 @@ Error JITDylib::define(std::unique_ptr &&MU) { return Error::success(); } else DEBUG_WITH_TYPE("orc", { - dbgs() << "Defining MU " << MU->getName() << " for " << getName() << "\n"; + dbgs() << "Defining MU " << MU->getName() << " for " << getName() + << " (tracker: "; + if (RT == getDefaultResourceTracker()) + dbgs() << "default)"; + else if (RT) + dbgs() << RT.get() << ")\n"; + else + dbgs() << "0x0, default will be used)\n"; }); return ES.runSessionLocked([&, this]() -> Error { if (auto Err = defineImpl(*MU)) return Err; + if (!RT) + RT = getDefaultResourceTracker(); + if (auto *P = ES.getPlatform()) { - if (auto Err = P->notifyAdding(*this, *MU)) + if (auto Err = P->notifyAdding(*RT, *MU)) return Err; } - /// defineImpl succeeded. - auto UMI = std::make_shared(std::move(MU)); - for (auto &KV : UMI->MU->getSymbols()) - UnmaterializedInfos[KV.first] = UMI; - + installMaterializationUnit(std::move(MU), *RT); return Error::success(); }); } template -Error JITDylib::define(std::unique_ptr &MU) { +Error JITDylib::define(std::unique_ptr &MU, + ResourceTrackerSP RT) { assert(MU && "Can not define with a null MU"); if (MU->getSymbols().empty()) { @@ -1354,30 +1582,36 @@ Error JITDylib::define(std::unique_ptr &MU) { return Error::success(); } else DEBUG_WITH_TYPE("orc", { - dbgs() << "Defining MU " << MU->getName() << " for " << getName() << "\n"; + dbgs() << "Defining MU " << MU->getName() << " for " << getName() + << " (tracker: "; + if (RT == getDefaultResourceTracker()) + dbgs() << "default)"; + else if (RT) + dbgs() << RT.get() << ")\n"; + else + dbgs() << "0x0, default will be used)\n"; }); return ES.runSessionLocked([&, this]() -> Error { if (auto Err = defineImpl(*MU)) return Err; + if (!RT) + RT = getDefaultResourceTracker(); + if (auto *P = ES.getPlatform()) { - if (auto Err = P->notifyAdding(*this, *MU)) + if (auto Err = P->notifyAdding(*RT, *MU)) return Err; } - /// defineImpl succeeded. - auto UMI = std::make_shared(std::move(MU)); - for (auto &KV : UMI->MU->getSymbols()) - UnmaterializedInfos[KV.first] = UMI; - + installMaterializationUnit(std::move(MU), *RT); return Error::success(); }); } /// ReexportsGenerator can be used with JITDylib::addGenerator to automatically /// re-export a subset of the source JITDylib's symbols in the target. -class ReexportsGenerator : public JITDylib::DefinitionGenerator { +class ReexportsGenerator : public DefinitionGenerator { public: using SymbolPredicate = std::function; @@ -1388,7 +1622,7 @@ public: JITDylibLookupFlags SourceJDLookupFlags, SymbolPredicate Allow = SymbolPredicate()); - Error tryToGenerate(LookupKind K, JITDylib &JD, + Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD, JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &LookupSet) override; @@ -1398,6 +1632,57 @@ private: SymbolPredicate Allow; }; +// --------------- IMPLEMENTATION -------------- +// Implementations for inline functions/methods. +// --------------------------------------------- + +inline MaterializationResponsibility::~MaterializationResponsibility() { + JD->getExecutionSession().OL_destroyMaterializationResponsibility(*this); +} + +inline SymbolNameSet MaterializationResponsibility::getRequestedSymbols() const { + return JD->getExecutionSession().OL_getRequestedSymbols(*this); +} + +inline Error MaterializationResponsibility::notifyResolved( + const SymbolMap &Symbols) { + return JD->getExecutionSession().OL_notifyResolved(*this, Symbols); +} + +inline Error MaterializationResponsibility::notifyEmitted() { + return JD->getExecutionSession().OL_notifyEmitted(*this); +} + +inline Error MaterializationResponsibility::defineMaterializing( + SymbolFlagsMap SymbolFlags) { + return JD->getExecutionSession().OL_defineMaterializing( + *this, std::move(SymbolFlags)); +} + +inline void MaterializationResponsibility::failMaterialization() { + JD->getExecutionSession().OL_notifyFailed(*this); +} + +inline Error MaterializationResponsibility::replace( + std::unique_ptr MU) { + return JD->getExecutionSession().OL_replace(*this, std::move(MU)); +} + +inline Expected> +MaterializationResponsibility::delegate(const SymbolNameSet &Symbols) { + return JD->getExecutionSession().OL_delegate(*this, Symbols); +} + +inline void MaterializationResponsibility::addDependencies( + const SymbolStringPtr &Name, const SymbolDependenceMap &Dependencies) { + JD->getExecutionSession().OL_addDependencies(*this, Name, Dependencies); +} + +inline void MaterializationResponsibility::addDependenciesForAll( + const SymbolDependenceMap &Dependencies) { + JD->getExecutionSession().OL_addDependenciesForAll(*this, Dependencies); +} + } // End namespace orc } // End namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h index 3b824b83b052..fdddc9694d0b 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h @@ -18,7 +18,7 @@ #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/ExecutionEngine/Orc/Core.h" #include "llvm/ExecutionEngine/Orc/Mangling.h" -#include "llvm/ExecutionEngine/Orc/OrcError.h" +#include "llvm/ExecutionEngine/Orc/Shared/OrcError.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/Object/Archive.h" #include "llvm/Support/DynamicLibrary.h" @@ -41,17 +41,6 @@ namespace orc { class ObjectLayer; -/// Run a main function, returning the result. -/// -/// If the optional ProgramName argument is given then it will be inserted -/// before the strings in Args as the first argument to the called function. -/// -/// It is legal to have an empty argument list and no program name, however -/// many main functions will expect a name argument at least, and will fail -/// if none is provided. -int runAsMain(int (*Main)(int, char *[]), ArrayRef Args, - Optional ProgramName = None); - /// This iterator provides a convenient way to iterate over the elements /// of an llvm.global_ctors/llvm.global_dtors instance. /// @@ -152,56 +141,6 @@ inline iterator_range getStaticInitGVs(Module &M) { return make_range(StaticInitGVIterator(M), StaticInitGVIterator()); } -/// Convenience class for recording constructor/destructor names for -/// later execution. -template -class LegacyCtorDtorRunner { -public: - /// Construct a CtorDtorRunner for the given range using the given - /// name mangling function. - LLVM_ATTRIBUTE_DEPRECATED( - LegacyCtorDtorRunner(std::vector CtorDtorNames, - VModuleKey K), - "ORCv1 utilities (utilities with the 'Legacy' prefix) are deprecated. " - "Please use the ORCv2 CtorDtorRunner utility instead"); - - LegacyCtorDtorRunner(ORCv1DeprecationAcknowledgement, - std::vector CtorDtorNames, VModuleKey K) - : CtorDtorNames(std::move(CtorDtorNames)), K(K) {} - - /// Run the recorded constructors/destructors through the given JIT - /// layer. - Error runViaLayer(JITLayerT &JITLayer) const { - using CtorDtorTy = void (*)(); - - for (const auto &CtorDtorName : CtorDtorNames) { - if (auto CtorDtorSym = JITLayer.findSymbolIn(K, CtorDtorName, false)) { - if (auto AddrOrErr = CtorDtorSym.getAddress()) { - CtorDtorTy CtorDtor = - reinterpret_cast(static_cast(*AddrOrErr)); - CtorDtor(); - } else - return AddrOrErr.takeError(); - } else { - if (auto Err = CtorDtorSym.takeError()) - return Err; - else - return make_error(CtorDtorName); - } - } - return Error::success(); - } - -private: - std::vector CtorDtorNames; - orc::VModuleKey K; -}; - -template -LegacyCtorDtorRunner::LegacyCtorDtorRunner( - std::vector CtorDtorNames, VModuleKey K) - : CtorDtorNames(std::move(CtorDtorNames)), K(K) {} - class CtorDtorRunner { public: CtorDtorRunner(JITDylib &JD) : JD(JD) {} @@ -250,45 +189,6 @@ protected: void *DSOHandle); }; -class LegacyLocalCXXRuntimeOverrides : public LocalCXXRuntimeOverridesBase { -public: - /// Create a runtime-overrides class. - template - LLVM_ATTRIBUTE_DEPRECATED( - LegacyLocalCXXRuntimeOverrides(const MangleFtorT &Mangle), - "ORCv1 utilities (utilities with the 'Legacy' prefix) are deprecated. " - "Please use the ORCv2 LocalCXXRuntimeOverrides utility instead"); - - template - LegacyLocalCXXRuntimeOverrides(ORCv1DeprecationAcknowledgement, - const MangleFtorT &Mangle) { - addOverride(Mangle("__dso_handle"), toTargetAddress(&DSOHandleOverride)); - addOverride(Mangle("__cxa_atexit"), toTargetAddress(&CXAAtExitOverride)); - } - - /// Search overrided symbols. - JITEvaluatedSymbol searchOverrides(const std::string &Name) { - auto I = CXXRuntimeOverrides.find(Name); - if (I != CXXRuntimeOverrides.end()) - return JITEvaluatedSymbol(I->second, JITSymbolFlags::Exported); - return nullptr; - } - -private: - void addOverride(const std::string &Name, JITTargetAddress Addr) { - CXXRuntimeOverrides.insert(std::make_pair(Name, Addr)); - } - - StringMap CXXRuntimeOverrides; -}; - -template -LegacyLocalCXXRuntimeOverrides::LegacyLocalCXXRuntimeOverrides( - const MangleFtorT &Mangle) { - addOverride(Mangle("__dso_handle"), toTargetAddress(&DSOHandleOverride)); - addOverride(Mangle("__cxa_atexit"), toTargetAddress(&CXAAtExitOverride)); -} - class LocalCXXRuntimeOverrides : public LocalCXXRuntimeOverridesBase { public: Error enable(JITDylib &JD, MangleAndInterner &Mangler); @@ -315,7 +215,7 @@ private: /// If an instance of this class is attached to a JITDylib as a fallback /// definition generator, then any symbol found in the given DynamicLibrary that /// passes the 'Allow' predicate will be added to the JITDylib. -class DynamicLibrarySearchGenerator : public JITDylib::DefinitionGenerator { +class DynamicLibrarySearchGenerator : public DefinitionGenerator { public: using SymbolPredicate = std::function; @@ -343,7 +243,7 @@ public: return Load(nullptr, GlobalPrefix, std::move(Allow)); } - Error tryToGenerate(LookupKind K, JITDylib &JD, + Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD, JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) override; @@ -358,7 +258,7 @@ private: /// If an instance of this class is attached to a JITDylib as a fallback /// definition generator, then any symbol found in the archive will result in /// the containing object being added to the JITDylib. -class StaticLibraryDefinitionGenerator : public JITDylib::DefinitionGenerator { +class StaticLibraryDefinitionGenerator : public DefinitionGenerator { public: /// Try to create a StaticLibraryDefinitionGenerator from the given path. /// @@ -381,7 +281,7 @@ public: static Expected> Create(ObjectLayer &L, std::unique_ptr ArchiveBuffer); - Error tryToGenerate(LookupKind K, JITDylib &JD, + Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD, JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) override; diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h deleted file mode 100644 index a4e43d4e1c9c..000000000000 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h +++ /dev/null @@ -1,111 +0,0 @@ -//===- GlobalMappingLayer.h - Run all IR through a functor ------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// Convenience layer for injecting symbols that will appear in calls to -// findSymbol. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_ORC_GLOBALMAPPINGLAYER_H -#define LLVM_EXECUTIONENGINE_ORC_GLOBALMAPPINGLAYER_H - -#include "llvm/ExecutionEngine/JITSymbol.h" -#include -#include -#include - -namespace llvm { - -class Module; -class JITSymbolResolver; - -namespace orc { - -/// Global mapping layer. -/// -/// This layer overrides the findSymbol method to first search a local symbol -/// table that the client can define. It can be used to inject new symbol -/// mappings into the JIT. Beware, however: symbols within a single IR module or -/// object file will still resolve locally (via RuntimeDyld's symbol table) - -/// such internal references cannot be overriden via this layer. -template -class GlobalMappingLayer { -public: - - /// Handle to an added module. - using ModuleHandleT = typename BaseLayerT::ModuleHandleT; - - /// Construct an GlobalMappingLayer with the given BaseLayer - GlobalMappingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {} - - /// Add the given module to the JIT. - /// @return A handle for the added modules. - Expected - addModule(std::shared_ptr M, - std::shared_ptr Resolver) { - return BaseLayer.addModule(std::move(M), std::move(Resolver)); - } - - /// Remove the module set associated with the handle H. - Error removeModule(ModuleHandleT H) { return BaseLayer.removeModule(H); } - - /// Manually set the address to return for the given symbol. - void setGlobalMapping(const std::string &Name, JITTargetAddress Addr) { - SymbolTable[Name] = Addr; - } - - /// Remove the given symbol from the global mapping. - void eraseGlobalMapping(const std::string &Name) { - SymbolTable.erase(Name); - } - - /// Search for the given named symbol. - /// - /// This method will first search the local symbol table, returning - /// any symbol found there. If the symbol is not found in the local - /// table then this call will be passed through to the base layer. - /// - /// @param Name The name of the symbol to search for. - /// @param ExportedSymbolsOnly If true, search only for exported symbols. - /// @return A handle for the given named symbol, if it exists. - JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { - auto I = SymbolTable.find(Name); - if (I != SymbolTable.end()) - return JITSymbol(I->second, JITSymbolFlags::Exported); - return BaseLayer.findSymbol(Name, ExportedSymbolsOnly); - } - - /// Get the address of the given symbol in the context of the of the - /// module represented by the handle H. This call is forwarded to the - /// base layer's implementation. - /// @param H The handle for the module to search in. - /// @param Name The name of the symbol to search for. - /// @param ExportedSymbolsOnly If true, search only for exported symbols. - /// @return A handle for the given named symbol, if it is found in the - /// given module. - JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name, - bool ExportedSymbolsOnly) { - return BaseLayer.findSymbolIn(H, Name, ExportedSymbolsOnly); - } - - /// Immediately emit and finalize the module set represented by the - /// given handle. - /// @param H Handle for module set to emit/finalize. - Error emitAndFinalize(ModuleHandleT H) { - return BaseLayer.emitAndFinalize(H); - } - -private: - BaseLayerT &BaseLayer; - std::map SymbolTable; -}; - -} // end namespace orc -} // end namespace llvm - -#endif // LLVM_EXECUTIONENGINE_ORC_GLOBALMAPPINGLAYER_H diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h index eb74d283f043..f8fdb171bbf9 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h @@ -45,8 +45,8 @@ public: IRSymbolMapper::ManglingOptions MO; }; - using NotifyCompiledFunction = - std::function; + using NotifyCompiledFunction = std::function; IRCompileLayer(ExecutionSession &ES, ObjectLayer &BaseLayer, std::unique_ptr Compile); @@ -55,7 +55,8 @@ public: void setNotifyCompiled(NotifyCompiledFunction NotifyCompiled); - void emit(MaterializationResponsibility R, ThreadSafeModule TSM) override; + void emit(std::unique_ptr R, + ThreadSafeModule TSM) override; private: mutable std::mutex IRLayerMutex; @@ -65,99 +66,6 @@ private: NotifyCompiledFunction NotifyCompiled = NotifyCompiledFunction(); }; -/// Eager IR compiling layer. -/// -/// This layer immediately compiles each IR module added via addModule to an -/// object file and adds this module file to the layer below, which must -/// implement the object layer concept. -template -class LegacyIRCompileLayer { -public: - /// Callback type for notifications when modules are compiled. - using NotifyCompiledCallback = - std::function)>; - - /// Construct an LegacyIRCompileLayer with the given BaseLayer, which must - /// implement the ObjectLayer concept. - LLVM_ATTRIBUTE_DEPRECATED( - LegacyIRCompileLayer( - BaseLayerT &BaseLayer, CompileFtor Compile, - NotifyCompiledCallback NotifyCompiled = NotifyCompiledCallback()), - "ORCv1 layers (layers with the 'Legacy' prefix) are deprecated. Please " - "use " - "the ORCv2 IRCompileLayer instead"); - - /// Legacy layer constructor with deprecation acknowledgement. - LegacyIRCompileLayer( - ORCv1DeprecationAcknowledgement, BaseLayerT &BaseLayer, - CompileFtor Compile, - NotifyCompiledCallback NotifyCompiled = NotifyCompiledCallback()) - : BaseLayer(BaseLayer), Compile(std::move(Compile)), - NotifyCompiled(std::move(NotifyCompiled)) {} - - /// Get a reference to the compiler functor. - CompileFtor& getCompiler() { return Compile; } - - /// (Re)set the NotifyCompiled callback. - void setNotifyCompiled(NotifyCompiledCallback NotifyCompiled) { - this->NotifyCompiled = std::move(NotifyCompiled); - } - - /// Compile the module, and add the resulting object to the base layer - /// along with the given memory manager and symbol resolver. - Error addModule(VModuleKey K, std::unique_ptr M) { - auto Obj = Compile(*M); - if (!Obj) - return Obj.takeError(); - if (auto Err = BaseLayer.addObject(std::move(K), std::move(*Obj))) - return Err; - if (NotifyCompiled) - NotifyCompiled(std::move(K), std::move(M)); - return Error::success(); - } - - /// Remove the module associated with the VModuleKey K. - Error removeModule(VModuleKey K) { return BaseLayer.removeObject(K); } - - /// Search for the given named symbol. - /// @param Name The name of the symbol to search for. - /// @param ExportedSymbolsOnly If true, search only for exported symbols. - /// @return A handle for the given named symbol, if it exists. - JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { - return BaseLayer.findSymbol(Name, ExportedSymbolsOnly); - } - - /// Get the address of the given symbol in compiled module represented - /// by the handle H. This call is forwarded to the base layer's - /// implementation. - /// @param K The VModuleKey for the module to search in. - /// @param Name The name of the symbol to search for. - /// @param ExportedSymbolsOnly If true, search only for exported symbols. - /// @return A handle for the given named symbol, if it is found in the - /// given module. - JITSymbol findSymbolIn(VModuleKey K, const std::string &Name, - bool ExportedSymbolsOnly) { - return BaseLayer.findSymbolIn(K, Name, ExportedSymbolsOnly); - } - - /// Immediately emit and finalize the module represented by the given - /// handle. - /// @param K The VModuleKey for the module to emit/finalize. - Error emitAndFinalize(VModuleKey K) { return BaseLayer.emitAndFinalize(K); } - -private: - BaseLayerT &BaseLayer; - CompileFtor Compile; - NotifyCompiledCallback NotifyCompiled; -}; - -template -LegacyIRCompileLayer::LegacyIRCompileLayer( - BaseLayerT &BaseLayer, CompileFtor Compile, - NotifyCompiledCallback NotifyCompiled) - : BaseLayer(BaseLayer), Compile(std::move(Compile)), - NotifyCompiled(std::move(NotifyCompiled)) {} - } // end namespace orc } // end namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h index 296d74ae6b86..66966a0f8762 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h @@ -13,6 +13,7 @@ #ifndef LLVM_EXECUTIONENGINE_ORC_IRTRANSFORMLAYER_H #define LLVM_EXECUTIONENGINE_ORC_IRTRANSFORMLAYER_H +#include "llvm/ADT/FunctionExtras.h" #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/ExecutionEngine/Orc/Layer.h" #include @@ -27,7 +28,7 @@ namespace orc { /// before operating on the module. class IRTransformLayer : public IRLayer { public: - using TransformFunction = std::function( + using TransformFunction = unique_function( ThreadSafeModule, MaterializationResponsibility &R)>; IRTransformLayer(ExecutionSession &ES, IRLayer &BaseLayer, @@ -37,7 +38,8 @@ public: this->Transform = std::move(Transform); } - void emit(MaterializationResponsibility R, ThreadSafeModule TSM) override; + void emit(std::unique_ptr R, + ThreadSafeModule TSM) override; static ThreadSafeModule identityTransform(ThreadSafeModule TSM, MaterializationResponsibility &R) { @@ -49,80 +51,6 @@ private: TransformFunction Transform; }; -/// IR mutating layer. -/// -/// This layer applies a user supplied transform to each module that is added, -/// then adds the transformed module to the layer below. -template -class LegacyIRTransformLayer { -public: - - /// Construct an LegacyIRTransformLayer with the given BaseLayer - LLVM_ATTRIBUTE_DEPRECATED( - LegacyIRTransformLayer(BaseLayerT &BaseLayer, - TransformFtor Transform = TransformFtor()), - "ORCv1 layers (layers with the 'Legacy' prefix) are deprecated. Please " - "use " - "the ORCv2 IRTransformLayer instead"); - - /// Legacy layer constructor with deprecation acknowledgement. - LegacyIRTransformLayer(ORCv1DeprecationAcknowledgement, BaseLayerT &BaseLayer, - TransformFtor Transform = TransformFtor()) - : BaseLayer(BaseLayer), Transform(std::move(Transform)) {} - - /// Apply the transform functor to the module, then add the module to - /// the layer below, along with the memory manager and symbol resolver. - /// - /// @return A handle for the added modules. - Error addModule(VModuleKey K, std::unique_ptr M) { - return BaseLayer.addModule(std::move(K), Transform(std::move(M))); - } - - /// Remove the module associated with the VModuleKey K. - Error removeModule(VModuleKey K) { return BaseLayer.removeModule(K); } - - /// Search for the given named symbol. - /// @param Name The name of the symbol to search for. - /// @param ExportedSymbolsOnly If true, search only for exported symbols. - /// @return A handle for the given named symbol, if it exists. - JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { - return BaseLayer.findSymbol(Name, ExportedSymbolsOnly); - } - - /// Get the address of the given symbol in the context of the module - /// represented by the VModuleKey K. This call is forwarded to the base - /// layer's implementation. - /// @param K The VModuleKey for the module to search in. - /// @param Name The name of the symbol to search for. - /// @param ExportedSymbolsOnly If true, search only for exported symbols. - /// @return A handle for the given named symbol, if it is found in the - /// given module. - JITSymbol findSymbolIn(VModuleKey K, const std::string &Name, - bool ExportedSymbolsOnly) { - return BaseLayer.findSymbolIn(K, Name, ExportedSymbolsOnly); - } - - /// Immediately emit and finalize the module represented by the given - /// VModuleKey. - /// @param K The VModuleKey for the module to emit/finalize. - Error emitAndFinalize(VModuleKey K) { return BaseLayer.emitAndFinalize(K); } - - /// Access the transform functor directly. - TransformFtor& getTransform() { return Transform; } - - /// Access the mumate functor directly. - const TransformFtor& getTransform() const { return Transform; } - -private: - BaseLayerT &BaseLayer; - TransformFtor Transform; -}; - -template -LegacyIRTransformLayer::LegacyIRTransformLayer( - BaseLayerT &BaseLayer, TransformFtor Transform) - : BaseLayer(BaseLayer), Transform(std::move(Transform)) {} - } // end namespace orc } // end namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h index e0cfd8bf2409..78e3ceef50e2 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h @@ -62,14 +62,33 @@ public: JITTargetAddress TrampolineAddr, NotifyLandingResolvedFunction OnLandingResolved) const>; - virtual ~TrampolinePool() {} + virtual ~TrampolinePool(); /// Get an available trampoline address. /// Returns an error if no trampoline can be created. - virtual Expected getTrampoline() = 0; + Expected getTrampoline() { + std::lock_guard Lock(TPMutex); + if (AvailableTrampolines.empty()) { + if (auto Err = grow()) + return std::move(Err); + } + assert(!AvailableTrampolines.empty() && "Failed to grow trampoline pool"); + auto TrampolineAddr = AvailableTrampolines.back(); + AvailableTrampolines.pop_back(); + return TrampolineAddr; + } -private: - virtual void anchor(); + /// Returns the given trampoline to the pool for re-use. + void releaseTrampoline(JITTargetAddress TrampolineAddr) { + std::lock_guard Lock(TPMutex); + AvailableTrampolines.push_back(TrampolineAddr); + } + +protected: + virtual Error grow() = 0; + + std::mutex TPMutex; + std::vector AvailableTrampolines; }; /// A trampoline pool for trampolines within the current process. @@ -90,26 +109,6 @@ public: return std::move(LTP); } - /// Get a free trampoline. Returns an error if one can not be provided (e.g. - /// because the pool is empty and can not be grown). - Expected getTrampoline() override { - std::lock_guard Lock(LTPMutex); - if (AvailableTrampolines.empty()) { - if (auto Err = grow()) - return std::move(Err); - } - assert(!AvailableTrampolines.empty() && "Failed to grow trampoline pool"); - auto TrampolineAddr = AvailableTrampolines.back(); - AvailableTrampolines.pop_back(); - return TrampolineAddr; - } - - /// Returns the given trampoline to the pool for re-use. - void releaseTrampoline(JITTargetAddress TrampolineAddr) { - std::lock_guard Lock(LTPMutex); - AvailableTrampolines.push_back(TrampolineAddr); - } - private: static JITTargetAddress reenter(void *TrampolinePoolPtr, void *TrampolineId) { LocalTrampolinePool *TrampolinePool = @@ -154,8 +153,8 @@ private: } } - Error grow() { - assert(this->AvailableTrampolines.empty() && "Growing prematurely?"); + Error grow() override { + assert(AvailableTrampolines.empty() && "Growing prematurely?"); std::error_code EC; auto TrampolineBlock = @@ -175,7 +174,7 @@ private: pointerToJITTargetAddress(ResolverBlock.base()), NumTrampolines); for (unsigned I = 0; I < NumTrampolines; ++I) - this->AvailableTrampolines.push_back(pointerToJITTargetAddress( + AvailableTrampolines.push_back(pointerToJITTargetAddress( TrampolineMem + (I * ORCABI::TrampolineSize))); if (auto EC = sys::Memory::protectMappedMemory( @@ -189,10 +188,8 @@ private: ResolveLandingFunction ResolveLanding; - std::mutex LTPMutex; sys::OwningMemoryBlock ResolverBlock; std::vector TrampolineBlocks; - std::vector AvailableTrampolines; }; /// Target-independent base class for compile callback management. diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h index 96f8e169e7dc..ff0aa0238523 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h @@ -19,7 +19,6 @@ #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" #include "llvm/ExecutionEngine/Orc/IRTransformLayer.h" #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" -#include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h" #include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ThreadPool.h" @@ -29,6 +28,8 @@ namespace orc { class LLJITBuilderState; class LLLazyJITBuilderState; +class ObjectTransformLayer; +class TargetProcessControl; /// A pre-fabricated ORC JIT stack that can serve as an alternative to MCJIT. /// @@ -85,21 +86,8 @@ public: return ES->createJITDylib(std::move(Name)); } - /// A convenience method for defining MUs in LLJIT's Main JITDylib. This can - /// be useful for succinctly defining absolute symbols, aliases and - /// re-exports. - template - Error define(std::unique_ptr &&MU) { - return Main->define(std::move(MU)); - } - - /// A convenience method for defining MUs in LLJIT's Main JITDylib. This can - /// be usedful for succinctly defining absolute symbols, aliases and - /// re-exports. - template - Error define(std::unique_ptr &MU) { - return Main->define(MU); - } + /// Adds an IR module with the given ResourceTracker. + Error addIRModule(ResourceTrackerSP RT, ThreadSafeModule TSM); /// Adds an IR module to the given JITDylib. Error addIRModule(JITDylib &JD, ThreadSafeModule TSM); @@ -109,6 +97,9 @@ public: return addIRModule(*Main, std::move(TSM)); } + /// Adds an object file to the given JITDylib. + Error addObjectFile(ResourceTrackerSP RT, std::unique_ptr Obj); + /// Adds an object file to the given JITDylib. Error addObjectFile(JITDylib &JD, std::unique_ptr Obj); @@ -178,7 +169,7 @@ public: ObjectLayer &getObjLinkingLayer() { return *ObjLinkingLayer; } /// Returns a reference to the object transform layer. - ObjectTransformLayer &getObjTransformLayer() { return ObjTransformLayer; } + ObjectTransformLayer &getObjTransformLayer() { return *ObjTransformLayer; } /// Returns a reference to the IR transform layer. IRTransformLayer &getIRTransformLayer() { return *TransformLayer; } @@ -195,7 +186,7 @@ public: } protected: - static std::unique_ptr + static Expected> createObjectLinkingLayer(LLJITBuilderState &S, ExecutionSession &ES); static Expected> @@ -218,7 +209,7 @@ protected: std::unique_ptr CompileThreads; std::unique_ptr ObjLinkingLayer; - ObjectTransformLayer ObjTransformLayer; + std::unique_ptr ObjTransformLayer; std::unique_ptr CompileLayer; std::unique_ptr TransformLayer; std::unique_ptr InitHelperTransformLayer; @@ -237,6 +228,9 @@ public: CODLayer->setPartitionFunction(std::move(Partition)); } + /// Returns a reference to the on-demand layer. + CompileOnDemandLayer &getCompileOnDemandLayer() { return *CODLayer; } + /// Add a module to be lazily compiled to JITDylib JD. Error addLazyIRModule(JITDylib &JD, ThreadSafeModule M); @@ -256,8 +250,9 @@ private: class LLJITBuilderState { public: - using ObjectLinkingLayerCreator = std::function( - ExecutionSession &, const Triple &TT)>; + using ObjectLinkingLayerCreator = + std::function>(ExecutionSession &, + const Triple &)>; using CompileFunctionCreator = std::function>( @@ -272,6 +267,7 @@ public: CompileFunctionCreator CreateCompileFunction; PlatformSetupFunction SetUpPlatform; unsigned NumCompileThreads = 0; + TargetProcessControl *TPC = nullptr; /// Called prior to JIT class construcion to fix up defaults. Error prepareForConstruction(); @@ -354,6 +350,17 @@ public: return impl(); } + /// Set a TargetProcessControl object. + /// + /// If the platform uses ObjectLinkingLayer by default and no + /// ObjectLinkingLayerCreator has been set then the TargetProcessControl + /// object will be used to supply the memory manager for the + /// ObjectLinkingLayer. + SetterImpl &setTargetProcessControl(TargetProcessControl &TPC) { + impl().TPC = &TPC; + return impl(); + } + /// Create an instance of the JIT. Expected> create() { if (auto Err = impl().prepareForConstruction()) diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LambdaResolver.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LambdaResolver.h deleted file mode 100644 index b31914f12a0d..000000000000 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LambdaResolver.h +++ /dev/null @@ -1,84 +0,0 @@ -//===- LambdaResolverMM - Redirect symbol lookup via a functor --*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// Defines a RuntimeDyld::SymbolResolver subclass that uses a user-supplied -// functor for symbol resolution. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_ORC_LAMBDARESOLVER_H -#define LLVM_EXECUTIONENGINE_ORC_LAMBDARESOLVER_H - -#include "llvm/ADT/STLExtras.h" -#include "llvm/ExecutionEngine/JITSymbol.h" -#include "llvm/ExecutionEngine/OrcV1Deprecation.h" -#include - -namespace llvm { -namespace orc { - -template -class LambdaResolver : public LegacyJITSymbolResolver { -public: - LLVM_ATTRIBUTE_DEPRECATED( - LambdaResolver(DylibLookupFtorT DylibLookupFtor, - ExternalLookupFtorT ExternalLookupFtor), - "ORCv1 utilities (including resolvers) are deprecated and will be " - "removed " - "in the next release. Please use ORCv2 (see docs/ORCv2.rst)"); - - LambdaResolver(ORCv1DeprecationAcknowledgement, - DylibLookupFtorT DylibLookupFtor, - ExternalLookupFtorT ExternalLookupFtor) - : DylibLookupFtor(DylibLookupFtor), - ExternalLookupFtor(ExternalLookupFtor) {} - - JITSymbol findSymbolInLogicalDylib(const std::string &Name) final { - return DylibLookupFtor(Name); - } - - JITSymbol findSymbol(const std::string &Name) final { - return ExternalLookupFtor(Name); - } - -private: - DylibLookupFtorT DylibLookupFtor; - ExternalLookupFtorT ExternalLookupFtor; -}; - -template -LambdaResolver::LambdaResolver( - DylibLookupFtorT DylibLookupFtor, ExternalLookupFtorT ExternalLookupFtor) - : DylibLookupFtor(DylibLookupFtor), ExternalLookupFtor(ExternalLookupFtor) { -} - -template -std::shared_ptr> -createLambdaResolver(DylibLookupFtorT DylibLookupFtor, - ExternalLookupFtorT ExternalLookupFtor) { - using LR = LambdaResolver; - return std::make_unique(std::move(DylibLookupFtor), - std::move(ExternalLookupFtor)); -} - -template -std::shared_ptr> -createLambdaResolver(ORCv1DeprecationAcknowledgement, - DylibLookupFtorT DylibLookupFtor, - ExternalLookupFtorT ExternalLookupFtor) { - using LR = LambdaResolver; - return std::make_unique(AcknowledgeORCv1Deprecation, - std::move(DylibLookupFtor), - std::move(ExternalLookupFtor)); -} - -} // end namespace orc -} // end namespace llvm - -#endif // LLVM_EXECUTIONENGINE_ORC_LAMBDARESOLVER_H diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Layer.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Layer.h index e843d0f56245..f9cc15583b42 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Layer.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Layer.h @@ -34,15 +34,15 @@ public: /// SymbolFlags and SymbolToDefinition maps. IRMaterializationUnit(ExecutionSession &ES, const IRSymbolMapper::ManglingOptions &MO, - ThreadSafeModule TSM, VModuleKey K); + ThreadSafeModule TSM); /// Create an IRMaterializationLayer from a module, and pre-existing /// SymbolFlags and SymbolToDefinition maps. The maps must provide /// entries for each definition in M. /// This constructor is useful for delegating work from one /// IRMaterializationUnit to another. - IRMaterializationUnit(ThreadSafeModule TSM, VModuleKey K, - SymbolFlagsMap SymbolFlags, SymbolStringPtr InitSymbol, + IRMaterializationUnit(ThreadSafeModule TSM, SymbolFlagsMap SymbolFlags, + SymbolStringPtr InitSymbol, SymbolNameToDefinitionMap SymbolToDefinition); /// Return the ModuleIdentifier as the name for this MaterializationUnit. @@ -94,13 +94,19 @@ public: /// Returns the current value of the CloneToNewContextOnEmit flag. bool getCloneToNewContextOnEmit() const { return CloneToNewContextOnEmit; } + /// Add a MaterializatinoUnit representing the given IR to the JITDylib + /// targeted by the given tracker. + virtual Error add(ResourceTrackerSP RT, ThreadSafeModule TSM); + /// Adds a MaterializationUnit representing the given IR to the given - /// JITDylib. - virtual Error add(JITDylib &JD, ThreadSafeModule TSM, - VModuleKey K = VModuleKey()); + /// JITDylib. If RT is not specif + Error add(JITDylib &JD, ThreadSafeModule TSM) { + return add(JD.getDefaultResourceTracker(), std::move(TSM)); + } /// Emit should materialize the given IR. - virtual void emit(MaterializationResponsibility R, ThreadSafeModule TSM) = 0; + virtual void emit(std::unique_ptr R, + ThreadSafeModule TSM) = 0; private: bool CloneToNewContextOnEmit = false; @@ -114,14 +120,12 @@ class BasicIRLayerMaterializationUnit : public IRMaterializationUnit { public: BasicIRLayerMaterializationUnit(IRLayer &L, const IRSymbolMapper::ManglingOptions &MO, - ThreadSafeModule TSM, VModuleKey K); + ThreadSafeModule TSM); private: - - void materialize(MaterializationResponsibility R) override; + void materialize(std::unique_ptr R) override; IRLayer &L; - VModuleKey K; }; /// Interface for Layers that accept object files. @@ -135,11 +139,14 @@ public: /// Adds a MaterializationUnit representing the given IR to the given /// JITDylib. - virtual Error add(JITDylib &JD, std::unique_ptr O, - VModuleKey K = VModuleKey()); + virtual Error add(ResourceTrackerSP RT, std::unique_ptr O); + + Error add(JITDylib &JD, std::unique_ptr O) { + return add(JD.getDefaultResourceTracker(), std::move(O)); + } /// Emit should materialize the given IR. - virtual void emit(MaterializationResponsibility R, + virtual void emit(std::unique_ptr R, std::unique_ptr O) = 0; private: @@ -151,9 +158,9 @@ private: class BasicObjectLayerMaterializationUnit : public MaterializationUnit { public: static Expected> - Create(ObjectLayer &L, VModuleKey K, std::unique_ptr O); + Create(ObjectLayer &L, std::unique_ptr O); - BasicObjectLayerMaterializationUnit(ObjectLayer &L, VModuleKey K, + BasicObjectLayerMaterializationUnit(ObjectLayer &L, std::unique_ptr O, SymbolFlagsMap SymbolFlags, SymbolStringPtr InitSymbol); @@ -162,8 +169,7 @@ public: StringRef getName() const override; private: - - void materialize(MaterializationResponsibility R) override; + void materialize(std::unique_ptr R) override; void discard(const JITDylib &JD, const SymbolStringPtr &Name) override; ObjectLayer &L; diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h deleted file mode 100644 index 84f5e0350c2e..000000000000 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h +++ /dev/null @@ -1,267 +0,0 @@ -//===- LazyEmittingLayer.h - Lazily emit IR to lower JIT layers -*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// Contains the definition for a lazy-emitting layer for the JIT. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H -#define LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H - -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ExecutionEngine/JITSymbol.h" -#include "llvm/ExecutionEngine/Orc/Core.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/IR/Mangler.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -#include -#include -#include -#include -#include - -namespace llvm { -namespace orc { - -/// Lazy-emitting IR layer. -/// -/// This layer accepts LLVM IR Modules (via addModule) but does not -/// immediately emit them the layer below. Instead, emission to the base layer -/// is deferred until the first time the client requests the address (via -/// JITSymbol::getAddress) for a symbol contained in this layer. -template class LazyEmittingLayer { -private: - class EmissionDeferredModule { - public: - EmissionDeferredModule(VModuleKey K, std::unique_ptr M) - : K(std::move(K)), M(std::move(M)) {} - - JITSymbol find(StringRef Name, bool ExportedSymbolsOnly, BaseLayerT &B) { - switch (EmitState) { - case NotEmitted: - if (auto GV = searchGVs(Name, ExportedSymbolsOnly)) { - JITSymbolFlags Flags = JITSymbolFlags::fromGlobalValue(*GV); - auto GetAddress = [this, ExportedSymbolsOnly, Name = Name.str(), - &B]() -> Expected { - if (this->EmitState == Emitting) - return 0; - else if (this->EmitState == NotEmitted) { - this->EmitState = Emitting; - if (auto Err = this->emitToBaseLayer(B)) - return std::move(Err); - this->EmitState = Emitted; - } - if (auto Sym = B.findSymbolIn(K, Name, ExportedSymbolsOnly)) - return Sym.getAddress(); - else if (auto Err = Sym.takeError()) - return std::move(Err); - else - llvm_unreachable("Successful symbol lookup should return " - "definition address here"); - }; - return JITSymbol(std::move(GetAddress), Flags); - } else - return nullptr; - case Emitting: - // Calling "emit" can trigger a recursive call to 'find' (e.g. to check - // for pre-existing definitions of common-symbol), but any symbol in - // this module would already have been found internally (in the - // RuntimeDyld that did the lookup), so just return a nullptr here. - return nullptr; - case Emitted: - return B.findSymbolIn(K, std::string(Name), ExportedSymbolsOnly); - } - llvm_unreachable("Invalid emit-state."); - } - - Error removeModuleFromBaseLayer(BaseLayerT& BaseLayer) { - return EmitState != NotEmitted ? BaseLayer.removeModule(K) - : Error::success(); - } - - void emitAndFinalize(BaseLayerT &BaseLayer) { - assert(EmitState != Emitting && - "Cannot emitAndFinalize while already emitting"); - if (EmitState == NotEmitted) { - EmitState = Emitting; - emitToBaseLayer(BaseLayer); - EmitState = Emitted; - } - BaseLayer.emitAndFinalize(K); - } - - private: - - const GlobalValue* searchGVs(StringRef Name, - bool ExportedSymbolsOnly) const { - // FIXME: We could clean all this up if we had a way to reliably demangle - // names: We could just demangle name and search, rather than - // mangling everything else. - - // If we have already built the mangled name set then just search it. - if (MangledSymbols) { - auto VI = MangledSymbols->find(Name); - if (VI == MangledSymbols->end()) - return nullptr; - auto GV = VI->second; - if (!ExportedSymbolsOnly || GV->hasDefaultVisibility()) - return GV; - return nullptr; - } - - // If we haven't built the mangled name set yet, try to build it. As an - // optimization this will leave MangledNames set to nullptr if we find - // Name in the process of building the set. - return buildMangledSymbols(Name, ExportedSymbolsOnly); - } - - Error emitToBaseLayer(BaseLayerT &BaseLayer) { - // We don't need the mangled names set any more: Once we've emitted this - // to the base layer we'll just look for symbols there. - MangledSymbols.reset(); - return BaseLayer.addModule(std::move(K), std::move(M)); - } - - // If the mangled name of the given GlobalValue matches the given search - // name (and its visibility conforms to the ExportedSymbolsOnly flag) then - // return the symbol. Otherwise, add the mangled name to the Names map and - // return nullptr. - const GlobalValue* addGlobalValue(StringMap &Names, - const GlobalValue &GV, - const Mangler &Mang, StringRef SearchName, - bool ExportedSymbolsOnly) const { - // Modules don't "provide" decls or common symbols. - if (GV.isDeclaration() || GV.hasCommonLinkage()) - return nullptr; - - // Mangle the GV name. - std::string MangledName; - { - raw_string_ostream MangledNameStream(MangledName); - Mang.getNameWithPrefix(MangledNameStream, &GV, false); - } - - // Check whether this is the name we were searching for, and if it is then - // bail out early. - if (MangledName == SearchName) - if (!ExportedSymbolsOnly || GV.hasDefaultVisibility()) - return &GV; - - // Otherwise add this to the map for later. - Names[MangledName] = &GV; - return nullptr; - } - - // Build the MangledSymbols map. Bails out early (with MangledSymbols left set - // to nullptr) if the given SearchName is found while building the map. - const GlobalValue* buildMangledSymbols(StringRef SearchName, - bool ExportedSymbolsOnly) const { - assert(!MangledSymbols && "Mangled symbols map already exists?"); - - auto Symbols = std::make_unique>(); - - Mangler Mang; - - for (const auto &GO : M->global_objects()) - if (auto GV = addGlobalValue(*Symbols, GO, Mang, SearchName, - ExportedSymbolsOnly)) - return GV; - - MangledSymbols = std::move(Symbols); - return nullptr; - } - - enum { NotEmitted, Emitting, Emitted } EmitState = NotEmitted; - VModuleKey K; - std::unique_ptr M; - mutable std::unique_ptr> MangledSymbols; - }; - - BaseLayerT &BaseLayer; - std::map> ModuleMap; - -public: - - /// Construct a lazy emitting layer. - LLVM_ATTRIBUTE_DEPRECATED( - LazyEmittingLayer(BaseLayerT &BaseLayer), - "ORCv1 layers (including LazyEmittingLayer) are deprecated. Please use " - "ORCv2, where lazy emission is the default"); - - /// Construct a lazy emitting layer. - LazyEmittingLayer(ORCv1DeprecationAcknowledgement, BaseLayerT &BaseLayer) - : BaseLayer(BaseLayer) {} - - /// Add the given module to the lazy emitting layer. - Error addModule(VModuleKey K, std::unique_ptr M) { - assert(!ModuleMap.count(K) && "VModuleKey K already in use"); - ModuleMap[K] = - std::make_unique(std::move(K), std::move(M)); - return Error::success(); - } - - /// Remove the module represented by the given handle. - /// - /// This method will free the memory associated with the given module, both - /// in this layer, and the base layer. - Error removeModule(VModuleKey K) { - auto I = ModuleMap.find(K); - assert(I != ModuleMap.end() && "VModuleKey K not valid here"); - auto EDM = std::move(I.second); - ModuleMap.erase(I); - return EDM->removeModuleFromBaseLayer(BaseLayer); - } - - /// Search for the given named symbol. - /// @param Name The name of the symbol to search for. - /// @param ExportedSymbolsOnly If true, search only for exported symbols. - /// @return A handle for the given named symbol, if it exists. - JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { - // Look for the symbol among existing definitions. - if (auto Symbol = BaseLayer.findSymbol(Name, ExportedSymbolsOnly)) - return Symbol; - - // If not found then search the deferred modules. If any of these contain a - // definition of 'Name' then they will return a JITSymbol that will emit - // the corresponding module when the symbol address is requested. - for (auto &KV : ModuleMap) - if (auto Symbol = KV.second->find(Name, ExportedSymbolsOnly, BaseLayer)) - return Symbol; - - // If no definition found anywhere return a null symbol. - return nullptr; - } - - /// Get the address of the given symbol in the context of the of - /// compiled modules represented by the key K. - JITSymbol findSymbolIn(VModuleKey K, const std::string &Name, - bool ExportedSymbolsOnly) { - assert(ModuleMap.count(K) && "VModuleKey K not valid here"); - return ModuleMap[K]->find(Name, ExportedSymbolsOnly, BaseLayer); - } - - /// Immediately emit and finalize the module represented by the given - /// key. - Error emitAndFinalize(VModuleKey K) { - assert(ModuleMap.count(K) && "VModuleKey K not valid here"); - return ModuleMap[K]->emitAndFinalize(BaseLayer); - } -}; - -template -LazyEmittingLayer::LazyEmittingLayer(BaseLayerT &BaseLayer) - : BaseLayer(BaseLayer) {} - -} // end namespace orc -} // end namespace llvm - -#endif // LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LazyReexports.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LazyReexports.h index 0d3ccecdf121..e6a9d8945285 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LazyReexports.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LazyReexports.h @@ -40,6 +40,9 @@ public: using NotifyResolvedFunction = unique_function; + LazyCallThroughManager(ExecutionSession &ES, + JITTargetAddress ErrorHandlerAddr, TrampolinePool *TP); + // Return a free call-through trampoline and bind it to look up and call // through to the given symbol. Expected @@ -56,9 +59,6 @@ protected: using NotifyLandingResolvedFunction = TrampolinePool::NotifyLandingResolvedFunction; - LazyCallThroughManager(ExecutionSession &ES, - JITTargetAddress ErrorHandlerAddr, TrampolinePool *TP); - struct ReexportsEntry { JITDylib *SourceJD; SymbolStringPtr SymbolName; @@ -144,12 +144,12 @@ public: IndirectStubsManager &ISManager, JITDylib &SourceJD, SymbolAliasMap CallableAliases, - ImplSymbolMap *SrcJDLoc, VModuleKey K); + ImplSymbolMap *SrcJDLoc); StringRef getName() const override; private: - void materialize(MaterializationResponsibility R) override; + void materialize(std::unique_ptr R) override; void discard(const JITDylib &JD, const SymbolStringPtr &Name) override; static SymbolFlagsMap extractFlags(const SymbolAliasMap &Aliases); @@ -166,11 +166,10 @@ private: inline std::unique_ptr lazyReexports(LazyCallThroughManager &LCTManager, IndirectStubsManager &ISManager, JITDylib &SourceJD, - SymbolAliasMap CallableAliases, ImplSymbolMap *SrcJDLoc = nullptr, - VModuleKey K = VModuleKey()) { + SymbolAliasMap CallableAliases, + ImplSymbolMap *SrcJDLoc = nullptr) { return std::make_unique( - LCTManager, ISManager, SourceJD, std::move(CallableAliases), SrcJDLoc, - std::move(K)); + LCTManager, ISManager, SourceJD, std::move(CallableAliases), SrcJDLoc); } } // End namespace orc diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Legacy.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Legacy.h deleted file mode 100644 index b20202a49ef6..000000000000 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Legacy.h +++ /dev/null @@ -1,211 +0,0 @@ -//===--- Legacy.h -- Adapters for ExecutionEngine API interop ---*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// Contains core ORC APIs. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_ORC_LEGACY_H -#define LLVM_EXECUTIONENGINE_ORC_LEGACY_H - -#include "llvm/ExecutionEngine/JITSymbol.h" -#include "llvm/ExecutionEngine/Orc/Core.h" - -namespace llvm { -namespace orc { - -/// SymbolResolver is a composable interface for looking up symbol flags -/// and addresses using the AsynchronousSymbolQuery type. It will -/// eventually replace the LegacyJITSymbolResolver interface as the -/// stardard ORC symbol resolver type. -/// -/// FIXME: SymbolResolvers should go away and be replaced with VSOs with -/// defenition generators. -class SymbolResolver { -public: - virtual ~SymbolResolver() = default; - - /// Returns the subset of the given symbols that the caller is responsible for - /// materializing. - virtual SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) = 0; - - /// For each symbol in Symbols that can be found, assigns that symbols - /// value in Query. Returns the set of symbols that could not be found. - virtual SymbolNameSet lookup(std::shared_ptr Query, - SymbolNameSet Symbols) = 0; - -private: - virtual void anchor(); -}; - -/// Implements SymbolResolver with a pair of supplied function objects -/// for convenience. See createSymbolResolver. -template -class LambdaSymbolResolver final : public SymbolResolver { -public: - template - LambdaSymbolResolver(GetResponsibilitySetFnRef &&GetResponsibilitySet, - LookupFnRef &&Lookup) - : GetResponsibilitySet( - std::forward(GetResponsibilitySet)), - Lookup(std::forward(Lookup)) {} - - SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) final { - return GetResponsibilitySet(Symbols); - } - - SymbolNameSet lookup(std::shared_ptr Query, - SymbolNameSet Symbols) final { - return Lookup(std::move(Query), std::move(Symbols)); - } - -private: - GetResponsibilitySetFn GetResponsibilitySet; - LookupFn Lookup; -}; - -/// Creates a SymbolResolver implementation from the pair of supplied -/// function objects. -template -std::unique_ptr>, - std::remove_cv_t>>> -createSymbolResolver(GetResponsibilitySetFn &&GetResponsibilitySet, - LookupFn &&Lookup) { - using LambdaSymbolResolverImpl = LambdaSymbolResolver< - std::remove_cv_t>, - std::remove_cv_t>>; - return std::make_unique( - std::forward(GetResponsibilitySet), - std::forward(Lookup)); -} - -/// Legacy adapter. Remove once we kill off the old ORC layers. -class JITSymbolResolverAdapter : public JITSymbolResolver { -public: - JITSymbolResolverAdapter(ExecutionSession &ES, SymbolResolver &R, - MaterializationResponsibility *MR); - Expected getResponsibilitySet(const LookupSet &Symbols) override; - void lookup(const LookupSet &Symbols, OnResolvedFunction OnResolved) override; - -private: - ExecutionSession &ES; - std::set ResolvedStrings; - SymbolResolver &R; - MaterializationResponsibility *MR; -}; - -/// Use the given legacy-style FindSymbol function (i.e. a function that takes -/// a const std::string& or StringRef and returns a JITSymbol) to get the -/// subset of symbols that the caller is responsible for materializing. If any -/// JITSymbol returned by FindSymbol is in an error state the function returns -/// immediately with that error. -/// -/// Useful for implementing getResponsibilitySet bodies that query legacy -/// resolvers. -template -Expected -getResponsibilitySetWithLegacyFn(const SymbolNameSet &Symbols, - FindSymbolFn FindSymbol) { - SymbolNameSet Result; - - for (auto &S : Symbols) { - if (JITSymbol Sym = FindSymbol(*S)) { - if (!Sym.getFlags().isStrong()) - Result.insert(S); - } else if (auto Err = Sym.takeError()) - return std::move(Err); - } - - return Result; -} - -/// Use the given legacy-style FindSymbol function (i.e. a function that -/// takes a const std::string& or StringRef and returns a JITSymbol) to -/// find the address and flags for each symbol in Symbols and store the -/// result in Query. If any JITSymbol returned by FindSymbol is in an -/// error then Query.notifyFailed(...) is called with that error and the -/// function returns immediately. On success, returns the set of symbols -/// not found. -/// -/// Useful for implementing lookup bodies that query legacy resolvers. -template -SymbolNameSet -lookupWithLegacyFn(ExecutionSession &ES, AsynchronousSymbolQuery &Query, - const SymbolNameSet &Symbols, FindSymbolFn FindSymbol) { - SymbolNameSet SymbolsNotFound; - bool NewSymbolsResolved = false; - - for (auto &S : Symbols) { - if (JITSymbol Sym = FindSymbol(*S)) { - if (auto Addr = Sym.getAddress()) { - Query.notifySymbolMetRequiredState( - S, JITEvaluatedSymbol(*Addr, Sym.getFlags())); - NewSymbolsResolved = true; - } else { - ES.legacyFailQuery(Query, Addr.takeError()); - return SymbolNameSet(); - } - } else if (auto Err = Sym.takeError()) { - ES.legacyFailQuery(Query, std::move(Err)); - return SymbolNameSet(); - } else - SymbolsNotFound.insert(S); - } - - if (NewSymbolsResolved && Query.isComplete()) - Query.handleComplete(); - - return SymbolsNotFound; -} - -/// An ORC SymbolResolver implementation that uses a legacy -/// findSymbol-like function to perform lookup; -template -class LegacyLookupFnResolver final : public SymbolResolver { -public: - using ErrorReporter = std::function; - - LegacyLookupFnResolver(ExecutionSession &ES, LegacyLookupFn LegacyLookup, - ErrorReporter ReportError) - : ES(ES), LegacyLookup(std::move(LegacyLookup)), - ReportError(std::move(ReportError)) {} - - SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) final { - if (auto ResponsibilitySet = - getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup)) - return std::move(*ResponsibilitySet); - else { - ReportError(ResponsibilitySet.takeError()); - return SymbolNameSet(); - } - } - - SymbolNameSet lookup(std::shared_ptr Query, - SymbolNameSet Symbols) final { - return lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup); - } - -private: - ExecutionSession &ES; - LegacyLookupFn LegacyLookup; - ErrorReporter ReportError; -}; - -template -std::shared_ptr> -createLegacyLookupResolver(ExecutionSession &ES, LegacyLookupFn LegacyLookup, - std::function ErrorReporter) { - return std::make_shared>( - ES, std::move(LegacyLookup), std::move(ErrorReporter)); -} - -} // End namespace orc -} // End namespace llvm - -#endif // LLVM_EXECUTIONENGINE_ORC_LEGACY_H diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h index 15fe079eccaf..90e1d4704f34 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h @@ -98,8 +98,9 @@ public: ExecutionSession &getExecutionSession() const { return ES; } Error setupJITDylib(JITDylib &JD) override; - Error notifyAdding(JITDylib &JD, const MaterializationUnit &MU) override; - Error notifyRemoving(JITDylib &JD, VModuleKey K) override; + Error notifyAdding(ResourceTracker &RT, + const MaterializationUnit &MU) override; + Error notifyRemoving(ResourceTracker &RT) override; Expected getInitializerSequence(JITDylib &JD); @@ -119,6 +120,19 @@ private: LocalDependenciesMap getSyntheticSymbolLocalDependencies( MaterializationResponsibility &MR) override; + // FIXME: We should be tentatively tracking scraped sections and discarding + // if the MR fails. + Error notifyFailed(MaterializationResponsibility &MR) override { + return Error::success(); + } + + Error notifyRemovingResources(ResourceKey K) override { + return Error::success(); + } + + void notifyTransferringResources(ResourceKey DstKey, + ResourceKey SrcKey) override {} + private: using InitSymbolDepMap = DenseMap; @@ -136,8 +150,6 @@ private: InitSymbolDepMap InitSymbolDeps; }; - static std::vector getDFSLinkOrder(JITDylib &JD); - void registerInitInfo(JITDylib &JD, JITTargetAddress ObjCImageInfoAddr, MachOJITDylibInitializers::SectionExtent ModInits, MachOJITDylibInitializers::SectionExtent ObjCSelRefs, diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/NullResolver.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/NullResolver.h deleted file mode 100644 index ffa37a13d064..000000000000 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/NullResolver.h +++ /dev/null @@ -1,43 +0,0 @@ -//===------ NullResolver.h - Reject symbol lookup requests ------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// Defines a RuntimeDyld::SymbolResolver subclass that rejects all symbol -// resolution requests, for clients that have no cross-object fixups. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_ORC_NULLRESOLVER_H -#define LLVM_EXECUTIONENGINE_ORC_NULLRESOLVER_H - -#include "llvm/ExecutionEngine/Orc/Legacy.h" -#include "llvm/ExecutionEngine/RuntimeDyld.h" - -namespace llvm { -namespace orc { - -class NullResolver : public SymbolResolver { -public: - SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) final; - - SymbolNameSet lookup(std::shared_ptr Query, - SymbolNameSet Symbols) final; -}; - -/// SymbolResolver impliementation that rejects all resolution requests. -/// Useful for clients that have no cross-object fixups. -class NullLegacyResolver : public LegacyJITSymbolResolver { -public: - JITSymbol findSymbol(const std::string &Name) final; - - JITSymbol findSymbolInLogicalDylib(const std::string &Name) final; -}; - -} // End namespace orc. -} // End namespace llvm. - -#endif // LLVM_EXECUTIONENGINE_ORC_NULLRESOLVER_H diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h index 2bfe3b001709..f2975e29fcd6 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h @@ -35,6 +35,7 @@ namespace llvm { namespace jitlink { class EHFrameRegistrar; +class LinkGraph; class Symbol; } // namespace jitlink @@ -51,7 +52,7 @@ class ObjectLinkingLayerJITLinkContext; /// Clients can use this class to add relocatable object files to an /// ExecutionSession, and it typically serves as the base layer (underneath /// a compiling layer like IRCompileLayer) for the rest of the JIT. -class ObjectLinkingLayer : public ObjectLayer { +class ObjectLinkingLayer : public ObjectLayer, private ResourceManager { friend class ObjectLinkingLayerJITLinkContext; public: @@ -72,10 +73,10 @@ public: virtual Error notifyEmitted(MaterializationResponsibility &MR) { return Error::success(); } - virtual Error notifyRemovingModule(VModuleKey K) { - return Error::success(); - } - virtual Error notifyRemovingAllModules() { return Error::success(); } + virtual Error notifyFailed(MaterializationResponsibility &MR) = 0; + virtual Error notifyRemovingResources(ResourceKey K) = 0; + virtual void notifyTransferringResources(ResourceKey DstKey, + ResourceKey SrcKey) = 0; /// Return any dependencies that synthetic symbols (e.g. init symbols) /// have on locally scoped jitlink::Symbols. This is used by the @@ -90,8 +91,14 @@ public: using ReturnObjectBufferFunction = std::function)>; - /// Construct an ObjectLinkingLayer with the given NotifyLoaded, - /// and NotifyEmitted functors. + /// Construct an ObjectLinkingLayer. + ObjectLinkingLayer(ExecutionSession &ES, + jitlink::JITLinkMemoryManager &MemMgr); + + /// Construct an ObjectLinkingLayer. Takes ownership of the given + /// JITLinkMemoryManager. This method is a temporary hack to simplify + /// co-existence with RTDyldObjectLinkingLayer (which also owns its + /// allocators). ObjectLinkingLayer(ExecutionSession &ES, std::unique_ptr MemMgr); @@ -112,10 +119,14 @@ public: return *this; } - /// Emit the object. - void emit(MaterializationResponsibility R, + /// Emit an object file. + void emit(std::unique_ptr R, std::unique_ptr O) override; + /// Emit a LinkGraph. + void emit(std::unique_ptr R, + std::unique_ptr G); + /// Instructs this ObjectLinkingLayer instance to override the symbol flags /// found in the AtomGraph with the flags supplied by the /// MaterializationResponsibility instance. This is a workaround to support @@ -155,27 +166,31 @@ private: void notifyLoaded(MaterializationResponsibility &MR); Error notifyEmitted(MaterializationResponsibility &MR, AllocPtr Alloc); - Error removeModule(VModuleKey K); - Error removeAllModules(); + Error handleRemoveResources(ResourceKey K) override; + void handleTransferResources(ResourceKey DstKey, ResourceKey SrcKey) override; mutable std::mutex LayerMutex; - std::unique_ptr MemMgr; + jitlink::JITLinkMemoryManager &MemMgr; + std::unique_ptr MemMgrOwnership; bool OverrideObjectFlags = false; bool AutoClaimObjectSymbols = false; ReturnObjectBufferFunction ReturnObjectBuffer; - DenseMap TrackedAllocs; - std::vector UntrackedAllocs; + DenseMap> Allocs; std::vector> Plugins; }; class EHFrameRegistrationPlugin : public ObjectLinkingLayer::Plugin { public: - EHFrameRegistrationPlugin(jitlink::EHFrameRegistrar &Registrar); - Error notifyEmitted(MaterializationResponsibility &MR) override; + EHFrameRegistrationPlugin( + ExecutionSession &ES, + std::unique_ptr Registrar); void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT, jitlink::PassConfiguration &PassConfig) override; - Error notifyRemovingModule(VModuleKey K) override; - Error notifyRemovingAllModules() override; + Error notifyEmitted(MaterializationResponsibility &MR) override; + Error notifyFailed(MaterializationResponsibility &MR) override; + Error notifyRemovingResources(ResourceKey K) override; + void notifyTransferringResources(ResourceKey DstKey, + ResourceKey SrcKey) override; private: @@ -185,10 +200,10 @@ private: }; std::mutex EHFramePluginMutex; - jitlink::EHFrameRegistrar &Registrar; + ExecutionSession &ES; + std::unique_ptr Registrar; DenseMap InProcessLinks; - DenseMap TrackedEHFrameRanges; - std::vector UntrackedEHFrameRanges; + DenseMap> EHFrameRanges; }; } // end namespace orc diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h index bf989cc8677c..d8395ab34e47 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h @@ -31,7 +31,7 @@ public: ObjectTransformLayer(ExecutionSession &ES, ObjectLayer &BaseLayer, TransformFunction Transform = TransformFunction()); - void emit(MaterializationResponsibility R, + void emit(std::unique_ptr R, std::unique_ptr O) override; void setTransform(TransformFunction Transform) { @@ -43,88 +43,6 @@ private: TransformFunction Transform; }; -/// Object mutating layer. -/// -/// This layer accepts sets of ObjectFiles (via addObject). It -/// immediately applies the user supplied functor to each object, then adds -/// the set of transformed objects to the layer below. -template -class LegacyObjectTransformLayer { -public: - /// Construct an ObjectTransformLayer with the given BaseLayer - LLVM_ATTRIBUTE_DEPRECATED( - LegacyObjectTransformLayer(BaseLayerT &BaseLayer, - TransformFtor Transform = TransformFtor()), - "ORCv1 layers (layers with the 'Legacy' prefix) are deprecated. Please " - "use " - "the ORCv2 ObjectTransformLayer instead"); - - /// Legacy layer constructor with deprecation acknowledgement. - LegacyObjectTransformLayer(ORCv1DeprecationAcknowledgement, - BaseLayerT &BaseLayer, - TransformFtor Transform = TransformFtor()) - : BaseLayer(BaseLayer), Transform(std::move(Transform)) {} - - /// Apply the transform functor to each object in the object set, then - /// add the resulting set of objects to the base layer, along with the - /// memory manager and symbol resolver. - /// - /// @return A handle for the added objects. - template Error addObject(VModuleKey K, ObjectPtr Obj) { - return BaseLayer.addObject(std::move(K), Transform(std::move(Obj))); - } - - /// Remove the object set associated with the VModuleKey K. - Error removeObject(VModuleKey K) { return BaseLayer.removeObject(K); } - - /// Search for the given named symbol. - /// @param Name The name of the symbol to search for. - /// @param ExportedSymbolsOnly If true, search only for exported symbols. - /// @return A handle for the given named symbol, if it exists. - JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { - return BaseLayer.findSymbol(Name, ExportedSymbolsOnly); - } - - /// Get the address of the given symbol in the context of the set of - /// objects represented by the VModuleKey K. This call is forwarded to - /// the base layer's implementation. - /// @param K The VModuleKey associated with the object set to search in. - /// @param Name The name of the symbol to search for. - /// @param ExportedSymbolsOnly If true, search only for exported symbols. - /// @return A handle for the given named symbol, if it is found in the - /// given object set. - JITSymbol findSymbolIn(VModuleKey K, const std::string &Name, - bool ExportedSymbolsOnly) { - return BaseLayer.findSymbolIn(K, Name, ExportedSymbolsOnly); - } - - /// Immediately emit and finalize the object set represented by the - /// given VModuleKey K. - Error emitAndFinalize(VModuleKey K) { return BaseLayer.emitAndFinalize(K); } - - /// Map section addresses for the objects associated with the - /// VModuleKey K. - void mapSectionAddress(VModuleKey K, const void *LocalAddress, - JITTargetAddress TargetAddr) { - BaseLayer.mapSectionAddress(K, LocalAddress, TargetAddr); - } - - /// Access the transform functor directly. - TransformFtor &getTransform() { return Transform; } - - /// Access the mumate functor directly. - const TransformFtor &getTransform() const { return Transform; } - -private: - BaseLayerT &BaseLayer; - TransformFtor Transform; -}; - -template -LegacyObjectTransformLayer:: - LegacyObjectTransformLayer(BaseLayerT &BaseLayer, TransformFtor Transform) - : BaseLayer(BaseLayer), Transform(std::move(Transform)) {} - } // end namespace orc } // end namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcError.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcError.h deleted file mode 100644 index 9b0d941f5459..000000000000 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcError.h +++ /dev/null @@ -1,74 +0,0 @@ -//===------ OrcError.h - Reject symbol lookup requests ------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// Define an error category, error codes, and helper utilities for Orc. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_ORC_ORCERROR_H -#define LLVM_EXECUTIONENGINE_ORC_ORCERROR_H - -#include "llvm/Support/Error.h" -#include "llvm/Support/raw_ostream.h" -#include -#include - -namespace llvm { -namespace orc { - -enum class OrcErrorCode : int { - // RPC Errors - UnknownORCError = 1, - DuplicateDefinition, - JITSymbolNotFound, - RemoteAllocatorDoesNotExist, - RemoteAllocatorIdAlreadyInUse, - RemoteMProtectAddrUnrecognized, - RemoteIndirectStubsOwnerDoesNotExist, - RemoteIndirectStubsOwnerIdAlreadyInUse, - RPCConnectionClosed, - RPCCouldNotNegotiateFunction, - RPCResponseAbandoned, - UnexpectedRPCCall, - UnexpectedRPCResponse, - UnknownErrorCodeFromRemote, - UnknownResourceHandle, - MissingSymbolDefinitions, - UnexpectedSymbolDefinitions, -}; - -std::error_code orcError(OrcErrorCode ErrCode); - -class DuplicateDefinition : public ErrorInfo { -public: - static char ID; - - DuplicateDefinition(std::string SymbolName); - std::error_code convertToErrorCode() const override; - void log(raw_ostream &OS) const override; - const std::string &getSymbolName() const; -private: - std::string SymbolName; -}; - -class JITSymbolNotFound : public ErrorInfo { -public: - static char ID; - - JITSymbolNotFound(std::string SymbolName); - std::error_code convertToErrorCode() const override; - void log(raw_ostream &OS) const override; - const std::string &getSymbolName() const; -private: - std::string SymbolName; -}; - -} // End namespace orc. -} // End namespace llvm. - -#endif // LLVM_EXECUTIONENGINE_ORC_ORCERROR_H diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcRPCTargetProcessControl.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcRPCTargetProcessControl.h new file mode 100644 index 000000000000..a8aa42799115 --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcRPCTargetProcessControl.h @@ -0,0 +1,415 @@ +//===--- OrcRPCTargetProcessControl.h - Remote target control ---*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Utilities for interacting with target processes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_ORCRPCTARGETPROCESSCONTROL_H +#define LLVM_EXECUTIONENGINE_ORC_ORCRPCTARGETPROCESSCONTROL_H + +#include "llvm/ExecutionEngine/Orc/Shared/RPCUtils.h" +#include "llvm/ExecutionEngine/Orc/Shared/RawByteChannel.h" +#include "llvm/ExecutionEngine/Orc/TargetProcess/OrcRPCTPCServer.h" +#include "llvm/ExecutionEngine/Orc/TargetProcessControl.h" +#include "llvm/Support/MSVCErrorWorkarounds.h" + +namespace llvm { +namespace orc { + +/// JITLinkMemoryManager implementation for a process connected via an ORC RPC +/// endpoint. +template +class OrcRPCTPCJITLinkMemoryManager : public jitlink::JITLinkMemoryManager { +private: + struct HostAlloc { + std::unique_ptr Mem; + uint64_t Size; + }; + + struct TargetAlloc { + JITTargetAddress Address = 0; + uint64_t AllocatedSize = 0; + }; + + using HostAllocMap = DenseMap; + using TargetAllocMap = DenseMap; + +public: + class OrcRPCAllocation : public Allocation { + public: + OrcRPCAllocation(OrcRPCTPCJITLinkMemoryManager &Parent, + HostAllocMap HostAllocs, TargetAllocMap TargetAllocs) + : Parent(Parent), HostAllocs(std::move(HostAllocs)), + TargetAllocs(std::move(TargetAllocs)) { + assert(HostAllocs.size() == TargetAllocs.size() && + "HostAllocs size should match TargetAllocs"); + } + + ~OrcRPCAllocation() override { + assert(TargetAllocs.empty() && "failed to deallocate"); + } + + MutableArrayRef getWorkingMemory(ProtectionFlags Seg) override { + auto I = HostAllocs.find(Seg); + assert(I != HostAllocs.end() && "No host allocation for segment"); + auto &HA = I->second; + return {HA.Mem.get(), static_cast(HA.Size)}; + } + + JITTargetAddress getTargetMemory(ProtectionFlags Seg) override { + auto I = TargetAllocs.find(Seg); + assert(I != TargetAllocs.end() && "No target allocation for segment"); + return I->second.Address; + } + + void finalizeAsync(FinalizeContinuation OnFinalize) override { + + std::vector BufferWrites; + orcrpctpc::ReleaseOrFinalizeMemRequest FMR; + + for (auto &KV : HostAllocs) { + assert(TargetAllocs.count(KV.first) && + "No target allocation for buffer"); + auto &HA = KV.second; + auto &TA = TargetAllocs[KV.first]; + BufferWrites.push_back({TA.Address, StringRef(HA.Mem.get(), HA.Size)}); + FMR.push_back({orcrpctpc::toWireProtectionFlags( + static_cast(KV.first)), + TA.Address, TA.AllocatedSize}); + } + + DEBUG_WITH_TYPE("orc", { + dbgs() << "finalizeAsync " << (void *)this << ":\n"; + auto FMRI = FMR.begin(); + for (auto &B : BufferWrites) { + auto Prot = FMRI->Prot; + ++FMRI; + dbgs() << " Writing " << formatv("{0:x16}", B.Buffer.size()) + << " bytes to " << ((Prot & orcrpctpc::WPF_Read) ? 'R' : '-') + << ((Prot & orcrpctpc::WPF_Write) ? 'W' : '-') + << ((Prot & orcrpctpc::WPF_Exec) ? 'X' : '-') + << " segment: local " << (const void *)B.Buffer.data() + << " -> target " << formatv("{0:x16}", B.Address) << "\n"; + } + }); + if (auto Err = + Parent.Parent.getMemoryAccess().writeBuffers(BufferWrites)) { + OnFinalize(std::move(Err)); + return; + } + + DEBUG_WITH_TYPE("orc", dbgs() << " Applying permissions...\n"); + if (auto Err = + Parent.getEndpoint().template callAsync( + [OF = std::move(OnFinalize)](Error Err2) { + // FIXME: Dispatch to work queue. + std::thread([OF = std::move(OF), + Err3 = std::move(Err2)]() mutable { + DEBUG_WITH_TYPE( + "orc", { dbgs() << " finalizeAsync complete\n"; }); + OF(std::move(Err3)); + }).detach(); + return Error::success(); + }, + FMR)) { + DEBUG_WITH_TYPE("orc", dbgs() << " failed.\n"); + Parent.getEndpoint().abandonPendingResponses(); + Parent.reportError(std::move(Err)); + } + DEBUG_WITH_TYPE("orc", { + dbgs() << "Leaving finalizeAsync (finalization may continue in " + "background)\n"; + }); + } + + Error deallocate() override { + orcrpctpc::ReleaseOrFinalizeMemRequest RMR; + for (auto &KV : TargetAllocs) + RMR.push_back({orcrpctpc::toWireProtectionFlags( + static_cast(KV.first)), + KV.second.Address, KV.second.AllocatedSize}); + TargetAllocs.clear(); + + return Parent.getEndpoint().template callB(RMR); + } + + private: + OrcRPCTPCJITLinkMemoryManager &Parent; + HostAllocMap HostAllocs; + TargetAllocMap TargetAllocs; + }; + + OrcRPCTPCJITLinkMemoryManager(OrcRPCTPCImplT &Parent) : Parent(Parent) {} + + Expected> + allocate(const jitlink::JITLinkDylib *JD, + const SegmentsRequestMap &Request) override { + orcrpctpc::ReserveMemRequest RMR; + HostAllocMap HostAllocs; + + for (auto &KV : Request) { + assert(KV.second.getContentSize() <= std::numeric_limits::max() && + "Content size is out-of-range for host"); + + RMR.push_back({orcrpctpc::toWireProtectionFlags( + static_cast(KV.first)), + KV.second.getContentSize() + KV.second.getZeroFillSize(), + KV.second.getAlignment()}); + HostAllocs[KV.first] = { + std::make_unique(KV.second.getContentSize()), + KV.second.getContentSize()}; + } + + DEBUG_WITH_TYPE("orc", { + dbgs() << "Orc remote memmgr got request:\n"; + for (auto &KV : Request) + dbgs() << " permissions: " + << ((KV.first & sys::Memory::MF_READ) ? 'R' : '-') + << ((KV.first & sys::Memory::MF_WRITE) ? 'W' : '-') + << ((KV.first & sys::Memory::MF_EXEC) ? 'X' : '-') + << ", content size: " + << formatv("{0:x16}", KV.second.getContentSize()) + << " + zero-fill-size: " + << formatv("{0:x16}", KV.second.getZeroFillSize()) + << ", align: " << KV.second.getAlignment() << "\n"; + }); + + // FIXME: LLVM RPC needs to be fixed to support alt + // serialization/deserialization on return types. For now just + // translate from std::map to DenseMap manually. + auto TmpTargetAllocs = + Parent.getEndpoint().template callB(RMR); + if (!TmpTargetAllocs) + return TmpTargetAllocs.takeError(); + + if (TmpTargetAllocs->size() != RMR.size()) + return make_error( + "Number of target allocations does not match request", + inconvertibleErrorCode()); + + TargetAllocMap TargetAllocs; + for (auto &E : *TmpTargetAllocs) + TargetAllocs[orcrpctpc::fromWireProtectionFlags(E.Prot)] = { + E.Address, E.AllocatedSize}; + + DEBUG_WITH_TYPE("orc", { + auto HAI = HostAllocs.begin(); + for (auto &KV : TargetAllocs) + dbgs() << " permissions: " + << ((KV.first & sys::Memory::MF_READ) ? 'R' : '-') + << ((KV.first & sys::Memory::MF_WRITE) ? 'W' : '-') + << ((KV.first & sys::Memory::MF_EXEC) ? 'X' : '-') + << " assigned local " << (void *)HAI->second.Mem.get() + << ", target " << formatv("{0:x16}", KV.second.Address) << "\n"; + }); + + return std::make_unique(*this, std::move(HostAllocs), + std::move(TargetAllocs)); + } + +private: + void reportError(Error Err) { Parent.reportError(std::move(Err)); } + + decltype(std::declval().getEndpoint()) getEndpoint() { + return Parent.getEndpoint(); + } + + OrcRPCTPCImplT &Parent; +}; + +/// TargetProcessControl::MemoryAccess implementation for a process connected +/// via an ORC RPC endpoint. +template +class OrcRPCTPCMemoryAccess : public TargetProcessControl::MemoryAccess { +public: + OrcRPCTPCMemoryAccess(OrcRPCTPCImplT &Parent) : Parent(Parent) {} + + void writeUInt8s(ArrayRef Ws, + WriteResultFn OnWriteComplete) override { + writeViaRPC(Ws, std::move(OnWriteComplete)); + } + + void writeUInt16s(ArrayRef Ws, + WriteResultFn OnWriteComplete) override { + writeViaRPC(Ws, std::move(OnWriteComplete)); + } + + void writeUInt32s(ArrayRef Ws, + WriteResultFn OnWriteComplete) override { + writeViaRPC(Ws, std::move(OnWriteComplete)); + } + + void writeUInt64s(ArrayRef Ws, + WriteResultFn OnWriteComplete) override { + writeViaRPC(Ws, std::move(OnWriteComplete)); + } + + void writeBuffers(ArrayRef Ws, + WriteResultFn OnWriteComplete) override { + writeViaRPC(Ws, std::move(OnWriteComplete)); + } + +private: + template + void writeViaRPC(ArrayRef Ws, WriteResultFn OnWriteComplete) { + if (auto Err = Parent.getEndpoint().template callAsync( + [OWC = std::move(OnWriteComplete)](Error Err2) mutable -> Error { + OWC(std::move(Err2)); + return Error::success(); + }, + Ws)) { + Parent.reportError(std::move(Err)); + Parent.getEndpoint().abandonPendingResponses(); + } + } + + OrcRPCTPCImplT &Parent; +}; + +// TargetProcessControl for a process connected via an ORC RPC Endpoint. +template +class OrcRPCTargetProcessControlBase : public TargetProcessControl { +public: + using ErrorReporter = unique_function; + + using OnCloseConnectionFunction = unique_function; + + OrcRPCTargetProcessControlBase(std::shared_ptr SSP, + RPCEndpointT &EP, ErrorReporter ReportError) + : TargetProcessControl(std::move(SSP)), + ReportError(std::move(ReportError)), EP(EP) {} + + void reportError(Error Err) { ReportError(std::move(Err)); } + + RPCEndpointT &getEndpoint() { return EP; } + + Expected loadDylib(const char *DylibPath) override { + DEBUG_WITH_TYPE("orc", { + dbgs() << "Loading dylib \"" << (DylibPath ? DylibPath : "") << "\" "; + if (!DylibPath) + dbgs() << "(process symbols)"; + dbgs() << "\n"; + }); + if (!DylibPath) + DylibPath = ""; + auto H = EP.template callB(DylibPath); + DEBUG_WITH_TYPE("orc", { + if (H) + dbgs() << " got handle " << formatv("{0:x16}", *H) << "\n"; + else + dbgs() << " error, unable to load\n"; + }); + return H; + } + + Expected> + lookupSymbols(ArrayRef Request) override { + std::vector RR; + for (auto &E : Request) { + RR.push_back({}); + RR.back().first = E.Handle; + for (auto &KV : E.Symbols) + RR.back().second.push_back( + {(*KV.first).str(), + KV.second == SymbolLookupFlags::WeaklyReferencedSymbol}); + } + DEBUG_WITH_TYPE("orc", { + dbgs() << "Compound lookup:\n"; + for (auto &R : Request) { + dbgs() << " In " << formatv("{0:x16}", R.Handle) << ": {"; + bool First = true; + for (auto &KV : R.Symbols) { + dbgs() << (First ? "" : ",") << " " << *KV.first; + First = false; + } + dbgs() << " }\n"; + } + }); + return EP.template callB(RR); + } + + Expected runAsMain(JITTargetAddress MainFnAddr, + ArrayRef Args) override { + DEBUG_WITH_TYPE("orc", { + dbgs() << "Running as main: " << formatv("{0:x16}", MainFnAddr) + << ", args = ["; + for (unsigned I = 0; I != Args.size(); ++I) + dbgs() << (I ? "," : "") << " \"" << Args[I] << "\""; + dbgs() << "]\n"; + }); + auto Result = EP.template callB(MainFnAddr, Args); + DEBUG_WITH_TYPE("orc", { + dbgs() << " call to " << formatv("{0:x16}", MainFnAddr); + if (Result) + dbgs() << " returned result " << *Result << "\n"; + else + dbgs() << " failed\n"; + }); + return Result; + } + + Expected + runWrapper(JITTargetAddress WrapperFnAddr, + ArrayRef ArgBuffer) override { + DEBUG_WITH_TYPE("orc", { + dbgs() << "Running as wrapper function " + << formatv("{0:x16}", WrapperFnAddr) << " with " + << formatv("{0:x16}", ArgBuffer.size()) << " argument buffer\n"; + }); + auto Result = + EP.template callB(WrapperFnAddr, ArgBuffer); + // dbgs() << "Returned from runWrapper...\n"; + return Result; + } + + Error closeConnection(OnCloseConnectionFunction OnCloseConnection) { + DEBUG_WITH_TYPE("orc", dbgs() << "Closing connection to remote\n"); + return EP.template callAsync( + std::move(OnCloseConnection)); + } + + Error closeConnectionAndWait() { + std::promise P; + auto F = P.get_future(); + if (auto Err = closeConnection([&](Error Err2) -> Error { + P.set_value(std::move(Err2)); + return Error::success(); + })) { + EP.abandonAllPendingResponses(); + return joinErrors(std::move(Err), F.get()); + } + return F.get(); + } + +protected: + /// Subclasses must call this during construction to initialize the + /// TargetTriple and PageSize members. + Error initializeORCRPCTPCBase() { + if (auto TripleOrErr = EP.template callB()) + TargetTriple = Triple(*TripleOrErr); + else + return TripleOrErr.takeError(); + + if (auto PageSizeOrErr = EP.template callB()) + PageSize = *PageSizeOrErr; + else + return PageSizeOrErr.takeError(); + + return Error::success(); + } + +private: + ErrorReporter ReportError; + RPCEndpointT &EP; +}; + +} // end namespace orc +} // end namespace llvm + +#endif // LLVM_EXECUTIONENGINE_ORC_ORCRPCTARGETPROCESSCONTROL_H diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h index 86e8d5df3ad9..3d139740d677 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h @@ -20,6 +20,7 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h" #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" #include "llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" @@ -53,7 +54,7 @@ namespace remote { /// OrcRemoteTargetServer class) via an RPC system (see RPCUtils.h) to carry out /// its actions. class OrcRemoteTargetClient - : public rpc::SingleThreadedRPCEndpoint { + : public shared::SingleThreadedRPCEndpoint { public: /// Remote-mapped RuntimeDyld-compatible memory manager. class RemoteRTDyldMemoryManager : public RuntimeDyld::MemoryManager { @@ -329,6 +330,221 @@ public: std::vector RegisteredEHFrames; }; + class RPCMMAlloc : public jitlink::JITLinkMemoryManager::Allocation { + using AllocationMap = DenseMap; + using FinalizeContinuation = + jitlink::JITLinkMemoryManager::Allocation::FinalizeContinuation; + using ProtectionFlags = sys::Memory::ProtectionFlags; + using SegmentsRequestMap = + DenseMap; + + RPCMMAlloc(OrcRemoteTargetClient &Client, ResourceIdMgr::ResourceId Id) + : Client(Client), Id(Id) {} + + public: + static Expected> + Create(OrcRemoteTargetClient &Client, ResourceIdMgr::ResourceId Id, + const SegmentsRequestMap &Request) { + auto *MM = new RPCMMAlloc(Client, Id); + + if (Error Err = MM->allocateHostBlocks(Request)) + return std::move(Err); + + if (Error Err = MM->allocateTargetBlocks()) + return std::move(Err); + + return std::unique_ptr(MM); + } + + MutableArrayRef getWorkingMemory(ProtectionFlags Seg) override { + assert(HostSegBlocks.count(Seg) && "No allocation for segment"); + return {static_cast(HostSegBlocks[Seg].base()), + HostSegBlocks[Seg].allocatedSize()}; + } + + JITTargetAddress getTargetMemory(ProtectionFlags Seg) override { + assert(TargetSegBlocks.count(Seg) && "No allocation for segment"); + return pointerToJITTargetAddress(TargetSegBlocks[Seg].base()); + } + + void finalizeAsync(FinalizeContinuation OnFinalize) override { + // Host allocations (working memory) remain ReadWrite. + OnFinalize(copyAndProtect()); + } + + Error deallocate() override { + // TODO: Cannot release target allocation. RPCAPI has no function + // symmetric to reserveMem(). Add RPC call like freeMem()? + return errorCodeToError(sys::Memory::releaseMappedMemory(HostAllocation)); + } + + private: + OrcRemoteTargetClient &Client; + ResourceIdMgr::ResourceId Id; + AllocationMap HostSegBlocks; + AllocationMap TargetSegBlocks; + JITTargetAddress TargetSegmentAddr; + sys::MemoryBlock HostAllocation; + + Error allocateHostBlocks(const SegmentsRequestMap &Request) { + unsigned TargetPageSize = Client.getPageSize(); + + if (!isPowerOf2_64(static_cast(TargetPageSize))) + return make_error("Host page size is not a power of 2", + inconvertibleErrorCode()); + + auto TotalSize = calcTotalAllocSize(Request, TargetPageSize); + if (!TotalSize) + return TotalSize.takeError(); + + // Allocate one slab to cover all the segments. + const sys::Memory::ProtectionFlags ReadWrite = + static_cast(sys::Memory::MF_READ | + sys::Memory::MF_WRITE); + std::error_code EC; + HostAllocation = + sys::Memory::allocateMappedMemory(*TotalSize, nullptr, ReadWrite, EC); + if (EC) + return errorCodeToError(EC); + + char *SlabAddr = static_cast(HostAllocation.base()); +#ifndef NDEBUG + char *SlabAddrEnd = SlabAddr + HostAllocation.allocatedSize(); +#endif + + // Allocate segment memory from the slab. + for (auto &KV : Request) { + const auto &Seg = KV.second; + + uint64_t SegmentSize = Seg.getContentSize() + Seg.getZeroFillSize(); + uint64_t AlignedSegmentSize = alignTo(SegmentSize, TargetPageSize); + + // Zero out zero-fill memory. + char *ZeroFillBegin = SlabAddr + Seg.getContentSize(); + memset(ZeroFillBegin, 0, Seg.getZeroFillSize()); + + // Record the block for this segment. + HostSegBlocks[KV.first] = + sys::MemoryBlock(SlabAddr, AlignedSegmentSize); + + SlabAddr += AlignedSegmentSize; + assert(SlabAddr <= SlabAddrEnd && "Out of range"); + } + + return Error::success(); + } + + Error allocateTargetBlocks() { + // Reserve memory for all blocks on the target. We need as much space on + // the target as we allocated on the host. + TargetSegmentAddr = Client.reserveMem(Id, HostAllocation.allocatedSize(), + Client.getPageSize()); + if (!TargetSegmentAddr) + return make_error("Failed to reserve memory on the target", + inconvertibleErrorCode()); + + // Map memory blocks into the allocation, that match the host allocation. + JITTargetAddress TargetAllocAddr = TargetSegmentAddr; + for (const auto &KV : HostSegBlocks) { + size_t TargetAllocSize = KV.second.allocatedSize(); + + TargetSegBlocks[KV.first] = + sys::MemoryBlock(jitTargetAddressToPointer(TargetAllocAddr), + TargetAllocSize); + + TargetAllocAddr += TargetAllocSize; + assert(TargetAllocAddr - TargetSegmentAddr <= + HostAllocation.allocatedSize() && + "Out of range on target"); + } + + return Error::success(); + } + + Error copyAndProtect() { + unsigned Permissions = 0u; + + // Copy segments one by one. + for (auto &KV : TargetSegBlocks) { + Permissions |= KV.first; + + const sys::MemoryBlock &TargetBlock = KV.second; + const sys::MemoryBlock &HostBlock = HostSegBlocks.lookup(KV.first); + + size_t TargetAllocSize = TargetBlock.allocatedSize(); + auto TargetAllocAddr = pointerToJITTargetAddress(TargetBlock.base()); + auto *HostAllocBegin = static_cast(HostBlock.base()); + + bool CopyErr = + Client.writeMem(TargetAllocAddr, HostAllocBegin, TargetAllocSize); + if (CopyErr) + return createStringError(inconvertibleErrorCode(), + "Failed to copy %d segment to the target", + KV.first); + } + + // Set permission flags for all segments at once. + bool ProtectErr = + Client.setProtections(Id, TargetSegmentAddr, Permissions); + if (ProtectErr) + return createStringError(inconvertibleErrorCode(), + "Failed to apply permissions for %d segment " + "on the target", + Permissions); + return Error::success(); + } + + static Expected + calcTotalAllocSize(const SegmentsRequestMap &Request, + unsigned TargetPageSize) { + size_t TotalSize = 0; + for (const auto &KV : Request) { + const auto &Seg = KV.second; + + if (Seg.getAlignment() > TargetPageSize) + return make_error("Cannot request alignment higher than " + "page alignment on target", + inconvertibleErrorCode()); + + TotalSize = alignTo(TotalSize, TargetPageSize); + TotalSize += Seg.getContentSize(); + TotalSize += Seg.getZeroFillSize(); + } + + return TotalSize; + } + }; + + class RemoteJITLinkMemoryManager : public jitlink::JITLinkMemoryManager { + public: + RemoteJITLinkMemoryManager(OrcRemoteTargetClient &Client, + ResourceIdMgr::ResourceId Id) + : Client(Client), Id(Id) {} + + RemoteJITLinkMemoryManager(const RemoteJITLinkMemoryManager &) = delete; + RemoteJITLinkMemoryManager(RemoteJITLinkMemoryManager &&) = default; + + RemoteJITLinkMemoryManager & + operator=(const RemoteJITLinkMemoryManager &) = delete; + RemoteJITLinkMemoryManager & + operator=(RemoteJITLinkMemoryManager &&) = delete; + + ~RemoteJITLinkMemoryManager() { + Client.destroyRemoteAllocator(Id); + LLVM_DEBUG(dbgs() << "Destroyed remote allocator " << Id << "\n"); + } + + Expected> + allocate(const jitlink::JITLinkDylib *JD, + const SegmentsRequestMap &Request) override { + return RPCMMAlloc::Create(Client, Id, Request); + } + + private: + OrcRemoteTargetClient &Client; + ResourceIdMgr::ResourceId Id; + }; + /// Remote indirect stubs manager. class RemoteIndirectStubsManager : public IndirectStubsManager { public: @@ -453,20 +669,8 @@ public: public: RemoteTrampolinePool(OrcRemoteTargetClient &Client) : Client(Client) {} - Expected getTrampoline() override { - std::lock_guard Lock(RTPMutex); - if (AvailableTrampolines.empty()) { - if (auto Err = grow()) - return std::move(Err); - } - assert(!AvailableTrampolines.empty() && "Failed to grow trampoline pool"); - auto TrampolineAddr = AvailableTrampolines.back(); - AvailableTrampolines.pop_back(); - return TrampolineAddr; - } - private: - Error grow() { + Error grow() override { JITTargetAddress BlockAddr = 0; uint32_t NumTrampolines = 0; if (auto TrampolineInfoOrErr = Client.emitTrampolineBlock()) @@ -476,14 +680,12 @@ public: uint32_t TrampolineSize = Client.getTrampolineSize(); for (unsigned I = 0; I < NumTrampolines; ++I) - this->AvailableTrampolines.push_back(BlockAddr + (I * TrampolineSize)); + AvailableTrampolines.push_back(BlockAddr + (I * TrampolineSize)); return Error::success(); } - std::mutex RTPMutex; OrcRemoteTargetClient &Client; - std::vector AvailableTrampolines; }; /// Remote compile callback manager. @@ -501,7 +703,7 @@ public: /// Channel is the ChannelT instance to communicate on. It is assumed that /// the channel is ready to be read from and written to. static Expected> - Create(rpc::RawByteChannel &Channel, ExecutionSession &ES) { + Create(shared::RawByteChannel &Channel, ExecutionSession &ES) { Error Err = Error::success(); auto Client = std::unique_ptr( new OrcRemoteTargetClient(Channel, ES, Err)); @@ -518,6 +720,14 @@ public: return callB(Addr); } + /// Call the int(int) function at the given address in the target and return + /// its result. + Expected callIntInt(JITTargetAddress Addr, int Arg) { + LLVM_DEBUG(dbgs() << "Calling int(*)(int) " << format("0x%016" PRIx64, Addr) + << "\n"); + return callB(Addr, Arg); + } + /// Call the int(int, char*[]) function at the given address in the target and /// return its result. Expected callMain(JITTargetAddress Addr, @@ -546,6 +756,18 @@ public: new RemoteRTDyldMemoryManager(*this, Id)); } + /// Create a JITLink-compatible memory manager which will allocate working + /// memory on the host and target memory on the remote target. + Expected> + createRemoteJITLinkMemoryManager() { + auto Id = AllocatorIds.getNext(); + if (auto Err = callB(Id)) + return std::move(Err); + LLVM_DEBUG(dbgs() << "Created remote allocator " << Id << "\n"); + return std::unique_ptr( + new RemoteJITLinkMemoryManager(*this, Id)); + } + /// Create an RCIndirectStubsManager that will allocate stubs on the remote /// target. Expected> @@ -583,9 +805,10 @@ public: Error terminateSession() { return callB(); } private: - OrcRemoteTargetClient(rpc::RawByteChannel &Channel, ExecutionSession &ES, + OrcRemoteTargetClient(shared::RawByteChannel &Channel, ExecutionSession &ES, Error &Err) - : rpc::SingleThreadedRPCEndpoint(Channel, true), + : shared::SingleThreadedRPCEndpoint(Channel, + true), ES(ES) { ErrorAsOutParameter EAO(&Err); diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h index 52a328165240..367bfb369191 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h @@ -16,8 +16,8 @@ #define LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETRPCAPI_H #include "llvm/ExecutionEngine/JITSymbol.h" -#include "llvm/ExecutionEngine/Orc/RPC/RPCUtils.h" -#include "llvm/ExecutionEngine/Orc/RPC/RawByteChannel.h" +#include "llvm/ExecutionEngine/Orc/Shared/RPCUtils.h" +#include "llvm/ExecutionEngine/Orc/Shared/RawByteChannel.h" namespace llvm { namespace orc { @@ -73,10 +73,9 @@ private: } // end namespace remote -namespace rpc { +namespace shared { -template <> -class RPCTypeName { +template <> class SerializationTypeName { public: static const char *getName() { return "JITSymbolFlags"; } }; @@ -100,7 +99,7 @@ public: } }; -template <> class RPCTypeName { +template <> class SerializationTypeName { public: static const char *getName() { return "DirectBufferWriter"; } }; @@ -133,7 +132,7 @@ public: } }; -} // end namespace rpc +} // end namespace shared namespace remote { @@ -167,20 +166,20 @@ private: namespace eh { /// Registers EH frames on the remote. - class RegisterEHFrames - : public rpc::Function { - public: - static const char *getName() { return "RegisterEHFrames"; } - }; +class RegisterEHFrames + : public shared::RPCFunction { +public: + static const char *getName() { return "RegisterEHFrames"; } +}; /// Deregisters EH frames on the remote. - class DeregisterEHFrames - : public rpc::Function { - public: - static const char *getName() { return "DeregisterEHFrames"; } - }; +class DeregisterEHFrames + : public shared::RPCFunction { +public: + static const char *getName() { return "DeregisterEHFrames"; } +}; } // end namespace eh @@ -189,28 +188,38 @@ namespace exec { /// Call an 'int32_t()'-type function on the remote, returns the called /// function's return value. - class CallIntVoid - : public rpc::Function { - public: - static const char *getName() { return "CallIntVoid"; } - }; +class CallIntVoid + : public shared::RPCFunction { +public: + static const char *getName() { return "CallIntVoid"; } +}; + + /// Call an 'int32_t(int32_t)'-type function on the remote, returns the called + /// function's return value. +class CallIntInt + : public shared::RPCFunction { +public: + static const char *getName() { return "CallIntInt"; } +}; /// Call an 'int32_t(int32_t, char**)'-type function on the remote, returns the /// called function's return value. - class CallMain - : public rpc::Function Args)> { - public: - static const char *getName() { return "CallMain"; } - }; +class CallMain + : public shared::RPCFunction Args)> { +public: + static const char *getName() { return "CallMain"; } +}; /// Calls a 'void()'-type function on the remote, returns when the called /// function completes. - class CallVoidVoid - : public rpc::Function { - public: - static const char *getName() { return "CallVoidVoid"; } - }; +class CallVoidVoid + : public shared::RPCFunction { +public: + static const char *getName() { return "CallVoidVoid"; } +}; } // end namespace exec @@ -218,60 +227,62 @@ namespace exec { namespace mem { /// Creates a memory allocator on the remote. - class CreateRemoteAllocator - : public rpc::Function { - public: - static const char *getName() { return "CreateRemoteAllocator"; } - }; +class CreateRemoteAllocator + : public shared::RPCFunction { +public: + static const char *getName() { return "CreateRemoteAllocator"; } +}; /// Destroys a remote allocator, freeing any memory allocated by it. - class DestroyRemoteAllocator - : public rpc::Function { - public: - static const char *getName() { return "DestroyRemoteAllocator"; } - }; +class DestroyRemoteAllocator + : public shared::RPCFunction { +public: + static const char *getName() { return "DestroyRemoteAllocator"; } +}; /// Read a remote memory block. - class ReadMem - : public rpc::Function(JITTargetAddress Src, - uint64_t Size)> { - public: - static const char *getName() { return "ReadMem"; } - }; +class ReadMem + : public shared::RPCFunction< + ReadMem, std::vector(JITTargetAddress Src, uint64_t Size)> { +public: + static const char *getName() { return "ReadMem"; } +}; /// Reserve a block of memory on the remote via the given allocator. - class ReserveMem - : public rpc::Function { - public: - static const char *getName() { return "ReserveMem"; } - }; +class ReserveMem + : public shared::RPCFunction< + ReserveMem, JITTargetAddress(ResourceIdMgr::ResourceId AllocID, + uint64_t Size, uint32_t Align)> { +public: + static const char *getName() { return "ReserveMem"; } +}; /// Set the memory protection on a memory block. - class SetProtections - : public rpc::Function { - public: - static const char *getName() { return "SetProtections"; } - }; +class SetProtections + : public shared::RPCFunction< + SetProtections, void(ResourceIdMgr::ResourceId AllocID, + JITTargetAddress Dst, uint32_t ProtFlags)> { +public: + static const char *getName() { return "SetProtections"; } +}; /// Write to a remote memory block. - class WriteMem - : public rpc::Function { - public: - static const char *getName() { return "WriteMem"; } - }; +class WriteMem + : public shared::RPCFunction { +public: + static const char *getName() { return "WriteMem"; } +}; /// Write to a remote pointer. - class WritePtr : public rpc::Function { - public: - static const char *getName() { return "WritePtr"; } - }; +class WritePtr + : public shared::RPCFunction { +public: + static const char *getName() { return "WritePtr"; } +}; } // end namespace mem @@ -279,45 +290,46 @@ namespace mem { namespace stubs { /// Creates an indirect stub owner on the remote. - class CreateIndirectStubsOwner - : public rpc::Function { - public: - static const char *getName() { return "CreateIndirectStubsOwner"; } - }; +class CreateIndirectStubsOwner + : public shared::RPCFunction { +public: + static const char *getName() { return "CreateIndirectStubsOwner"; } +}; /// RPC function for destroying an indirect stubs owner. - class DestroyIndirectStubsOwner - : public rpc::Function { - public: - static const char *getName() { return "DestroyIndirectStubsOwner"; } - }; +class DestroyIndirectStubsOwner + : public shared::RPCFunction { +public: + static const char *getName() { return "DestroyIndirectStubsOwner"; } +}; /// EmitIndirectStubs result is (StubsBase, PtrsBase, NumStubsEmitted). - class EmitIndirectStubs - : public rpc::Function< - EmitIndirectStubs, - std::tuple( - ResourceIdMgr::ResourceId StubsOwnerID, - uint32_t NumStubsRequired)> { - public: - static const char *getName() { return "EmitIndirectStubs"; } - }; +class EmitIndirectStubs + : public shared::RPCFunction< + EmitIndirectStubs, + std::tuple( + ResourceIdMgr::ResourceId StubsOwnerID, + uint32_t NumStubsRequired)> { +public: + static const char *getName() { return "EmitIndirectStubs"; } +}; /// RPC function to emit the resolver block and return its address. - class EmitResolverBlock : public rpc::Function { - public: - static const char *getName() { return "EmitResolverBlock"; } - }; +class EmitResolverBlock + : public shared::RPCFunction { +public: + static const char *getName() { return "EmitResolverBlock"; } +}; /// EmitTrampolineBlock result is (BlockAddr, NumTrampolines). - class EmitTrampolineBlock - : public rpc::Function()> { - public: - static const char *getName() { return "EmitTrampolineBlock"; } - }; +class EmitTrampolineBlock + : public shared::RPCFunction()> { +public: + static const char *getName() { return "EmitTrampolineBlock"; } +}; } // end namespace stubs @@ -326,44 +338,44 @@ namespace utils { /// GetRemoteInfo result is (Triple, PointerSize, PageSize, TrampolineSize, /// IndirectStubsSize). - class GetRemoteInfo - : public rpc::Function< - GetRemoteInfo, - std::tuple()> { - public: - static const char *getName() { return "GetRemoteInfo"; } - }; +class GetRemoteInfo + : public shared::RPCFunction< + GetRemoteInfo, + std::tuple()> { +public: + static const char *getName() { return "GetRemoteInfo"; } +}; /// Get the address of a remote symbol. - class GetSymbolAddress - : public rpc::Function { - public: - static const char *getName() { return "GetSymbolAddress"; } - }; +class GetSymbolAddress + : public shared::RPCFunction { +public: + static const char *getName() { return "GetSymbolAddress"; } +}; /// Request that the host execute a compile callback. - class RequestCompile - : public rpc::Function< - RequestCompile, JITTargetAddress(JITTargetAddress TrampolineAddr)> { - public: - static const char *getName() { return "RequestCompile"; } - }; +class RequestCompile + : public shared::RPCFunction< + RequestCompile, JITTargetAddress(JITTargetAddress TrampolineAddr)> { +public: + static const char *getName() { return "RequestCompile"; } +}; /// Notify the remote and terminate the session. - class TerminateSession : public rpc::Function { - public: - static const char *getName() { return "TerminateSession"; } - }; +class TerminateSession : public shared::RPCFunction { +public: + static const char *getName() { return "TerminateSession"; } +}; } // namespace utils class OrcRemoteTargetRPCAPI - : public rpc::SingleThreadedRPCEndpoint { + : public shared::SingleThreadedRPCEndpoint { public: // FIXME: Remove constructors once MSVC supports synthesizing move-ops. - OrcRemoteTargetRPCAPI(rpc::RawByteChannel &C) - : rpc::SingleThreadedRPCEndpoint(C, true) {} + OrcRemoteTargetRPCAPI(shared::RawByteChannel &C) + : shared::SingleThreadedRPCEndpoint(C, true) {} }; } // end namespace remote diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h index 50c155d77db1..ce9bf064303d 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h @@ -16,8 +16,8 @@ #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" -#include "llvm/ExecutionEngine/Orc/OrcError.h" #include "llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h" +#include "llvm/ExecutionEngine/Orc/Shared/OrcError.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Error.h" #include "llvm/Support/Format.h" @@ -46,7 +46,7 @@ namespace remote { template class OrcRemoteTargetServer - : public rpc::SingleThreadedRPCEndpoint { + : public shared::SingleThreadedRPCEndpoint { public: using SymbolLookupFtor = std::function; @@ -57,12 +57,14 @@ public: OrcRemoteTargetServer(ChannelT &Channel, SymbolLookupFtor SymbolLookup, EHFrameRegistrationFtor EHFramesRegister, EHFrameRegistrationFtor EHFramesDeregister) - : rpc::SingleThreadedRPCEndpoint(Channel, true), + : shared::SingleThreadedRPCEndpoint(Channel, + true), SymbolLookup(std::move(SymbolLookup)), EHFramesRegister(std::move(EHFramesRegister)), EHFramesDeregister(std::move(EHFramesDeregister)) { using ThisT = std::remove_reference_t; addHandler(*this, &ThisT::handleCallIntVoid); + addHandler(*this, &ThisT::handleCallIntInt); addHandler(*this, &ThisT::handleCallMain); addHandler(*this, &ThisT::handleCallVoidVoid); addHandler(*this, @@ -168,6 +170,19 @@ private: return Result; } + Expected handleCallIntInt(JITTargetAddress Addr, int Arg) { + using IntIntFnTy = int (*)(int); + + IntIntFnTy Fn = reinterpret_cast(static_cast(Addr)); + + LLVM_DEBUG(dbgs() << " Calling " << format("0x%016x", Addr) + << " with argument " << Arg << "\n"); + int Result = Fn(Arg); + LLVM_DEBUG(dbgs() << " Result = " << Result << "\n"); + + return Result; + } + Expected handleCallMain(JITTargetAddress Addr, std::vector Args) { using MainFnTy = int (*)(int, const char *[]); diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPC/RPCSerialization.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPC/RPCSerialization.h deleted file mode 100644 index 2f37ab40c7f8..000000000000 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPC/RPCSerialization.h +++ /dev/null @@ -1,702 +0,0 @@ -//===- llvm/ExecutionEngine/Orc/RPC/RPCSerialization.h --------------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_ORC_RPCSERIALIZATION_H -#define LLVM_EXECUTIONENGINE_ORC_RPCSERIALIZATION_H - -#include "llvm/ExecutionEngine/Orc/OrcError.h" -#include "llvm/Support/thread.h" -#include -#include -#include -#include -#include -#include - -namespace llvm { -namespace orc { -namespace rpc { - -template -class RPCTypeName; - -/// TypeNameSequence is a utility for rendering sequences of types to a string -/// by rendering each type, separated by ", ". -template class RPCTypeNameSequence {}; - -/// Render an empty TypeNameSequence to an ostream. -template -OStream &operator<<(OStream &OS, const RPCTypeNameSequence<> &V) { - return OS; -} - -/// Render a TypeNameSequence of a single type to an ostream. -template -OStream &operator<<(OStream &OS, const RPCTypeNameSequence &V) { - OS << RPCTypeName::getName(); - return OS; -} - -/// Render a TypeNameSequence of more than one type to an ostream. -template -OStream& -operator<<(OStream &OS, const RPCTypeNameSequence &V) { - OS << RPCTypeName::getName() << ", " - << RPCTypeNameSequence(); - return OS; -} - -template <> -class RPCTypeName { -public: - static const char* getName() { return "void"; } -}; - -template <> -class RPCTypeName { -public: - static const char* getName() { return "int8_t"; } -}; - -template <> -class RPCTypeName { -public: - static const char* getName() { return "uint8_t"; } -}; - -template <> -class RPCTypeName { -public: - static const char* getName() { return "int16_t"; } -}; - -template <> -class RPCTypeName { -public: - static const char* getName() { return "uint16_t"; } -}; - -template <> -class RPCTypeName { -public: - static const char* getName() { return "int32_t"; } -}; - -template <> -class RPCTypeName { -public: - static const char* getName() { return "uint32_t"; } -}; - -template <> -class RPCTypeName { -public: - static const char* getName() { return "int64_t"; } -}; - -template <> -class RPCTypeName { -public: - static const char* getName() { return "uint64_t"; } -}; - -template <> -class RPCTypeName { -public: - static const char* getName() { return "bool"; } -}; - -template <> -class RPCTypeName { -public: - static const char* getName() { return "std::string"; } -}; - -template <> -class RPCTypeName { -public: - static const char* getName() { return "Error"; } -}; - -template -class RPCTypeName> { -public: - static const char* getName() { - static std::string Name = [] { - std::string Name; - raw_string_ostream(Name) << "Expected<" - << RPCTypeNameSequence() - << ">"; - return Name; - }(); - return Name.data(); - } -}; - -template -class RPCTypeName> { -public: - static const char* getName() { - static std::string Name = [] { - std::string Name; - raw_string_ostream(Name) << "std::pair<" << RPCTypeNameSequence() - << ">"; - return Name; - }(); - return Name.data(); - } -}; - -template -class RPCTypeName> { -public: - static const char* getName() { - static std::string Name = [] { - std::string Name; - raw_string_ostream(Name) << "std::tuple<" - << RPCTypeNameSequence() << ">"; - return Name; - }(); - return Name.data(); - } -}; - -template -class RPCTypeName> { -public: - static const char*getName() { - static std::string Name = [] { - std::string Name; - raw_string_ostream(Name) << "std::vector<" << RPCTypeName::getName() - << ">"; - return Name; - }(); - return Name.data(); - } -}; - -template class RPCTypeName> { -public: - static const char *getName() { - static std::string Name = [] { - std::string Name; - raw_string_ostream(Name) - << "std::set<" << RPCTypeName::getName() << ">"; - return Name; - }(); - return Name.data(); - } -}; - -template class RPCTypeName> { -public: - static const char *getName() { - static std::string Name = [] { - std::string Name; - raw_string_ostream(Name) - << "std::map<" << RPCTypeNameSequence() << ">"; - return Name; - }(); - return Name.data(); - } -}; - -/// The SerializationTraits class describes how to serialize and -/// deserialize an instance of type T to/from an abstract channel of type -/// ChannelT. It also provides a representation of the type's name via the -/// getName method. -/// -/// Specializations of this class should provide the following functions: -/// -/// @code{.cpp} -/// -/// static const char* getName(); -/// static Error serialize(ChannelT&, const T&); -/// static Error deserialize(ChannelT&, T&); -/// -/// @endcode -/// -/// The third argument of SerializationTraits is intended to support SFINAE. -/// E.g.: -/// -/// @code{.cpp} -/// -/// class MyVirtualChannel { ... }; -/// -/// template -/// class SerializationTraits::value -/// >> { -/// public: -/// static const char* getName() { ... }; -/// } -/// -/// @endcode -template -class SerializationTraits; - -template -class SequenceTraits { -public: - static Error emitSeparator(ChannelT &C) { return Error::success(); } - static Error consumeSeparator(ChannelT &C) { return Error::success(); } -}; - -/// Utility class for serializing sequences of values of varying types. -/// Specializations of this class contain 'serialize' and 'deserialize' methods -/// for the given channel. The ArgTs... list will determine the "over-the-wire" -/// types to be serialized. The serialize and deserialize methods take a list -/// CArgTs... ("caller arg types") which must be the same length as ArgTs..., -/// but may be different types from ArgTs, provided that for each CArgT there -/// is a SerializationTraits specialization -/// SerializeTraits with methods that can serialize the -/// caller argument to over-the-wire value. -template -class SequenceSerialization; - -template -class SequenceSerialization { -public: - static Error serialize(ChannelT &C) { return Error::success(); } - static Error deserialize(ChannelT &C) { return Error::success(); } -}; - -template -class SequenceSerialization { -public: - - template - static Error serialize(ChannelT &C, CArgT &&CArg) { - return SerializationTraits>::serialize( - C, std::forward(CArg)); - } - - template - static Error deserialize(ChannelT &C, CArgT &CArg) { - return SerializationTraits::deserialize(C, CArg); - } -}; - -template -class SequenceSerialization { -public: - - template - static Error serialize(ChannelT &C, CArgT &&CArg, - CArgTs &&... CArgs) { - if (auto Err = - SerializationTraits>::serialize( - C, std::forward(CArg))) - return Err; - if (auto Err = SequenceTraits::emitSeparator(C)) - return Err; - return SequenceSerialization:: - serialize(C, std::forward(CArgs)...); - } - - template - static Error deserialize(ChannelT &C, CArgT &CArg, - CArgTs &... CArgs) { - if (auto Err = - SerializationTraits::deserialize(C, CArg)) - return Err; - if (auto Err = SequenceTraits::consumeSeparator(C)) - return Err; - return SequenceSerialization::deserialize(C, CArgs...); - } -}; - -template -Error serializeSeq(ChannelT &C, ArgTs &&... Args) { - return SequenceSerialization...>::serialize( - C, std::forward(Args)...); -} - -template -Error deserializeSeq(ChannelT &C, ArgTs &... Args) { - return SequenceSerialization::deserialize(C, Args...); -} - -template -class SerializationTraits { -public: - - using WrappedErrorSerializer = - std::function; - - using WrappedErrorDeserializer = - std::function; - - template - static void registerErrorType(std::string Name, SerializeFtor Serialize, - DeserializeFtor Deserialize) { - assert(!Name.empty() && - "The empty string is reserved for the Success value"); - - const std::string *KeyName = nullptr; - { - // We're abusing the stability of std::map here: We take a reference to the - // key of the deserializers map to save us from duplicating the string in - // the serializer. This should be changed to use a stringpool if we switch - // to a map type that may move keys in memory. - std::lock_guard Lock(DeserializersMutex); - auto I = - Deserializers.insert(Deserializers.begin(), - std::make_pair(std::move(Name), - std::move(Deserialize))); - KeyName = &I->first; - } - - { - assert(KeyName != nullptr && "No keyname pointer"); - std::lock_guard Lock(SerializersMutex); - Serializers[ErrorInfoT::classID()] = - [KeyName, Serialize = std::move(Serialize)]( - ChannelT &C, const ErrorInfoBase &EIB) -> Error { - assert(EIB.dynamicClassID() == ErrorInfoT::classID() && - "Serializer called for wrong error type"); - if (auto Err = serializeSeq(C, *KeyName)) - return Err; - return Serialize(C, static_cast(EIB)); - }; - } - } - - static Error serialize(ChannelT &C, Error &&Err) { - std::lock_guard Lock(SerializersMutex); - - if (!Err) - return serializeSeq(C, std::string()); - - return handleErrors(std::move(Err), - [&C](const ErrorInfoBase &EIB) { - auto SI = Serializers.find(EIB.dynamicClassID()); - if (SI == Serializers.end()) - return serializeAsStringError(C, EIB); - return (SI->second)(C, EIB); - }); - } - - static Error deserialize(ChannelT &C, Error &Err) { - std::lock_guard Lock(DeserializersMutex); - - std::string Key; - if (auto Err = deserializeSeq(C, Key)) - return Err; - - if (Key.empty()) { - ErrorAsOutParameter EAO(&Err); - Err = Error::success(); - return Error::success(); - } - - auto DI = Deserializers.find(Key); - assert(DI != Deserializers.end() && "No deserializer for error type"); - return (DI->second)(C, Err); - } - -private: - - static Error serializeAsStringError(ChannelT &C, const ErrorInfoBase &EIB) { - std::string ErrMsg; - { - raw_string_ostream ErrMsgStream(ErrMsg); - EIB.log(ErrMsgStream); - } - return serialize(C, make_error(std::move(ErrMsg), - inconvertibleErrorCode())); - } - - static std::recursive_mutex SerializersMutex; - static std::recursive_mutex DeserializersMutex; - static std::map Serializers; - static std::map Deserializers; -}; - -template -std::recursive_mutex SerializationTraits::SerializersMutex; - -template -std::recursive_mutex SerializationTraits::DeserializersMutex; - -template -std::map::WrappedErrorSerializer> -SerializationTraits::Serializers; - -template -std::map::WrappedErrorDeserializer> -SerializationTraits::Deserializers; - -/// Registers a serializer and deserializer for the given error type on the -/// given channel type. -template -void registerErrorSerialization(std::string Name, SerializeFtor &&Serialize, - DeserializeFtor &&Deserialize) { - SerializationTraits::template registerErrorType( - std::move(Name), - std::forward(Serialize), - std::forward(Deserialize)); -} - -/// Registers serialization/deserialization for StringError. -template -void registerStringError() { - static bool AlreadyRegistered = false; - if (!AlreadyRegistered) { - registerErrorSerialization( - "StringError", - [](ChannelT &C, const StringError &SE) { - return serializeSeq(C, SE.getMessage()); - }, - [](ChannelT &C, Error &Err) -> Error { - ErrorAsOutParameter EAO(&Err); - std::string Msg; - if (auto E2 = deserializeSeq(C, Msg)) - return E2; - Err = - make_error(std::move(Msg), - orcError( - OrcErrorCode::UnknownErrorCodeFromRemote)); - return Error::success(); - }); - AlreadyRegistered = true; - } -} - -/// SerializationTraits for Expected from an Expected. -template -class SerializationTraits, Expected> { -public: - - static Error serialize(ChannelT &C, Expected &&ValOrErr) { - if (ValOrErr) { - if (auto Err = serializeSeq(C, true)) - return Err; - return SerializationTraits::serialize(C, *ValOrErr); - } - if (auto Err = serializeSeq(C, false)) - return Err; - return serializeSeq(C, ValOrErr.takeError()); - } - - static Error deserialize(ChannelT &C, Expected &ValOrErr) { - ExpectedAsOutParameter EAO(&ValOrErr); - bool HasValue; - if (auto Err = deserializeSeq(C, HasValue)) - return Err; - if (HasValue) - return SerializationTraits::deserialize(C, *ValOrErr); - Error Err = Error::success(); - if (auto E2 = deserializeSeq(C, Err)) - return E2; - ValOrErr = std::move(Err); - return Error::success(); - } -}; - -/// SerializationTraits for Expected from a T2. -template -class SerializationTraits, T2> { -public: - - static Error serialize(ChannelT &C, T2 &&Val) { - return serializeSeq(C, Expected(std::forward(Val))); - } -}; - -/// SerializationTraits for Expected from an Error. -template -class SerializationTraits, Error> { -public: - - static Error serialize(ChannelT &C, Error &&Err) { - return serializeSeq(C, Expected(std::move(Err))); - } -}; - -/// SerializationTraits default specialization for std::pair. -template -class SerializationTraits, std::pair> { -public: - static Error serialize(ChannelT &C, const std::pair &V) { - if (auto Err = SerializationTraits::serialize(C, V.first)) - return Err; - return SerializationTraits::serialize(C, V.second); - } - - static Error deserialize(ChannelT &C, std::pair &V) { - if (auto Err = - SerializationTraits::deserialize(C, V.first)) - return Err; - return SerializationTraits::deserialize(C, V.second); - } -}; - -/// SerializationTraits default specialization for std::tuple. -template -class SerializationTraits> { -public: - - /// RPC channel serialization for std::tuple. - static Error serialize(ChannelT &C, const std::tuple &V) { - return serializeTupleHelper(C, V, std::index_sequence_for()); - } - - /// RPC channel deserialization for std::tuple. - static Error deserialize(ChannelT &C, std::tuple &V) { - return deserializeTupleHelper(C, V, std::index_sequence_for()); - } - -private: - // Serialization helper for std::tuple. - template - static Error serializeTupleHelper(ChannelT &C, const std::tuple &V, - std::index_sequence _) { - return serializeSeq(C, std::get(V)...); - } - - // Serialization helper for std::tuple. - template - static Error deserializeTupleHelper(ChannelT &C, std::tuple &V, - std::index_sequence _) { - return deserializeSeq(C, std::get(V)...); - } -}; - -/// SerializationTraits default specialization for std::vector. -template -class SerializationTraits> { -public: - - /// Serialize a std::vector from std::vector. - static Error serialize(ChannelT &C, const std::vector &V) { - if (auto Err = serializeSeq(C, static_cast(V.size()))) - return Err; - - for (const auto &E : V) - if (auto Err = serializeSeq(C, E)) - return Err; - - return Error::success(); - } - - /// Deserialize a std::vector to a std::vector. - static Error deserialize(ChannelT &C, std::vector &V) { - assert(V.empty() && - "Expected default-constructed vector to deserialize into"); - - uint64_t Count = 0; - if (auto Err = deserializeSeq(C, Count)) - return Err; - - V.resize(Count); - for (auto &E : V) - if (auto Err = deserializeSeq(C, E)) - return Err; - - return Error::success(); - } -}; - -template -class SerializationTraits, std::set> { -public: - /// Serialize a std::set from std::set. - static Error serialize(ChannelT &C, const std::set &S) { - if (auto Err = serializeSeq(C, static_cast(S.size()))) - return Err; - - for (const auto &E : S) - if (auto Err = SerializationTraits::serialize(C, E)) - return Err; - - return Error::success(); - } - - /// Deserialize a std::set to a std::set. - static Error deserialize(ChannelT &C, std::set &S) { - assert(S.empty() && "Expected default-constructed set to deserialize into"); - - uint64_t Count = 0; - if (auto Err = deserializeSeq(C, Count)) - return Err; - - while (Count-- != 0) { - T2 Val; - if (auto Err = SerializationTraits::deserialize(C, Val)) - return Err; - - auto Added = S.insert(Val).second; - if (!Added) - return make_error("Duplicate element in deserialized set", - orcError(OrcErrorCode::UnknownORCError)); - } - - return Error::success(); - } -}; - -template -class SerializationTraits, std::map> { -public: - /// Serialize a std::map from std::map. - static Error serialize(ChannelT &C, const std::map &M) { - if (auto Err = serializeSeq(C, static_cast(M.size()))) - return Err; - - for (const auto &E : M) { - if (auto Err = - SerializationTraits::serialize(C, E.first)) - return Err; - if (auto Err = - SerializationTraits::serialize(C, E.second)) - return Err; - } - - return Error::success(); - } - - /// Deserialize a std::map to a std::map. - static Error deserialize(ChannelT &C, std::map &M) { - assert(M.empty() && "Expected default-constructed map to deserialize into"); - - uint64_t Count = 0; - if (auto Err = deserializeSeq(C, Count)) - return Err; - - while (Count-- != 0) { - std::pair Val; - if (auto Err = - SerializationTraits::deserialize(C, Val.first)) - return Err; - - if (auto Err = - SerializationTraits::deserialize(C, Val.second)) - return Err; - - auto Added = M.insert(Val).second; - if (!Added) - return make_error("Duplicate element in deserialized map", - orcError(OrcErrorCode::UnknownORCError)); - } - - return Error::success(); - } -}; - -} // end namespace rpc -} // end namespace orc -} // end namespace llvm - -#endif // LLVM_EXECUTIONENGINE_ORC_RPCSERIALIZATION_H diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPC/RPCUtils.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPC/RPCUtils.h deleted file mode 100644 index f348844f39ce..000000000000 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPC/RPCUtils.h +++ /dev/null @@ -1,1687 +0,0 @@ -//===- RPCUtils.h - Utilities for building RPC APIs -------------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// Utilities to support construction of simple RPC APIs. -// -// The RPC utilities aim for ease of use (minimal conceptual overhead) for C++ -// programmers, high performance, low memory overhead, and efficient use of the -// communications channel. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_ORC_RPCUTILS_H -#define LLVM_EXECUTIONENGINE_ORC_RPCUTILS_H - -#include -#include -#include - -#include "llvm/ADT/STLExtras.h" -#include "llvm/ExecutionEngine/Orc/OrcError.h" -#include "llvm/ExecutionEngine/Orc/RPC/RPCSerialization.h" -#include "llvm/Support/MSVCErrorWorkarounds.h" - -#include - -namespace llvm { -namespace orc { -namespace rpc { - -/// Base class of all fatal RPC errors (those that necessarily result in the -/// termination of the RPC session). -class RPCFatalError : public ErrorInfo { -public: - static char ID; -}; - -/// RPCConnectionClosed is returned from RPC operations if the RPC connection -/// has already been closed due to either an error or graceful disconnection. -class ConnectionClosed : public ErrorInfo { -public: - static char ID; - std::error_code convertToErrorCode() const override; - void log(raw_ostream &OS) const override; -}; - -/// BadFunctionCall is returned from handleOne when the remote makes a call with -/// an unrecognized function id. -/// -/// This error is fatal because Orc RPC needs to know how to parse a function -/// call to know where the next call starts, and if it doesn't recognize the -/// function id it cannot parse the call. -template -class BadFunctionCall - : public ErrorInfo, RPCFatalError> { -public: - static char ID; - - BadFunctionCall(FnIdT FnId, SeqNoT SeqNo) - : FnId(std::move(FnId)), SeqNo(std::move(SeqNo)) {} - - std::error_code convertToErrorCode() const override { - return orcError(OrcErrorCode::UnexpectedRPCCall); - } - - void log(raw_ostream &OS) const override { - OS << "Call to invalid RPC function id '" << FnId << "' with " - "sequence number " << SeqNo; - } - -private: - FnIdT FnId; - SeqNoT SeqNo; -}; - -template -char BadFunctionCall::ID = 0; - -/// InvalidSequenceNumberForResponse is returned from handleOne when a response -/// call arrives with a sequence number that doesn't correspond to any in-flight -/// function call. -/// -/// This error is fatal because Orc RPC needs to know how to parse the rest of -/// the response call to know where the next call starts, and if it doesn't have -/// a result parser for this sequence number it can't do that. -template -class InvalidSequenceNumberForResponse - : public ErrorInfo, RPCFatalError> { -public: - static char ID; - - InvalidSequenceNumberForResponse(SeqNoT SeqNo) - : SeqNo(std::move(SeqNo)) {} - - std::error_code convertToErrorCode() const override { - return orcError(OrcErrorCode::UnexpectedRPCCall); - }; - - void log(raw_ostream &OS) const override { - OS << "Response has unknown sequence number " << SeqNo; - } -private: - SeqNoT SeqNo; -}; - -template -char InvalidSequenceNumberForResponse::ID = 0; - -/// This non-fatal error will be passed to asynchronous result handlers in place -/// of a result if the connection goes down before a result returns, or if the -/// function to be called cannot be negotiated with the remote. -class ResponseAbandoned : public ErrorInfo { -public: - static char ID; - - std::error_code convertToErrorCode() const override; - void log(raw_ostream &OS) const override; -}; - -/// This error is returned if the remote does not have a handler installed for -/// the given RPC function. -class CouldNotNegotiate : public ErrorInfo { -public: - static char ID; - - CouldNotNegotiate(std::string Signature); - std::error_code convertToErrorCode() const override; - void log(raw_ostream &OS) const override; - const std::string &getSignature() const { return Signature; } -private: - std::string Signature; -}; - -template class Function; - -// RPC Function class. -// DerivedFunc should be a user defined class with a static 'getName()' method -// returning a const char* representing the function's name. -template -class Function { -public: - /// User defined function type. - using Type = RetT(ArgTs...); - - /// Return type. - using ReturnType = RetT; - - /// Returns the full function prototype as a string. - static const char *getPrototype() { - static std::string Name = [] { - std::string Name; - raw_string_ostream(Name) - << RPCTypeName::getName() << " " << DerivedFunc::getName() - << "(" << llvm::orc::rpc::RPCTypeNameSequence() << ")"; - return Name; - }(); - return Name.data(); - } -}; - -/// Allocates RPC function ids during autonegotiation. -/// Specializations of this class must provide four members: -/// -/// static T getInvalidId(): -/// Should return a reserved id that will be used to represent missing -/// functions during autonegotiation. -/// -/// static T getResponseId(): -/// Should return a reserved id that will be used to send function responses -/// (return values). -/// -/// static T getNegotiateId(): -/// Should return a reserved id for the negotiate function, which will be used -/// to negotiate ids for user defined functions. -/// -/// template T allocate(): -/// Allocate a unique id for function Func. -template class RPCFunctionIdAllocator; - -/// This specialization of RPCFunctionIdAllocator provides a default -/// implementation for integral types. -template -class RPCFunctionIdAllocator::value>> { -public: - static T getInvalidId() { return T(0); } - static T getResponseId() { return T(1); } - static T getNegotiateId() { return T(2); } - - template T allocate() { return NextId++; } - -private: - T NextId = 3; -}; - -namespace detail { - -/// Provides a typedef for a tuple containing the decayed argument types. -template class FunctionArgsTuple; - -template -class FunctionArgsTuple { -public: - using Type = std::tuple>...>; -}; - -// ResultTraits provides typedefs and utilities specific to the return type -// of functions. -template class ResultTraits { -public: - // The return type wrapped in llvm::Expected. - using ErrorReturnType = Expected; - -#ifdef _MSC_VER - // The ErrorReturnType wrapped in a std::promise. - using ReturnPromiseType = std::promise>; - - // The ErrorReturnType wrapped in a std::future. - using ReturnFutureType = std::future>; -#else - // The ErrorReturnType wrapped in a std::promise. - using ReturnPromiseType = std::promise; - - // The ErrorReturnType wrapped in a std::future. - using ReturnFutureType = std::future; -#endif - - // Create a 'blank' value of the ErrorReturnType, ready and safe to - // overwrite. - static ErrorReturnType createBlankErrorReturnValue() { - return ErrorReturnType(RetT()); - } - - // Consume an abandoned ErrorReturnType. - static void consumeAbandoned(ErrorReturnType RetOrErr) { - consumeError(RetOrErr.takeError()); - } -}; - -// ResultTraits specialization for void functions. -template <> class ResultTraits { -public: - // For void functions, ErrorReturnType is llvm::Error. - using ErrorReturnType = Error; - -#ifdef _MSC_VER - // The ErrorReturnType wrapped in a std::promise. - using ReturnPromiseType = std::promise; - - // The ErrorReturnType wrapped in a std::future. - using ReturnFutureType = std::future; -#else - // The ErrorReturnType wrapped in a std::promise. - using ReturnPromiseType = std::promise; - - // The ErrorReturnType wrapped in a std::future. - using ReturnFutureType = std::future; -#endif - - // Create a 'blank' value of the ErrorReturnType, ready and safe to - // overwrite. - static ErrorReturnType createBlankErrorReturnValue() { - return ErrorReturnType::success(); - } - - // Consume an abandoned ErrorReturnType. - static void consumeAbandoned(ErrorReturnType Err) { - consumeError(std::move(Err)); - } -}; - -// ResultTraits is equivalent to ResultTraits. This allows -// handlers for void RPC functions to return either void (in which case they -// implicitly succeed) or Error (in which case their error return is -// propagated). See usage in HandlerTraits::runHandlerHelper. -template <> class ResultTraits : public ResultTraits {}; - -// ResultTraits> is equivalent to ResultTraits. This allows -// handlers for RPC functions returning a T to return either a T (in which -// case they implicitly succeed) or Expected (in which case their error -// return is propagated). See usage in HandlerTraits::runHandlerHelper. -template -class ResultTraits> : public ResultTraits {}; - -// Determines whether an RPC function's defined error return type supports -// error return value. -template -class SupportsErrorReturn { -public: - static const bool value = false; -}; - -template <> -class SupportsErrorReturn { -public: - static const bool value = true; -}; - -template -class SupportsErrorReturn> { -public: - static const bool value = true; -}; - -// RespondHelper packages return values based on whether or not the declared -// RPC function return type supports error returns. -template -class RespondHelper; - -// RespondHelper specialization for functions that support error returns. -template <> -class RespondHelper { -public: - - // Send Expected. - template - static Error sendResult(ChannelT &C, const FunctionIdT &ResponseId, - SequenceNumberT SeqNo, - Expected ResultOrErr) { - if (!ResultOrErr && ResultOrErr.template errorIsA()) - return ResultOrErr.takeError(); - - // Open the response message. - if (auto Err = C.startSendMessage(ResponseId, SeqNo)) - return Err; - - // Serialize the result. - if (auto Err = - SerializationTraits>::serialize( - C, std::move(ResultOrErr))) - return Err; - - // Close the response message. - if (auto Err = C.endSendMessage()) - return Err; - return C.send(); - } - - template - static Error sendResult(ChannelT &C, const FunctionIdT &ResponseId, - SequenceNumberT SeqNo, Error Err) { - if (Err && Err.isA()) - return Err; - if (auto Err2 = C.startSendMessage(ResponseId, SeqNo)) - return Err2; - if (auto Err2 = serializeSeq(C, std::move(Err))) - return Err2; - if (auto Err2 = C.endSendMessage()) - return Err2; - return C.send(); - } - -}; - -// RespondHelper specialization for functions that do not support error returns. -template <> -class RespondHelper { -public: - - template - static Error sendResult(ChannelT &C, const FunctionIdT &ResponseId, - SequenceNumberT SeqNo, - Expected ResultOrErr) { - if (auto Err = ResultOrErr.takeError()) - return Err; - - // Open the response message. - if (auto Err = C.startSendMessage(ResponseId, SeqNo)) - return Err; - - // Serialize the result. - if (auto Err = - SerializationTraits::serialize( - C, *ResultOrErr)) - return Err; - - // End the response message. - if (auto Err = C.endSendMessage()) - return Err; - - return C.send(); - } - - template - static Error sendResult(ChannelT &C, const FunctionIdT &ResponseId, - SequenceNumberT SeqNo, Error Err) { - if (Err) - return Err; - if (auto Err2 = C.startSendMessage(ResponseId, SeqNo)) - return Err2; - if (auto Err2 = C.endSendMessage()) - return Err2; - return C.send(); - } - -}; - - -// Send a response of the given wire return type (WireRetT) over the -// channel, with the given sequence number. -template -Error respond(ChannelT &C, const FunctionIdT &ResponseId, - SequenceNumberT SeqNo, Expected ResultOrErr) { - return RespondHelper::value>:: - template sendResult(C, ResponseId, SeqNo, std::move(ResultOrErr)); -} - -// Send an empty response message on the given channel to indicate that -// the handler ran. -template -Error respond(ChannelT &C, const FunctionIdT &ResponseId, SequenceNumberT SeqNo, - Error Err) { - return RespondHelper::value>:: - sendResult(C, ResponseId, SeqNo, std::move(Err)); -} - -// Converts a given type to the equivalent error return type. -template class WrappedHandlerReturn { -public: - using Type = Expected; -}; - -template class WrappedHandlerReturn> { -public: - using Type = Expected; -}; - -template <> class WrappedHandlerReturn { -public: - using Type = Error; -}; - -template <> class WrappedHandlerReturn { -public: - using Type = Error; -}; - -template <> class WrappedHandlerReturn { -public: - using Type = Error; -}; - -// Traits class that strips the response function from the list of handler -// arguments. -template class AsyncHandlerTraits; - -template -class AsyncHandlerTraits)>, ArgTs...)> { -public: - using Type = Error(ArgTs...); - using ResultType = Expected; -}; - -template -class AsyncHandlerTraits, ArgTs...)> { -public: - using Type = Error(ArgTs...); - using ResultType = Error; -}; - -template -class AsyncHandlerTraits, ArgTs...)> { -public: - using Type = Error(ArgTs...); - using ResultType = Error; -}; - -template -class AsyncHandlerTraits, ArgTs...)> { -public: - using Type = Error(ArgTs...); - using ResultType = Error; -}; - -template -class AsyncHandlerTraits - : public AsyncHandlerTraits, - ArgTs...)> {}; - -// This template class provides utilities related to RPC function handlers. -// The base case applies to non-function types (the template class is -// specialized for function types) and inherits from the appropriate -// speciilization for the given non-function type's call operator. -template -class HandlerTraits : public HandlerTraits::type::operator())> { -}; - -// Traits for handlers with a given function type. -template -class HandlerTraits { -public: - // Function type of the handler. - using Type = RetT(ArgTs...); - - // Return type of the handler. - using ReturnType = RetT; - - // Call the given handler with the given arguments. - template - static typename WrappedHandlerReturn::Type - unpackAndRun(HandlerT &Handler, std::tuple &Args) { - return unpackAndRunHelper(Handler, Args, - std::index_sequence_for()); - } - - // Call the given handler with the given arguments. - template - static Error unpackAndRunAsync(HandlerT &Handler, ResponderT &Responder, - std::tuple &Args) { - return unpackAndRunAsyncHelper(Handler, Responder, Args, - std::index_sequence_for()); - } - - // Call the given handler with the given arguments. - template - static std::enable_if_t< - std::is_void::ReturnType>::value, Error> - run(HandlerT &Handler, ArgTs &&... Args) { - Handler(std::move(Args)...); - return Error::success(); - } - - template - static std::enable_if_t< - !std::is_void::ReturnType>::value, - typename HandlerTraits::ReturnType> - run(HandlerT &Handler, TArgTs... Args) { - return Handler(std::move(Args)...); - } - - // Serialize arguments to the channel. - template - static Error serializeArgs(ChannelT &C, const CArgTs... CArgs) { - return SequenceSerialization::serialize(C, CArgs...); - } - - // Deserialize arguments from the channel. - template - static Error deserializeArgs(ChannelT &C, std::tuple &Args) { - return deserializeArgsHelper(C, Args, std::index_sequence_for()); - } - -private: - template - static Error deserializeArgsHelper(ChannelT &C, std::tuple &Args, - std::index_sequence _) { - return SequenceSerialization::deserialize( - C, std::get(Args)...); - } - - template - static typename WrappedHandlerReturn< - typename HandlerTraits::ReturnType>::Type - unpackAndRunHelper(HandlerT &Handler, ArgTuple &Args, - std::index_sequence) { - return run(Handler, std::move(std::get(Args))...); - } - - template - static typename WrappedHandlerReturn< - typename HandlerTraits::ReturnType>::Type - unpackAndRunAsyncHelper(HandlerT &Handler, ResponderT &Responder, - ArgTuple &Args, std::index_sequence) { - return run(Handler, Responder, std::move(std::get(Args))...); - } -}; - -// Handler traits for free functions. -template -class HandlerTraits - : public HandlerTraits {}; - -// Handler traits for class methods (especially call operators for lambdas). -template -class HandlerTraits - : public HandlerTraits {}; - -// Handler traits for const class methods (especially call operators for -// lambdas). -template -class HandlerTraits - : public HandlerTraits {}; - -// Utility to peel the Expected wrapper off a response handler error type. -template class ResponseHandlerArg; - -template class ResponseHandlerArg)> { -public: - using ArgType = Expected; - using UnwrappedArgType = ArgT; -}; - -template -class ResponseHandlerArg)> { -public: - using ArgType = Expected; - using UnwrappedArgType = ArgT; -}; - -template <> class ResponseHandlerArg { -public: - using ArgType = Error; -}; - -template <> class ResponseHandlerArg { -public: - using ArgType = Error; -}; - -// ResponseHandler represents a handler for a not-yet-received function call -// result. -template class ResponseHandler { -public: - virtual ~ResponseHandler() {} - - // Reads the function result off the wire and acts on it. The meaning of - // "act" will depend on how this method is implemented in any given - // ResponseHandler subclass but could, for example, mean running a - // user-specified handler or setting a promise value. - virtual Error handleResponse(ChannelT &C) = 0; - - // Abandons this outstanding result. - virtual void abandon() = 0; - - // Create an error instance representing an abandoned response. - static Error createAbandonedResponseError() { - return make_error(); - } -}; - -// ResponseHandler subclass for RPC functions with non-void returns. -template -class ResponseHandlerImpl : public ResponseHandler { -public: - ResponseHandlerImpl(HandlerT Handler) : Handler(std::move(Handler)) {} - - // Handle the result by deserializing it from the channel then passing it - // to the user defined handler. - Error handleResponse(ChannelT &C) override { - using UnwrappedArgType = typename ResponseHandlerArg< - typename HandlerTraits::Type>::UnwrappedArgType; - UnwrappedArgType Result; - if (auto Err = - SerializationTraits::deserialize(C, Result)) - return Err; - if (auto Err = C.endReceiveMessage()) - return Err; - return Handler(std::move(Result)); - } - - // Abandon this response by calling the handler with an 'abandoned response' - // error. - void abandon() override { - if (auto Err = Handler(this->createAbandonedResponseError())) { - // Handlers should not fail when passed an abandoned response error. - report_fatal_error(std::move(Err)); - } - } - -private: - HandlerT Handler; -}; - -// ResponseHandler subclass for RPC functions with void returns. -template -class ResponseHandlerImpl - : public ResponseHandler { -public: - ResponseHandlerImpl(HandlerT Handler) : Handler(std::move(Handler)) {} - - // Handle the result (no actual value, just a notification that the function - // has completed on the remote end) by calling the user-defined handler with - // Error::success(). - Error handleResponse(ChannelT &C) override { - if (auto Err = C.endReceiveMessage()) - return Err; - return Handler(Error::success()); - } - - // Abandon this response by calling the handler with an 'abandoned response' - // error. - void abandon() override { - if (auto Err = Handler(this->createAbandonedResponseError())) { - // Handlers should not fail when passed an abandoned response error. - report_fatal_error(std::move(Err)); - } - } - -private: - HandlerT Handler; -}; - -template -class ResponseHandlerImpl, HandlerT> - : public ResponseHandler { -public: - ResponseHandlerImpl(HandlerT Handler) : Handler(std::move(Handler)) {} - - // Handle the result by deserializing it from the channel then passing it - // to the user defined handler. - Error handleResponse(ChannelT &C) override { - using HandlerArgType = typename ResponseHandlerArg< - typename HandlerTraits::Type>::ArgType; - HandlerArgType Result((typename HandlerArgType::value_type())); - - if (auto Err = - SerializationTraits, - HandlerArgType>::deserialize(C, Result)) - return Err; - if (auto Err = C.endReceiveMessage()) - return Err; - return Handler(std::move(Result)); - } - - // Abandon this response by calling the handler with an 'abandoned response' - // error. - void abandon() override { - if (auto Err = Handler(this->createAbandonedResponseError())) { - // Handlers should not fail when passed an abandoned response error. - report_fatal_error(std::move(Err)); - } - } - -private: - HandlerT Handler; -}; - -template -class ResponseHandlerImpl - : public ResponseHandler { -public: - ResponseHandlerImpl(HandlerT Handler) : Handler(std::move(Handler)) {} - - // Handle the result by deserializing it from the channel then passing it - // to the user defined handler. - Error handleResponse(ChannelT &C) override { - Error Result = Error::success(); - if (auto Err = SerializationTraits::deserialize( - C, Result)) { - consumeError(std::move(Result)); - return Err; - } - if (auto Err = C.endReceiveMessage()) { - consumeError(std::move(Result)); - return Err; - } - return Handler(std::move(Result)); - } - - // Abandon this response by calling the handler with an 'abandoned response' - // error. - void abandon() override { - if (auto Err = Handler(this->createAbandonedResponseError())) { - // Handlers should not fail when passed an abandoned response error. - report_fatal_error(std::move(Err)); - } - } - -private: - HandlerT Handler; -}; - -// Create a ResponseHandler from a given user handler. -template -std::unique_ptr> createResponseHandler(HandlerT H) { - return std::make_unique>( - std::move(H)); -} - -// Helper for wrapping member functions up as functors. This is useful for -// installing methods as result handlers. -template -class MemberFnWrapper { -public: - using MethodT = RetT (ClassT::*)(ArgTs...); - MemberFnWrapper(ClassT &Instance, MethodT Method) - : Instance(Instance), Method(Method) {} - RetT operator()(ArgTs &&... Args) { - return (Instance.*Method)(std::move(Args)...); - } - -private: - ClassT &Instance; - MethodT Method; -}; - -// Helper that provides a Functor for deserializing arguments. -template class ReadArgs { -public: - Error operator()() { return Error::success(); } -}; - -template -class ReadArgs : public ReadArgs { -public: - ReadArgs(ArgT &Arg, ArgTs &... Args) - : ReadArgs(Args...), Arg(Arg) {} - - Error operator()(ArgT &ArgVal, ArgTs &... ArgVals) { - this->Arg = std::move(ArgVal); - return ReadArgs::operator()(ArgVals...); - } - -private: - ArgT &Arg; -}; - -// Manage sequence numbers. -template class SequenceNumberManager { -public: - // Reset, making all sequence numbers available. - void reset() { - std::lock_guard Lock(SeqNoLock); - NextSequenceNumber = 0; - FreeSequenceNumbers.clear(); - } - - // Get the next available sequence number. Will re-use numbers that have - // been released. - SequenceNumberT getSequenceNumber() { - std::lock_guard Lock(SeqNoLock); - if (FreeSequenceNumbers.empty()) - return NextSequenceNumber++; - auto SequenceNumber = FreeSequenceNumbers.back(); - FreeSequenceNumbers.pop_back(); - return SequenceNumber; - } - - // Release a sequence number, making it available for re-use. - void releaseSequenceNumber(SequenceNumberT SequenceNumber) { - std::lock_guard Lock(SeqNoLock); - FreeSequenceNumbers.push_back(SequenceNumber); - } - -private: - std::mutex SeqNoLock; - SequenceNumberT NextSequenceNumber = 0; - std::vector FreeSequenceNumbers; -}; - -// Checks that predicate P holds for each corresponding pair of type arguments -// from T1 and T2 tuple. -template