aboutsummaryrefslogtreecommitdiff
path: root/include/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm')
-rw-r--r--include/llvm/ADT/APFloat.h27
-rw-r--r--include/llvm/ADT/APInt.h46
-rw-r--r--include/llvm/ADT/ArrayRef.h46
-rw-r--r--include/llvm/ADT/BitVector.h18
-rw-r--r--include/llvm/ADT/BitmaskEnum.h153
-rw-r--r--include/llvm/ADT/DenseMap.h76
-rw-r--r--include/llvm/ADT/DenseMapInfo.h30
-rw-r--r--include/llvm/ADT/DenseSet.h15
-rw-r--r--include/llvm/ADT/FoldingSet.h20
-rw-r--r--include/llvm/ADT/Hashing.h4
-rw-r--r--include/llvm/ADT/PointerEmbeddedInt.h30
-rw-r--r--include/llvm/ADT/PostOrderIterator.h2
-rw-r--r--include/llvm/ADT/PriorityWorklist.h224
-rw-r--r--include/llvm/ADT/STLExtras.h53
-rw-r--r--include/llvm/ADT/Sequence.h79
-rw-r--r--include/llvm/ADT/SetVector.h49
-rw-r--r--include/llvm/ADT/SmallBitVector.h65
-rw-r--r--include/llvm/ADT/SmallPtrSet.h96
-rw-r--r--include/llvm/ADT/SmallSet.h5
-rw-r--r--include/llvm/ADT/SmallVector.h67
-rw-r--r--include/llvm/ADT/SparseSet.h5
-rw-r--r--include/llvm/ADT/Statistic.h81
-rw-r--r--include/llvm/ADT/StringExtras.h57
-rw-r--r--include/llvm/ADT/StringMap.h92
-rw-r--r--include/llvm/ADT/StringRef.h32
-rw-r--r--include/llvm/ADT/StringSet.h6
-rw-r--r--include/llvm/ADT/TinyPtrVector.h34
-rw-r--r--include/llvm/ADT/Triple.h145
-rw-r--r--include/llvm/ADT/ilist.h88
-rw-r--r--include/llvm/ADT/iterator.h20
-rw-r--r--include/llvm/Analysis/AliasAnalysis.h262
-rw-r--r--include/llvm/Analysis/AliasAnalysisEvaluator.h70
-rw-r--r--include/llvm/Analysis/AliasSetTracker.h134
-rw-r--r--include/llvm/Analysis/AssumptionCache.h25
-rw-r--r--include/llvm/Analysis/BasicAliasAnalysis.h52
-rw-r--r--include/llvm/Analysis/BlockFrequencyInfo.h40
-rw-r--r--include/llvm/Analysis/BlockFrequencyInfoImpl.h123
-rw-r--r--include/llvm/Analysis/BranchProbabilityInfo.h94
-rw-r--r--include/llvm/Analysis/CFLAndersAliasAnalysis.h138
-rw-r--r--include/llvm/Analysis/CFLSteensAliasAnalysis.h (renamed from include/llvm/Analysis/CFLAliasAnalysis.h)103
-rw-r--r--include/llvm/Analysis/CGSCCPassManager.h409
-rw-r--r--include/llvm/Analysis/CallGraph.h20
-rw-r--r--include/llvm/Analysis/CallGraphSCCPass.h28
-rw-r--r--include/llvm/Analysis/CallPrinter.h6
-rw-r--r--include/llvm/Analysis/CodeMetrics.h28
-rw-r--r--include/llvm/Analysis/ConstantFolding.h77
-rw-r--r--include/llvm/Analysis/DemandedBits.h76
-rw-r--r--include/llvm/Analysis/DependenceAnalysis.h48
-rw-r--r--include/llvm/Analysis/DominanceFrontier.h80
-rw-r--r--include/llvm/Analysis/EHPersonalities.h5
-rw-r--r--include/llvm/Analysis/GlobalsModRef.h18
-rw-r--r--include/llvm/Analysis/IVUsers.h56
-rw-r--r--include/llvm/Analysis/IndirectCallPromotionAnalysis.h67
-rw-r--r--include/llvm/Analysis/IndirectCallSiteVisitor.h43
-rw-r--r--include/llvm/Analysis/InlineCost.h21
-rw-r--r--include/llvm/Analysis/InstructionSimplify.h111
-rw-r--r--include/llvm/Analysis/Interval.h10
-rw-r--r--include/llvm/Analysis/IteratedDominanceFrontier.h13
-rw-r--r--include/llvm/Analysis/LazyBlockFrequencyInfo.h125
-rw-r--r--include/llvm/Analysis/LazyCallGraph.h787
-rw-r--r--include/llvm/Analysis/LazyValueInfo.h71
-rw-r--r--include/llvm/Analysis/Loads.h77
-rw-r--r--include/llvm/Analysis/LoopAccessAnalysis.h177
-rw-r--r--include/llvm/Analysis/LoopInfo.h57
-rw-r--r--include/llvm/Analysis/LoopInfoImpl.h2
-rw-r--r--include/llvm/Analysis/LoopPass.h7
-rw-r--r--include/llvm/Analysis/LoopPassManager.h142
-rw-r--r--include/llvm/Analysis/LoopUnrollAnalyzer.h95
-rw-r--r--include/llvm/Analysis/MemoryBuiltins.h22
-rw-r--r--include/llvm/Analysis/MemoryDependenceAnalysis.h863
-rw-r--r--include/llvm/Analysis/MemoryLocation.h2
-rw-r--r--include/llvm/Analysis/ModuleSummaryAnalysis.h91
-rw-r--r--include/llvm/Analysis/ObjCARCAliasAnalysis.h20
-rw-r--r--include/llvm/Analysis/ObjCARCAnalysisUtils.h1
-rw-r--r--include/llvm/Analysis/ObjCARCInstKind.h1
-rw-r--r--include/llvm/Analysis/OptimizationDiagnosticInfo.h104
-rw-r--r--include/llvm/Analysis/Passes.h13
-rw-r--r--include/llvm/Analysis/PostDominators.h89
-rw-r--r--include/llvm/Analysis/ProfileSummaryInfo.h113
-rw-r--r--include/llvm/Analysis/RegionInfo.h63
-rw-r--r--include/llvm/Analysis/RegionInfoImpl.h7
-rw-r--r--include/llvm/Analysis/ScalarEvolution.h623
-rw-r--r--include/llvm/Analysis/ScalarEvolutionAliasAnalysis.h19
-rw-r--r--include/llvm/Analysis/ScalarEvolutionExpander.h64
-rw-r--r--include/llvm/Analysis/ScalarEvolutionExpressions.h178
-rw-r--r--include/llvm/Analysis/ScopedNoAliasAA.h19
-rw-r--r--include/llvm/Analysis/SparsePropagation.h1
-rw-r--r--include/llvm/Analysis/TargetLibraryInfo.def5
-rw-r--r--include/llvm/Analysis/TargetLibraryInfo.h97
-rw-r--r--include/llvm/Analysis/TargetTransformInfo.h154
-rw-r--r--include/llvm/Analysis/TargetTransformInfoImpl.h43
-rw-r--r--include/llvm/Analysis/TypeBasedAliasAnalysis.h19
-rw-r--r--include/llvm/Analysis/TypeMetadataUtils.h45
-rw-r--r--include/llvm/Analysis/ValueTracking.h226
-rw-r--r--include/llvm/Analysis/VectorUtils.h40
-rw-r--r--include/llvm/AsmParser/Parser.h19
-rw-r--r--include/llvm/Bitcode/BitCodes.h8
-rw-r--r--include/llvm/Bitcode/BitcodeWriterPass.h24
-rw-r--r--include/llvm/Bitcode/BitstreamReader.h349
-rw-r--r--include/llvm/Bitcode/BitstreamWriter.h51
-rw-r--r--include/llvm/Bitcode/LLVMBitCodes.h891
-rw-r--r--include/llvm/Bitcode/ReaderWriter.h81
-rw-r--r--include/llvm/CodeGen/Analysis.h2
-rw-r--r--include/llvm/CodeGen/AsmPrinter.h11
-rw-r--r--include/llvm/CodeGen/BasicTTIImpl.h215
-rw-r--r--include/llvm/CodeGen/CallingConvLower.h20
-rw-r--r--include/llvm/CodeGen/CommandFlags.h64
-rw-r--r--include/llvm/CodeGen/DFAPacketizer.h94
-rw-r--r--include/llvm/CodeGen/DIE.h69
-rw-r--r--include/llvm/CodeGen/DIEValue.def1
-rw-r--r--include/llvm/CodeGen/FastISel.h10
-rw-r--r--include/llvm/CodeGen/FaultMaps.h1
-rw-r--r--include/llvm/CodeGen/FunctionLoweringInfo.h72
-rw-r--r--include/llvm/CodeGen/GCMetadata.h5
-rw-r--r--include/llvm/CodeGen/GlobalISel/CallLowering.h72
-rw-r--r--include/llvm/CodeGen/GlobalISel/GISelAccessor.h33
-rw-r--r--include/llvm/CodeGen/GlobalISel/IRTranslator.h158
-rw-r--r--include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h146
-rw-r--r--include/llvm/CodeGen/GlobalISel/RegBankSelect.h614
-rw-r--r--include/llvm/CodeGen/GlobalISel/RegisterBank.h101
-rw-r--r--include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h602
-rw-r--r--include/llvm/CodeGen/GlobalISel/Types.h32
-rw-r--r--include/llvm/CodeGen/ISDOpcodes.h55
-rw-r--r--include/llvm/CodeGen/LiveInterval.h18
-rw-r--r--include/llvm/CodeGen/LiveIntervalAnalysis.h28
-rw-r--r--include/llvm/CodeGen/LivePhysRegs.h36
-rw-r--r--include/llvm/CodeGen/LiveRangeEdit.h45
-rw-r--r--include/llvm/CodeGen/LiveVariables.h49
-rw-r--r--include/llvm/CodeGen/MIRParser/MIRParser.h2
-rw-r--r--include/llvm/CodeGen/MIRYamlMapping.h6
-rw-r--r--include/llvm/CodeGen/MachineBasicBlock.h95
-rw-r--r--include/llvm/CodeGen/MachineBlockFrequencyInfo.h4
-rw-r--r--include/llvm/CodeGen/MachineCombinerPattern.h35
-rw-r--r--include/llvm/CodeGen/MachineDominators.h23
-rw-r--r--include/llvm/CodeGen/MachineFrameInfo.h130
-rw-r--r--include/llvm/CodeGen/MachineFunction.h102
-rw-r--r--include/llvm/CodeGen/MachineFunctionPass.h26
-rw-r--r--include/llvm/CodeGen/MachineInstr.h61
-rw-r--r--include/llvm/CodeGen/MachineInstrBuilder.h158
-rw-r--r--include/llvm/CodeGen/MachineInstrBundle.h43
-rw-r--r--include/llvm/CodeGen/MachineInstrBundleIterator.h92
-rw-r--r--include/llvm/CodeGen/MachineLoopInfo.h54
-rw-r--r--include/llvm/CodeGen/MachineMemOperand.h136
-rw-r--r--include/llvm/CodeGen/MachineModuleInfoImpls.h27
-rw-r--r--include/llvm/CodeGen/MachineOperand.h9
-rw-r--r--include/llvm/CodeGen/MachineRegisterInfo.h149
-rw-r--r--include/llvm/CodeGen/MachineSSAUpdater.h1
-rw-r--r--include/llvm/CodeGen/MachineScheduler.h96
-rw-r--r--include/llvm/CodeGen/MachineTraceMetrics.h13
-rw-r--r--include/llvm/CodeGen/MachineValueType.h25
-rw-r--r--include/llvm/CodeGen/PBQP/Graph.h16
-rw-r--r--include/llvm/CodeGen/ParallelCG.h25
-rw-r--r--include/llvm/CodeGen/Passes.h421
-rw-r--r--include/llvm/CodeGen/PreISelIntrinsicLowering.h26
-rw-r--r--include/llvm/CodeGen/PseudoSourceValue.h4
-rw-r--r--include/llvm/CodeGen/RegAllocPBQP.h1
-rw-r--r--include/llvm/CodeGen/RegisterPressure.h128
-rw-r--r--include/llvm/CodeGen/RegisterScavenging.h13
-rw-r--r--include/llvm/CodeGen/RegisterUsageInfo.h75
-rw-r--r--include/llvm/CodeGen/ResourcePriorityQueue.h8
-rw-r--r--include/llvm/CodeGen/RuntimeLibcalls.h86
-rw-r--r--include/llvm/CodeGen/ScheduleDAG.h11
-rw-r--r--include/llvm/CodeGen/ScheduleDAGInstrs.h76
-rw-r--r--include/llvm/CodeGen/ScheduleDAGMutation.h31
-rw-r--r--include/llvm/CodeGen/ScheduleHazardRecognizer.h11
-rw-r--r--include/llvm/CodeGen/ScoreboardHazardRecognizer.h6
-rw-r--r--include/llvm/CodeGen/SelectionDAG.h544
-rw-r--r--include/llvm/CodeGen/SelectionDAGISel.h42
-rw-r--r--include/llvm/CodeGen/SelectionDAGNodes.h507
-rw-r--r--include/llvm/CodeGen/SelectionDAGTargetInfo.h (renamed from include/llvm/Target/TargetSelectionDAGInfo.h)82
-rw-r--r--include/llvm/CodeGen/SlotIndexes.h78
-rw-r--r--include/llvm/CodeGen/StackMaps.h2
-rw-r--r--include/llvm/CodeGen/StackProtector.h10
-rw-r--r--include/llvm/CodeGen/TailDuplicator.h92
-rw-r--r--include/llvm/CodeGen/TargetLoweringObjectFileImpl.h19
-rw-r--r--include/llvm/CodeGen/TargetPassConfig.h376
-rw-r--r--include/llvm/CodeGen/UnreachableBlockElim.h37
-rw-r--r--include/llvm/CodeGen/ValueTypes.h8
-rw-r--r--include/llvm/CodeGen/ValueTypes.td20
-rw-r--r--include/llvm/CodeGen/WinEHFuncInfo.h2
-rw-r--r--include/llvm/Config/config.h.cmake26
-rw-r--r--include/llvm/Config/config.h.in538
-rw-r--r--include/llvm/Config/llvm-config.h.in104
-rw-r--r--include/llvm/DebugInfo/CodeView/ByteStream.h58
-rw-r--r--include/llvm/DebugInfo/CodeView/CVRecord.h56
-rw-r--r--include/llvm/DebugInfo/CodeView/CVSymbolTypes.def258
-rw-r--r--include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h103
-rw-r--r--include/llvm/DebugInfo/CodeView/CVTypeVisitor.h44
-rw-r--r--include/llvm/DebugInfo/CodeView/CodeView.h509
-rw-r--r--include/llvm/DebugInfo/CodeView/CodeViewError.h44
-rw-r--r--include/llvm/DebugInfo/CodeView/EnumTables.h42
-rw-r--r--include/llvm/DebugInfo/CodeView/FieldListRecordBuilder.h37
-rw-r--r--include/llvm/DebugInfo/CodeView/Line.h50
-rw-r--r--include/llvm/DebugInfo/CodeView/ListRecordBuilder.h22
-rw-r--r--include/llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h48
-rw-r--r--include/llvm/DebugInfo/CodeView/ModuleSubstream.h87
-rw-r--r--include/llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h121
-rw-r--r--include/llvm/DebugInfo/CodeView/RecordSerialization.h278
-rw-r--r--include/llvm/DebugInfo/CodeView/StreamArray.h275
-rw-r--r--include/llvm/DebugInfo/CodeView/StreamInterface.h55
-rw-r--r--include/llvm/DebugInfo/CodeView/StreamReader.h111
-rw-r--r--include/llvm/DebugInfo/CodeView/StreamRef.h104
-rw-r--r--include/llvm/DebugInfo/CodeView/StreamWriter.h86
-rw-r--r--include/llvm/DebugInfo/CodeView/SymbolDumpDelegate.h37
-rw-r--r--include/llvm/DebugInfo/CodeView/SymbolDumper.h54
-rw-r--r--include/llvm/DebugInfo/CodeView/SymbolRecord.h1452
-rw-r--r--include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h33
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeDumper.h105
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeIndex.h76
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeRecord.h1024
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h17
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeRecords.def252
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeStreamMerger.h26
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeSymbolEmitter.h3
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeTableBuilder.h26
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h63
-rw-r--r--include/llvm/DebugInfo/DIContext.h5
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h6
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFContext.h17
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h1
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h6
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h1
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFFormValue.h2
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h6
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFUnit.h18
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h11
-rw-r--r--include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h2
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIADataStream.h2
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h2
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h3
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h3
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h3
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIAError.h46
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIALineNumber.h3
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h8
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIASession.h33
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIASourceFile.h7
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIASupport.h11
-rw-r--r--include/llvm/DebugInfo/PDB/GenericError.h42
-rw-r--r--include/llvm/DebugInfo/PDB/IPDBDataStream.h2
-rw-r--r--include/llvm/DebugInfo/PDB/IPDBEnumChildren.h2
-rw-r--r--include/llvm/DebugInfo/PDB/IPDBLineNumber.h3
-rw-r--r--include/llvm/DebugInfo/PDB/IPDBRawSymbol.h11
-rw-r--r--include/llvm/DebugInfo/PDB/IPDBSession.h22
-rw-r--r--include/llvm/DebugInfo/PDB/IPDBSourceFile.h7
-rw-r--r--include/llvm/DebugInfo/PDB/PDB.h14
-rw-r--r--include/llvm/DebugInfo/PDB/PDBContext.h73
-rw-r--r--include/llvm/DebugInfo/PDB/PDBExtras.h9
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymDumper.h2
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbol.h12
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h4
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolBlock.h5
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h7
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h4
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h4
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolCustom.h3
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolData.h4
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolExe.h5
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolFunc.h4
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h4
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h3
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolLabel.h3
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h3
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolThunk.h4
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h3
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h3
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h3
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h3
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h3
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h3
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h3
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h3
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h3
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h3
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h3
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h3
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h4
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h3
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h3
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h2
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h3
-rw-r--r--include/llvm/DebugInfo/PDB/PDBTypes.h272
-rw-r--r--include/llvm/DebugInfo/PDB/Raw/DbiStream.h149
-rw-r--r--include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h56
-rw-r--r--include/llvm/DebugInfo/PDB/Raw/DirectoryStreamData.h37
-rw-r--r--include/llvm/DebugInfo/PDB/Raw/EnumTables.h22
-rw-r--r--include/llvm/DebugInfo/PDB/Raw/Hash.h25
-rw-r--r--include/llvm/DebugInfo/PDB/Raw/IPDBFile.h44
-rw-r--r--include/llvm/DebugInfo/PDB/Raw/IPDBStreamData.h38
-rw-r--r--include/llvm/DebugInfo/PDB/Raw/ISectionContribVisitor.h28
-rw-r--r--include/llvm/DebugInfo/PDB/Raw/IndexedStreamData.h34
-rw-r--r--include/llvm/DebugInfo/PDB/Raw/InfoStream.h77
-rw-r--r--include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h53
-rw-r--r--include/llvm/DebugInfo/PDB/Raw/MappedBlockStream.h68
-rw-r--r--include/llvm/DebugInfo/PDB/Raw/ModInfo.h79
-rw-r--r--include/llvm/DebugInfo/PDB/Raw/ModStream.h57
-rw-r--r--include/llvm/DebugInfo/PDB/Raw/MsfBuilder.h141
-rw-r--r--include/llvm/DebugInfo/PDB/Raw/MsfCommon.h90
-rw-r--r--include/llvm/DebugInfo/PDB/Raw/NameHashTable.h54
-rw-r--r--include/llvm/DebugInfo/PDB/Raw/NameMap.h45
-rw-r--r--include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h41
-rw-r--r--include/llvm/DebugInfo/PDB/Raw/PDBFile.h113
-rw-r--r--include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h59
-rw-r--r--include/llvm/DebugInfo/PDB/Raw/PublicsStream.h74
-rw-r--r--include/llvm/DebugInfo/PDB/Raw/RawConstants.h94
-rw-r--r--include/llvm/DebugInfo/PDB/Raw/RawError.h49
-rw-r--r--include/llvm/DebugInfo/PDB/Raw/RawSession.h75
-rw-r--r--include/llvm/DebugInfo/PDB/Raw/RawTypes.h86
-rw-r--r--include/llvm/DebugInfo/PDB/Raw/SymbolStream.h41
-rw-r--r--include/llvm/DebugInfo/PDB/Raw/TpiStream.h72
-rw-r--r--include/llvm/DebugInfo/Symbolize/DIPrinter.h2
-rw-r--r--include/llvm/DebugInfo/Symbolize/SymbolizableModule.h2
-rw-r--r--include/llvm/DebugInfo/Symbolize/Symbolize.h34
-rw-r--r--include/llvm/ExecutionEngine/ExecutionEngine.h10
-rw-r--r--include/llvm/ExecutionEngine/GenericValue.h1
-rw-r--r--include/llvm/ExecutionEngine/JITEventListener.h4
-rw-r--r--include/llvm/ExecutionEngine/JITSymbolFlags.h10
-rw-r--r--include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h69
-rw-r--r--include/llvm/ExecutionEngine/Orc/CompileUtils.h5
-rw-r--r--include/llvm/ExecutionEngine/Orc/IRCompileLayer.h31
-rw-r--r--include/llvm/ExecutionEngine/Orc/IndirectionUtils.h127
-rw-r--r--include/llvm/ExecutionEngine/Orc/JITSymbol.h10
-rw-r--r--include/llvm/ExecutionEngine/Orc/LambdaResolver.h37
-rw-r--r--include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h9
-rw-r--r--include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h260
-rw-r--r--include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h4
-rw-r--r--include/llvm/ExecutionEngine/Orc/OrcABISupport.h232
-rw-r--r--include/llvm/ExecutionEngine/Orc/OrcArchitectureSupport.h148
-rw-r--r--include/llvm/ExecutionEngine/Orc/OrcError.h6
-rw-r--r--include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h562
-rw-r--r--include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h181
-rw-r--r--include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h233
-rw-r--r--include/llvm/ExecutionEngine/Orc/RPCChannel.h188
-rw-r--r--include/llvm/ExecutionEngine/Orc/RPCUtils.h614
-rw-r--r--include/llvm/ExecutionEngine/RTDyldMemoryManager.h16
-rw-r--r--include/llvm/ExecutionEngine/RuntimeDyld.h47
-rw-r--r--include/llvm/ExecutionEngine/RuntimeDyldChecker.h6
-rw-r--r--include/llvm/IR/Argument.h17
-rw-r--r--include/llvm/IR/Attributes.h92
-rw-r--r--include/llvm/IR/Attributes.td16
-rw-r--r--include/llvm/IR/AutoUpgrade.h17
-rw-r--r--include/llvm/IR/BasicBlock.h8
-rw-r--r--include/llvm/IR/CallSite.h83
-rw-r--r--include/llvm/IR/CallingConv.h25
-rw-r--r--include/llvm/IR/Comdat.h5
-rw-r--r--include/llvm/IR/Constant.h50
-rw-r--r--include/llvm/IR/ConstantRange.h50
-rw-r--r--include/llvm/IR/Constants.h473
-rw-r--r--include/llvm/IR/DIBuilder.h73
-rw-r--r--include/llvm/IR/DataLayout.h18
-rw-r--r--include/llvm/IR/DebugInfo.h23
-rw-r--r--include/llvm/IR/DebugInfoFlags.def5
-rw-r--r--include/llvm/IR/DebugInfoMetadata.h350
-rw-r--r--include/llvm/IR/DerivedTypes.h180
-rw-r--r--include/llvm/IR/DiagnosticInfo.h215
-rw-r--r--include/llvm/IR/Dominators.h66
-rw-r--r--include/llvm/IR/Function.h152
-rw-r--r--include/llvm/IR/FunctionInfo.h241
-rw-r--r--include/llvm/IR/GVMaterializer.h10
-rw-r--r--include/llvm/IR/GetElementPtrTypeIterator.h12
-rw-r--r--include/llvm/IR/GlobalAlias.h44
-rw-r--r--include/llvm/IR/GlobalIFunc.h76
-rw-r--r--include/llvm/IR/GlobalIndirectSymbol.h84
-rw-r--r--include/llvm/IR/GlobalObject.h78
-rw-r--r--include/llvm/IR/GlobalValue.h255
-rw-r--r--include/llvm/IR/GlobalVariable.h12
-rw-r--r--include/llvm/IR/IRBuilder.h97
-rw-r--r--include/llvm/IR/IRPrintingPasses.h5
-rw-r--r--include/llvm/IR/InlineAsm.h24
-rw-r--r--include/llvm/IR/InstrTypes.h73
-rw-r--r--include/llvm/IR/Instruction.h198
-rw-r--r--include/llvm/IR/Instructions.h313
-rw-r--r--include/llvm/IR/IntrinsicInst.h68
-rw-r--r--include/llvm/IR/Intrinsics.h28
-rw-r--r--include/llvm/IR/Intrinsics.td131
-rw-r--r--include/llvm/IR/IntrinsicsAArch64.td35
-rw-r--r--include/llvm/IR/IntrinsicsAMDGPU.td425
-rw-r--r--include/llvm/IR/IntrinsicsARM.td66
-rw-r--r--include/llvm/IR/IntrinsicsHexagon.td24
-rw-r--r--include/llvm/IR/IntrinsicsMips.td22
-rw-r--r--include/llvm/IR/IntrinsicsNVVM.td244
-rw-r--r--include/llvm/IR/IntrinsicsPowerPC.td36
-rw-r--r--include/llvm/IR/IntrinsicsSystemZ.td19
-rw-r--r--include/llvm/IR/IntrinsicsWebAssembly.td4
-rw-r--r--include/llvm/IR/IntrinsicsX86.td2642
-rw-r--r--include/llvm/IR/LLVMContext.h80
-rw-r--r--include/llvm/IR/LegacyPassManagers.h15
-rw-r--r--include/llvm/IR/Mangler.h2
-rw-r--r--include/llvm/IR/Metadata.def1
-rw-r--r--include/llvm/IR/Metadata.h152
-rw-r--r--include/llvm/IR/Module.h214
-rw-r--r--include/llvm/IR/ModuleSlotTracker.h6
-rw-r--r--include/llvm/IR/ModuleSummaryIndex.h508
-rw-r--r--include/llvm/IR/Operator.h5
-rw-r--r--include/llvm/IR/OptBisect.h81
-rw-r--r--include/llvm/IR/PassManager.h364
-rw-r--r--include/llvm/IR/PassManagerInternal.h123
-rw-r--r--include/llvm/IR/PatternMatch.h37
-rw-r--r--include/llvm/IR/ProfileSummary.h85
-rw-r--r--include/llvm/IR/Statepoint.h78
-rw-r--r--include/llvm/IR/SymbolTableListTraits.h2
-rw-r--r--include/llvm/IR/TrackingMDRef.h1
-rw-r--r--include/llvm/IR/Type.h176
-rw-r--r--include/llvm/IR/TypeFinder.h3
-rw-r--r--include/llvm/IR/Use.h12
-rw-r--r--include/llvm/IR/UseListOrder.h3
-rw-r--r--include/llvm/IR/User.h4
-rw-r--r--include/llvm/IR/Value.def20
-rw-r--r--include/llvm/IR/Value.h79
-rw-r--r--include/llvm/IR/ValueMap.h25
-rw-r--r--include/llvm/IR/ValueSymbolTable.h3
-rw-r--r--include/llvm/IR/Verifier.h51
-rw-r--r--include/llvm/IRReader/IRReader.h5
-rw-r--r--include/llvm/InitializePasses.h286
-rw-r--r--include/llvm/LTO/LTO.h74
-rw-r--r--include/llvm/LTO/legacy/LTOCodeGenerator.h (renamed from include/llvm/LTO/LTOCodeGenerator.h)70
-rw-r--r--include/llvm/LTO/legacy/LTOModule.h (renamed from include/llvm/LTO/LTOModule.h)28
-rw-r--r--include/llvm/LTO/legacy/ThinLTOCodeGenerator.h276
-rw-r--r--include/llvm/LTO/legacy/UpdateCompilerUsed.h32
-rw-r--r--include/llvm/LibDriver/LibDriver.h6
-rw-r--r--include/llvm/LineEditor/LineEditor.h3
-rw-r--r--include/llvm/LinkAllIR.h5
-rw-r--r--include/llvm/LinkAllPasses.h35
-rw-r--r--include/llvm/Linker/IRMover.h24
-rw-r--r--include/llvm/Linker/Linker.h32
-rw-r--r--include/llvm/MC/MCAsmBackend.h28
-rw-r--r--include/llvm/MC/MCAsmInfo.h45
-rw-r--r--include/llvm/MC/MCAsmInfoELF.h4
-rw-r--r--include/llvm/MC/MCAssembler.h9
-rw-r--r--include/llvm/MC/MCCodeGenInfo.h51
-rw-r--r--include/llvm/MC/MCCodeView.h210
-rw-r--r--include/llvm/MC/MCContext.h104
-rw-r--r--include/llvm/MC/MCDirectives.h1
-rw-r--r--include/llvm/MC/MCDisassembler/MCDisassembler.h (renamed from include/llvm/MC/MCDisassembler.h)8
-rw-r--r--include/llvm/MC/MCDisassembler/MCExternalSymbolizer.h (renamed from include/llvm/MC/MCExternalSymbolizer.h)6
-rw-r--r--include/llvm/MC/MCDisassembler/MCRelocationInfo.h (renamed from include/llvm/MC/MCRelocationInfo.h)8
-rw-r--r--include/llvm/MC/MCDisassembler/MCSymbolizer.h (renamed from include/llvm/MC/MCSymbolizer.h)6
-rw-r--r--include/llvm/MC/MCDwarf.h30
-rw-r--r--include/llvm/MC/MCELFObjectWriter.h22
-rw-r--r--include/llvm/MC/MCELFStreamer.h1
-rw-r--r--include/llvm/MC/MCExpr.h37
-rw-r--r--include/llvm/MC/MCFragment.h107
-rw-r--r--include/llvm/MC/MCInstPrinter.h2
-rw-r--r--include/llvm/MC/MCLinkerOptimizationHint.h25
-rw-r--r--include/llvm/MC/MCMachObjectWriter.h1
-rw-r--r--include/llvm/MC/MCObjectFileInfo.h31
-rw-r--r--include/llvm/MC/MCObjectStreamer.h24
-rw-r--r--include/llvm/MC/MCObjectWriter.h1
-rw-r--r--include/llvm/MC/MCParser/AsmLexer.h11
-rw-r--r--include/llvm/MC/MCParser/MCAsmLexer.h18
-rw-r--r--include/llvm/MC/MCParser/MCTargetAsmParser.h (renamed from include/llvm/MC/MCTargetAsmParser.h)6
-rw-r--r--include/llvm/MC/MCRegisterInfo.h14
-rw-r--r--include/llvm/MC/MCSchedule.h4
-rw-r--r--include/llvm/MC/MCSection.h1
-rw-r--r--include/llvm/MC/MCSectionCOFF.h13
-rw-r--r--include/llvm/MC/MCSectionELF.h1
-rw-r--r--include/llvm/MC/MCStreamer.h86
-rw-r--r--include/llvm/MC/MCSubtargetInfo.h1
-rw-r--r--include/llvm/MC/MCSymbol.h4
-rw-r--r--include/llvm/MC/MCSymbolMachO.h15
-rw-r--r--include/llvm/MC/MCTargetOptions.h4
-rw-r--r--include/llvm/MC/MCWin64EH.h1
-rw-r--r--include/llvm/MC/MCWinEH.h51
-rw-r--r--include/llvm/MC/SectionKind.h8
-rw-r--r--include/llvm/MC/StringTableBuilder.h16
-rw-r--r--include/llvm/MC/SubtargetFeature.h3
-rw-r--r--include/llvm/Object/Archive.h58
-rw-r--r--include/llvm/Object/ArchiveWriter.h45
-rw-r--r--include/llvm/Object/Binary.h12
-rw-r--r--include/llvm/Object/COFF.h142
-rw-r--r--include/llvm/Object/ELF.h78
-rw-r--r--include/llvm/Object/ELFObjectFile.h146
-rw-r--r--include/llvm/Object/ELFTypes.h89
-rw-r--r--include/llvm/Object/Error.h47
-rw-r--r--include/llvm/Object/FunctionIndexObjectFile.h110
-rw-r--r--include/llvm/Object/IRObjectFile.h10
-rw-r--r--include/llvm/Object/MachO.h30
-rw-r--r--include/llvm/Object/MachOUniversal.h70
-rw-r--r--include/llvm/Object/ModuleSummaryIndexObjectFile.h103
-rw-r--r--include/llvm/Object/ObjectFile.h48
-rw-r--r--include/llvm/Object/RelocVisitor.h16
-rw-r--r--include/llvm/Object/StackMapParser.h3
-rw-r--r--include/llvm/Object/SymbolicFile.h9
-rw-r--r--include/llvm/ObjectYAML/COFFYAML.h (renamed from include/llvm/Object/COFFYAML.h)12
-rw-r--r--include/llvm/ObjectYAML/ELFYAML.h (renamed from include/llvm/Object/ELFYAML.h)6
-rw-r--r--include/llvm/ObjectYAML/MachOYAML.h296
-rw-r--r--include/llvm/ObjectYAML/ObjectYAML.h35
-rw-r--r--include/llvm/ObjectYAML/YAML.h (renamed from include/llvm/MC/YAML.h)13
-rw-r--r--include/llvm/Option/OptParser.td3
-rw-r--r--include/llvm/Option/Option.h2
-rw-r--r--include/llvm/Pass.h20
-rw-r--r--include/llvm/PassAnalysisSupport.h8
-rw-r--r--include/llvm/PassRegistry.h2
-rw-r--r--include/llvm/PassSupport.h210
-rw-r--r--include/llvm/Passes/PassBuilder.h170
-rw-r--r--include/llvm/ProfileData/Coverage/CoverageMapping.h (renamed from include/llvm/ProfileData/CoverageMapping.h)126
-rw-r--r--include/llvm/ProfileData/Coverage/CoverageMappingReader.h (renamed from include/llvm/ProfileData/CoverageMappingReader.h)41
-rw-r--r--include/llvm/ProfileData/Coverage/CoverageMappingWriter.h (renamed from include/llvm/ProfileData/CoverageMappingWriter.h)2
-rw-r--r--include/llvm/ProfileData/InstrProf.h545
-rw-r--r--include/llvm/ProfileData/InstrProfData.inc338
-rw-r--r--include/llvm/ProfileData/InstrProfReader.h135
-rw-r--r--include/llvm/ProfileData/InstrProfWriter.h30
-rw-r--r--include/llvm/ProfileData/ProfileCommon.h102
-rw-r--r--include/llvm/ProfileData/SampleProf.h44
-rw-r--r--include/llvm/ProfileData/SampleProfReader.h42
-rw-r--r--include/llvm/ProfileData/SampleProfWriter.h22
-rw-r--r--include/llvm/Support/AArch64TargetParser.def72
-rw-r--r--include/llvm/Support/AIXDataTypesFix.h25
-rw-r--r--include/llvm/Support/ARMBuildAttributes.h6
-rw-r--r--include/llvm/Support/ARMTargetParser.def270
-rw-r--r--include/llvm/Support/AlignOf.h21
-rw-r--r--include/llvm/Support/Allocator.h2
-rw-r--r--include/llvm/Support/Atomic.h9
-rw-r--r--include/llvm/Support/AtomicOrdering.h153
-rw-r--r--include/llvm/Support/BranchProbability.h2
-rw-r--r--include/llvm/Support/COFF.h29
-rw-r--r--include/llvm/Support/CachePruning.h69
-rw-r--r--include/llvm/Support/CodeGen.h47
-rw-r--r--include/llvm/Support/CodeGenCWrappers.h64
-rw-r--r--include/llvm/Support/CommandLine.h89
-rw-r--r--include/llvm/Support/Compiler.h35
-rw-r--r--include/llvm/Support/ConvertUTF.h35
-rw-r--r--include/llvm/Support/CrashRecoveryContext.h11
-rw-r--r--include/llvm/Support/DataTypes.h.cmake41
-rw-r--r--include/llvm/Support/DataTypes.h.in123
-rw-r--r--include/llvm/Support/Dwarf.def23
-rw-r--r--include/llvm/Support/Dwarf.h23
-rw-r--r--include/llvm/Support/ELF.h58
-rw-r--r--include/llvm/Support/ELFRelocs/AMDGPU.def12
-rw-r--r--include/llvm/Support/ELFRelocs/BPF.def9
-rw-r--r--include/llvm/Support/ELFRelocs/Hexagon.def1
-rw-r--r--include/llvm/Support/ELFRelocs/Lanai.def19
-rw-r--r--include/llvm/Support/ELFRelocs/Mips.def4
-rw-r--r--include/llvm/Support/ELFRelocs/i386.def2
-rw-r--r--include/llvm/Support/ELFRelocs/x86_64.def3
-rw-r--r--include/llvm/Support/Endian.h4
-rw-r--r--include/llvm/Support/EndianStream.h5
-rw-r--r--include/llvm/Support/Error.h950
-rw-r--r--include/llvm/Support/ErrorHandling.h2
-rw-r--r--include/llvm/Support/ErrorOr.h29
-rw-r--r--include/llvm/Support/FileSystem.h88
-rw-r--r--include/llvm/Support/Format.h8
-rw-r--r--include/llvm/Support/GenericDomTree.h24
-rw-r--r--include/llvm/Support/Host.h2
-rw-r--r--include/llvm/Support/JamCRC.h3
-rw-r--r--include/llvm/Support/Locale.h4
-rw-r--r--include/llvm/Support/LockFileManager.h13
-rw-r--r--include/llvm/Support/MD5.h15
-rw-r--r--include/llvm/Support/MachO.def106
-rw-r--r--include/llvm/Support/MachO.h150
-rw-r--r--include/llvm/Support/ManagedStatic.h53
-rw-r--r--include/llvm/Support/MathExtras.h140
-rw-r--r--include/llvm/Support/OnDiskHashTable.h18
-rw-r--r--include/llvm/Support/Path.h21
-rw-r--r--include/llvm/Support/PointerLikeTypeTraits.h6
-rw-r--r--include/llvm/Support/PrettyStackTrace.h10
-rw-r--r--include/llvm/Support/Printable.h4
-rw-r--r--include/llvm/Support/Process.h5
-rw-r--r--include/llvm/Support/Program.h4
-rw-r--r--include/llvm/Support/RandomNumberGenerator.h2
-rw-r--r--include/llvm/Support/Registry.h179
-rw-r--r--include/llvm/Support/RegistryParser.h55
-rw-r--r--include/llvm/Support/SHA1.h82
-rw-r--r--include/llvm/Support/ScaledNumber.h4
-rw-r--r--include/llvm/Support/ScopedPrinter.h378
-rw-r--r--include/llvm/Support/Signals.h10
-rw-r--r--include/llvm/Support/StreamingMemoryObject.h10
-rw-r--r--include/llvm/Support/SwapByteOrder.h1
-rw-r--r--include/llvm/Support/TargetParser.h56
-rw-r--r--include/llvm/Support/TargetRegistry.h86
-rw-r--r--include/llvm/Support/ThreadPool.h1
-rw-r--r--include/llvm/Support/Threading.h81
-rw-r--r--include/llvm/Support/Timer.h3
-rw-r--r--include/llvm/Support/TrailingObjects.h49
-rw-r--r--include/llvm/Support/TypeName.h65
-rw-r--r--include/llvm/Support/Unicode.h4
-rw-r--r--include/llvm/Support/Valgrind.h12
-rw-r--r--include/llvm/Support/YAMLParser.h1
-rw-r--r--include/llvm/Support/YAMLTraits.h44
-rw-r--r--include/llvm/Support/raw_sha1_ostream.h47
-rw-r--r--include/llvm/Support/thread.h1
-rw-r--r--include/llvm/Support/type_traits.h12
-rw-r--r--include/llvm/TableGen/Record.h319
-rw-r--r--include/llvm/TableGen/SearchableTable.td41
-rw-r--r--include/llvm/TableGen/StringToOffsetTable.h20
-rw-r--r--include/llvm/Target/GenericOpcodes.td46
-rw-r--r--include/llvm/Target/Target.td64
-rw-r--r--include/llvm/Target/TargetCallingConv.h18
-rw-r--r--include/llvm/Target/TargetCallingConv.td10
-rw-r--r--include/llvm/Target/TargetFrameLowering.h72
-rw-r--r--include/llvm/Target/TargetInstrInfo.h281
-rw-r--r--include/llvm/Target/TargetLowering.h366
-rw-r--r--include/llvm/Target/TargetLoweringObjectFile.h7
-rw-r--r--include/llvm/Target/TargetMachine.h39
-rw-r--r--include/llvm/Target/TargetOpcodes.def177
-rw-r--r--include/llvm/Target/TargetOpcodes.h122
-rw-r--r--include/llvm/Target/TargetOptions.h40
-rw-r--r--include/llvm/Target/TargetRecip.h9
-rw-r--r--include/llvm/Target/TargetRegisterInfo.h153
-rw-r--r--include/llvm/Target/TargetSchedule.td23
-rw-r--r--include/llvm/Target/TargetSelectionDAG.td42
-rw-r--r--include/llvm/Target/TargetSubtargetInfo.h24
-rw-r--r--include/llvm/Transforms/GCOVProfiler.h31
-rw-r--r--include/llvm/Transforms/IPO.h35
-rw-r--r--include/llvm/Transforms/IPO/ConstantMerge.h35
-rw-r--r--include/llvm/Transforms/IPO/CrossDSOCFI.h28
-rw-r--r--include/llvm/Transforms/IPO/DeadArgumentElimination.h133
-rw-r--r--include/llvm/Transforms/IPO/ElimAvailExtern.h31
-rw-r--r--include/llvm/Transforms/IPO/ForceFunctionAttrs.h6
-rw-r--r--include/llvm/Transforms/IPO/FunctionAttrs.h57
-rw-r--r--include/llvm/Transforms/IPO/FunctionImport.h100
-rw-r--r--include/llvm/Transforms/IPO/GlobalDCE.h46
-rw-r--r--include/llvm/Transforms/IPO/GlobalOpt.h32
-rw-r--r--include/llvm/Transforms/IPO/InferFunctionAttrs.h6
-rw-r--r--include/llvm/Transforms/IPO/InlinerPass.h32
-rw-r--r--include/llvm/Transforms/IPO/Internalize.h79
-rw-r--r--include/llvm/Transforms/IPO/LowerTypeTests.h (renamed from include/llvm/Transforms/IPO/LowerBitSets.h)28
-rw-r--r--include/llvm/Transforms/IPO/PartialInlining.h32
-rw-r--r--include/llvm/Transforms/IPO/PassManagerBuilder.h28
-rw-r--r--include/llvm/Transforms/IPO/SCCP.h34
-rw-r--r--include/llvm/Transforms/IPO/StripDeadPrototypes.h6
-rw-r--r--include/llvm/Transforms/IPO/WholeProgramDevirt.h223
-rw-r--r--include/llvm/Transforms/InstCombine/InstCombine.h32
-rw-r--r--include/llvm/Transforms/InstCombine/InstCombineWorklist.h3
-rw-r--r--include/llvm/Transforms/InstrProfiling.h105
-rw-r--r--include/llvm/Transforms/Instrumentation.h31
-rw-r--r--include/llvm/Transforms/PGOInstrumentation.h48
-rw-r--r--include/llvm/Transforms/SampleProfile.h27
-rw-r--r--include/llvm/Transforms/Scalar.h94
-rw-r--r--include/llvm/Transforms/Scalar/ADCE.h6
-rw-r--r--include/llvm/Transforms/Scalar/AlignmentFromAssumptions.h51
-rw-r--r--include/llvm/Transforms/Scalar/BDCE.h31
-rw-r--r--include/llvm/Transforms/Scalar/ConstantHoisting.h149
-rw-r--r--include/llvm/Transforms/Scalar/CorrelatedValuePropagation.h24
-rw-r--r--include/llvm/Transforms/Scalar/DCE.h29
-rw-r--r--include/llvm/Transforms/Scalar/DeadStoreElimination.h34
-rw-r--r--include/llvm/Transforms/Scalar/EarlyCSE.h7
-rw-r--r--include/llvm/Transforms/Scalar/Float2Int.h51
-rw-r--r--include/llvm/Transforms/Scalar/GVN.h240
-rw-r--r--include/llvm/Transforms/Scalar/GuardWidening.h32
-rw-r--r--include/llvm/Transforms/Scalar/IndVarSimplify.h29
-rw-r--r--include/llvm/Transforms/Scalar/JumpThreading.h141
-rw-r--r--include/llvm/Transforms/Scalar/LICM.h48
-rw-r--r--include/llvm/Transforms/Scalar/LoopDeletion.h38
-rw-r--r--include/llvm/Transforms/Scalar/LoopDistribute.h30
-rw-r--r--include/llvm/Transforms/Scalar/LoopIdiomRecognize.h31
-rw-r--r--include/llvm/Transforms/Scalar/LoopInstSimplify.h29
-rw-r--r--include/llvm/Transforms/Scalar/LoopRotation.h30
-rw-r--r--include/llvm/Transforms/Scalar/LoopSimplifyCFG.h32
-rw-r--r--include/llvm/Transforms/Scalar/LowerAtomic.h29
-rw-r--r--include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h7
-rw-r--r--include/llvm/Transforms/Scalar/MemCpyOptimizer.h68
-rw-r--r--include/llvm/Transforms/Scalar/MergedLoadStoreMotion.h39
-rw-r--r--include/llvm/Transforms/Scalar/PartiallyInlineLibCalls.h30
-rw-r--r--include/llvm/Transforms/Scalar/Reassociate.h100
-rw-r--r--include/llvm/Transforms/Scalar/SCCP.h36
-rw-r--r--include/llvm/Transforms/Scalar/SROA.h8
-rw-r--r--include/llvm/Transforms/Scalar/SimplifyCFG.h6
-rw-r--r--include/llvm/Transforms/Scalar/Sink.h30
-rw-r--r--include/llvm/Transforms/Scalar/TailRecursionElimination.h66
-rw-r--r--include/llvm/Transforms/Utils/AddDiscriminators.h29
-rw-r--r--include/llvm/Transforms/Utils/BasicBlockUtils.h142
-rw-r--r--include/llvm/Transforms/Utils/BuildLibCalls.h120
-rw-r--r--include/llvm/Transforms/Utils/Cloning.h26
-rw-r--r--include/llvm/Transforms/Utils/CodeExtractor.h2
-rw-r--r--include/llvm/Transforms/Utils/Evaluator.h119
-rw-r--r--include/llvm/Transforms/Utils/FunctionImportUtils.h100
-rw-r--r--include/llvm/Transforms/Utils/LCSSA.h44
-rw-r--r--include/llvm/Transforms/Utils/Local.h180
-rw-r--r--include/llvm/Transforms/Utils/LoopSimplify.h65
-rw-r--r--include/llvm/Transforms/Utils/LoopUtils.h114
-rw-r--r--include/llvm/Transforms/Utils/LoopVersioning.h40
-rw-r--r--include/llvm/Transforms/Utils/Mem2Reg.h28
-rw-r--r--include/llvm/Transforms/Utils/MemorySSA.h949
-rw-r--r--include/llvm/Transforms/Utils/ModuleUtils.h20
-rw-r--r--include/llvm/Transforms/Utils/PromoteMemToReg.h3
-rw-r--r--include/llvm/Transforms/Utils/SSAUpdater.h6
-rw-r--r--include/llvm/Transforms/Utils/SSAUpdaterImpl.h1
-rw-r--r--include/llvm/Transforms/Utils/SanitizerStats.h56
-rw-r--r--include/llvm/Transforms/Utils/SimplifyIndVar.h13
-rw-r--r--include/llvm/Transforms/Utils/SimplifyInstructions.h31
-rw-r--r--include/llvm/Transforms/Utils/SimplifyLibCalls.h4
-rw-r--r--include/llvm/Transforms/Utils/SplitModule.h5
-rw-r--r--include/llvm/Transforms/Utils/UnrollLoop.h19
-rw-r--r--include/llvm/Transforms/Utils/ValueMapper.h360
-rw-r--r--include/llvm/Transforms/Vectorize.h7
-rw-r--r--include/llvm/Transforms/Vectorize/LoopVectorize.h103
-rw-r--r--include/llvm/Transforms/Vectorize/SLPVectorizer.h113
-rw-r--r--include/llvm/module.modulemap96
689 files changed, 39142 insertions, 14833 deletions
diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h
index 3fe04060fd59..3f6bd00a779c 100644
--- a/include/llvm/ADT/APFloat.h
+++ b/include/llvm/ADT/APFloat.h
@@ -25,6 +25,8 @@ struct fltSemantics;
class APSInt;
class StringRef;
+template <typename T> class SmallVectorImpl;
+
/// Enum that represents what fraction of the LSB truncated bits of an fp number
/// represent.
///
@@ -511,19 +513,12 @@ public:
/// 0 -> \c IEK_Zero
/// Inf -> \c IEK_Inf
///
- friend int ilogb(const APFloat &Arg) {
- if (Arg.isNaN())
- return IEK_NaN;
- if (Arg.isZero())
- return IEK_Zero;
- if (Arg.isInfinity())
- return IEK_Inf;
-
- return Arg.exponent;
- }
+ friend int ilogb(const APFloat &Arg);
/// \brief Returns: X * 2^Exp for integral exponents.
- friend APFloat scalbn(APFloat X, int Exp);
+ friend APFloat scalbn(APFloat X, int Exp, roundingMode);
+
+ friend APFloat frexp(const APFloat &X, int &Exp, roundingMode);
private:
@@ -579,6 +574,7 @@ private:
const APInt *fill);
void makeInf(bool Neg = false);
void makeZero(bool Neg = false);
+ void makeQuiet();
/// @}
@@ -651,7 +647,14 @@ private:
/// These additional declarations are required in order to compile LLVM with IBM
/// xlC compiler.
hash_code hash_value(const APFloat &Arg);
-APFloat scalbn(APFloat X, int Exp);
+int ilogb(const APFloat &Arg);
+APFloat scalbn(APFloat X, int Exp, APFloat::roundingMode);
+
+/// \brief Equivalent of C standard library function.
+///
+/// While the C standard says Exp is an unspecified value for infinity and nan,
+/// this returns INT_MAX for infinities, and INT_MIN for NaNs.
+APFloat frexp(const APFloat &Val, int &Exp, APFloat::roundingMode RM);
/// \brief Returns the absolute value of the argument.
inline APFloat abs(APFloat X) {
diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h
index e2a0cb5e69dc..d77d1c7ca93f 100644
--- a/include/llvm/ADT/APInt.h
+++ b/include/llvm/ADT/APInt.h
@@ -16,7 +16,6 @@
#ifndef LLVM_ADT_APINT_H
#define LLVM_ADT_APINT_H
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MathExtras.h"
#include <cassert>
@@ -31,6 +30,7 @@ class hash_code;
class raw_ostream;
template <typename T> class SmallVectorImpl;
+template <typename T> class ArrayRef;
// An unsigned host type used as a single part of a multi-part
// bignum.
@@ -177,11 +177,11 @@ class APInt {
/// provides a more convenient form of divide for internal use since KnuthDiv
/// has specific constraints on its inputs. If those constraints are not met
/// then it provides a simpler form of divide.
- static void divide(const APInt LHS, unsigned lhsWords, const APInt &RHS,
+ static void divide(const APInt &LHS, unsigned lhsWords, const APInt &RHS,
unsigned rhsWords, APInt *Quotient, APInt *Remainder);
/// out-of-line slow case for inline constructor
- void initSlowCase(unsigned numBits, uint64_t val, bool isSigned);
+ void initSlowCase(uint64_t val, bool isSigned);
/// shared code between two array constructors
void initFromArray(ArrayRef<uint64_t> array);
@@ -239,7 +239,7 @@ public:
if (isSingleWord())
VAL = val;
else
- initSlowCase(numBits, val, isSigned);
+ initSlowCase(val, isSigned);
clearUnusedBits();
}
@@ -625,7 +625,12 @@ public:
/// Negates *this using two's complement logic.
///
/// \returns An APInt value representing the negation of *this.
- APInt operator-() const { return APInt(BitWidth, 0) - (*this); }
+ APInt operator-() const {
+ APInt Result(*this);
+ Result.flipAllBits();
+ ++Result;
+ return Result;
+ }
/// \brief Logical negation operator.
///
@@ -835,13 +840,13 @@ public:
///
/// Adds RHS to this APInt and returns the result.
APInt operator+(const APInt &RHS) const;
- APInt operator+(uint64_t RHS) const { return (*this) + APInt(BitWidth, RHS); }
+ APInt operator+(uint64_t RHS) const;
/// \brief Subtraction operator.
///
/// Subtracts RHS from this APInt and returns the result.
APInt operator-(const APInt &RHS) const;
- APInt operator-(uint64_t RHS) const { return (*this) - APInt(BitWidth, RHS); }
+ APInt operator-(uint64_t RHS) const;
/// \brief Left logical shift operator.
///
@@ -1451,6 +1456,10 @@ public:
/// \returns a byte-swapped representation of this APInt Value.
APInt LLVM_ATTRIBUTE_UNUSED_RESULT byteSwap() const;
+ /// \returns the value with the bit representation reversed of this APInt
+ /// Value.
+ APInt LLVM_ATTRIBUTE_UNUSED_RESULT reverseBits() const;
+
/// \brief Converts this APInt to a double value.
double roundToDouble(bool isSigned) const;
@@ -1744,16 +1753,24 @@ inline raw_ostream &operator<<(raw_ostream &OS, const APInt &I) {
namespace APIntOps {
/// \brief Determine the smaller of two APInts considered to be signed.
-inline APInt smin(const APInt &A, const APInt &B) { return A.slt(B) ? A : B; }
+inline const APInt &smin(const APInt &A, const APInt &B) {
+ return A.slt(B) ? A : B;
+}
/// \brief Determine the larger of two APInts considered to be signed.
-inline APInt smax(const APInt &A, const APInt &B) { return A.sgt(B) ? A : B; }
+inline const APInt &smax(const APInt &A, const APInt &B) {
+ return A.sgt(B) ? A : B;
+}
/// \brief Determine the smaller of two APInts considered to be signed.
-inline APInt umin(const APInt &A, const APInt &B) { return A.ult(B) ? A : B; }
+inline const APInt &umin(const APInt &A, const APInt &B) {
+ return A.ult(B) ? A : B;
+}
/// \brief Determine the larger of two APInts considered to be unsigned.
-inline APInt umax(const APInt &A, const APInt &B) { return A.ugt(B) ? A : B; }
+inline const APInt &umax(const APInt &A, const APInt &B) {
+ return A.ugt(B) ? A : B;
+}
/// \brief Check if the specified APInt has a N-bits unsigned integer value.
inline bool isIntN(unsigned N, const APInt &APIVal) { return APIVal.isIntN(N); }
@@ -1770,6 +1787,13 @@ inline bool isMask(unsigned numBits, const APInt &APIVal) {
APIVal == APInt::getLowBitsSet(APIVal.getBitWidth(), numBits);
}
+/// \returns true if the argument is a non-empty sequence of ones starting at
+/// the least significant bit with the remainder zero (32 bit version).
+/// Ex. isMask(0x0000FFFFU) == true.
+inline bool isMask(const APInt &Value) {
+ return (Value != 0) && ((Value + 1) & Value) == 0;
+}
+
/// \brief Return true if the argument APInt value contains a sequence of ones
/// with the remainder zero.
inline bool isShiftedMask(unsigned numBits, const APInt &APIVal) {
diff --git a/include/llvm/ADT/ArrayRef.h b/include/llvm/ADT/ArrayRef.h
index 517ba39849e1..95a1e62ef005 100644
--- a/include/llvm/ADT/ArrayRef.h
+++ b/include/llvm/ADT/ArrayRef.h
@@ -16,7 +16,6 @@
#include <vector>
namespace llvm {
-
/// ArrayRef - Represent a constant reference to an array (0 or more elements
/// consecutively in memory), i.e. a start pointer and a length. It allows
/// various APIs to take consecutive elements easily and conveniently.
@@ -92,19 +91,20 @@ namespace llvm {
/// Construct an ArrayRef<const T*> from ArrayRef<T*>. This uses SFINAE to
/// ensure that only ArrayRefs of pointers can be converted.
template <typename U>
- ArrayRef(const ArrayRef<U *> &A,
- typename std::enable_if<
- std::is_convertible<U *const *, T const *>::value>::type* = 0)
+ ArrayRef(
+ const ArrayRef<U *> &A,
+ typename std::enable_if<
+ std::is_convertible<U *const *, T const *>::value>::type * = nullptr)
: Data(A.data()), Length(A.size()) {}
/// Construct an ArrayRef<const T*> from a SmallVector<T*>. This is
/// templated in order to avoid instantiating SmallVectorTemplateCommon<T>
/// whenever we copy-construct an ArrayRef.
template<typename U, typename DummyT>
- /*implicit*/ ArrayRef(const SmallVectorTemplateCommon<U*, DummyT> &Vec,
- typename std::enable_if<
- std::is_convertible<U *const *,
- T const *>::value>::type* = 0)
+ /*implicit*/ ArrayRef(
+ const SmallVectorTemplateCommon<U *, DummyT> &Vec,
+ typename std::enable_if<
+ std::is_convertible<U *const *, T const *>::value>::type * = nullptr)
: Data(Vec.data()), Length(Vec.size()) {
}
@@ -161,20 +161,26 @@ namespace llvm {
}
/// slice(n) - Chop off the first N elements of the array.
- ArrayRef<T> slice(unsigned N) const {
+ ArrayRef<T> slice(size_t N) const {
assert(N <= size() && "Invalid specifier");
return ArrayRef<T>(data()+N, size()-N);
}
/// slice(n, m) - Chop off the first N elements of the array, and keep M
/// elements in the array.
- ArrayRef<T> slice(unsigned N, unsigned M) const {
+ ArrayRef<T> slice(size_t N, size_t M) const {
assert(N+M <= size() && "Invalid specifier");
return ArrayRef<T>(data()+N, M);
}
- // \brief Drop the last \p N elements of the array.
- ArrayRef<T> drop_back(unsigned N = 1) const {
+ /// \brief Drop the first \p N elements of the array.
+ ArrayRef<T> drop_front(size_t N = 1) const {
+ assert(size() >= N && "Dropping more elements than exist");
+ return slice(N, size() - N);
+ }
+
+ /// \brief Drop the last \p N elements of the array.
+ ArrayRef<T> drop_back(size_t N = 1) const {
assert(size() >= N && "Dropping more elements than exist");
return slice(0, size() - N);
}
@@ -273,19 +279,25 @@ namespace llvm {
}
/// slice(n) - Chop off the first N elements of the array.
- MutableArrayRef<T> slice(unsigned N) const {
+ MutableArrayRef<T> slice(size_t N) const {
assert(N <= this->size() && "Invalid specifier");
return MutableArrayRef<T>(data()+N, this->size()-N);
}
/// slice(n, m) - Chop off the first N elements of the array, and keep M
/// elements in the array.
- MutableArrayRef<T> slice(unsigned N, unsigned M) const {
+ MutableArrayRef<T> slice(size_t N, size_t M) const {
assert(N+M <= this->size() && "Invalid specifier");
return MutableArrayRef<T>(data()+N, M);
}
- MutableArrayRef<T> drop_back(unsigned N) const {
+ /// \brief Drop the first \p N elements of the array.
+ MutableArrayRef<T> drop_front(size_t N = 1) const {
+ assert(this->size() >= N && "Dropping more elements than exist");
+ return slice(N, this->size() - N);
+ }
+
+ MutableArrayRef<T> drop_back(size_t N = 1) const {
assert(this->size() >= N && "Dropping more elements than exist");
return slice(0, this->size() - N);
}
@@ -379,6 +391,6 @@ namespace llvm {
template <typename T> hash_code hash_value(ArrayRef<T> S) {
return hash_combine_range(S.begin(), S.end());
}
-}
+} // end namespace llvm
-#endif
+#endif // LLVM_ADT_ARRAYREF_H
diff --git a/include/llvm/ADT/BitVector.h b/include/llvm/ADT/BitVector.h
index ad00d51f99e9..661437126d48 100644
--- a/include/llvm/ADT/BitVector.h
+++ b/include/llvm/ADT/BitVector.h
@@ -14,13 +14,13 @@
#ifndef LLVM_ADT_BITVECTOR_H
#define LLVM_ADT_BITVECTOR_H
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include <algorithm>
#include <cassert>
#include <climits>
+#include <cstdint>
#include <cstdlib>
+#include <cstring>
namespace llvm {
@@ -69,7 +69,7 @@ public:
}
operator bool() const {
- return ((*WordRef) & (BitWord(1) << BitPos)) ? true : false;
+ return ((*WordRef) & (BitWord(1) << BitPos)) != 0;
}
};
@@ -105,6 +105,7 @@ public:
BitVector(BitVector &&RHS)
: Bits(RHS.Bits), Size(RHS.Size), Capacity(RHS.Capacity) {
RHS.Bits = nullptr;
+ RHS.Size = RHS.Capacity = 0;
}
~BitVector() {
@@ -244,7 +245,7 @@ public:
BitWord PrefixMask = ~0UL << (I % BITWORD_SIZE);
Bits[I / BITWORD_SIZE] |= PrefixMask;
- I = RoundUpToAlignment(I, BITWORD_SIZE);
+ I = alignTo(I, BITWORD_SIZE);
for (; I + BITWORD_SIZE <= E; I += BITWORD_SIZE)
Bits[I / BITWORD_SIZE] = ~0UL;
@@ -283,7 +284,7 @@ public:
BitWord PrefixMask = ~0UL << (I % BITWORD_SIZE);
Bits[I / BITWORD_SIZE] &= ~PrefixMask;
- I = RoundUpToAlignment(I, BITWORD_SIZE);
+ I = alignTo(I, BITWORD_SIZE);
for (; I + BITWORD_SIZE <= E; I += BITWORD_SIZE)
Bits[I / BITWORD_SIZE] = 0UL;
@@ -454,6 +455,7 @@ public:
Capacity = RHS.Capacity;
RHS.Bits = nullptr;
+ RHS.Size = RHS.Capacity = 0;
return *this;
}
@@ -576,7 +578,7 @@ static inline size_t capacity_in_bytes(const BitVector &X) {
return X.getMemorySize();
}
-} // End llvm namespace
+} // end namespace llvm
namespace std {
/// Implement std::swap in terms of BitVector swap.
@@ -584,6 +586,6 @@ namespace std {
swap(llvm::BitVector &LHS, llvm::BitVector &RHS) {
LHS.swap(RHS);
}
-}
+} // end namespace std
-#endif
+#endif // LLVM_ADT_BITVECTOR_H
diff --git a/include/llvm/ADT/BitmaskEnum.h b/include/llvm/ADT/BitmaskEnum.h
new file mode 100644
index 000000000000..18c6ba5a3eb8
--- /dev/null
+++ b/include/llvm/ADT/BitmaskEnum.h
@@ -0,0 +1,153 @@
+//===-- llvm/ADT/BitmaskEnum.h ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_BITMASKENUM_H
+#define LLVM_ADT_BITMASKENUM_H
+
+#include <cassert>
+#include <type_traits>
+#include <utility>
+
+#include "llvm/Support/MathExtras.h"
+
+/// LLVM_MARK_AS_BITMASK_ENUM lets you opt in an individual enum type so you can
+/// perform bitwise operations on it without putting static_cast everywhere.
+///
+/// \code
+/// enum MyEnum {
+/// E1 = 1, E2 = 2, E3 = 4, E4 = 8,
+/// LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ E4)
+/// };
+///
+/// void Foo() {
+/// MyEnum A = (E1 | E2) & E3 ^ ~E4; // Look, ma: No static_cast!
+/// }
+/// \endcode
+///
+/// Normally when you do a bitwise operation on an enum value, you get back an
+/// instance of the underlying type (e.g. int). But using this macro, bitwise
+/// ops on your enum will return you back instances of the enum. This is
+/// particularly useful for enums which represent a combination of flags.
+///
+/// The parameter to LLVM_MARK_AS_BITMASK_ENUM should be the largest individual
+/// value in your enum.
+///
+/// All of the enum's values must be non-negative.
+#define LLVM_MARK_AS_BITMASK_ENUM(LargestValue) \
+ LLVM_BITMASK_LARGEST_ENUMERATOR = LargestValue
+
+/// LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE() pulls the operator overloads used
+/// by LLVM_MARK_AS_BITMASK_ENUM into the current namespace.
+///
+/// Suppose you have an enum foo::bar::MyEnum. Before using
+/// LLVM_MARK_AS_BITMASK_ENUM on MyEnum, you must put
+/// LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE() somewhere inside namespace foo or
+/// namespace foo::bar. This allows the relevant operator overloads to be found
+/// by ADL.
+///
+/// You don't need to use this macro in namespace llvm; it's done at the bottom
+/// of this file.
+#define LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE() \
+ using ::llvm::BitmaskEnumDetail::operator~; \
+ using ::llvm::BitmaskEnumDetail::operator|; \
+ using ::llvm::BitmaskEnumDetail::operator&; \
+ using ::llvm::BitmaskEnumDetail::operator^; \
+ using ::llvm::BitmaskEnumDetail::operator|=; \
+ using ::llvm::BitmaskEnumDetail::operator&=; \
+ /* Force a semicolon at the end of this macro. */ \
+ using ::llvm::BitmaskEnumDetail::operator^=
+
+namespace llvm {
+
+/// Traits class to determine whether an enum has a
+/// LLVM_BITMASK_LARGEST_ENUMERATOR enumerator.
+template <typename E, typename Enable = void>
+struct is_bitmask_enum : std::false_type {};
+
+template <typename E>
+struct is_bitmask_enum<
+ E, typename std::enable_if<sizeof(E::LLVM_BITMASK_LARGEST_ENUMERATOR) >=
+ 0>::type> : std::true_type {};
+namespace BitmaskEnumDetail {
+
+/// Get a bitmask with 1s in all places up to the high-order bit of E's largest
+/// value.
+template <typename E> typename std::underlying_type<E>::type Mask() {
+ // On overflow, NextPowerOf2 returns zero with the type uint64_t, so
+ // subtracting 1 gives us the mask with all bits set, like we want.
+ return NextPowerOf2(static_cast<typename std::underlying_type<E>::type>(
+ E::LLVM_BITMASK_LARGEST_ENUMERATOR)) -
+ 1;
+}
+
+/// Check that Val is in range for E, and return Val cast to E's underlying
+/// type.
+template <typename E> typename std::underlying_type<E>::type Underlying(E Val) {
+ auto U = static_cast<typename std::underlying_type<E>::type>(Val);
+ assert(U >= 0 && "Negative enum values are not allowed.");
+ assert(U <= Mask<E>() && "Enum value too large (or largest val too small?)");
+ return U;
+}
+
+template <typename E,
+ typename = typename std::enable_if<is_bitmask_enum<E>::value>::type>
+E operator~(E Val) {
+ return static_cast<E>(~Underlying(Val) & Mask<E>());
+}
+
+template <typename E,
+ typename = typename std::enable_if<is_bitmask_enum<E>::value>::type>
+E operator|(E LHS, E RHS) {
+ return static_cast<E>(Underlying(LHS) | Underlying(RHS));
+}
+
+template <typename E,
+ typename = typename std::enable_if<is_bitmask_enum<E>::value>::type>
+E operator&(E LHS, E RHS) {
+ return static_cast<E>(Underlying(LHS) & Underlying(RHS));
+}
+
+template <typename E,
+ typename = typename std::enable_if<is_bitmask_enum<E>::value>::type>
+E operator^(E LHS, E RHS) {
+ return static_cast<E>(Underlying(LHS) ^ Underlying(RHS));
+}
+
+// |=, &=, and ^= return a reference to LHS, to match the behavior of the
+// operators on builtin types.
+
+template <typename E,
+ typename = typename std::enable_if<is_bitmask_enum<E>::value>::type>
+E &operator|=(E &LHS, E RHS) {
+ LHS = LHS | RHS;
+ return LHS;
+}
+
+template <typename E,
+ typename = typename std::enable_if<is_bitmask_enum<E>::value>::type>
+E &operator&=(E &LHS, E RHS) {
+ LHS = LHS & RHS;
+ return LHS;
+}
+
+template <typename E,
+ typename = typename std::enable_if<is_bitmask_enum<E>::value>::type>
+E &operator^=(E &LHS, E RHS) {
+ LHS = LHS ^ RHS;
+ return LHS;
+}
+
+} // namespace BitmaskEnumDetail
+
+// Enable bitmask enums in namespace ::llvm and all nested namespaces.
+LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
+
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h
index 6ee1960b5c82..917c086beba3 100644
--- a/include/llvm/ADT/DenseMap.h
+++ b/include/llvm/ADT/DenseMap.h
@@ -81,11 +81,13 @@ public:
}
unsigned size() const { return getNumEntries(); }
- /// Grow the densemap so that it has at least Size buckets. Does not shrink
- void resize(size_type Size) {
+ /// Grow the densemap so that it can contain at least \p NumEntries items
+ /// before resizing again.
+ void reserve(size_type NumEntries) {
+ auto NumBuckets = getMinBucketToReserveForEntries(NumEntries);
incrementEpoch();
- if (Size > getNumBuckets())
- grow(Size);
+ if (NumBuckets > getNumBuckets())
+ grow(NumBuckets);
}
void clear() {
@@ -195,6 +197,26 @@ public:
true);
}
+ /// Alternate version of insert() which allows a different, and possibly
+ /// less expensive, key type.
+ /// The DenseMapInfo is responsible for supplying methods
+ /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key
+ /// type used.
+ template <typename LookupKeyT>
+ std::pair<iterator, bool> insert_as(std::pair<KeyT, ValueT> &&KV,
+ const LookupKeyT &Val) {
+ BucketT *TheBucket;
+ if (LookupBucketFor(Val, TheBucket))
+ return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
+ false); // Already in map.
+
+ // Otherwise, insert the new element.
+ TheBucket = InsertIntoBucket(std::move(KV.first), std::move(KV.second), Val,
+ TheBucket);
+ return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
+ true);
+ }
+
/// insert - Range insertion of pairs.
template<typename InputIt>
void insert(InputIt I, InputIt E) {
@@ -285,6 +307,17 @@ protected:
::new (&B->getFirst()) KeyT(EmptyKey);
}
+ /// Returns the number of buckets to allocate to ensure that the DenseMap can
+ /// accommodate \p NumEntries without need to grow().
+ unsigned getMinBucketToReserveForEntries(unsigned NumEntries) {
+ // Ensure that "NumEntries * 4 < NumBuckets * 3"
+ if (NumEntries == 0)
+ return 0;
+ // +1 is required because of the strict equality.
+ // For example if NumEntries is 48, we need to return 401.
+ return NextPowerOf2(NumEntries * 4 / 3 + 1);
+ }
+
void moveFromOldBuckets(BucketT *OldBucketsBegin, BucketT *OldBucketsEnd) {
initEmpty();
@@ -399,7 +432,7 @@ private:
BucketT *InsertIntoBucket(const KeyT &Key, const ValueT &Value,
BucketT *TheBucket) {
- TheBucket = InsertIntoBucketImpl(Key, TheBucket);
+ TheBucket = InsertIntoBucketImpl(Key, Key, TheBucket);
TheBucket->getFirst() = Key;
::new (&TheBucket->getSecond()) ValueT(Value);
@@ -408,7 +441,7 @@ private:
BucketT *InsertIntoBucket(const KeyT &Key, ValueT &&Value,
BucketT *TheBucket) {
- TheBucket = InsertIntoBucketImpl(Key, TheBucket);
+ TheBucket = InsertIntoBucketImpl(Key, Key, TheBucket);
TheBucket->getFirst() = Key;
::new (&TheBucket->getSecond()) ValueT(std::move(Value));
@@ -416,14 +449,26 @@ private:
}
BucketT *InsertIntoBucket(KeyT &&Key, ValueT &&Value, BucketT *TheBucket) {
- TheBucket = InsertIntoBucketImpl(Key, TheBucket);
+ TheBucket = InsertIntoBucketImpl(Key, Key, TheBucket);
TheBucket->getFirst() = std::move(Key);
::new (&TheBucket->getSecond()) ValueT(std::move(Value));
return TheBucket;
}
- BucketT *InsertIntoBucketImpl(const KeyT &Key, BucketT *TheBucket) {
+ template <typename LookupKeyT>
+ BucketT *InsertIntoBucket(KeyT &&Key, ValueT &&Value, LookupKeyT &Lookup,
+ BucketT *TheBucket) {
+ TheBucket = InsertIntoBucketImpl(Key, Lookup, TheBucket);
+
+ TheBucket->getFirst() = std::move(Key);
+ ::new (&TheBucket->getSecond()) ValueT(std::move(Value));
+ return TheBucket;
+ }
+
+ template <typename LookupKeyT>
+ BucketT *InsertIntoBucketImpl(const KeyT &Key, const LookupKeyT &Lookup,
+ BucketT *TheBucket) {
incrementEpoch();
// If the load of the hash table is more than 3/4, or if fewer than 1/8 of
@@ -439,12 +484,12 @@ private:
unsigned NumBuckets = getNumBuckets();
if (LLVM_UNLIKELY(NewNumEntries * 4 >= NumBuckets * 3)) {
this->grow(NumBuckets * 2);
- LookupBucketFor(Key, TheBucket);
+ LookupBucketFor(Lookup, TheBucket);
NumBuckets = getNumBuckets();
} else if (LLVM_UNLIKELY(NumBuckets-(NewNumEntries+getNumTombstones()) <=
NumBuckets/8)) {
this->grow(NumBuckets);
- LookupBucketFor(Key, TheBucket);
+ LookupBucketFor(Lookup, TheBucket);
}
assert(TheBucket);
@@ -550,9 +595,9 @@ class DenseMap : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>,
unsigned NumBuckets;
public:
- explicit DenseMap(unsigned NumInitBuckets = 0) {
- init(NumInitBuckets);
- }
+ /// Create a DenseMap wth an optional \p InitialReserve that guarantee that
+ /// this number of elements can be inserted in the map without grow()
+ explicit DenseMap(unsigned InitialReserve = 0) { init(InitialReserve); }
DenseMap(const DenseMap &other) : BaseT() {
init(0);
@@ -566,7 +611,7 @@ public:
template<typename InputIt>
DenseMap(const InputIt &I, const InputIt &E) {
- init(NextPowerOf2(std::distance(I, E)));
+ init(std::distance(I, E));
this->insert(I, E);
}
@@ -609,7 +654,8 @@ public:
}
}
- void init(unsigned InitBuckets) {
+ void init(unsigned InitNumEntries) {
+ auto InitBuckets = BaseT::getMinBucketToReserveForEntries(InitNumEntries);
if (allocateBuckets(InitBuckets)) {
this->BaseT::initEmpty();
} else {
diff --git a/include/llvm/ADT/DenseMapInfo.h b/include/llvm/ADT/DenseMapInfo.h
index a844ebcccf5b..18c692e0cbcc 100644
--- a/include/llvm/ADT/DenseMapInfo.h
+++ b/include/llvm/ADT/DenseMapInfo.h
@@ -30,6 +30,36 @@ struct DenseMapInfo {
//static bool isEqual(const T &LHS, const T &RHS);
};
+template <typename T> struct CachedHash {
+ CachedHash(T Val) : Val(std::move(Val)) {
+ Hash = DenseMapInfo<T>::getHashValue(Val);
+ }
+ CachedHash(T Val, unsigned Hash) : Val(std::move(Val)), Hash(Hash) {}
+ T Val;
+ unsigned Hash;
+};
+
+// Provide DenseMapInfo for all CachedHash<T>.
+template <typename T> struct DenseMapInfo<CachedHash<T>> {
+ static CachedHash<T> getEmptyKey() {
+ T N = DenseMapInfo<T>::getEmptyKey();
+ return {N, 0};
+ }
+ static CachedHash<T> getTombstoneKey() {
+ T N = DenseMapInfo<T>::getTombstoneKey();
+ return {N, 0};
+ }
+ static unsigned getHashValue(CachedHash<T> Val) {
+ assert(!isEqual(Val, getEmptyKey()) && "Cannot hash the empty key!");
+ assert(!isEqual(Val, getTombstoneKey()) &&
+ "Cannot hash the tombstone key!");
+ return Val.Hash;
+ }
+ static bool isEqual(CachedHash<T> A, CachedHash<T> B) {
+ return DenseMapInfo<T>::isEqual(A.Val, B.Val);
+ }
+};
+
// Provide DenseMapInfo for all pointers.
template<typename T>
struct DenseMapInfo<T*> {
diff --git a/include/llvm/ADT/DenseSet.h b/include/llvm/ADT/DenseSet.h
index ef09dce37980..3724a09623f3 100644
--- a/include/llvm/ADT/DenseSet.h
+++ b/include/llvm/ADT/DenseSet.h
@@ -94,6 +94,7 @@ public:
ValueT *operator->() { return &I->getFirst(); }
Iterator& operator++() { ++I; return *this; }
+ Iterator operator++(int) { auto T = *this; ++I; return T; }
bool operator==(const Iterator& X) const { return I == X.I; }
bool operator!=(const Iterator& X) const { return I != X.I; }
};
@@ -115,6 +116,7 @@ public:
const ValueT *operator->() { return &I->getFirst(); }
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; }
};
@@ -152,6 +154,19 @@ public:
return TheMap.insert(std::make_pair(V, Empty));
}
+ /// Alternative version of insert that uses a different (and possibly less
+ /// expensive) key type.
+ template <typename LookupKeyT>
+ std::pair<iterator, bool> insert_as(const ValueT &V,
+ const LookupKeyT &LookupKey) {
+ return insert_as(ValueT(V), LookupKey);
+ }
+ template <typename LookupKeyT>
+ std::pair<iterator, bool> insert_as(ValueT &&V, const LookupKeyT &LookupKey) {
+ detail::DenseSetEmpty Empty;
+ return TheMap.insert_as(std::make_pair(std::move(V), Empty), LookupKey);
+ }
+
// Range insertion of values.
template<typename InputIt>
void insert(InputIt I, InputIt E) {
diff --git a/include/llvm/ADT/FoldingSet.h b/include/llvm/ADT/FoldingSet.h
index c9205396591b..f16258af4ae2 100644
--- a/include/llvm/ADT/FoldingSet.h
+++ b/include/llvm/ADT/FoldingSet.h
@@ -17,10 +17,8 @@
#define LLVM_ADT_FOLDINGSET_H
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator.h"
#include "llvm/Support/Allocator.h"
-#include "llvm/Support/DataTypes.h"
namespace llvm {
/// This folding set used for two purposes:
@@ -98,6 +96,7 @@ namespace llvm {
/// The result indicates whether the node existed in the folding set.
class FoldingSetNodeID;
+class StringRef;
//===----------------------------------------------------------------------===//
/// FoldingSetImpl - Implements the folding set functionality. The main
@@ -181,11 +180,26 @@ public:
/// empty - Returns true if there are no nodes in the folding set.
bool empty() const { return NumNodes == 0; }
+ /// reserve - Increase the number of buckets such that adding the
+ /// EltCount-th node won't cause a rebucket operation. reserve is permitted
+ /// to allocate more space than requested by EltCount.
+ void reserve(unsigned EltCount);
+ /// capacity - Returns the number of nodes permitted in the folding set
+ /// before a rebucket operation is performed.
+ unsigned capacity() {
+ // We allow a load factor of up to 2.0,
+ // so that means our capacity is NumBuckets * 2
+ return NumBuckets * 2;
+ }
+
private:
/// GrowHashTable - Double the size of the hash table and rehash everything.
- ///
void GrowHashTable();
+ /// GrowBucketCount - resize the hash table and rehash everything.
+ /// NewBucketCount must be a power of two, and must be greater than the old
+ /// bucket count.
+ void GrowBucketCount(unsigned NewBucketCount);
protected:
/// GetNodeProfile - Instantiations of the FoldingSet template implement
/// this function to gather data bits for the given node.
diff --git a/include/llvm/ADT/Hashing.h b/include/llvm/ADT/Hashing.h
index de56f91eddb1..c3b574102f69 100644
--- a/include/llvm/ADT/Hashing.h
+++ b/include/llvm/ADT/Hashing.h
@@ -52,7 +52,6 @@
#include <algorithm>
#include <cassert>
#include <cstring>
-#include <iterator>
#include <string>
#include <utility>
@@ -632,7 +631,8 @@ inline hash_code hash_integer_value(uint64_t value) {
template <typename T>
typename std::enable_if<is_integral_or_enum<T>::value, hash_code>::type
hash_value(T value) {
- return ::llvm::hashing::detail::hash_integer_value(value);
+ return ::llvm::hashing::detail::hash_integer_value(
+ static_cast<uint64_t>(value));
}
// Declared and documented above, but defined here so that any of the hashing
diff --git a/include/llvm/ADT/PointerEmbeddedInt.h b/include/llvm/ADT/PointerEmbeddedInt.h
index 8781d1803ac7..2279d43405fa 100644
--- a/include/llvm/ADT/PointerEmbeddedInt.h
+++ b/include/llvm/ADT/PointerEmbeddedInt.h
@@ -11,6 +11,7 @@
#define LLVM_ADT_POINTEREMBEDDEDINT_H
#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/Support/MathExtras.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
#include <climits>
@@ -30,6 +31,8 @@ template <typename IntT, int Bits = sizeof(IntT) * CHAR_BIT>
class PointerEmbeddedInt {
uintptr_t Value;
+ // Note: This '<' is correct; using '<=' would result in some shifts
+ // overflowing their storage types.
static_assert(Bits < sizeof(uintptr_t) * CHAR_BIT,
"Cannot embed more bits than we have in a pointer!");
@@ -42,25 +45,36 @@ class PointerEmbeddedInt {
Mask = static_cast<uintptr_t>(-1) << Bits
};
+ struct RawValueTag {
+ explicit RawValueTag() = default;
+ };
+
friend class PointerLikeTypeTraits<PointerEmbeddedInt>;
- explicit PointerEmbeddedInt(uintptr_t Value) : Value(Value) {}
+ explicit PointerEmbeddedInt(uintptr_t Value, RawValueTag) : Value(Value) {}
public:
PointerEmbeddedInt() : Value(0) {}
- PointerEmbeddedInt(IntT I) : Value(static_cast<uintptr_t>(I) << Shift) {
- assert((I & Mask) == 0 && "Integer has bits outside those preserved!");
+ PointerEmbeddedInt(IntT I) {
+ *this = I;
}
PointerEmbeddedInt &operator=(IntT I) {
- assert((I & Mask) == 0 && "Integer has bits outside those preserved!");
+ assert((std::is_signed<IntT>::value ? llvm::isInt<Bits>(I)
+ : llvm::isUInt<Bits>(I)) &&
+ "Integer has bits outside those preserved!");
Value = static_cast<uintptr_t>(I) << Shift;
+ return *this;
}
- // Note that this imilict conversion additionally allows all of the basic
+ // Note that this implicit conversion additionally allows all of the basic
// comparison operators to work transparently, etc.
- operator IntT() const { return static_cast<IntT>(Value >> Shift); }
+ operator IntT() const {
+ if (std::is_signed<IntT>::value)
+ return static_cast<IntT>(static_cast<intptr_t>(Value) >> Shift);
+ return static_cast<IntT>(Value >> Shift);
+ }
};
// Provide pointer like traits to support use with pointer unions and sum
@@ -74,10 +88,10 @@ public:
return reinterpret_cast<void *>(P.Value);
}
static inline T getFromVoidPointer(void *P) {
- return T(reinterpret_cast<uintptr_t>(P));
+ return T(reinterpret_cast<uintptr_t>(P), typename T::RawValueTag());
}
static inline T getFromVoidPointer(const void *P) {
- return T(reinterpret_cast<uintptr_t>(P));
+ return T(reinterpret_cast<uintptr_t>(P), typename T::RawValueTag());
}
enum { NumLowBitsAvailable = T::Shift };
diff --git a/include/llvm/ADT/PostOrderIterator.h b/include/llvm/ADT/PostOrderIterator.h
index ce343a161b7b..0cc504b5c39e 100644
--- a/include/llvm/ADT/PostOrderIterator.h
+++ b/include/llvm/ADT/PostOrderIterator.h
@@ -28,7 +28,7 @@ namespace llvm {
// visited nodes during the po_iterator's depth-first traversal.
//
// The default implementation simply contains a set of visited nodes, while
-// the Extended=true version uses a reference to an external set.
+// the External=true version uses a reference to an external set.
//
// It is possible to prune the depth-first traversal in several ways:
//
diff --git a/include/llvm/ADT/PriorityWorklist.h b/include/llvm/ADT/PriorityWorklist.h
new file mode 100644
index 000000000000..00549b88fd02
--- /dev/null
+++ b/include/llvm/ADT/PriorityWorklist.h
@@ -0,0 +1,224 @@
+//===- PriorityWorklist.h - Worklist with insertion priority ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+///
+/// This file provides a priority worklist. See the class comments for details.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_PRIORITYWORKLIST_H
+#define LLVM_ADT_PRIORITYWORKLIST_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include <algorithm>
+#include <cassert>
+#include <utility>
+#include <vector>
+
+namespace llvm {
+
+/// A FILO worklist that prioritizes on re-insertion without duplication.
+///
+/// This is very similar to a \c SetVector with the primary difference that
+/// while re-insertion does not create a duplicate, it does adjust the
+/// visitation order to respect the last insertion point. This can be useful
+/// when the visit order needs to be prioritized based on insertion point
+/// without actually having duplicate visits.
+///
+/// Note that this doesn't prevent re-insertion of elements which have been
+/// visited -- if you need to break cycles, a set will still be necessary.
+///
+/// The type \c T must be default constructable to a null value that will be
+/// ignored. It is an error to insert such a value, and popping elements will
+/// never produce such a value. It is expected to be used with common nullable
+/// types like pointers or optionals.
+///
+/// Internally this uses a vector to store the worklist and a map to identify
+/// existing elements in the worklist. Both of these may be customized, but the
+/// map must support the basic DenseMap API for mapping from a T to an integer
+/// index into the vector.
+///
+/// A partial specialization is provided to automatically select a SmallVector
+/// and a SmallDenseMap if custom data structures are not provided.
+template <typename T, typename VectorT = std::vector<T>,
+ typename MapT = DenseMap<T, ptrdiff_t>>
+class PriorityWorklist {
+public:
+ typedef T value_type;
+ typedef T key_type;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef typename MapT::size_type size_type;
+
+ /// Construct an empty PriorityWorklist
+ PriorityWorklist() {}
+
+ /// Determine if the PriorityWorklist is empty or not.
+ bool empty() const {
+ return V.empty();
+ }
+
+ /// Returns the number of elements in the worklist.
+ size_type size() const {
+ return M.size();
+ }
+
+ /// Count the number of elements of a given key in the PriorityWorklist.
+ /// \returns 0 if the element is not in the PriorityWorklist, 1 if it is.
+ size_type count(const key_type &key) const {
+ return M.count(key);
+ }
+
+ /// Return the last element of the PriorityWorklist.
+ const T &back() const {
+ assert(!empty() && "Cannot call back() on empty PriorityWorklist!");
+ return V.back();
+ }
+
+ /// Insert a new element into the PriorityWorklist.
+ /// \returns true if the element was inserted into the PriorityWorklist.
+ bool insert(const T &X) {
+ assert(X != T() && "Cannot insert a null (default constructed) value!");
+ auto InsertResult = M.insert({X, V.size()});
+ if (InsertResult.second) {
+ // Fresh value, just append it to the vector.
+ V.push_back(X);
+ return true;
+ }
+
+ auto &Index = InsertResult.first->second;
+ assert(V[Index] == X && "Value not actually at index in map!");
+ if (Index != (ptrdiff_t)(V.size() - 1)) {
+ // If the element isn't at the back, null it out and append a fresh one.
+ V[Index] = T();
+ Index = (ptrdiff_t)V.size();
+ V.push_back(X);
+ }
+ return false;
+ }
+
+ /// Remove the last element of the PriorityWorklist.
+ void pop_back() {
+ assert(!empty() && "Cannot remove an element when empty!");
+ assert(back() != T() && "Cannot have a null element at the back!");
+ M.erase(back());
+ do {
+ V.pop_back();
+ } while (!V.empty() && V.back() == T());
+ }
+
+ T LLVM_ATTRIBUTE_UNUSED_RESULT pop_back_val() {
+ T Ret = back();
+ pop_back();
+ return Ret;
+ }
+
+ /// Erase an item from the worklist.
+ ///
+ /// Note that this is constant time due to the nature of the worklist implementation.
+ bool erase(const T& X) {
+ auto I = M.find(X);
+ if (I == M.end())
+ return false;
+
+ assert(V[I->second] == X && "Value not actually at index in map!");
+ if (I->second == (ptrdiff_t)(V.size() - 1)) {
+ do {
+ V.pop_back();
+ } while (!V.empty() && V.back() == T());
+ } else {
+ V[I->second] = T();
+ }
+ M.erase(I);
+ return true;
+ }
+
+ /// Erase items from the set vector based on a predicate function.
+ ///
+ /// This is intended to be equivalent to the following code, if we could
+ /// write it:
+ ///
+ /// \code
+ /// V.erase(std::remove_if(V.begin(), V.end(), P), V.end());
+ /// \endcode
+ ///
+ /// However, PriorityWorklist doesn't expose non-const iterators, making any
+ /// algorithm like remove_if impossible to use.
+ ///
+ /// \returns true if any element is removed.
+ template <typename UnaryPredicate>
+ bool erase_if(UnaryPredicate P) {
+ typename VectorT::iterator E = std::remove_if(
+ V.begin(), V.end(), TestAndEraseFromMap<UnaryPredicate>(P, M));
+ if (E == V.end())
+ return false;
+ for (auto I = V.begin(); I != E; ++I)
+ if (*I != T())
+ M[*I] = I - V.begin();
+ V.erase(E, V.end());
+ return true;
+ }
+
+ /// Completely clear the PriorityWorklist
+ void clear() {
+ M.clear();
+ V.clear();
+ }
+
+private:
+ /// A wrapper predicate designed for use with std::remove_if.
+ ///
+ /// This predicate wraps a predicate suitable for use with std::remove_if to
+ /// call M.erase(x) on each element which is slated for removal. This just
+ /// allows the predicate to be move only which we can't do with lambdas
+ /// today.
+ template <typename UnaryPredicateT>
+ class TestAndEraseFromMap {
+ UnaryPredicateT P;
+ MapT &M;
+
+ public:
+ TestAndEraseFromMap(UnaryPredicateT P, MapT &M)
+ : P(std::move(P)), M(M) {}
+
+ bool operator()(const T &Arg) {
+ if (Arg == T())
+ // Skip null values in the PriorityWorklist.
+ return false;
+
+ if (P(Arg)) {
+ M.erase(Arg);
+ return true;
+ }
+ return false;
+ }
+ };
+
+ /// The map from value to index in the vector.
+ MapT M;
+
+ /// The vector of elements in insertion order.
+ VectorT V;
+};
+
+/// A version of \c PriorityWorklist that selects small size optimized data
+/// structures for the vector and map.
+template <typename T, unsigned N>
+class SmallPriorityWorklist
+ : public PriorityWorklist<T, SmallVector<T, N>,
+ SmallDenseMap<T, ptrdiff_t>> {
+public:
+ SmallPriorityWorklist() {}
+};
+
+}
+
+#endif
diff --git a/include/llvm/ADT/STLExtras.h b/include/llvm/ADT/STLExtras.h
index d4360fa8d218..abd39dacc671 100644
--- a/include/llvm/ADT/STLExtras.h
+++ b/include/llvm/ADT/STLExtras.h
@@ -17,7 +17,6 @@
#ifndef LLVM_ADT_STLEXTRAS_H
#define LLVM_ADT_STLEXTRAS_H
-#include "llvm/Support/Compiler.h"
#include <algorithm> // for std::all_of
#include <cassert>
#include <cstddef> // for std::size_t
@@ -27,6 +26,9 @@
#include <memory>
#include <utility> // for std::pair
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Compiler.h"
+
namespace llvm {
//===----------------------------------------------------------------------===//
@@ -117,7 +119,9 @@ public:
iterator_category;
typedef typename std::iterator_traits<RootIt>::difference_type
difference_type;
- typedef typename UnaryFunc::result_type value_type;
+ typedef typename std::result_of<
+ UnaryFunc(decltype(*std::declval<RootIt>()))>
+ ::type value_type;
typedef void pointer;
//typedef typename UnaryFunc::result_type *pointer;
@@ -379,6 +383,14 @@ bool any_of(R &&Range, UnaryPredicate &&P) {
std::forward<UnaryPredicate>(P));
}
+/// Provide wrappers to std::none_of which take ranges instead of having to pass
+/// begin/end explicitly.
+template <typename R, class UnaryPredicate>
+bool none_of(R &&Range, UnaryPredicate &&P) {
+ return std::none_of(Range.begin(), Range.end(),
+ std::forward<UnaryPredicate>(P));
+}
+
/// Provide wrappers to std::find which take ranges instead of having to pass
/// begin/end explicitly.
template<typename R, class T>
@@ -386,6 +398,43 @@ auto find(R &&Range, const T &val) -> decltype(Range.begin()) {
return std::find(Range.begin(), Range.end(), val);
}
+/// Provide wrappers to std::find_if which take ranges instead of having to pass
+/// begin/end explicitly.
+template <typename R, class T>
+auto find_if(R &&Range, const T &Pred) -> decltype(Range.begin()) {
+ return std::find_if(Range.begin(), Range.end(), Pred);
+}
+
+/// Provide wrappers to std::remove_if which take ranges instead of having to
+/// pass begin/end explicitly.
+template<typename R, class UnaryPredicate>
+auto remove_if(R &&Range, UnaryPredicate &&P) -> decltype(Range.begin()) {
+ return std::remove_if(Range.begin(), Range.end(), P);
+}
+
+/// Wrapper function around std::find to detect if an element exists
+/// in a container.
+template <typename R, typename E>
+bool is_contained(R &&Range, const E &Element) {
+ return std::find(Range.begin(), Range.end(), Element) != Range.end();
+}
+
+/// Wrapper function around std::count_if to count the number of times an
+/// element satisfying a given predicate occurs in a range.
+template <typename R, typename UnaryPredicate>
+auto count_if(R &&Range, UnaryPredicate &&P)
+ -> typename std::iterator_traits<decltype(Range.begin())>::difference_type {
+ return std::count_if(Range.begin(), Range.end(), P);
+}
+
+/// Wrapper function around std::transform to apply a function to a range and
+/// store the result elsewhere.
+template <typename R, class OutputIt, typename UnaryPredicate>
+OutputIt transform(R &&Range, OutputIt d_first, UnaryPredicate &&P) {
+ return std::transform(Range.begin(), Range.end(), d_first,
+ std::forward<UnaryPredicate>(P));
+}
+
//===----------------------------------------------------------------------===//
// Extra additions to <memory>
//===----------------------------------------------------------------------===//
diff --git a/include/llvm/ADT/Sequence.h b/include/llvm/ADT/Sequence.h
new file mode 100644
index 000000000000..5d36831cc128
--- /dev/null
+++ b/include/llvm/ADT/Sequence.h
@@ -0,0 +1,79 @@
+//===- Sequence.h - Utility for producing sequences of values ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This routine provides some synthesis utilities to produce sequences of
+/// values. The names are intentionally kept very short as they tend to occur
+/// in common and widely used contexts.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_SEQ_H
+#define LLVM_ADT_SEQ_H
+
+#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/iterator_range.h"
+
+namespace llvm {
+
+namespace detail {
+template <typename ValueT>
+class value_sequence_iterator
+ : public iterator_facade_base<value_sequence_iterator<ValueT>,
+ std::random_access_iterator_tag,
+ const ValueT> {
+ typedef typename value_sequence_iterator::iterator_facade_base BaseT;
+
+ ValueT Value;
+
+public:
+ typedef typename BaseT::difference_type difference_type;
+ typedef typename BaseT::reference reference;
+
+ value_sequence_iterator() = default;
+ value_sequence_iterator(const value_sequence_iterator &) = default;
+ value_sequence_iterator(value_sequence_iterator &&Arg)
+ : Value(std::move(Arg.Value)) {}
+
+ template <typename U, typename Enabler = decltype(ValueT(std::declval<U>()))>
+ value_sequence_iterator(U &&Value) : Value(std::forward<U>(Value)) {}
+
+ value_sequence_iterator &operator+=(difference_type N) {
+ Value += N;
+ return *this;
+ }
+ value_sequence_iterator &operator-=(difference_type N) {
+ Value -= N;
+ return *this;
+ }
+ using BaseT::operator-;
+ difference_type operator-(const value_sequence_iterator &RHS) const {
+ return Value - RHS.Value;
+ }
+
+ bool operator==(const value_sequence_iterator &RHS) const {
+ return Value == RHS.Value;
+ }
+ bool operator<(const value_sequence_iterator &RHS) const {
+ return Value < RHS.Value;
+ }
+
+ reference operator*() const { return Value; }
+};
+} // End detail namespace.
+
+template <typename ValueT>
+iterator_range<detail::value_sequence_iterator<ValueT>> seq(ValueT Begin,
+ ValueT End) {
+ return make_range(detail::value_sequence_iterator<ValueT>(Begin),
+ detail::value_sequence_iterator<ValueT>(End));
+}
+
+}
+
+#endif
diff --git a/include/llvm/ADT/SetVector.h b/include/llvm/ADT/SetVector.h
index bc563570c203..2bb0fdbd3370 100644
--- a/include/llvm/ADT/SetVector.h
+++ b/include/llvm/ADT/SetVector.h
@@ -24,6 +24,7 @@
#include "llvm/ADT/SmallSet.h"
#include <algorithm>
#include <cassert>
+#include <utility>
#include <vector>
namespace llvm {
@@ -123,7 +124,7 @@ public:
}
/// \brief Insert a new element into the SetVector.
- /// \returns true iff the element was inserted into the SetVector.
+ /// \returns true if the element was inserted into the SetVector.
bool insert(const value_type &X) {
bool result = set_.insert(X).second;
if (result)
@@ -151,6 +152,24 @@ public:
return false;
}
+ /// Erase a single element from the set vector.
+ /// \returns an iterator pointing to the next element that followed the
+ /// element erased. This is the end of the SetVector if the last element is
+ /// erased.
+ iterator erase(iterator I) {
+ const key_type &V = *I;
+ assert(set_.count(V) && "Corrupted SetVector instances!");
+ set_.erase(V);
+
+ // FIXME: No need to use the non-const iterator when built with
+ // std:vector.erase(const_iterator) as defined in C++11. This is for
+ // compatibility with non-standard libstdc++ up to 4.8 (fixed in 4.9).
+ auto NI = vector_.begin();
+ std::advance(NI, std::distance<iterator>(NI, I));
+
+ return vector_.erase(NI);
+ }
+
/// \brief Remove items from the set vector based on a predicate function.
///
/// This is intended to be equivalent to the following code, if we could
@@ -207,6 +226,31 @@ public:
bool operator!=(const SetVector &that) const {
return vector_ != that.vector_;
}
+
+ /// \brief Compute This := This u S, return whether 'This' changed.
+ /// TODO: We should be able to use set_union from SetOperations.h, but
+ /// SetVector interface is inconsistent with DenseSet.
+ template <class STy>
+ bool set_union(const STy &S) {
+ bool Changed = false;
+
+ for (typename STy::const_iterator SI = S.begin(), SE = S.end(); SI != SE;
+ ++SI)
+ if (insert(*SI))
+ Changed = true;
+
+ return Changed;
+ }
+
+ /// \brief Compute This := This - B
+ /// TODO: We should be able to use set_subtract from SetOperations.h, but
+ /// SetVector interface is inconsistent with DenseSet.
+ template <class STy>
+ void set_subtract(const STy &S) {
+ for (typename STy::const_iterator SI = S.begin(), SE = S.end(); SI != SE;
+ ++SI)
+ remove(*SI);
+ }
private:
/// \brief A wrapper predicate designed for use with std::remove_if.
@@ -219,7 +263,8 @@ private:
set_type &set_;
public:
- TestAndEraseFromSet(UnaryPredicate P, set_type &set_) : P(P), set_(set_) {}
+ TestAndEraseFromSet(UnaryPredicate P, set_type &set_)
+ : P(std::move(P)), set_(set_) {}
template <typename ArgumentT>
bool operator()(const ArgumentT &Arg) {
diff --git a/include/llvm/ADT/SmallBitVector.h b/include/llvm/ADT/SmallBitVector.h
index 4aa3bc217f41..bb99e0cf221f 100644
--- a/include/llvm/ADT/SmallBitVector.h
+++ b/include/llvm/ADT/SmallBitVector.h
@@ -15,19 +15,16 @@
#define LLVM_ADT_SMALLBITVECTOR_H
#include "llvm/ADT/BitVector.h"
-#include "llvm/Support/Compiler.h"
#include "llvm/Support/MathExtras.h"
#include <cassert>
namespace llvm {
-/// SmallBitVector - This is a 'bitvector' (really, a variable-sized bit array),
-/// optimized for the case when the array is small. It contains one
-/// pointer-sized field, which is directly used as a plain collection of bits
-/// when possible, or as a pointer to a larger heap-allocated array when
-/// necessary. This allows normal "small" cases to be fast without losing
-/// generality for large inputs.
-///
+/// This is a 'bitvector' (really, a variable-sized bit array), optimized for
+/// the case when the array is small. It contains one pointer-sized field, which
+/// is directly used as a plain collection of bits when possible, or as a
+/// pointer to a larger heap-allocated array when necessary. This allows normal
+/// "small" cases to be fast without losing generality for large inputs.
class SmallBitVector {
// TODO: In "large" mode, a pointer to a BitVector is used, leading to an
// unnecessary level of indirection. It would be more efficient to use a
@@ -139,11 +136,11 @@ private:
}
public:
- /// SmallBitVector default ctor - Creates an empty bitvector.
+ /// Creates an empty bitvector.
SmallBitVector() : X(1) {}
- /// SmallBitVector ctor - Creates a bitvector of specified number of bits. All
- /// bits are initialized to the specified value.
+ /// Creates a bitvector of specified number of bits. All bits are initialized
+ /// to the specified value.
explicit SmallBitVector(unsigned s, bool t = false) {
if (s <= SmallNumDataBits)
switchToSmall(t ? ~uintptr_t(0) : 0, s);
@@ -168,17 +165,17 @@ public:
delete getPointer();
}
- /// empty - Tests whether there are no bits in this bitvector.
+ /// Tests whether there are no bits in this bitvector.
bool empty() const {
return isSmall() ? getSmallSize() == 0 : getPointer()->empty();
}
- /// size - Returns the number of bits in this bitvector.
+ /// Returns the number of bits in this bitvector.
size_t size() const {
return isSmall() ? getSmallSize() : getPointer()->size();
}
- /// count - Returns the number of bits which are set.
+ /// Returns the number of bits which are set.
size_type count() const {
if (isSmall()) {
uintptr_t Bits = getSmallBits();
@@ -187,29 +184,28 @@ public:
return getPointer()->count();
}
- /// any - Returns true if any bit is set.
+ /// Returns true if any bit is set.
bool any() const {
if (isSmall())
return getSmallBits() != 0;
return getPointer()->any();
}
- /// all - Returns true if all bits are set.
+ /// Returns true if all bits are set.
bool all() const {
if (isSmall())
return getSmallBits() == (uintptr_t(1) << getSmallSize()) - 1;
return getPointer()->all();
}
- /// none - Returns true if none of the bits are set.
+ /// Returns true if none of the bits are set.
bool none() const {
if (isSmall())
return getSmallBits() == 0;
return getPointer()->none();
}
- /// find_first - Returns the index of the first set bit, -1 if none
- /// of the bits are set.
+ /// Returns the index of the first set bit, -1 if none of the bits are set.
int find_first() const {
if (isSmall()) {
uintptr_t Bits = getSmallBits();
@@ -220,8 +216,8 @@ public:
return getPointer()->find_first();
}
- /// find_next - Returns the index of the next set bit following the
- /// "Prev" bit. Returns -1 if the next set bit is not found.
+ /// Returns the index of the next set bit following the "Prev" bit.
+ /// Returns -1 if the next set bit is not found.
int find_next(unsigned Prev) const {
if (isSmall()) {
uintptr_t Bits = getSmallBits();
@@ -234,14 +230,14 @@ public:
return getPointer()->find_next(Prev);
}
- /// clear - Clear all bits.
+ /// Clear all bits.
void clear() {
if (!isSmall())
delete getPointer();
switchToSmall(0, 0);
}
- /// resize - Grow or shrink the bitvector.
+ /// Grow or shrink the bitvector.
void resize(unsigned N, bool t = false) {
if (!isSmall()) {
getPointer()->resize(N, t);
@@ -296,7 +292,7 @@ public:
return *this;
}
- /// set - Efficiently set a range of bits in [I, E)
+ /// Efficiently set a range of bits in [I, E)
SmallBitVector &set(unsigned I, unsigned E) {
assert(I <= E && "Attempted to set backwards range!");
assert(E <= size() && "Attempted to set out-of-bounds range!");
@@ -327,7 +323,7 @@ public:
return *this;
}
- /// reset - Efficiently reset a range of bits in [I, E)
+ /// Efficiently reset a range of bits in [I, E)
SmallBitVector &reset(unsigned I, unsigned E) {
assert(I <= E && "Attempted to reset backwards range!");
assert(E <= size() && "Attempted to reset out-of-bounds range!");
@@ -422,7 +418,7 @@ public:
return *this;
}
- /// reset - Reset bits that are set in RHS. Same as *this &= ~RHS.
+ /// Reset bits that are set in RHS. Same as *this &= ~RHS.
SmallBitVector &reset(const SmallBitVector &RHS) {
if (isSmall() && RHS.isSmall())
setSmallBits(getSmallBits() & ~RHS.getSmallBits());
@@ -436,8 +432,7 @@ public:
return *this;
}
- /// test - Check if (This - RHS) is zero.
- /// This is the same as reset(RHS) and any().
+ /// Check if (This - RHS) is zero. This is the same as reset(RHS) and any().
bool test(const SmallBitVector &RHS) const {
if (isSmall() && RHS.isSmall())
return (getSmallBits() & ~RHS.getSmallBits()) != 0;
@@ -514,7 +509,7 @@ public:
std::swap(X, RHS.X);
}
- /// setBitsInMask - Add '1' bits from Mask to this vector. Don't resize.
+ /// Add '1' bits from Mask to this vector. Don't resize.
/// This computes "*this |= Mask".
void setBitsInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
if (isSmall())
@@ -523,8 +518,8 @@ public:
getPointer()->setBitsInMask(Mask, MaskWords);
}
- /// clearBitsInMask - Clear any bits in this vector that are set in Mask.
- /// Don't resize. This computes "*this &= ~Mask".
+ /// Clear any bits in this vector that are set in Mask. Don't resize.
+ /// This computes "*this &= ~Mask".
void clearBitsInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
if (isSmall())
applyMask<false, false>(Mask, MaskWords);
@@ -532,8 +527,8 @@ public:
getPointer()->clearBitsInMask(Mask, MaskWords);
}
- /// setBitsNotInMask - Add a bit to this vector for every '0' bit in Mask.
- /// Don't resize. This computes "*this |= ~Mask".
+ /// Add a bit to this vector for every '0' bit in Mask. Don't resize.
+ /// This computes "*this |= ~Mask".
void setBitsNotInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
if (isSmall())
applyMask<true, true>(Mask, MaskWords);
@@ -541,8 +536,8 @@ public:
getPointer()->setBitsNotInMask(Mask, MaskWords);
}
- /// clearBitsNotInMask - Clear a bit in this vector for every '0' bit in Mask.
- /// Don't resize. This computes "*this &= Mask".
+ /// Clear a bit in this vector for every '0' bit in Mask. Don't resize.
+ /// This computes "*this &= Mask".
void clearBitsNotInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
if (isSmall())
applyMask<false, true>(Mask, MaskWords);
diff --git a/include/llvm/ADT/SmallPtrSet.h b/include/llvm/ADT/SmallPtrSet.h
index 3d98e8fac43b..eaed6aa05dcb 100644
--- a/include/llvm/ADT/SmallPtrSet.h
+++ b/include/llvm/ADT/SmallPtrSet.h
@@ -21,6 +21,7 @@
#include <cassert>
#include <cstddef>
#include <cstring>
+#include <cstdlib>
#include <iterator>
#include <utility>
@@ -58,36 +59,45 @@ protected:
/// CurArraySize - The allocated size of CurArray, always a power of two.
unsigned CurArraySize;
- // If small, this is # elts allocated consecutively
- unsigned NumElements;
+ /// Number of elements in CurArray that contain a value or are a tombstone.
+ /// If small, all these elements are at the beginning of CurArray and the rest
+ /// is uninitialized.
+ unsigned NumNonEmpty;
+ /// Number of tombstones in CurArray.
unsigned NumTombstones;
// Helpers to copy and move construct a SmallPtrSet.
- SmallPtrSetImplBase(const void **SmallStorage, const SmallPtrSetImplBase &that);
+ SmallPtrSetImplBase(const void **SmallStorage,
+ const SmallPtrSetImplBase &that);
SmallPtrSetImplBase(const void **SmallStorage, unsigned SmallSize,
- SmallPtrSetImplBase &&that);
- explicit SmallPtrSetImplBase(const void **SmallStorage, unsigned SmallSize) :
- SmallArray(SmallStorage), CurArray(SmallStorage), CurArraySize(SmallSize) {
+ SmallPtrSetImplBase &&that);
+ explicit SmallPtrSetImplBase(const void **SmallStorage, unsigned SmallSize)
+ : SmallArray(SmallStorage), CurArray(SmallStorage),
+ CurArraySize(SmallSize), NumNonEmpty(0), NumTombstones(0) {
assert(SmallSize && (SmallSize & (SmallSize-1)) == 0 &&
"Initial size must be a power of two!");
- clear();
}
- ~SmallPtrSetImplBase();
+ ~SmallPtrSetImplBase() {
+ if (!isSmall())
+ free(CurArray);
+ }
public:
typedef unsigned size_type;
bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { return size() == 0; }
- size_type size() const { return NumElements; }
+ size_type size() const { return NumNonEmpty - NumTombstones; }
void clear() {
// If the capacity of the array is huge, and the # elements used is small,
// shrink the array.
- if (!isSmall() && NumElements*4 < CurArraySize && CurArraySize > 32)
- return shrink_and_clear();
+ if (!isSmall()) {
+ if (size() * 4 < CurArraySize && CurArraySize > 32)
+ return shrink_and_clear();
+ // Fill the array with empty markers.
+ memset(CurArray, -1, CurArraySize * sizeof(void *));
+ }
- // Fill the array with empty markers.
- memset(CurArray, -1, CurArraySize*sizeof(void*));
- NumElements = 0;
+ NumNonEmpty = 0;
NumTombstones = 0;
}
@@ -99,10 +109,42 @@ protected:
return reinterpret_cast<void*>(-1);
}
+ const void **EndPointer() const {
+ return isSmall() ? CurArray + NumNonEmpty : CurArray + CurArraySize;
+ }
+
/// insert_imp - This returns true if the pointer was new to the set, false if
/// it was already in the set. This is hidden from the client so that the
/// derived class can check that the right type of pointer is passed in.
- std::pair<const void *const *, bool> insert_imp(const void *Ptr);
+ std::pair<const void *const *, bool> insert_imp(const void *Ptr) {
+ if (isSmall()) {
+ // Check to see if it is already in the set.
+ const void **LastTombstone = nullptr;
+ for (const void **APtr = SmallArray, **E = SmallArray + NumNonEmpty;
+ APtr != E; ++APtr) {
+ const void *Value = *APtr;
+ if (Value == Ptr)
+ return std::make_pair(APtr, false);
+ if (Value == getTombstoneMarker())
+ LastTombstone = APtr;
+ }
+
+ // Did we find any tombstone marker?
+ if (LastTombstone != nullptr) {
+ *LastTombstone = Ptr;
+ --NumTombstones;
+ return std::make_pair(LastTombstone, true);
+ }
+
+ // Nope, there isn't. If we stay small, just 'pushback' now.
+ if (NumNonEmpty < CurArraySize) {
+ SmallArray[NumNonEmpty++] = Ptr;
+ return std::make_pair(SmallArray + (NumNonEmpty - 1), true);
+ }
+ // Otherwise, hit the big set case, which will call grow.
+ }
+ return insert_imp_big(Ptr);
+ }
/// erase_imp - If the set contains the specified pointer, remove it and
/// return true, otherwise return false. This is hidden from the client so
@@ -114,7 +156,7 @@ protected:
if (isSmall()) {
// Linear search for the item.
for (const void *const *APtr = SmallArray,
- *const *E = SmallArray+NumElements; APtr != E; ++APtr)
+ *const *E = SmallArray + NumNonEmpty; APtr != E; ++APtr)
if (*APtr == Ptr)
return true;
return false;
@@ -127,6 +169,8 @@ protected:
private:
bool isSmall() const { return CurArray == SmallArray; }
+ std::pair<const void *const *, bool> insert_imp_big(const void *Ptr);
+
const void * const *FindBucketFor(const void *Ptr) const;
void shrink_and_clear();
@@ -142,6 +186,12 @@ protected:
void CopyFrom(const SmallPtrSetImplBase &RHS);
void MoveFrom(unsigned SmallSize, SmallPtrSetImplBase &&RHS);
+
+private:
+ /// Code shared by MoveFrom() and move constructor.
+ void MoveHelper(unsigned SmallSize, SmallPtrSetImplBase &&RHS);
+ /// Code shared by CopyFrom() and copy constructor.
+ void CopyHelper(const SmallPtrSetImplBase &RHS);
};
/// SmallPtrSetIteratorImpl - This is the common base class shared between all
@@ -154,7 +204,7 @@ protected:
public:
explicit SmallPtrSetIteratorImpl(const void *const *BP, const void*const *E)
: Bucket(BP), End(E) {
- AdvanceIfNotValid();
+ AdvanceIfNotValid();
}
bool operator==(const SmallPtrSetIteratorImpl &RHS) const {
@@ -266,7 +316,7 @@ public:
/// the element equal to Ptr.
std::pair<iterator, bool> insert(PtrType Ptr) {
auto p = insert_imp(PtrTraits::getAsVoidPointer(Ptr));
- return std::make_pair(iterator(p.first, CurArray + CurArraySize), p.second);
+ return std::make_pair(iterator(p.first, EndPointer()), p.second);
}
/// erase - If the set contains the specified pointer, remove it and return
@@ -287,10 +337,11 @@ public:
}
inline iterator begin() const {
- return iterator(CurArray, CurArray+CurArraySize);
+ return iterator(CurArray, EndPointer());
}
inline iterator end() const {
- return iterator(CurArray+CurArraySize, CurArray+CurArraySize);
+ const void *const *End = EndPointer();
+ return iterator(End, End);
}
};
@@ -300,6 +351,11 @@ public:
/// SmallPtrSetImplBase for details of the algorithm.
template<class PtrType, unsigned SmallSize>
class SmallPtrSet : public SmallPtrSetImpl<PtrType> {
+ // In small mode SmallPtrSet uses linear search for the elements, so it is
+ // not a good idea to choose this value too high. You may consider using a
+ // DenseSet<> instead if you expect many elements in the set.
+ static_assert(SmallSize <= 32, "SmallSize should be small");
+
typedef SmallPtrSetImpl<PtrType> BaseT;
// Make sure that SmallSize is a power of two, round up if not.
diff --git a/include/llvm/ADT/SmallSet.h b/include/llvm/ADT/SmallSet.h
index 39a57b87b2a7..aaa5ff0ae939 100644
--- a/include/llvm/ADT/SmallSet.h
+++ b/include/llvm/ADT/SmallSet.h
@@ -38,6 +38,11 @@ class SmallSet {
typedef typename SmallVector<T, N>::const_iterator VIterator;
typedef typename SmallVector<T, N>::iterator mutable_iterator;
+ // In small mode SmallPtrSet uses linear search for the elements, so it is
+ // not a good idea to choose this value too high. You may consider using a
+ // DenseSet<> instead if you expect many elements in the set.
+ static_assert(N <= 32, "N should be small");
+
public:
typedef size_t size_type;
SmallSet() {}
diff --git a/include/llvm/ADT/SmallVector.h b/include/llvm/ADT/SmallVector.h
index d1062acbbb61..42eedc63e079 100644
--- a/include/llvm/ADT/SmallVector.h
+++ b/include/llvm/ADT/SmallVector.h
@@ -184,33 +184,12 @@ protected:
}
}
- /// Use move-assignment to move the range [I, E) onto the
- /// objects starting with "Dest". This is just <memory>'s
- /// std::move, but not all stdlibs actually provide that.
- template<typename It1, typename It2>
- static It2 move(It1 I, It1 E, It2 Dest) {
- for (; I != E; ++I, ++Dest)
- *Dest = ::std::move(*I);
- return Dest;
- }
-
- /// Use move-assignment to move the range
- /// [I, E) onto the objects ending at "Dest", moving objects
- /// in reverse order. This is just <algorithm>'s
- /// std::move_backward, but not all stdlibs actually provide that.
- template<typename It1, typename It2>
- static It2 move_backward(It1 I, It1 E, It2 Dest) {
- while (I != E)
- *--Dest = ::std::move(*--E);
- return Dest;
- }
-
/// Move the range [I, E) into the uninitialized memory starting with "Dest",
/// constructing elements as needed.
template<typename It1, typename It2>
static void uninitialized_move(It1 I, It1 E, It2 Dest) {
- for (; I != E; ++I, ++Dest)
- ::new ((void*) &*Dest) T(::std::move(*I));
+ std::uninitialized_copy(std::make_move_iterator(I),
+ std::make_move_iterator(E), Dest);
}
/// Copy the range [I, E) onto the uninitialized memory starting with "Dest",
@@ -283,20 +262,6 @@ protected:
// No need to do a destroy loop for POD's.
static void destroy_range(T *, T *) {}
- /// Use move-assignment to move the range [I, E) onto the
- /// objects starting with "Dest". For PODs, this is just memcpy.
- template<typename It1, typename It2>
- static It2 move(It1 I, It1 E, It2 Dest) {
- return ::std::copy(I, E, Dest);
- }
-
- /// Use move-assignment to move the range [I, E) onto the objects ending at
- /// "Dest", moving objects in reverse order.
- template<typename It1, typename It2>
- static It2 move_backward(It1 I, It1 E, It2 Dest) {
- return ::std::copy_backward(I, E, Dest);
- }
-
/// Move the range [I, E) onto the uninitialized memory
/// starting with "Dest", constructing elements into it as needed.
template<typename It1, typename It2>
@@ -356,6 +321,7 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
SmallVectorImpl(const SmallVectorImpl&) = delete;
public:
typedef typename SuperClass::iterator iterator;
+ typedef typename SuperClass::const_iterator const_iterator;
typedef typename SuperClass::size_type size_type;
protected:
@@ -459,26 +425,33 @@ public:
append(IL);
}
- iterator erase(iterator I) {
+ iterator erase(const_iterator CI) {
+ // Just cast away constness because this is a non-const member function.
+ iterator I = const_cast<iterator>(CI);
+
assert(I >= this->begin() && "Iterator to erase is out of bounds.");
assert(I < this->end() && "Erasing at past-the-end iterator.");
iterator N = I;
// Shift all elts down one.
- this->move(I+1, this->end(), I);
+ std::move(I+1, this->end(), I);
// Drop the last elt.
this->pop_back();
return(N);
}
- iterator erase(iterator S, iterator E) {
+ iterator erase(const_iterator CS, const_iterator CE) {
+ // Just cast away constness because this is a non-const member function.
+ iterator S = const_cast<iterator>(CS);
+ iterator E = const_cast<iterator>(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.");
iterator N = S;
// Shift all elts down.
- iterator I = this->move(E, this->end(), S);
+ iterator I = std::move(E, this->end(), S);
// Drop the last elts.
this->destroy_range(I, this->end());
this->setEnd(I);
@@ -502,7 +475,7 @@ public:
::new ((void*) this->end()) T(::std::move(this->back()));
// Push everything else over.
- this->move_backward(I, this->end()-1, this->end());
+ std::move_backward(I, this->end()-1, this->end());
this->setEnd(this->end()+1);
// If we just moved the element we're inserting, be sure to update
@@ -531,7 +504,7 @@ public:
}
::new ((void*) this->end()) T(std::move(this->back()));
// Push everything else over.
- this->move_backward(I, this->end()-1, this->end());
+ std::move_backward(I, this->end()-1, this->end());
this->setEnd(this->end()+1);
// If we just moved the element we're inserting, be sure to update
@@ -572,7 +545,7 @@ public:
std::move_iterator<iterator>(this->end()));
// Copy the existing elements that get replaced.
- this->move_backward(I, OldEnd-NumToInsert, OldEnd);
+ std::move_backward(I, OldEnd-NumToInsert, OldEnd);
std::fill_n(I, NumToInsert, Elt);
return I;
@@ -626,7 +599,7 @@ public:
std::move_iterator<iterator>(this->end()));
// Copy the existing elements that get replaced.
- this->move_backward(I, OldEnd-NumToInsert, OldEnd);
+ std::move_backward(I, OldEnd-NumToInsert, OldEnd);
std::copy(From, To, I);
return I;
@@ -807,7 +780,7 @@ SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) {
// Assign common elements.
iterator NewEnd = this->begin();
if (RHSSize)
- NewEnd = this->move(RHS.begin(), RHS.end(), NewEnd);
+ NewEnd = std::move(RHS.begin(), RHS.end(), NewEnd);
// Destroy excess elements and trim the bounds.
this->destroy_range(NewEnd, this->end());
@@ -831,7 +804,7 @@ SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) {
this->grow(RHSSize);
} else if (CurSize) {
// Otherwise, use assignment for the already-constructed elements.
- this->move(RHS.begin(), RHS.begin()+CurSize, this->begin());
+ std::move(RHS.begin(), RHS.begin()+CurSize, this->begin());
}
// Move-construct the new elements in place.
diff --git a/include/llvm/ADT/SparseSet.h b/include/llvm/ADT/SparseSet.h
index a45d1c8d6b8a..5b6494d17129 100644
--- a/include/llvm/ADT/SparseSet.h
+++ b/include/llvm/ADT/SparseSet.h
@@ -263,6 +263,11 @@ public:
return *insert(ValueT(Key)).first;
}
+ ValueT pop_back_val() {
+ // Sparse does not need to be cleared, see find().
+ return Dense.pop_back_val();
+ }
+
/// erase - Erases an existing element identified by a valid iterator.
///
/// This invalidates all iterators, but erase() returns an iterator pointing
diff --git a/include/llvm/ADT/Statistic.h b/include/llvm/ADT/Statistic.h
index 7c84e3ef6b4d..32175fdc7c5c 100644
--- a/include/llvm/ADT/Statistic.h
+++ b/include/llvm/ADT/Statistic.h
@@ -27,7 +27,8 @@
#define LLVM_ADT_STATISTIC_H
#include "llvm/Support/Atomic.h"
-#include "llvm/Support/Valgrind.h"
+#include "llvm/Support/Compiler.h"
+#include <atomic>
#include <memory>
namespace llvm {
@@ -36,77 +37,66 @@ class raw_fd_ostream;
class Statistic {
public:
+ const char *DebugType;
const char *Name;
const char *Desc;
- volatile llvm::sys::cas_flag Value;
+ std::atomic<unsigned> Value;
bool Initialized;
- llvm::sys::cas_flag getValue() const { return Value; }
+ unsigned getValue() const { return Value.load(std::memory_order_relaxed); }
+ const char *getDebugType() const { return DebugType; }
const char *getName() const { return Name; }
const char *getDesc() const { return Desc; }
/// construct - This should only be called for non-global statistics.
- void construct(const char *name, const char *desc) {
- Name = name; Desc = desc;
- Value = 0; Initialized = false;
+ void construct(const char *debugtype, const char *name, const char *desc) {
+ DebugType = debugtype;
+ Name = name;
+ Desc = desc;
+ Value = 0;
+ Initialized = false;
}
// Allow use of this class as the value itself.
- operator unsigned() const { return Value; }
+ operator unsigned() const { return getValue(); }
#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
const Statistic &operator=(unsigned Val) {
- Value = Val;
+ Value.store(Val, std::memory_order_relaxed);
return init();
}
const Statistic &operator++() {
- // FIXME: This function and all those that follow carefully use an
- // atomic operation to update the value safely in the presence of
- // concurrent accesses, but not to read the return value, so the
- // return value is not thread safe.
- sys::AtomicIncrement(&Value);
+ Value.fetch_add(1, std::memory_order_relaxed);
return init();
}
unsigned operator++(int) {
init();
- unsigned OldValue = Value;
- sys::AtomicIncrement(&Value);
- return OldValue;
+ return Value.fetch_add(1, std::memory_order_relaxed);
}
const Statistic &operator--() {
- sys::AtomicDecrement(&Value);
+ Value.fetch_sub(1, std::memory_order_relaxed);
return init();
}
unsigned operator--(int) {
init();
- unsigned OldValue = Value;
- sys::AtomicDecrement(&Value);
- return OldValue;
+ return Value.fetch_sub(1, std::memory_order_relaxed);
}
- const Statistic &operator+=(const unsigned &V) {
- if (!V) return *this;
- sys::AtomicAdd(&Value, V);
- return init();
- }
-
- const Statistic &operator-=(const unsigned &V) {
- if (!V) return *this;
- sys::AtomicAdd(&Value, -V);
- return init();
- }
-
- const Statistic &operator*=(const unsigned &V) {
- sys::AtomicMul(&Value, V);
+ const Statistic &operator+=(unsigned V) {
+ if (V == 0)
+ return *this;
+ Value.fetch_add(V, std::memory_order_relaxed);
return init();
}
- const Statistic &operator/=(const unsigned &V) {
- sys::AtomicDiv(&Value, V);
+ const Statistic &operator-=(unsigned V) {
+ if (V == 0)
+ return *this;
+ Value.fetch_sub(V, std::memory_order_relaxed);
return init();
}
@@ -140,14 +130,6 @@ public:
return *this;
}
- const Statistic &operator*=(const unsigned &V) {
- return *this;
- }
-
- const Statistic &operator/=(const unsigned &V) {
- return *this;
- }
-
#endif // !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
protected:
@@ -163,8 +145,8 @@ protected:
// STATISTIC - A macro to make definition of statistics really simple. This
// automatically passes the DEBUG_TYPE of the file into the statistic.
-#define STATISTIC(VARNAME, DESC) \
- static llvm::Statistic VARNAME = { DEBUG_TYPE, DESC, 0, 0 }
+#define STATISTIC(VARNAME, DESC) \
+ static llvm::Statistic VARNAME = {DEBUG_TYPE, #VARNAME, DESC, {0}, 0}
/// \brief Enable the collection and printing of statistics.
void EnableStatistics();
@@ -181,6 +163,9 @@ void PrintStatistics();
/// \brief Print statistics to the given output stream.
void PrintStatistics(raw_ostream &OS);
-} // End llvm namespace
+/// Print statistics in JSON format.
+void PrintStatisticsJSON(raw_ostream &OS);
+
+} // end llvm namespace
-#endif
+#endif // LLVM_ADT_STATISTIC_H
diff --git a/include/llvm/ADT/StringExtras.h b/include/llvm/ADT/StringExtras.h
index 0992f5d4a549..bdbb4d3f5932 100644
--- a/include/llvm/ADT/StringExtras.h
+++ b/include/llvm/ADT/StringExtras.h
@@ -44,55 +44,40 @@ static inline unsigned hexDigitValue(char C) {
return -1U;
}
-/// utohex_buffer - Emit the specified number into the buffer specified by
-/// BufferEnd, returning a pointer to the start of the string. This can be used
-/// like this: (note that the buffer must be large enough to handle any number):
-/// char Buffer[40];
-/// printf("0x%s", utohex_buffer(X, Buffer+40));
-///
-/// This should only be used with unsigned types.
-///
-template<typename IntTy>
-static inline char *utohex_buffer(IntTy X, char *BufferEnd, bool LowerCase = false) {
- char *BufPtr = BufferEnd;
- *--BufPtr = 0; // Null terminate buffer.
- if (X == 0) {
- *--BufPtr = '0'; // Handle special case.
- return BufPtr;
- }
+static inline std::string utohexstr(uint64_t X, bool LowerCase = false) {
+ char Buffer[17];
+ char *BufPtr = std::end(Buffer);
+
+ if (X == 0) *--BufPtr = '0';
while (X) {
unsigned char Mod = static_cast<unsigned char>(X) & 15;
*--BufPtr = hexdigit(Mod, LowerCase);
X >>= 4;
}
- return BufPtr;
-}
-static inline std::string utohexstr(uint64_t X, bool LowerCase = false) {
- char Buffer[17];
- return utohex_buffer(X, Buffer+17, LowerCase);
+ return std::string(BufPtr, std::end(Buffer));
}
-static inline std::string utostr_32(uint32_t X, bool isNeg = false) {
- char Buffer[11];
- char *BufPtr = Buffer+11;
-
- if (X == 0) *--BufPtr = '0'; // Handle special case...
-
- while (X) {
- *--BufPtr = '0' + char(X % 10);
- X /= 10;
+/// Convert buffer \p Input to its hexadecimal representation.
+/// The returned string is double the size of \p Input.
+static inline std::string toHex(StringRef Input) {
+ static const char *const LUT = "0123456789ABCDEF";
+ size_t Length = Input.size();
+
+ std::string Output;
+ Output.reserve(2 * Length);
+ for (size_t i = 0; i < Length; ++i) {
+ const unsigned char c = Input[i];
+ Output.push_back(LUT[c >> 4]);
+ Output.push_back(LUT[c & 15]);
}
-
- if (isNeg) *--BufPtr = '-'; // Add negative sign...
-
- return std::string(BufPtr, Buffer+11);
+ return Output;
}
static inline std::string utostr(uint64_t X, bool isNeg = false) {
char Buffer[21];
- char *BufPtr = Buffer+21;
+ char *BufPtr = std::end(Buffer);
if (X == 0) *--BufPtr = '0'; // Handle special case...
@@ -102,7 +87,7 @@ static inline std::string utostr(uint64_t X, bool isNeg = false) {
}
if (isNeg) *--BufPtr = '-'; // Add negative sign...
- return std::string(BufPtr, Buffer+21);
+ return std::string(BufPtr, std::end(Buffer));
}
diff --git a/include/llvm/ADT/StringMap.h b/include/llvm/ADT/StringMap.h
index 700bb9e10ef7..260275295c99 100644
--- a/include/llvm/ADT/StringMap.h
+++ b/include/llvm/ADT/StringMap.h
@@ -16,6 +16,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
#include <cstring>
#include <utility>
@@ -88,12 +89,15 @@ protected:
/// table, returning it. If the key is not in the table, this returns null.
StringMapEntryBase *RemoveKey(StringRef Key);
-private:
+ /// Allocate the table with the specified number of buckets and otherwise
+ /// setup the map as empty.
void init(unsigned Size);
public:
static StringMapEntryBase *getTombstoneVal() {
- return (StringMapEntryBase*)-1;
+ uintptr_t Val = static_cast<uintptr_t>(-1);
+ Val <<= PointerLikeTypeTraits<StringMapEntryBase *>::NumLowBitsAvailable;
+ return reinterpret_cast<StringMapEntryBase *>(Val);
}
unsigned getNumBuckets() const { return NumBuckets; }
@@ -122,9 +126,9 @@ public:
explicit StringMapEntry(unsigned strLen)
: StringMapEntryBase(strLen), second() {}
- template <class InitTy>
- StringMapEntry(unsigned strLen, InitTy &&V)
- : StringMapEntryBase(strLen), second(std::forward<InitTy>(V)) {}
+ template <typename... InitTy>
+ StringMapEntry(unsigned strLen, InitTy &&... InitVals)
+ : StringMapEntryBase(strLen), second(std::forward<InitTy>(InitVals)...) {}
StringRef getKey() const {
return StringRef(getKeyData(), getKeyLength());
@@ -142,11 +146,11 @@ public:
StringRef first() const { return StringRef(getKeyData(), getKeyLength()); }
- /// Create - Create a StringMapEntry for the specified key and default
- /// construct the value.
- template <typename AllocatorTy, typename InitType>
+ /// Create a StringMapEntry for the specified key construct the value using
+ /// \p InitiVals.
+ template <typename AllocatorTy, typename... InitTy>
static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator,
- InitType &&InitVal) {
+ InitTy &&... InitVals) {
unsigned KeyLength = Key.size();
// Allocate a new item with space for the string at the end and a null
@@ -158,8 +162,8 @@ public:
StringMapEntry *NewItem =
static_cast<StringMapEntry*>(Allocator.Allocate(AllocSize,Alignment));
- // Default construct the value.
- new (NewItem) StringMapEntry(KeyLength, std::forward<InitType>(InitVal));
+ // Construct the value.
+ new (NewItem) StringMapEntry(KeyLength, std::forward<InitTy>(InitVals)...);
// Copy the string information.
char *StrBuffer = const_cast<char*>(NewItem->getKeyData());
@@ -169,16 +173,11 @@ public:
return NewItem;
}
- template<typename AllocatorTy>
- static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator) {
- return Create(Key, Allocator, ValueTy());
- }
-
/// Create - Create a StringMapEntry with normal malloc/free.
- template<typename InitType>
- static StringMapEntry *Create(StringRef Key, InitType &&InitVal) {
+ template <typename... InitType>
+ static StringMapEntry *Create(StringRef Key, InitType &&... InitVal) {
MallocAllocator A;
- return Create(Key, A, std::forward<InitType>(InitVal));
+ return Create(Key, A, std::forward<InitType>(InitVal)...);
}
static StringMapEntry *Create(StringRef Key) {
@@ -233,7 +232,7 @@ public:
Allocator(A) {}
StringMap(std::initializer_list<std::pair<StringRef, ValueTy>> List)
- : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) {
+ : StringMapImpl(List.size(), static_cast<unsigned>(sizeof(MapEntryTy))) {
for (const auto &P : List) {
insert(P);
}
@@ -248,7 +247,40 @@ public:
return *this;
}
- // FIXME: Implement copy operations if/when they're needed.
+ StringMap(const StringMap &RHS) :
+ StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))),
+ Allocator(RHS.Allocator) {
+ if (RHS.empty())
+ return;
+
+ // Allocate TheTable of the same size as RHS's TheTable, and set the
+ // sentinel appropriately (and NumBuckets).
+ init(RHS.NumBuckets);
+ unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1),
+ *RHSHashTable = (unsigned *)(RHS.TheTable + NumBuckets + 1);
+
+ NumItems = RHS.NumItems;
+ NumTombstones = RHS.NumTombstones;
+ for (unsigned I = 0, E = NumBuckets; I != E; ++I) {
+ StringMapEntryBase *Bucket = RHS.TheTable[I];
+ if (!Bucket || Bucket == getTombstoneVal()) {
+ TheTable[I] = Bucket;
+ continue;
+ }
+
+ TheTable[I] = MapEntryTy::Create(
+ static_cast<MapEntryTy *>(Bucket)->getKey(), Allocator,
+ static_cast<MapEntryTy *>(Bucket)->getValue());
+ HashTable[I] = RHSHashTable[I];
+ }
+
+ // Note that here we've copied everything from the RHS into this object,
+ // tombstones included. We could, instead, have re-probed for each key to
+ // instantiate this new object without any tombstone buckets. The
+ // assumption here is that items are rarely deleted from most StringMaps,
+ // and so tombstones are rare, so the cost of re-probing for all inputs is
+ // not worthwhile.
+ }
AllocatorTy &getAllocator() { return Allocator; }
const AllocatorTy &getAllocator() const { return Allocator; }
@@ -295,8 +327,10 @@ public:
return ValueTy();
}
+ /// Lookup the ValueTy for the \p Key, or create a default constructed value
+ /// if the key is not in the map.
ValueTy &operator[](StringRef Key) {
- return insert(std::make_pair(Key, ValueTy())).first->second;
+ return emplace_second(Key).first->second;
}
/// count - Return 1 if the element is in the map, 0 otherwise.
@@ -328,7 +362,16 @@ public:
/// if and only if the insertion takes place, and the iterator component of
/// the pair points to the element with key equivalent to the key of the pair.
std::pair<iterator, bool> insert(std::pair<StringRef, ValueTy> KV) {
- unsigned BucketNo = LookupBucketFor(KV.first);
+ return emplace_second(KV.first, std::move(KV.second));
+ }
+
+ /// Emplace a new element for the specified key into the map if the key isn't
+ /// already in the map. The bool component of the returned pair is true
+ /// if and only if the insertion takes place, and the iterator component of
+ /// the pair points to the element with key equivalent to the key of the pair.
+ template <typename... ArgsTy>
+ std::pair<iterator, bool> emplace_second(StringRef Key, ArgsTy &&... Args) {
+ unsigned BucketNo = LookupBucketFor(Key);
StringMapEntryBase *&Bucket = TheTable[BucketNo];
if (Bucket && Bucket != getTombstoneVal())
return std::make_pair(iterator(TheTable + BucketNo, false),
@@ -336,8 +379,7 @@ public:
if (Bucket == getTombstoneVal())
--NumTombstones;
- Bucket =
- MapEntryTy::Create(KV.first, Allocator, std::move(KV.second));
+ Bucket = MapEntryTy::Create(Key, Allocator, std::forward<ArgsTy>(Args)...);
++NumItems;
assert(NumItems + NumTombstones <= NumBuckets);
diff --git a/include/llvm/ADT/StringRef.h b/include/llvm/ADT/StringRef.h
index 350032b8c4e7..398ca6920249 100644
--- a/include/llvm/ADT/StringRef.h
+++ b/include/llvm/ADT/StringRef.h
@@ -10,6 +10,7 @@
#ifndef LLVM_ADT_STRINGREF_H
#define LLVM_ADT_STRINGREF_H
+#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Compiler.h"
#include <algorithm>
#include <cassert>
@@ -101,6 +102,9 @@ namespace llvm {
const unsigned char *bytes_end() const {
return reinterpret_cast<const unsigned char *>(end());
}
+ iterator_range<const unsigned char *> bytes() const {
+ return make_range(bytes_begin(), bytes_end());
+ }
/// @}
/// @name String Operations
@@ -133,6 +137,9 @@ namespace llvm {
// copy - Allocate copy in Allocator and return StringRef to it.
template <typename Allocator> StringRef copy(Allocator &A) const {
+ // Don't request a length 0 copy from the allocator.
+ if (empty())
+ return StringRef();
char *S = A.template Allocate<char>(Length);
std::copy(begin(), end(), S);
return StringRef(S, Length);
@@ -443,9 +450,10 @@ namespace llvm {
/// empty substring will be returned.
///
/// \param End The index following the last character to include in the
- /// substring. If this is npos, or less than \p Start, or exceeds the
- /// number of characters remaining in the string, the string suffix
- /// (starting with \p Start) will be returned.
+ /// substring. If this is npos or exceeds the number of characters
+ /// remaining in the string, the string suffix (starting with \p Start)
+ /// will be returned. If this is less than \p Start, an empty string will
+ /// be returned.
LLVM_ATTRIBUTE_ALWAYS_INLINE
StringRef slice(size_t Start, size_t End) const {
Start = std::min(Start, Length);
@@ -539,18 +547,36 @@ namespace llvm {
return std::make_pair(slice(0, Idx), slice(Idx+1, npos));
}
+ /// Return string with consecutive \p Char characters starting from the
+ /// the left removed.
+ StringRef ltrim(char Char) const {
+ return drop_front(std::min(Length, find_first_not_of(Char)));
+ }
+
/// Return string with consecutive characters in \p Chars starting from
/// the left removed.
StringRef ltrim(StringRef Chars = " \t\n\v\f\r") const {
return drop_front(std::min(Length, find_first_not_of(Chars)));
}
+ /// Return string with consecutive \p Char characters starting from the
+ /// right removed.
+ StringRef rtrim(char Char) const {
+ return drop_back(Length - std::min(Length, find_last_not_of(Char) + 1));
+ }
+
/// Return string with consecutive characters in \p Chars starting from
/// the right removed.
StringRef rtrim(StringRef Chars = " \t\n\v\f\r") const {
return drop_back(Length - std::min(Length, find_last_not_of(Chars) + 1));
}
+ /// Return string with consecutive \p Char characters starting from the
+ /// left and right removed.
+ StringRef trim(char Char) const {
+ return ltrim(Char).rtrim(Char);
+ }
+
/// Return string with consecutive characters in \p Chars starting from
/// the left and right removed.
StringRef trim(StringRef Chars = " \t\n\v\f\r") const {
diff --git a/include/llvm/ADT/StringSet.h b/include/llvm/ADT/StringSet.h
index 08626dc7af84..c32c2a497438 100644
--- a/include/llvm/ADT/StringSet.h
+++ b/include/llvm/ADT/StringSet.h
@@ -33,6 +33,12 @@ namespace llvm {
assert(!Key.empty());
return base::insert(std::make_pair(Key, '\0'));
}
+
+ template <typename InputIt>
+ void insert(const InputIt &Begin, const InputIt &End) {
+ for (auto It = Begin; It != End; ++It)
+ base::insert(std::make_pair(*It, '\0'));
+ }
};
}
diff --git a/include/llvm/ADT/TinyPtrVector.h b/include/llvm/ADT/TinyPtrVector.h
index 487aa46cf642..605f0e70a857 100644
--- a/include/llvm/ADT/TinyPtrVector.h
+++ b/include/llvm/ADT/TinyPtrVector.h
@@ -104,8 +104,16 @@ public:
/// This also is a constructor for individual array elements due to the single
/// element constructor for ArrayRef.
explicit TinyPtrVector(ArrayRef<EltTy> Elts)
- : Val(Elts.size() == 1 ? PtrUnion(Elts[0])
- : PtrUnion(new VecTy(Elts.begin(), Elts.end()))) {}
+ : Val(Elts.empty()
+ ? PtrUnion()
+ : Elts.size() == 1
+ ? PtrUnion(Elts[0])
+ : PtrUnion(new VecTy(Elts.begin(), Elts.end()))) {}
+
+ TinyPtrVector(size_t Count, EltTy Value)
+ : Val(Count == 0 ? PtrUnion()
+ : Count == 1 ? PtrUnion(Value)
+ : PtrUnion(new VecTy(Count, Value))) {}
// implicit conversion operator to ArrayRef.
operator ArrayRef<EltTy>() const {
@@ -125,6 +133,15 @@ public:
return *Val.template get<VecTy*>();
}
+ // Implicit conversion to ArrayRef<U> if EltTy* implicitly converts to U*.
+ template<typename U,
+ typename std::enable_if<
+ std::is_convertible<ArrayRef<EltTy>, ArrayRef<U>>::value,
+ bool>::type = false>
+ operator ArrayRef<U>() const {
+ return operator ArrayRef<EltTy>();
+ }
+
bool empty() const {
// This vector can be empty if it contains no element, or if it
// contains a pointer to an empty vector.
@@ -142,8 +159,10 @@ public:
return Val.template get<VecTy*>()->size();
}
- typedef const EltTy *const_iterator;
typedef EltTy *iterator;
+ typedef const EltTy *const_iterator;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
iterator begin() {
if (Val.template is<EltTy>())
@@ -166,6 +185,15 @@ public:
return (const_iterator)const_cast<TinyPtrVector*>(this)->end();
}
+ reverse_iterator rbegin() { return reverse_iterator(end()); }
+ reverse_iterator rend() { return reverse_iterator(begin()); }
+ const_reverse_iterator rbegin() const {
+ return const_reverse_iterator(end());
+ }
+ const_reverse_iterator rend() const {
+ return const_reverse_iterator(begin());
+ }
+
EltTy operator[](unsigned i) const {
assert(!Val.isNull() && "can't index into an empty vector");
if (EltTy V = Val.template dyn_cast<EltTy>()) {
diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h
index e01db0a61fd5..47813049d2f2 100644
--- a/include/llvm/ADT/Triple.h
+++ b/include/llvm/ADT/Triple.h
@@ -46,49 +46,52 @@ public:
enum ArchType {
UnknownArch,
- arm, // ARM (little endian): arm, armv.*, xscale
- armeb, // ARM (big endian): armeb
- aarch64, // AArch64 (little endian): aarch64
- aarch64_be, // AArch64 (big endian): aarch64_be
- 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)
- hexagon, // Hexagon: hexagon
- mips, // MIPS: mips, mipsallegrex
- mipsel, // MIPSEL: mipsel, mipsallegrexel
- mips64, // MIPS64: mips64
- mips64el, // MIPS64EL: mips64el
- msp430, // MSP430: msp430
- ppc, // PPC: powerpc
- ppc64, // PPC64: powerpc64, ppu
- ppc64le, // PPC64LE: powerpc64le
- r600, // R600: AMD GPUs HD2XXX - HD6XXX
- amdgcn, // AMDGCN: AMD GCN GPUs
- sparc, // Sparc: sparc
- sparcv9, // Sparcv9: Sparcv9
- sparcel, // Sparc: (endianness = little). NB: 'Sparcle' is a CPU variant
- systemz, // SystemZ: s390x
- tce, // TCE (http://tce.cs.tut.fi/): tce
- thumb, // Thumb (little endian): thumb, thumbv.*
- thumbeb, // Thumb (big endian): thumbeb
- x86, // X86: i[3-9]86
- x86_64, // X86-64: amd64, x86_64
- xcore, // XCore: xcore
- nvptx, // NVPTX: 32-bit
- nvptx64, // NVPTX: 64-bit
- le32, // le32: generic little-endian 32-bit CPU (PNaCl)
- le64, // le64: generic little-endian 64-bit CPU (PNaCl)
- amdil, // AMDIL
- amdil64, // AMDIL with 64-bit pointers
- hsail, // AMD HSAIL
- hsail64, // AMD HSAIL with 64-bit pointers
- spir, // SPIR: standard portable IR for OpenCL 32-bit version
- spir64, // SPIR: standard portable IR for OpenCL 64-bit version
- kalimba, // Kalimba: generic kalimba
- shave, // SHAVE: Movidius vector VLIW processors
- wasm32, // WebAssembly with 32-bit pointers
- wasm64, // WebAssembly with 64-bit pointers
- LastArchType = wasm64
+ arm, // ARM (little endian): arm, armv.*, xscale
+ armeb, // ARM (big endian): armeb
+ aarch64, // AArch64 (little endian): aarch64
+ aarch64_be, // AArch64 (big endian): aarch64_be
+ 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)
+ hexagon, // Hexagon: hexagon
+ mips, // MIPS: mips, mipsallegrex
+ mipsel, // MIPSEL: mipsel, mipsallegrexel
+ mips64, // MIPS64: mips64
+ mips64el, // MIPS64EL: mips64el
+ msp430, // MSP430: msp430
+ ppc, // PPC: powerpc
+ ppc64, // PPC64: powerpc64, ppu
+ ppc64le, // PPC64LE: powerpc64le
+ r600, // R600: AMD GPUs HD2XXX - HD6XXX
+ amdgcn, // AMDGCN: AMD GCN GPUs
+ sparc, // Sparc: sparc
+ sparcv9, // Sparcv9: Sparcv9
+ sparcel, // Sparc: (endianness = little). NB: 'Sparcle' is a CPU variant
+ systemz, // SystemZ: s390x
+ tce, // TCE (http://tce.cs.tut.fi/): tce
+ thumb, // Thumb (little endian): thumb, thumbv.*
+ thumbeb, // Thumb (big endian): thumbeb
+ x86, // X86: i[3-9]86
+ x86_64, // X86-64: amd64, x86_64
+ xcore, // XCore: xcore
+ nvptx, // NVPTX: 32-bit
+ nvptx64, // NVPTX: 64-bit
+ le32, // le32: generic little-endian 32-bit CPU (PNaCl)
+ le64, // le64: generic little-endian 64-bit CPU (PNaCl)
+ amdil, // AMDIL
+ amdil64, // AMDIL with 64-bit pointers
+ hsail, // AMD HSAIL
+ hsail64, // AMD HSAIL with 64-bit pointers
+ spir, // SPIR: standard portable IR for OpenCL 32-bit version
+ spir64, // SPIR: standard portable IR for OpenCL 64-bit version
+ kalimba, // Kalimba: generic kalimba
+ shave, // SHAVE: Movidius vector VLIW processors
+ lanai, // Lanai: Lanai 32-bit
+ wasm32, // WebAssembly with 32-bit pointers
+ wasm64, // WebAssembly with 64-bit pointers
+ renderscript32, // 32-bit RenderScript
+ renderscript64, // 64-bit RenderScript
+ LastArchType = renderscript64
};
enum SubArchType {
NoSubArch,
@@ -96,6 +99,8 @@ public:
ARMSubArch_v8_2a,
ARMSubArch_v8_1a,
ARMSubArch_v8,
+ ARMSubArch_v8m_baseline,
+ ARMSubArch_v8m_mainline,
ARMSubArch_v7,
ARMSubArch_v7em,
ARMSubArch_v7m,
@@ -128,7 +133,9 @@ public:
NVIDIA,
CSR,
Myriad,
- LastVendorType = Myriad
+ AMD,
+ Mesa,
+ LastVendorType = Mesa
};
enum OSType {
UnknownOS,
@@ -160,7 +167,8 @@ public:
ELFIAMCU,
TvOS, // Apple tvOS
WatchOS, // Apple watchOS
- LastOSType = WatchOS
+ Mesa3D,
+ LastOSType = Mesa3D
};
enum EnvironmentType {
UnknownEnvironment,
@@ -173,6 +181,9 @@ public:
EABI,
EABIHF,
Android,
+ Musl,
+ MuslEABI,
+ MuslEABIHF,
MSVC,
Itanium,
@@ -390,8 +401,8 @@ public:
/// isMacOSXVersionLT - Comparison function for checking OS X version
/// compatibility, which handles supporting skewed version numbering schemes
/// used by the "darwin" triples.
- unsigned isMacOSXVersionLT(unsigned Major, unsigned Minor = 0,
- unsigned Micro = 0) const {
+ bool isMacOSXVersionLT(unsigned Major, unsigned Minor = 0,
+ unsigned Micro = 0) const {
assert(isMacOSX() && "Not an OS X triple!");
// If this is OS X, expect a sane version number.
@@ -428,6 +439,10 @@ public:
return getOS() == Triple::WatchOS;
}
+ bool isWatchABI() const {
+ return getSubArch() == Triple::ARMSubArch_v7k;
+ }
+
/// isOSDarwin - Is this a "Darwin" OS (OS X, iOS, or watchOS).
bool isOSDarwin() const {
return isMacOSX() || isiOS() || isWatchOS();
@@ -459,6 +474,12 @@ public:
return getOS() == Triple::ELFIAMCU;
}
+ bool isGNUEnvironment() const {
+ EnvironmentType Env = getEnvironment();
+ return Env == Triple::GNU || Env == Triple::GNUEABI ||
+ Env == Triple::GNUEABIHF || Env == Triple::GNUX32;
+ }
+
/// Checks if the environment could be MSVC.
bool isWindowsMSVCEnvironment() const {
return getOS() == Triple::Win32 &&
@@ -513,6 +534,16 @@ public:
return getOS() == Triple::Linux;
}
+ /// Tests whether the OS is kFreeBSD.
+ bool isOSKFreeBSD() const {
+ return getOS() == Triple::KFreeBSD;
+ }
+
+ /// Tests whether the OS uses glibc.
+ bool isOSGlibc() const {
+ return getOS() == Triple::Linux || getOS() == Triple::KFreeBSD;
+ }
+
/// Tests whether the OS uses the ELF binary format.
bool isOSBinFormatELF() const {
return getObjectFormat() == Triple::ELF;
@@ -544,6 +575,21 @@ public:
/// Tests whether the target is Android
bool isAndroid() const { return getEnvironment() == Triple::Android; }
+ /// Tests whether the environment is musl-libc
+ bool isMusl() const {
+ return getEnvironment() == Triple::Musl ||
+ getEnvironment() == Triple::MuslEABI ||
+ getEnvironment() == Triple::MuslEABIHF;
+ }
+
+ /// Tests whether the target is NVPTX (32- or 64-bit).
+ bool isNVPTX() const {
+ return getArch() == Triple::nvptx || getArch() == Triple::nvptx64;
+ }
+
+ /// Tests wether the target supports comdat
+ bool supportsCOMDAT() const { return !isOSBinFormatMachO(); }
+
/// @}
/// @name Mutators
/// @{
@@ -632,6 +678,11 @@ public:
/// string then the triple's arch name is used.
StringRef getARMCPUForArch(StringRef Arch = StringRef()) const;
+ /// Tests whether the target triple is little endian.
+ ///
+ /// \returns true if the triple is little endian, false otherwise.
+ bool isLittleEndian() const;
+
/// @}
/// @name Static helpers for IDs.
/// @{
diff --git a/include/llvm/ADT/ilist.h b/include/llvm/ADT/ilist.h
index 3044a6c435f1..8e4d45dfef22 100644
--- a/include/llvm/ADT/ilist.h
+++ b/include/llvm/ADT/ilist.h
@@ -186,53 +186,38 @@ template<typename Ty>
struct ilist_traits<const Ty> : public ilist_traits<Ty> {};
//===----------------------------------------------------------------------===//
-// ilist_iterator<Node> - Iterator for intrusive list.
+// Iterator for intrusive list.
//
-template<typename NodeTy>
+template <typename NodeTy>
class ilist_iterator
- : public std::iterator<std::bidirectional_iterator_tag, NodeTy, ptrdiff_t> {
-
+ : public std::iterator<std::bidirectional_iterator_tag, NodeTy, ptrdiff_t> {
public:
typedef ilist_traits<NodeTy> Traits;
- typedef std::iterator<std::bidirectional_iterator_tag,
- NodeTy, ptrdiff_t> super;
+ typedef std::iterator<std::bidirectional_iterator_tag, NodeTy, ptrdiff_t>
+ super;
typedef typename super::value_type value_type;
typedef typename super::difference_type difference_type;
typedef typename super::pointer pointer;
typedef typename super::reference reference;
+
private:
pointer NodePtr;
- // ilist_iterator is not a random-access iterator, but it has an
- // implicit conversion to pointer-type, which is. Declare (but
- // don't define) these functions as private to help catch
- // accidental misuse.
- void operator[](difference_type) const;
- void operator+(difference_type) const;
- void operator-(difference_type) const;
- void operator+=(difference_type) const;
- void operator-=(difference_type) const;
- template<class T> void operator<(T) const;
- template<class T> void operator<=(T) const;
- template<class T> void operator>(T) const;
- template<class T> void operator>=(T) const;
- template<class T> void operator-(T) const;
public:
-
explicit ilist_iterator(pointer NP) : NodePtr(NP) {}
explicit ilist_iterator(reference NR) : NodePtr(&NR) {}
ilist_iterator() : NodePtr(nullptr) {}
// This is templated so that we can allow constructing a const iterator from
// a nonconst iterator...
- template<class node_ty>
+ template <class node_ty>
ilist_iterator(const ilist_iterator<node_ty> &RHS)
- : NodePtr(RHS.getNodePtrUnchecked()) {}
+ : NodePtr(RHS.getNodePtrUnchecked()) {}
// This is templated so that we can allow assigning to a const iterator from
// a nonconst iterator...
- template<class node_ty>
+ template <class node_ty>
const ilist_iterator &operator=(const ilist_iterator<node_ty> &RHS) {
NodePtr = RHS.getNodePtrUnchecked();
return *this;
@@ -241,13 +226,8 @@ public:
void reset(pointer NP) { NodePtr = NP; }
// Accessors...
- explicit operator pointer() const {
- return NodePtr;
- }
-
- reference operator*() const {
- return *NodePtr;
- }
+ explicit operator pointer() const { return NodePtr; }
+ reference operator*() const { return *NodePtr; }
pointer operator->() const { return &operator*(); }
// Comparison operators
@@ -259,21 +239,21 @@ public:
}
// Increment and decrement operators...
- ilist_iterator &operator--() { // predecrement - Back up
+ ilist_iterator &operator--() {
NodePtr = Traits::getPrev(NodePtr);
assert(NodePtr && "--'d off the beginning of an ilist!");
return *this;
}
- ilist_iterator &operator++() { // preincrement - Advance
+ ilist_iterator &operator++() {
NodePtr = Traits::getNext(NodePtr);
return *this;
}
- ilist_iterator operator--(int) { // postdecrement operators...
+ ilist_iterator operator--(int) {
ilist_iterator tmp = *this;
--*this;
return tmp;
}
- ilist_iterator operator++(int) { // postincrement operators...
+ ilist_iterator operator++(int) {
ilist_iterator tmp = *this;
++*this;
return tmp;
@@ -283,38 +263,6 @@ public:
pointer getNodePtrUnchecked() const { return NodePtr; }
};
-// These are to catch errors when people try to use them as random access
-// iterators.
-template<typename T>
-void operator-(int, ilist_iterator<T>) = delete;
-template<typename T>
-void operator-(ilist_iterator<T>,int) = delete;
-
-template<typename T>
-void operator+(int, ilist_iterator<T>) = delete;
-template<typename T>
-void operator+(ilist_iterator<T>,int) = delete;
-
-// operator!=/operator== - Allow mixed comparisons without dereferencing
-// the iterator, which could very likely be pointing to end().
-template<typename T>
-bool operator!=(const T* LHS, const ilist_iterator<const T> &RHS) {
- return LHS != RHS.getNodePtrUnchecked();
-}
-template<typename T>
-bool operator==(const T* LHS, const ilist_iterator<const T> &RHS) {
- return LHS == RHS.getNodePtrUnchecked();
-}
-template<typename T>
-bool operator!=(T* LHS, const ilist_iterator<T> &RHS) {
- return LHS != RHS.getNodePtrUnchecked();
-}
-template<typename T>
-bool operator==(T* LHS, const ilist_iterator<T> &RHS) {
- return LHS == RHS.getNodePtrUnchecked();
-}
-
-
// Allow ilist_iterators to convert into pointers to a node automatically when
// used by the dyn_cast, cast, isa mechanisms...
@@ -474,6 +422,10 @@ public:
return iterator(New);
}
+ iterator insert(iterator where, const NodeTy &New) {
+ return this->insert(where, new NodeTy(New));
+ }
+
iterator insertAfter(iterator where, NodeTy *New) {
if (empty())
return insert(begin(), New);
@@ -720,7 +672,7 @@ struct ilist : public iplist<NodeTy> {
typedef typename iplist<NodeTy>::iterator iterator;
ilist() {}
- ilist(const ilist &right) {
+ ilist(const ilist &right) : iplist<NodeTy>() {
insert(this->begin(), right.begin(), right.end());
}
explicit ilist(size_type count) {
diff --git a/include/llvm/ADT/iterator.h b/include/llvm/ADT/iterator.h
index c30792892703..2898a677db37 100644
--- a/include/llvm/ADT/iterator.h
+++ b/include/llvm/ADT/iterator.h
@@ -46,6 +46,22 @@ protected:
std::is_base_of<std::bidirectional_iterator_tag, IteratorCategoryT>::value,
};
+ /// A proxy object for computing a reference via indirecting a copy of an
+ /// iterator. This is used in APIs which need to produce a reference via
+ /// indirection but for which the iterator object might be a temporary. The
+ /// proxy preserves the iterator internally and exposes the indirected
+ /// reference via a conversion operator.
+ class ReferenceProxy {
+ friend iterator_facade_base;
+
+ DerivedT I;
+
+ ReferenceProxy(DerivedT I) : I(std::move(I)) {}
+
+ public:
+ operator ReferenceT() const { return *I; }
+ };
+
public:
DerivedT operator+(DifferenceTypeT n) const {
static_assert(
@@ -120,10 +136,10 @@ public:
PointerT operator->() const {
return &static_cast<const DerivedT *>(this)->operator*();
}
- ReferenceT operator[](DifferenceTypeT n) const {
+ ReferenceProxy operator[](DifferenceTypeT n) const {
static_assert(IsRandomAccess,
"Subscripting is only defined for random access iterators.");
- return *static_cast<const DerivedT *>(this)->operator+(n);
+ return ReferenceProxy(static_cast<const DerivedT *>(this)->operator+(n));
}
};
diff --git a/include/llvm/Analysis/AliasAnalysis.h b/include/llvm/Analysis/AliasAnalysis.h
index 5cc840a64a62..d6308b7073a0 100644
--- a/include/llvm/Analysis/AliasAnalysis.h
+++ b/include/llvm/Analysis/AliasAnalysis.h
@@ -38,11 +38,11 @@
#ifndef LLVM_ANALYSIS_ALIASANALYSIS_H
#define LLVM_ANALYSIS_ALIASANALYSIS_H
-#include "llvm/ADT/DenseMap.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Analysis/MemoryLocation.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
namespace llvm {
class BasicAAResult;
@@ -50,7 +50,6 @@ class LoadInst;
class StoreInst;
class VAArgInst;
class DataLayout;
-class TargetLibraryInfo;
class Pass;
class AnalysisUsage;
class MemTransferInst;
@@ -141,7 +140,7 @@ enum FunctionModRefBehavior {
/// non-volatile loads and stores from objects pointed to by its
/// pointer-typed arguments, with arbitrary offsets.
///
- /// This property corresponds to the IntrReadWriteArgMem LLVM intrinsic flag.
+ /// This property corresponds to the IntrArgMemOnly LLVM intrinsic flag.
FMRB_OnlyAccessesArgumentPointees = FMRL_ArgumentPointees | MRI_ModRef,
/// This function does not perform any non-local stores or volatile loads,
@@ -152,6 +151,13 @@ enum FunctionModRefBehavior {
/// This property corresponds to the IntrReadMem LLVM intrinsic flag.
FMRB_OnlyReadsMemory = FMRL_Anywhere | MRI_Ref,
+ // This function does not read from memory anywhere, but may write to any
+ // memory location.
+ //
+ // This property corresponds to the LLVM IR 'writeonly' attribute.
+ // This property corresponds to the IntrWriteMem LLVM intrinsic flag.
+ FMRB_DoesNotReadMemory = FMRL_Anywhere | MRI_Mod,
+
/// This indicates that the function could not be classified into one of the
/// behaviors above.
FMRB_UnknownModRefBehavior = FMRL_Anywhere | MRI_ModRef
@@ -161,9 +167,8 @@ class AAResults {
public:
// Make these results default constructable and movable. We have to spell
// these out because MSVC won't synthesize them.
- AAResults() {}
+ AAResults(const TargetLibraryInfo &TLI) : TLI(TLI) {}
AAResults(AAResults &&Arg);
- AAResults &operator=(AAResults &&Arg);
~AAResults();
/// Register a specific AA result.
@@ -314,6 +319,12 @@ public:
return !(MRB & MRI_Mod);
}
+ /// Checks if functions with the specified behavior are known to only write
+ /// memory (or not access memory at all).
+ static bool doesNotReadMemory(FunctionModRefBehavior MRB) {
+ return !(MRB & MRI_Ref);
+ }
+
/// Checks if functions with the specified behavior are known to read and
/// write at most from objects pointed to by their pointer-typed arguments
/// (with arbitrary offsets).
@@ -450,11 +461,11 @@ public:
ModRefInfo getModRefInfo(const Instruction *I) {
if (auto CS = ImmutableCallSite(I)) {
auto MRB = getModRefBehavior(CS);
- if (MRB & MRI_ModRef)
+ if ((MRB & MRI_ModRef) == MRI_ModRef)
return MRI_ModRef;
- else if (MRB & MRI_Ref)
+ if (MRB & MRI_Ref)
return MRI_Ref;
- else if (MRB & MRI_Mod)
+ if (MRB & MRI_Mod)
return MRI_Mod;
return MRI_NoModRef;
}
@@ -557,6 +568,8 @@ private:
template <typename T> friend class AAResultBase;
+ const TargetLibraryInfo &TLI;
+
std::vector<std::unique_ptr<Concept>> AAs;
};
@@ -753,20 +766,23 @@ protected:
}
};
- const TargetLibraryInfo &TLI;
-
- explicit AAResultBase(const TargetLibraryInfo &TLI) : TLI(TLI) {}
+ explicit AAResultBase() {}
// Provide all the copy and move constructors so that derived types aren't
// constrained.
- AAResultBase(const AAResultBase &Arg) : TLI(Arg.TLI) {}
- AAResultBase(AAResultBase &&Arg) : TLI(Arg.TLI) {}
+ AAResultBase(const AAResultBase &Arg) {}
+ AAResultBase(AAResultBase &&Arg) {}
/// Get a proxy for the best AA result set to query at this time.
///
/// When this result is part of a larger aggregation, this will proxy to that
/// aggregation. When this result is used in isolation, it will just delegate
/// back to the derived class's implementation.
+ ///
+ /// Note that callers of this need to take considerable care to not cause
+ /// performance problems when they use this routine, in the case of a large
+ /// number of alias analyses being aggregated, it can be expensive to walk
+ /// back across the chain.
AAResultsProxy getBestAAResults() { return AAResultsProxy(AAR, derived()); }
public:
@@ -783,13 +799,6 @@ public:
}
FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS) {
- if (!CS.hasOperandBundles())
- // If CS has operand bundles then aliasing attributes from the function it
- // calls do not directly apply to the CallSite. This can be made more
- // precise in the future.
- if (const Function *F = CS.getCalledFunction())
- return getBestAAResults().getModRefBehavior(F);
-
return FMRB_UnknownModRefBehavior;
}
@@ -797,170 +806,24 @@ public:
return FMRB_UnknownModRefBehavior;
}
- ModRefInfo getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc);
-
- ModRefInfo getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2);
-};
-
-/// Synthesize \c ModRefInfo for a call site and memory location by examining
-/// the general behavior of the call site and any specific information for its
-/// arguments.
-///
-/// This essentially, delegates across the alias analysis interface to collect
-/// information which may be enough to (conservatively) fulfill the query.
-template <typename DerivedT>
-ModRefInfo AAResultBase<DerivedT>::getModRefInfo(ImmutableCallSite CS,
- const MemoryLocation &Loc) {
- auto MRB = getBestAAResults().getModRefBehavior(CS);
- if (MRB == FMRB_DoesNotAccessMemory)
- return MRI_NoModRef;
-
- ModRefInfo Mask = MRI_ModRef;
- if (AAResults::onlyReadsMemory(MRB))
- Mask = MRI_Ref;
-
- if (AAResults::onlyAccessesArgPointees(MRB)) {
- bool DoesAlias = false;
- ModRefInfo AllArgsMask = MRI_NoModRef;
- if (AAResults::doesAccessArgPointees(MRB)) {
- for (ImmutableCallSite::arg_iterator AI = CS.arg_begin(),
- AE = CS.arg_end();
- AI != AE; ++AI) {
- const Value *Arg = *AI;
- if (!Arg->getType()->isPointerTy())
- continue;
- unsigned ArgIdx = std::distance(CS.arg_begin(), AI);
- MemoryLocation ArgLoc = MemoryLocation::getForArgument(CS, ArgIdx, TLI);
- AliasResult ArgAlias = getBestAAResults().alias(ArgLoc, Loc);
- if (ArgAlias != NoAlias) {
- ModRefInfo ArgMask = getBestAAResults().getArgModRefInfo(CS, ArgIdx);
- DoesAlias = true;
- AllArgsMask = ModRefInfo(AllArgsMask | ArgMask);
- }
- }
- }
- if (!DoesAlias)
- return MRI_NoModRef;
- Mask = ModRefInfo(Mask & AllArgsMask);
- }
-
- // If Loc is a constant memory location, the call definitely could not
- // modify the memory location.
- if ((Mask & MRI_Mod) &&
- getBestAAResults().pointsToConstantMemory(Loc, /*OrLocal*/ false))
- Mask = ModRefInfo(Mask & ~MRI_Mod);
-
- return Mask;
-}
-
-/// Synthesize \c ModRefInfo for two call sites by examining the general
-/// behavior of the call site and any specific information for its arguments.
-///
-/// This essentially, delegates across the alias analysis interface to collect
-/// information which may be enough to (conservatively) fulfill the query.
-template <typename DerivedT>
-ModRefInfo AAResultBase<DerivedT>::getModRefInfo(ImmutableCallSite CS1,
- ImmutableCallSite CS2) {
- // If CS1 or CS2 are readnone, they don't interact.
- auto CS1B = getBestAAResults().getModRefBehavior(CS1);
- if (CS1B == FMRB_DoesNotAccessMemory)
- return MRI_NoModRef;
-
- auto CS2B = getBestAAResults().getModRefBehavior(CS2);
- if (CS2B == FMRB_DoesNotAccessMemory)
- return MRI_NoModRef;
-
- // If they both only read from memory, there is no dependence.
- if (AAResults::onlyReadsMemory(CS1B) && AAResults::onlyReadsMemory(CS2B))
- return MRI_NoModRef;
-
- ModRefInfo Mask = MRI_ModRef;
-
- // If CS1 only reads memory, the only dependence on CS2 can be
- // from CS1 reading memory written by CS2.
- if (AAResults::onlyReadsMemory(CS1B))
- Mask = ModRefInfo(Mask & MRI_Ref);
-
- // If CS2 only access memory through arguments, accumulate the mod/ref
- // information from CS1's references to the memory referenced by
- // CS2's arguments.
- if (AAResults::onlyAccessesArgPointees(CS2B)) {
- ModRefInfo R = MRI_NoModRef;
- if (AAResults::doesAccessArgPointees(CS2B)) {
- for (ImmutableCallSite::arg_iterator I = CS2.arg_begin(),
- E = CS2.arg_end();
- I != E; ++I) {
- const Value *Arg = *I;
- if (!Arg->getType()->isPointerTy())
- continue;
- unsigned CS2ArgIdx = std::distance(CS2.arg_begin(), I);
- auto CS2ArgLoc = MemoryLocation::getForArgument(CS2, CS2ArgIdx, TLI);
-
- // ArgMask indicates what CS2 might do to CS2ArgLoc, and the dependence
- // of CS1 on that location is the inverse.
- ModRefInfo ArgMask =
- getBestAAResults().getArgModRefInfo(CS2, CS2ArgIdx);
- if (ArgMask == MRI_Mod)
- ArgMask = MRI_ModRef;
- else if (ArgMask == MRI_Ref)
- ArgMask = MRI_Mod;
-
- ArgMask = ModRefInfo(ArgMask &
- getBestAAResults().getModRefInfo(CS1, CS2ArgLoc));
-
- R = ModRefInfo((R | ArgMask) & Mask);
- if (R == Mask)
- break;
- }
- }
- return R;
+ ModRefInfo getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc) {
+ return MRI_ModRef;
}
- // If CS1 only accesses memory through arguments, check if CS2 references
- // any of the memory referenced by CS1's arguments. If not, return NoModRef.
- if (AAResults::onlyAccessesArgPointees(CS1B)) {
- ModRefInfo R = MRI_NoModRef;
- if (AAResults::doesAccessArgPointees(CS1B)) {
- for (ImmutableCallSite::arg_iterator I = CS1.arg_begin(),
- E = CS1.arg_end();
- I != E; ++I) {
- const Value *Arg = *I;
- if (!Arg->getType()->isPointerTy())
- continue;
- unsigned CS1ArgIdx = std::distance(CS1.arg_begin(), I);
- auto CS1ArgLoc = MemoryLocation::getForArgument(CS1, CS1ArgIdx, TLI);
-
- // ArgMask indicates what CS1 might do to CS1ArgLoc; if CS1 might Mod
- // CS1ArgLoc, then we care about either a Mod or a Ref by CS2. If CS1
- // might Ref, then we care only about a Mod by CS2.
- ModRefInfo ArgMask = getBestAAResults().getArgModRefInfo(CS1, CS1ArgIdx);
- ModRefInfo ArgR = getBestAAResults().getModRefInfo(CS2, CS1ArgLoc);
- if (((ArgMask & MRI_Mod) != MRI_NoModRef &&
- (ArgR & MRI_ModRef) != MRI_NoModRef) ||
- ((ArgMask & MRI_Ref) != MRI_NoModRef &&
- (ArgR & MRI_Mod) != MRI_NoModRef))
- R = ModRefInfo((R | ArgMask) & Mask);
-
- if (R == Mask)
- break;
- }
- }
- return R;
+ ModRefInfo getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2) {
+ return MRI_ModRef;
}
+};
- return Mask;
-}
-/// isNoAliasCall - Return true if this pointer is returned by a noalias
-/// function.
+/// Return true if this pointer is returned by a noalias function.
bool isNoAliasCall(const Value *V);
-/// isNoAliasArgument - Return true if this is an argument with the noalias
-/// attribute.
+/// Return true if this is an argument with the noalias attribute.
bool isNoAliasArgument(const Value *V);
-/// isIdentifiedObject - Return true if this pointer refers to a distinct and
-/// identifiable object. This returns true for:
+/// Return true if this pointer refers to a distinct and identifiable object.
+/// This returns true for:
/// Global Variables and Functions (but not Global Aliases)
/// Allocas
/// ByVal and NoAlias Arguments
@@ -968,8 +831,8 @@ bool isNoAliasArgument(const Value *V);
///
bool isIdentifiedObject(const Value *V);
-/// isIdentifiedFunctionLocal - Return true if V is umabigously identified
-/// at the function-level. Different IdentifiedFunctionLocals can't alias.
+/// Return true if V is umabigously identified at the function-level.
+/// Different IdentifiedFunctionLocals can't alias.
/// Further, an IdentifiedFunctionLocal can not alias with any function
/// arguments other than itself, which is not necessarily true for
/// IdentifiedObjects.
@@ -987,42 +850,48 @@ bool isIdentifiedFunctionLocal(const Value *V);
/// This manager effectively wraps the AnalysisManager for registering alias
/// analyses. When you register your alias analysis with this manager, it will
/// ensure the analysis itself is registered with its AnalysisManager.
-class AAManager {
+class AAManager : public AnalysisInfoMixin<AAManager> {
public:
typedef AAResults Result;
// This type hase value semantics. We have to spell these out because MSVC
// won't synthesize them.
AAManager() {}
- AAManager(AAManager &&Arg)
- : FunctionResultGetters(std::move(Arg.FunctionResultGetters)) {}
- AAManager(const AAManager &Arg)
- : FunctionResultGetters(Arg.FunctionResultGetters) {}
+ AAManager(AAManager &&Arg) : ResultGetters(std::move(Arg.ResultGetters)) {}
+ AAManager(const AAManager &Arg) : ResultGetters(Arg.ResultGetters) {}
AAManager &operator=(AAManager &&RHS) {
- FunctionResultGetters = std::move(RHS.FunctionResultGetters);
+ ResultGetters = std::move(RHS.ResultGetters);
return *this;
}
AAManager &operator=(const AAManager &RHS) {
- FunctionResultGetters = RHS.FunctionResultGetters;
+ ResultGetters = RHS.ResultGetters;
return *this;
}
/// Register a specific AA result.
template <typename AnalysisT> void registerFunctionAnalysis() {
- FunctionResultGetters.push_back(&getFunctionAAResultImpl<AnalysisT>);
+ ResultGetters.push_back(&getFunctionAAResultImpl<AnalysisT>);
+ }
+
+ /// Register a specific AA result.
+ template <typename AnalysisT> void registerModuleAnalysis() {
+ ResultGetters.push_back(&getModuleAAResultImpl<AnalysisT>);
}
Result run(Function &F, AnalysisManager<Function> &AM) {
- Result R;
- for (auto &Getter : FunctionResultGetters)
+ Result R(AM.getResult<TargetLibraryAnalysis>(F));
+ for (auto &Getter : ResultGetters)
(*Getter)(F, AM, R);
return R;
}
private:
+ friend AnalysisInfoMixin<AAManager>;
+ static char PassID;
+
SmallVector<void (*)(Function &F, AnalysisManager<Function> &AM,
AAResults &AAResults),
- 4> FunctionResultGetters;
+ 4> ResultGetters;
template <typename AnalysisT>
static void getFunctionAAResultImpl(Function &F,
@@ -1030,6 +899,15 @@ private:
AAResults &AAResults) {
AAResults.addAAResult(AM.template getResult<AnalysisT>(F));
}
+
+ template <typename AnalysisT>
+ static void getModuleAAResultImpl(Function &F, AnalysisManager<Function> &AM,
+ AAResults &AAResults) {
+ auto &MAM =
+ AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
+ if (auto *R = MAM.template getCachedResult<AnalysisT>(*F.getParent()))
+ AAResults.addAAResult(*R);
+ }
};
/// A wrapper pass to provide the legacy pass manager access to a suitably
@@ -1065,8 +943,16 @@ ImmutablePass *createExternalAAWrapperPass(
/// A helper for the legacy pass manager to create a \c AAResults
/// object populated to the best of our ability for a particular function when
/// inside of a \c ModulePass or a \c CallGraphSCCPass.
+///
+/// If a \c ModulePass or a \c CallGraphSCCPass calls \p
+/// createLegacyPMAAResults, it also needs to call \p addUsedAAAnalyses in \p
+/// getAnalysisUsage.
AAResults createLegacyPMAAResults(Pass &P, Function &F, BasicAAResult &BAR);
+/// A helper for the legacy pass manager to populate \p AU to add uses to make
+/// sure the analyses required by \p createLegacyPMAAResults are available.
+void getAAResultsAnalysisUsage(AnalysisUsage &AU);
+
} // End llvm namespace
#endif
diff --git a/include/llvm/Analysis/AliasAnalysisEvaluator.h b/include/llvm/Analysis/AliasAnalysisEvaluator.h
new file mode 100644
index 000000000000..505ed0d9723a
--- /dev/null
+++ b/include/llvm/Analysis/AliasAnalysisEvaluator.h
@@ -0,0 +1,70 @@
+//===- AliasAnalysisEvaluator.h - Alias Analysis Accuracy Evaluator -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file implements a simple N^2 alias analysis accuracy evaluator. The
+/// analysis result is a set of statistics of how many times the AA
+/// infrastructure provides each kind of alias result and mod/ref result when
+/// queried with all pairs of pointers in the function.
+///
+/// It can be used to evaluate a change in an alias analysis implementation,
+/// algorithm, or the AA pipeline infrastructure itself. It acts like a stable
+/// and easily tested consumer of all AA information exposed.
+///
+/// This is inspired and adapted from code by: Naveen Neelakantam, Francesco
+/// Spadini, and Wojciech Stryjewski.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ANALYSIS_ALIASANALYSISEVALUATOR_H
+#define LLVM_ANALYSIS_ALIASANALYSISEVALUATOR_H
+
+#include "llvm/IR/Function.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+class AAResults;
+
+class AAEvaluator : public PassInfoMixin<AAEvaluator> {
+ int64_t FunctionCount;
+ int64_t NoAliasCount, MayAliasCount, PartialAliasCount, MustAliasCount;
+ int64_t NoModRefCount, ModCount, RefCount, ModRefCount;
+
+public:
+ AAEvaluator()
+ : FunctionCount(), NoAliasCount(), MayAliasCount(), PartialAliasCount(),
+ MustAliasCount(), NoModRefCount(), ModCount(), RefCount(),
+ ModRefCount() {}
+ AAEvaluator(AAEvaluator &&Arg)
+ : FunctionCount(Arg.FunctionCount), NoAliasCount(Arg.NoAliasCount),
+ MayAliasCount(Arg.MayAliasCount),
+ PartialAliasCount(Arg.PartialAliasCount),
+ MustAliasCount(Arg.MustAliasCount), NoModRefCount(Arg.NoModRefCount),
+ ModCount(Arg.ModCount), RefCount(Arg.RefCount),
+ ModRefCount(Arg.ModRefCount) {
+ Arg.FunctionCount = 0;
+ }
+ ~AAEvaluator();
+
+ /// \brief Run the pass over the function.
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
+
+private:
+ // Allow the legacy pass to run this using an internal API.
+ friend class AAEvalLegacyPass;
+
+ void runInternal(Function &F, AAResults &AA);
+};
+
+/// Create a wrapper of the above for the legacy pass manager.
+FunctionPass *createAAEvalPass();
+
+}
+
+#endif
diff --git a/include/llvm/Analysis/AliasSetTracker.h b/include/llvm/Analysis/AliasSetTracker.h
index 37fd69b081cc..cec56889c0ae 100644
--- a/include/llvm/Analysis/AliasSetTracker.h
+++ b/include/llvm/Analysis/AliasSetTracker.h
@@ -7,9 +7,9 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines two classes: AliasSetTracker and AliasSet. These interface
+// This file defines two classes: AliasSetTracker and AliasSet. These interfaces
// are used to classify a collection of pointer references into a maximal number
-// of disjoint sets. Each AliasSet object constructed by the AliasSetTracker
+// of disjoint sets. Each AliasSet object constructed by the AliasSetTracker
// object refers to memory disjoint from the other sets.
//
//===----------------------------------------------------------------------===//
@@ -30,6 +30,7 @@ namespace llvm {
class LoadInst;
class StoreInst;
class VAArgInst;
+class MemSetInst;
class AliasSetTracker;
class AliasSet;
@@ -58,8 +59,12 @@ class AliasSet : public ilist_node<AliasSet> {
return &NextInList;
}
- void updateSizeAndAAInfo(uint64_t NewSize, const AAMDNodes &NewAAInfo) {
- if (NewSize > Size) Size = NewSize;
+ bool updateSizeAndAAInfo(uint64_t NewSize, const AAMDNodes &NewAAInfo) {
+ bool SizeChanged = false;
+ if (NewSize > Size) {
+ Size = NewSize;
+ SizeChanged = true;
+ }
if (AAInfo == DenseMapInfo<AAMDNodes>::getEmptyKey())
// We don't have a AAInfo yet. Set it to NewAAInfo.
@@ -67,12 +72,14 @@ class AliasSet : public ilist_node<AliasSet> {
else if (AAInfo != NewAAInfo)
// NewAAInfo conflicts with AAInfo.
AAInfo = DenseMapInfo<AAMDNodes>::getTombstoneKey();
+
+ return SizeChanged;
}
uint64_t getSize() const { return Size; }
- /// getAAInfo - Return the AAInfo, or null if there is no
- /// information or conflicting information.
+ /// Return the AAInfo, or null if there is no information or conflicting
+ /// information.
AAMDNodes getAAInfo() const {
// If we have missing or conflicting AAInfo, return null.
if (AAInfo == DenseMapInfo<AAMDNodes>::getEmptyKey() ||
@@ -111,11 +118,11 @@ class AliasSet : public ilist_node<AliasSet> {
PointerRec *PtrList, **PtrListEnd; // Doubly linked list of nodes.
AliasSet *Forward; // Forwarding pointer.
- // All instructions without a specific address in this alias set.
+ /// All instructions without a specific address in this alias set.
std::vector<AssertingVH<Instruction> > UnknownInsts;
- // RefCount - Number of nodes pointing to this AliasSet plus the number of
- // AliasSets forwarding to it.
+ /// Number of nodes pointing to this AliasSet plus the number of AliasSets
+ /// forwarding to it.
unsigned RefCount : 28;
/// The kinds of access this alias set models.
@@ -143,8 +150,8 @@ class AliasSet : public ilist_node<AliasSet> {
};
unsigned Alias : 1;
- // Volatile - True if this alias set contains volatile loads or stores.
- bool Volatile : 1;
+ /// True if this alias set contains volatile loads or stores.
+ unsigned Volatile : 1;
void addRef() { ++RefCount; }
void dropRef(AliasSetTracker &AST) {
@@ -165,20 +172,18 @@ public:
bool isMustAlias() const { return Alias == SetMustAlias; }
bool isMayAlias() const { return Alias == SetMayAlias; }
- // isVolatile - Return true if this alias set contains volatile loads or
- // stores.
+ /// Return true if this alias set contains volatile loads or stores.
bool isVolatile() const { return Volatile; }
- /// isForwardingAliasSet - Return true if this alias set should be ignored as
- /// part of the AliasSetTracker object.
+ /// Return true if this alias set should be ignored as part of the
+ /// AliasSetTracker object.
bool isForwardingAliasSet() const { return Forward; }
- /// mergeSetIn - Merge the specified alias set into this alias set...
- ///
+ /// Merge the specified alias set into this alias set.
void mergeSetIn(AliasSet &AS, AliasSetTracker &AST);
- // Alias Set iteration - Allow access to all of the pointer which are part of
- // this alias set...
+ // Alias Set iteration - Allow access to all of the pointers which are part of
+ // this alias set.
class iterator;
iterator begin() const { return iterator(PtrList); }
iterator end() const { return iterator(); }
@@ -236,9 +241,9 @@ private:
return PtrList;
}
- /// getForwardedTarget - Return the real alias set this represents. If this
- /// has been merged with another set and is forwarding, return the ultimate
- /// destination set. This also implements the union-find collapsing as well.
+ /// Return the real alias set this represents. If this has been merged with
+ /// another set and is forwarding, return the ultimate destination set. This
+ /// also implements the union-find collapsing as well.
AliasSet *getForwardedTarget(AliasSetTracker &AST) {
if (!Forward) return this;
@@ -271,9 +276,8 @@ private:
void setVolatile() { Volatile = true; }
public:
- /// aliasesPointer - Return true if the specified pointer "may" (or must)
- /// alias one of the members in the set.
- ///
+ /// Return true if the specified pointer "may" (or must) alias one of the
+ /// members in the set.
bool aliasesPointer(const Value *Ptr, uint64_t Size, const AAMDNodes &AAInfo,
AliasAnalysis &AA) const;
bool aliasesUnknownInst(const Instruction *Inst, AliasAnalysis &AA) const;
@@ -285,8 +289,8 @@ inline raw_ostream& operator<<(raw_ostream &OS, const AliasSet &AS) {
}
class AliasSetTracker {
- /// CallbackVH - A CallbackVH to arrange for AliasSetTracker to be
- /// notified whenever a Value is deleted.
+ /// A CallbackVH to arrange for AliasSetTracker to be notified whenever a
+ /// Value is deleted.
class ASTCallbackVH final : public CallbackVH {
AliasSetTracker *AST;
void deleted() override;
@@ -296,8 +300,8 @@ class AliasSetTracker {
ASTCallbackVH(Value *V, AliasSetTracker *AST = nullptr);
ASTCallbackVH &operator=(Value *V);
};
- /// ASTCallbackVHDenseMapInfo - Traits to tell DenseMap that tell us how to
- /// compare and hash the value handle.
+ /// Traits to tell DenseMap that tell us how to compare and hash the value
+ /// handle.
struct ASTCallbackVHDenseMapInfo : public DenseMapInfo<Value *> {};
AliasAnalysis &AA;
@@ -311,15 +315,14 @@ class AliasSetTracker {
PointerMapType PointerMap;
public:
- /// AliasSetTracker ctor - Create an empty collection of AliasSets, and use
- /// the specified alias analysis object to disambiguate load and store
- /// addresses.
+ /// 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) {}
~AliasSetTracker() { clear(); }
- /// add methods - These methods are used to add different types of
- /// instructions to the alias sets. Adding a new instruction can result in
- /// one of three actions happening:
+ /// These methods are used to add different types of instructions to the alias
+ /// sets. Adding a new instruction can result in one of three actions
+ /// happening:
///
/// 1. If the instruction doesn't alias any other sets, create a new set.
/// 2. If the instruction aliases exactly one set, add it to the set
@@ -333,47 +336,46 @@ public:
bool add(LoadInst *LI);
bool add(StoreInst *SI);
bool add(VAArgInst *VAAI);
+ bool add(MemSetInst *MSI);
bool add(Instruction *I); // Dispatch to one of the other add methods...
void add(BasicBlock &BB); // Add all instructions in basic block
void add(const AliasSetTracker &AST); // Add alias relations from another AST
bool addUnknown(Instruction *I);
- /// remove methods - These methods are used to remove all entries that might
- /// be aliased by the specified instruction. These methods return true if any
- /// alias sets were eliminated.
- // Remove a location
+ /// These methods are used to remove all entries that might be aliased by the
+ /// specified instruction. These methods return true if any alias sets were
+ /// eliminated.
bool remove(Value *Ptr, uint64_t Size, const AAMDNodes &AAInfo);
bool remove(LoadInst *LI);
bool remove(StoreInst *SI);
bool remove(VAArgInst *VAAI);
+ bool remove(MemSetInst *MSI);
bool remove(Instruction *I);
void remove(AliasSet &AS);
bool removeUnknown(Instruction *I);
void clear();
- /// getAliasSets - Return the alias sets that are active.
- ///
+ /// Return the alias sets that are active.
const ilist<AliasSet> &getAliasSets() const { return AliasSets; }
- /// getAliasSetForPointer - Return the alias set that the specified pointer
- /// lives in. If the New argument is non-null, this method sets the value to
- /// true if a new alias set is created to contain the pointer (because the
- /// pointer didn't alias anything).
+ /// Return the alias set that the specified pointer lives in. If the New
+ /// argument is non-null, this method sets the value to true if a new alias
+ /// set is created to contain the pointer (because the pointer didn't alias
+ /// anything).
AliasSet &getAliasSetForPointer(Value *P, uint64_t Size,
const AAMDNodes &AAInfo,
bool *New = nullptr);
- /// getAliasSetForPointerIfExists - Return the alias set containing the
- /// location specified if one exists, otherwise return null.
+ /// Return the alias set containing the location specified if one exists,
+ /// otherwise return null.
AliasSet *getAliasSetForPointerIfExists(const Value *P, uint64_t Size,
const AAMDNodes &AAInfo) {
- return findAliasSetForPointer(P, Size, AAInfo);
+ return mergeAliasSetsForPointer(P, Size, AAInfo);
}
- /// containsPointer - Return true if the specified location is represented by
- /// this alias set, false otherwise. This does not modify the AST object or
- /// alias sets.
+ /// Return true if the specified location is represented by this alias set,
+ /// false otherwise. This does not modify the AST object or alias sets.
bool containsPointer(const Value *P, uint64_t Size,
const AAMDNodes &AAInfo) const;
@@ -381,23 +383,19 @@ public:
/// members in any of the sets.
bool containsUnknown(const Instruction *I) const;
- /// getAliasAnalysis - Return the underlying alias analysis object used by
- /// this tracker.
+ /// Return the underlying alias analysis object used by this tracker.
AliasAnalysis &getAliasAnalysis() const { return AA; }
- /// deleteValue method - This method is used to remove a pointer value from
- /// the AliasSetTracker entirely. It should be used when an instruction is
- /// deleted from the program to update the AST. If you don't use this, you
- /// would have dangling pointers to deleted instructions.
- ///
+ /// This method is used to remove a pointer value from the AliasSetTracker
+ /// entirely. It should be used when an instruction is deleted from the
+ /// program to update the AST. If you don't use this, you would have dangling
+ /// pointers to deleted instructions.
void deleteValue(Value *PtrVal);
- /// copyValue - This method should be used whenever a preexisting value in the
- /// program is copied or cloned, introducing a new value. Note that it is ok
- /// for clients that use this method to introduce the same value multiple
- /// times: if the tracker already knows about a value, it will ignore the
- /// request.
- ///
+ /// This method should be used whenever a preexisting value in the program is
+ /// copied or cloned, introducing a new value. Note that it is ok for clients
+ /// that use this method to introduce the same value multiple times: if the
+ /// tracker already knows about a value, it will ignore the request.
void copyValue(Value *From, Value *To);
typedef ilist<AliasSet>::iterator iterator;
@@ -416,8 +414,8 @@ private:
friend class AliasSet;
void removeAliasSet(AliasSet *AS);
- // getEntryFor - Just like operator[] on the map, except that it creates an
- // entry for the pointer if it doesn't already exist.
+ /// Just like operator[] on the map, except that it creates an entry for the
+ /// pointer if it doesn't already exist.
AliasSet::PointerRec &getEntryFor(Value *V) {
AliasSet::PointerRec *&Entry = PointerMap[ASTCallbackVH(V, this)];
if (!Entry)
@@ -433,8 +431,8 @@ private:
AS.Access |= E;
return AS;
}
- AliasSet *findAliasSetForPointer(const Value *Ptr, uint64_t Size,
- const AAMDNodes &AAInfo);
+ AliasSet *mergeAliasSetsForPointer(const Value *Ptr, uint64_t Size,
+ const AAMDNodes &AAInfo);
AliasSet *findAliasSetForUnknownInst(Instruction *Inst);
};
diff --git a/include/llvm/Analysis/AssumptionCache.h b/include/llvm/Analysis/AssumptionCache.h
index b903f96d55b2..06f2a117ac21 100644
--- a/include/llvm/Analysis/AssumptionCache.h
+++ b/include/llvm/Analysis/AssumptionCache.h
@@ -22,16 +22,12 @@
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/ValueHandle.h"
+#include "llvm/IR/PassManager.h"
#include "llvm/Pass.h"
#include <memory>
namespace llvm {
-// FIXME: Replace this brittle forward declaration with the include of the new
-// PassManager.h when doing so doesn't break the PassManagerBuilder.
-template <typename IRUnitT> class AnalysisManager;
-class PreservedAnalyses;
-
/// \brief A cache of @llvm.assume calls within a function.
///
/// This cache provides fast lookup of assumptions within a function by caching
@@ -97,36 +93,31 @@ public:
///
/// This analysis is intended for use with the new pass manager and will vend
/// assumption caches for a given function.
-class AssumptionAnalysis {
+class AssumptionAnalysis : public AnalysisInfoMixin<AssumptionAnalysis> {
+ friend AnalysisInfoMixin<AssumptionAnalysis>;
static char PassID;
public:
typedef AssumptionCache Result;
- /// \brief Opaque, unique identifier for this analysis pass.
- static void *ID() { return (void *)&PassID; }
-
- /// \brief Provide a name for the analysis for debugging and logging.
- static StringRef name() { return "AssumptionAnalysis"; }
-
AssumptionAnalysis() {}
AssumptionAnalysis(const AssumptionAnalysis &Arg) {}
AssumptionAnalysis(AssumptionAnalysis &&Arg) {}
AssumptionAnalysis &operator=(const AssumptionAnalysis &RHS) { return *this; }
AssumptionAnalysis &operator=(AssumptionAnalysis &&RHS) { return *this; }
- AssumptionCache run(Function &F) { return AssumptionCache(F); }
+ AssumptionCache run(Function &F, FunctionAnalysisManager &) {
+ return AssumptionCache(F);
+ }
};
/// \brief Printer pass for the \c AssumptionAnalysis results.
-class AssumptionPrinterPass {
+class AssumptionPrinterPass : public PassInfoMixin<AssumptionPrinterPass> {
raw_ostream &OS;
public:
explicit AssumptionPrinterPass(raw_ostream &OS) : OS(OS) {}
- PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM);
-
- static StringRef name() { return "AssumptionPrinterPass"; }
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
};
/// \brief An immutable pass that tracks lazily created \c AssumptionCache
diff --git a/include/llvm/Analysis/BasicAliasAnalysis.h b/include/llvm/Analysis/BasicAliasAnalysis.h
index 181a9327024c..a3195d17b029 100644
--- a/include/llvm/Analysis/BasicAliasAnalysis.h
+++ b/include/llvm/Analysis/BasicAliasAnalysis.h
@@ -40,6 +40,7 @@ class BasicAAResult : public AAResultBase<BasicAAResult> {
friend AAResultBase<BasicAAResult>;
const DataLayout &DL;
+ const TargetLibraryInfo &TLI;
AssumptionCache &AC;
DominatorTree *DT;
LoopInfo *LI;
@@ -48,13 +49,14 @@ public:
BasicAAResult(const DataLayout &DL, const TargetLibraryInfo &TLI,
AssumptionCache &AC, DominatorTree *DT = nullptr,
LoopInfo *LI = nullptr)
- : AAResultBase(TLI), DL(DL), AC(AC), DT(DT), LI(LI) {}
+ : AAResultBase(), DL(DL), TLI(TLI), AC(AC), DT(DT), LI(LI) {}
BasicAAResult(const BasicAAResult &Arg)
- : AAResultBase(Arg), DL(Arg.DL), AC(Arg.AC), DT(Arg.DT), LI(Arg.LI) {}
- BasicAAResult(BasicAAResult &&Arg)
- : AAResultBase(std::move(Arg)), DL(Arg.DL), AC(Arg.AC), DT(Arg.DT),
+ : AAResultBase(Arg), DL(Arg.DL), TLI(Arg.TLI), AC(Arg.AC), DT(Arg.DT),
LI(Arg.LI) {}
+ BasicAAResult(BasicAAResult &&Arg)
+ : AAResultBase(std::move(Arg)), DL(Arg.DL), TLI(Arg.TLI), AC(Arg.AC),
+ DT(Arg.DT), LI(Arg.LI) {}
/// Handle invalidation events from the new pass manager.
///
@@ -107,6 +109,20 @@ private:
}
};
+ // Represents the internal structure of a GEP, decomposed into a base pointer,
+ // constant offsets, and variable scaled indices.
+ struct DecomposedGEP {
+ // Base pointer of the GEP
+ const Value *Base;
+ // Total constant offset w.r.t the base from indexing into structs
+ int64_t StructOffset;
+ // Total constant offset w.r.t the base from indexing through
+ // pointers/arrays/vectors
+ int64_t OtherOffset;
+ // Scaled variable (non-constant) indices.
+ SmallVector<VariableGEPIndex, 4> VarIndices;
+ };
+
/// Track alias queries to guard against recursion.
typedef std::pair<MemoryLocation, MemoryLocation> LocPair;
typedef SmallDenseMap<LocPair, AliasResult, 8> AliasCacheTy;
@@ -137,11 +153,13 @@ private:
const DataLayout &DL, unsigned Depth, AssumptionCache *AC,
DominatorTree *DT, bool &NSW, bool &NUW);
- static const Value *
- DecomposeGEPExpression(const Value *V, int64_t &BaseOffs,
- SmallVectorImpl<VariableGEPIndex> &VarIndices,
- bool &MaxLookupReached, const DataLayout &DL,
- AssumptionCache *AC, DominatorTree *DT);
+ static bool DecomposeGEPExpression(const Value *V, DecomposedGEP &Decomposed,
+ const DataLayout &DL, AssumptionCache *AC, DominatorTree *DT);
+
+ static bool isGEPBaseAtNegativeOffset(const GEPOperator *GEPOp,
+ const DecomposedGEP &DecompGEP, const DecomposedGEP &DecompObject,
+ uint64_t ObjectAccessSize);
+
/// \brief A Heuristic for aliasGEP that searches for a constant offset
/// between the variables.
///
@@ -178,20 +196,14 @@ private:
};
/// Analysis pass providing a never-invalidated alias analysis result.
-class BasicAA {
+class BasicAA : public AnalysisInfoMixin<BasicAA> {
+ friend AnalysisInfoMixin<BasicAA>;
+ static char PassID;
+
public:
typedef BasicAAResult Result;
- /// \brief Opaque, unique identifier for this analysis pass.
- static void *ID() { return (void *)&PassID; }
-
- BasicAAResult run(Function &F, AnalysisManager<Function> *AM);
-
- /// \brief Provide access to a name for this pass for debugging purposes.
- static StringRef name() { return "BasicAliasAnalysis"; }
-
-private:
- static char PassID;
+ BasicAAResult run(Function &F, AnalysisManager<Function> &AM);
};
/// Legacy wrapper pass to provide the BasicAAResult object.
diff --git a/include/llvm/Analysis/BlockFrequencyInfo.h b/include/llvm/Analysis/BlockFrequencyInfo.h
index 6f2a2b522769..7d48dfc9121e 100644
--- a/include/llvm/Analysis/BlockFrequencyInfo.h
+++ b/include/llvm/Analysis/BlockFrequencyInfo.h
@@ -14,6 +14,8 @@
#ifndef LLVM_ANALYSIS_BLOCKFREQUENCYINFO_H
#define LLVM_ANALYSIS_BLOCKFREQUENCYINFO_H
+#include "llvm/ADT/Optional.h"
+#include "llvm/IR/PassManager.h"
#include "llvm/Pass.h"
#include "llvm/Support/BlockFrequency.h"
#include <climits>
@@ -30,12 +32,21 @@ class BlockFrequencyInfo {
typedef BlockFrequencyInfoImpl<BasicBlock> ImplType;
std::unique_ptr<ImplType> BFI;
+ void operator=(const BlockFrequencyInfo &) = delete;
+ BlockFrequencyInfo(const BlockFrequencyInfo &) = delete;
+
public:
BlockFrequencyInfo();
BlockFrequencyInfo(const Function &F, const BranchProbabilityInfo &BPI,
const LoopInfo &LI);
+ BlockFrequencyInfo(BlockFrequencyInfo &&Arg);
+
+ BlockFrequencyInfo &operator=(BlockFrequencyInfo &&RHS);
+
+ ~BlockFrequencyInfo();
const Function *getFunction() const;
+ const BranchProbabilityInfo *getBPI() const;
void view() const;
/// getblockFreq - Return block frequency. Return 0 if we don't have the
@@ -45,6 +56,11 @@ public:
/// floating points.
BlockFrequency getBlockFreq(const BasicBlock *BB) const;
+ /// \brief Returns the estimated profile count of \p BB.
+ /// This computes the relative block frequency of \p BB and multiplies it by
+ /// the enclosing function's count (if available) and returns the value.
+ Optional<uint64_t> getBlockProfileCount(const BasicBlock *BB) const;
+
// Set the frequency of the given basic block.
void setBlockFreq(const BasicBlock *BB, uint64_t Freq);
@@ -65,6 +81,30 @@ public:
void print(raw_ostream &OS) const;
};
+/// \brief Analysis pass which computes \c BlockFrequencyInfo.
+class BlockFrequencyAnalysis
+ : public AnalysisInfoMixin<BlockFrequencyAnalysis> {
+ friend AnalysisInfoMixin<BlockFrequencyAnalysis>;
+ static char PassID;
+
+public:
+ /// \brief Provide the result typedef for this analysis pass.
+ typedef BlockFrequencyInfo Result;
+
+ /// \brief Run the analysis pass over a function and produce BFI.
+ Result run(Function &F, AnalysisManager<Function> &AM);
+};
+
+/// \brief Printer pass for the \c BlockFrequencyInfo results.
+class BlockFrequencyPrinterPass
+ : public PassInfoMixin<BlockFrequencyPrinterPass> {
+ raw_ostream &OS;
+
+public:
+ explicit BlockFrequencyPrinterPass(raw_ostream &OS) : OS(OS) {}
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
+};
+
/// \brief Legacy analysis pass which computes \c BlockFrequencyInfo.
class BlockFrequencyInfoWrapperPass : public FunctionPass {
BlockFrequencyInfo BFI;
diff --git a/include/llvm/Analysis/BlockFrequencyInfoImpl.h b/include/llvm/Analysis/BlockFrequencyInfoImpl.h
index 387e9a887d93..7ed06b1bb68f 100644
--- a/include/llvm/Analysis/BlockFrequencyInfoImpl.h
+++ b/include/llvm/Analysis/BlockFrequencyInfoImpl.h
@@ -16,12 +16,16 @@
#define LLVM_ANALYSIS_BLOCKFREQUENCYINFOIMPL_H
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/Support/BlockFrequency.h"
#include "llvm/Support/BranchProbability.h"
+#include "llvm/Support/DOTGraphTraits.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/Format.h"
#include "llvm/Support/ScaledNumber.h"
#include "llvm/Support/raw_ostream.h"
#include <deque>
@@ -476,6 +480,8 @@ public:
Scaled64 getFloatingBlockFreq(const BlockNode &Node) const;
BlockFrequency getBlockFreq(const BlockNode &Node) const;
+ Optional<uint64_t> getBlockProfileCount(const Function &F,
+ const BlockNode &Node) const;
void setBlockFreq(const BlockNode &Node, uint64_t Freq);
@@ -915,11 +921,17 @@ public:
BlockFrequency getBlockFreq(const BlockT *BB) const {
return BlockFrequencyInfoImplBase::getBlockFreq(getNode(BB));
}
+ Optional<uint64_t> getBlockProfileCount(const Function &F,
+ const BlockT *BB) const {
+ return BlockFrequencyInfoImplBase::getBlockProfileCount(F, getNode(BB));
+ }
void setBlockFreq(const BlockT *BB, uint64_t Freq);
Scaled64 getFloatingBlockFreq(const BlockT *BB) const {
return BlockFrequencyInfoImplBase::getFloatingBlockFreq(getNode(BB));
}
+ const BranchProbabilityInfoT &getBPI() const { return *BPI; }
+
/// \brief Print the frequencies for the current function.
///
/// Prints the frequencies for the blocks in the current function.
@@ -1173,12 +1185,10 @@ void BlockFrequencyInfoImpl<BT>::computeIrreducibleMass(
updateLoopWithIrreducible(*OuterLoop);
}
-namespace {
// A helper function that converts a branch probability into weight.
inline uint32_t getWeightFromBranchProb(const BranchProbability Prob) {
return Prob.getNumerator();
}
-} // namespace
template <class BT>
bool
@@ -1224,6 +1234,115 @@ raw_ostream &BlockFrequencyInfoImpl<BT>::print(raw_ostream &OS) const {
return OS;
}
+// Graph trait base class for block frequency information graph
+// viewer.
+
+enum GVDAGType { GVDT_None, GVDT_Fraction, GVDT_Integer, GVDT_Count };
+
+template <class BlockFrequencyInfoT, class BranchProbabilityInfoT>
+struct BFIDOTGraphTraitsBase : public DefaultDOTGraphTraits {
+ explicit BFIDOTGraphTraitsBase(bool isSimple = false)
+ : DefaultDOTGraphTraits(isSimple) {}
+
+ typedef GraphTraits<BlockFrequencyInfoT *> GTraits;
+ typedef typename GTraits::NodeType NodeType;
+ typedef typename GTraits::ChildIteratorType EdgeIter;
+ typedef typename GTraits::nodes_iterator NodeIter;
+
+ uint64_t MaxFrequency = 0;
+ static std::string getGraphName(const BlockFrequencyInfoT *G) {
+ return G->getFunction()->getName();
+ }
+
+ std::string getNodeAttributes(const NodeType *Node,
+ const BlockFrequencyInfoT *Graph,
+ unsigned HotPercentThreshold = 0) {
+ std::string Result;
+ if (!HotPercentThreshold)
+ return Result;
+
+ // Compute MaxFrequency on the fly:
+ if (!MaxFrequency) {
+ for (NodeIter I = GTraits::nodes_begin(Graph),
+ E = GTraits::nodes_end(Graph);
+ I != E; ++I) {
+ NodeType &N = *I;
+ MaxFrequency =
+ std::max(MaxFrequency, Graph->getBlockFreq(&N).getFrequency());
+ }
+ }
+ BlockFrequency Freq = Graph->getBlockFreq(Node);
+ BlockFrequency HotFreq =
+ (BlockFrequency(MaxFrequency) *
+ BranchProbability::getBranchProbability(HotPercentThreshold, 100));
+
+ if (Freq < HotFreq)
+ return Result;
+
+ raw_string_ostream OS(Result);
+ OS << "color=\"red\"";
+ OS.flush();
+ return Result;
+ }
+
+ std::string getNodeLabel(const NodeType *Node,
+ const BlockFrequencyInfoT *Graph, GVDAGType GType) {
+ std::string Result;
+ raw_string_ostream OS(Result);
+
+ OS << Node->getName().str() << " : ";
+ switch (GType) {
+ case GVDT_Fraction:
+ Graph->printBlockFreq(OS, Node);
+ break;
+ case GVDT_Integer:
+ OS << Graph->getBlockFreq(Node).getFrequency();
+ break;
+ case GVDT_Count: {
+ auto Count = Graph->getBlockProfileCount(Node);
+ if (Count)
+ OS << Count.getValue();
+ else
+ OS << "Unknown";
+ break;
+ }
+ case GVDT_None:
+ llvm_unreachable("If we are not supposed to render a graph we should "
+ "never reach this point.");
+ }
+ return Result;
+ }
+
+ std::string getEdgeAttributes(const NodeType *Node, EdgeIter EI,
+ const BlockFrequencyInfoT *BFI,
+ const BranchProbabilityInfoT *BPI,
+ unsigned HotPercentThreshold = 0) {
+ std::string Str;
+ if (!BPI)
+ return Str;
+
+ BranchProbability BP = BPI->getEdgeProbability(Node, EI);
+ uint32_t N = BP.getNumerator();
+ uint32_t D = BP.getDenominator();
+ double Percent = 100.0 * N / D;
+ raw_string_ostream OS(Str);
+ OS << format("label=\"%.1f%%\"", Percent);
+
+ if (HotPercentThreshold) {
+ BlockFrequency EFreq = BFI->getBlockFreq(Node) * BP;
+ BlockFrequency HotFreq = BlockFrequency(MaxFrequency) *
+ BranchProbability(HotPercentThreshold, 100);
+
+ if (EFreq >= HotFreq) {
+ OS << ",color=\"red\"";
+ }
+ }
+
+ OS.flush();
+ return Str;
+ }
+};
+
} // end namespace llvm
#undef DEBUG_TYPE
diff --git a/include/llvm/Analysis/BranchProbabilityInfo.h b/include/llvm/Analysis/BranchProbabilityInfo.h
index cfdf218491bd..6434ba962ebc 100644
--- a/include/llvm/Analysis/BranchProbabilityInfo.h
+++ b/include/llvm/Analysis/BranchProbabilityInfo.h
@@ -15,8 +15,11 @@
#define LLVM_ANALYSIS_BRANCHPROBABILITYINFO_H
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/IR/CFG.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/IR/ValueHandle.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#include "llvm/Support/BranchProbability.h"
@@ -40,7 +43,22 @@ class raw_ostream;
class BranchProbabilityInfo {
public:
BranchProbabilityInfo() {}
- BranchProbabilityInfo(Function &F, const LoopInfo &LI) { calculate(F, LI); }
+ BranchProbabilityInfo(const Function &F, const LoopInfo &LI) {
+ calculate(F, LI);
+ }
+
+ BranchProbabilityInfo(BranchProbabilityInfo &&Arg)
+ : Probs(std::move(Arg.Probs)), LastF(Arg.LastF),
+ PostDominatedByUnreachable(std::move(Arg.PostDominatedByUnreachable)),
+ PostDominatedByColdCall(std::move(Arg.PostDominatedByColdCall)) {}
+
+ BranchProbabilityInfo &operator=(BranchProbabilityInfo &&RHS) {
+ releaseMemory();
+ Probs = std::move(RHS.Probs);
+ PostDominatedByColdCall = std::move(RHS.PostDominatedByColdCall);
+ PostDominatedByUnreachable = std::move(RHS.PostDominatedByUnreachable);
+ return *this;
+ }
void releaseMemory();
@@ -74,7 +92,7 @@ public:
///
/// Given a basic block, look through its successors and if one exists for
/// which \see isEdgeHot would return true, return that successor block.
- BasicBlock *getHotSucc(BasicBlock *BB) const;
+ const BasicBlock *getHotSucc(const BasicBlock *BB) const;
/// \brief Print an edge's probability.
///
@@ -98,9 +116,31 @@ public:
return IsLikely ? LikelyProb : LikelyProb.getCompl();
}
- void calculate(Function &F, const LoopInfo& LI);
+ void calculate(const Function &F, const LoopInfo &LI);
+
+ /// Forget analysis results for the given basic block.
+ void eraseBlock(const BasicBlock *BB);
private:
+ void operator=(const BranchProbabilityInfo &) = delete;
+ BranchProbabilityInfo(const BranchProbabilityInfo &) = delete;
+
+ // We need to store CallbackVH's in order to correctly handle basic block
+ // removal.
+ class BasicBlockCallbackVH final : public CallbackVH {
+ BranchProbabilityInfo *BPI;
+ void deleted() override {
+ assert(BPI != nullptr);
+ BPI->eraseBlock(cast<BasicBlock>(getValPtr()));
+ BPI->Handles.erase(*this);
+ }
+
+ public:
+ BasicBlockCallbackVH(const Value *V, BranchProbabilityInfo *BPI=nullptr)
+ : CallbackVH(const_cast<Value *>(V)), BPI(BPI) {}
+ };
+ DenseSet<BasicBlockCallbackVH, DenseMapInfo<Value*>> 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.
typedef std::pair<const BasicBlock *, unsigned> Edge;
@@ -116,22 +156,46 @@ private:
DenseMap<Edge, BranchProbability> Probs;
/// \brief Track the last function we run over for printing.
- Function *LastF;
+ const Function *LastF;
/// \brief Track the set of blocks directly succeeded by a returning block.
- SmallPtrSet<BasicBlock *, 16> PostDominatedByUnreachable;
+ SmallPtrSet<const BasicBlock *, 16> PostDominatedByUnreachable;
/// \brief Track the set of blocks that always lead to a cold call.
- SmallPtrSet<BasicBlock *, 16> PostDominatedByColdCall;
-
- bool calcUnreachableHeuristics(BasicBlock *BB);
- bool calcMetadataWeights(BasicBlock *BB);
- bool calcColdCallHeuristics(BasicBlock *BB);
- bool calcPointerHeuristics(BasicBlock *BB);
- bool calcLoopBranchHeuristics(BasicBlock *BB, const LoopInfo &LI);
- bool calcZeroHeuristics(BasicBlock *BB);
- bool calcFloatingPointHeuristics(BasicBlock *BB);
- bool calcInvokeHeuristics(BasicBlock *BB);
+ SmallPtrSet<const BasicBlock *, 16> PostDominatedByColdCall;
+
+ bool calcUnreachableHeuristics(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);
+ bool calcZeroHeuristics(const BasicBlock *BB);
+ bool calcFloatingPointHeuristics(const BasicBlock *BB);
+ bool calcInvokeHeuristics(const BasicBlock *BB);
+};
+
+/// \brief Analysis pass which computes \c BranchProbabilityInfo.
+class BranchProbabilityAnalysis
+ : public AnalysisInfoMixin<BranchProbabilityAnalysis> {
+ friend AnalysisInfoMixin<BranchProbabilityAnalysis>;
+ static char PassID;
+
+public:
+ /// \brief Provide the result typedef for this analysis pass.
+ typedef BranchProbabilityInfo Result;
+
+ /// \brief Run the analysis pass over a function and produce BPI.
+ BranchProbabilityInfo run(Function &F, AnalysisManager<Function> &AM);
+};
+
+/// \brief Printer pass for the \c BranchProbabilityAnalysis results.
+class BranchProbabilityPrinterPass
+ : public PassInfoMixin<BranchProbabilityPrinterPass> {
+ raw_ostream &OS;
+
+public:
+ explicit BranchProbabilityPrinterPass(raw_ostream &OS) : OS(OS) {}
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
};
/// \brief Legacy analysis pass which computes \c BranchProbabilityInfo.
diff --git a/include/llvm/Analysis/CFLAndersAliasAnalysis.h b/include/llvm/Analysis/CFLAndersAliasAnalysis.h
new file mode 100644
index 000000000000..48eca888419a
--- /dev/null
+++ b/include/llvm/Analysis/CFLAndersAliasAnalysis.h
@@ -0,0 +1,138 @@
+//=- CFLAndersAliasAnalysis.h - Unification-based Alias Analysis ---*- C++-*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This is the interface for LLVM's inclusion-based alias analysis
+/// implemented with CFL graph reachability.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ANALYSIS_CFLANDERSALIASANALYSIS_H
+#define LLVM_ANALYSIS_CFLANDERSALIASANALYSIS_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/Analysis/AliasAnalysis.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/ValueHandle.h"
+#include "llvm/Pass.h"
+#include <forward_list>
+
+namespace llvm {
+
+class TargetLibraryInfo;
+
+namespace cflaa {
+struct AliasSummary;
+}
+
+class CFLAndersAAResult : public AAResultBase<CFLAndersAAResult> {
+ friend AAResultBase<CFLAndersAAResult>;
+ class FunctionInfo;
+
+public:
+ explicit CFLAndersAAResult(const TargetLibraryInfo &);
+ CFLAndersAAResult(CFLAndersAAResult &&);
+ ~CFLAndersAAResult();
+
+ /// Handle invalidation events from the new pass manager.
+ /// By definition, this result is stateless and so remains valid.
+ bool invalidate(Function &, const PreservedAnalyses &) { return false; }
+ /// Evict the given function from cache
+ void evict(const Function &Fn);
+
+ /// \brief Get the alias summary for the given function
+ /// Return nullptr if the summary is not found or not available
+ const cflaa::AliasSummary *getAliasSummary(const Function &);
+
+ AliasResult query(const MemoryLocation &, const MemoryLocation &);
+ AliasResult alias(const MemoryLocation &, const MemoryLocation &);
+
+private:
+ struct FunctionHandle final : public CallbackVH {
+ FunctionHandle(Function *Fn, CFLAndersAAResult *Result)
+ : CallbackVH(Fn), Result(Result) {
+ assert(Fn != nullptr);
+ assert(Result != nullptr);
+ }
+
+ void deleted() override { removeSelfFromCache(); }
+ void allUsesReplacedWith(Value *) override { removeSelfFromCache(); }
+
+ private:
+ CFLAndersAAResult *Result;
+
+ void removeSelfFromCache() {
+ assert(Result != nullptr);
+ auto *Val = getValPtr();
+ Result->evict(*cast<Function>(Val));
+ setValPtr(nullptr);
+ }
+ };
+
+ /// \brief Ensures that the given function is available in the cache.
+ /// Returns the appropriate entry from the cache.
+ const Optional<FunctionInfo> &ensureCached(const Function &);
+
+ /// \brief Inserts the given Function into the cache.
+ void scan(const Function &);
+
+ /// \brief Build summary for a given function
+ FunctionInfo buildInfoFrom(const Function &);
+
+ const TargetLibraryInfo &TLI;
+
+ /// \brief Cached mapping of Functions to their StratifiedSets.
+ /// If a function's sets are currently being built, it is marked
+ /// in the cache as an Optional without a value. This way, if we
+ /// have any kind of recursion, it is discernable from a function
+ /// that simply has empty sets.
+ DenseMap<const Function *, Optional<FunctionInfo>> Cache;
+
+ std::forward_list<FunctionHandle> Handles;
+};
+
+/// Analysis pass providing a never-invalidated alias analysis result.
+///
+/// FIXME: We really should refactor CFL to use the analysis more heavily, and
+/// in particular to leverage invalidation to trigger re-computation.
+class CFLAndersAA : public AnalysisInfoMixin<CFLAndersAA> {
+ friend AnalysisInfoMixin<CFLAndersAA>;
+ static char PassID;
+
+public:
+ typedef CFLAndersAAResult Result;
+
+ CFLAndersAAResult run(Function &F, AnalysisManager<Function> &AM);
+};
+
+/// Legacy wrapper pass to provide the CFLAndersAAResult object.
+class CFLAndersAAWrapperPass : public ImmutablePass {
+ std::unique_ptr<CFLAndersAAResult> Result;
+
+public:
+ static char ID;
+
+ CFLAndersAAWrapperPass();
+
+ CFLAndersAAResult &getResult() { return *Result; }
+ const CFLAndersAAResult &getResult() const { return *Result; }
+
+ void initializePass() override;
+ void getAnalysisUsage(AnalysisUsage &AU) const override;
+};
+
+//===--------------------------------------------------------------------===//
+//
+// createCFLAndersAAWrapperPass - This pass implements a set-based approach to
+// alias analysis.
+//
+ImmutablePass *createCFLAndersAAWrapperPass();
+}
+
+#endif
diff --git a/include/llvm/Analysis/CFLAliasAnalysis.h b/include/llvm/Analysis/CFLSteensAliasAnalysis.h
index 7473a454ab30..80a00d02b811 100644
--- a/include/llvm/Analysis/CFLAliasAnalysis.h
+++ b/include/llvm/Analysis/CFLSteensAliasAnalysis.h
@@ -1,4 +1,4 @@
-//===- CFLAliasAnalysis.h - CFL-Based Alias Analysis Interface ---*- C++ -*-==//
+//=- CFLSteensAliasAnalysis.h - Unification-based Alias Analysis ---*- C++-*-=//
//
// The LLVM Compiler Infrastructure
//
@@ -7,17 +7,18 @@
//
//===----------------------------------------------------------------------===//
/// \file
-/// This is the interface for LLVM's primary stateless and local alias analysis.
+/// This is the interface for LLVM's unification-based alias analysis
+/// implemented with CFL graph reachability.
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_ANALYSIS_CFLALIASANALYSIS_H
-#define LLVM_ANALYSIS_CFLALIASANALYSIS_H
+#ifndef LLVM_ANALYSIS_CFLSTEENSALIASANALYSIS_H
+#define LLVM_ANALYSIS_CFLSTEENSALIASANALYSIS_H
-#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ValueHandle.h"
@@ -26,14 +27,20 @@
namespace llvm {
-class CFLAAResult : public AAResultBase<CFLAAResult> {
- friend AAResultBase<CFLAAResult>;
+class TargetLibraryInfo;
- struct FunctionInfo;
+namespace cflaa {
+struct AliasSummary;
+}
+
+class CFLSteensAAResult : public AAResultBase<CFLSteensAAResult> {
+ friend AAResultBase<CFLSteensAAResult>;
+ class FunctionInfo;
public:
- explicit CFLAAResult(const TargetLibraryInfo &TLI);
- CFLAAResult(CFLAAResult &&Arg);
+ explicit CFLSteensAAResult(const TargetLibraryInfo &);
+ CFLSteensAAResult(CFLSteensAAResult &&Arg);
+ ~CFLSteensAAResult();
/// Handle invalidation events from the new pass manager.
///
@@ -49,26 +56,23 @@ public:
/// Returns the appropriate entry from the cache.
const Optional<FunctionInfo> &ensureCached(Function *Fn);
+ /// \brief Get the alias summary for the given function
+ /// Return nullptr if the summary is not found or not available
+ const cflaa::AliasSummary *getAliasSummary(Function &Fn);
+
AliasResult query(const MemoryLocation &LocA, const MemoryLocation &LocB);
AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB) {
- if (LocA.Ptr == LocB.Ptr) {
- if (LocA.Size == LocB.Size) {
- return MustAlias;
- } else {
- return PartialAlias;
- }
- }
+ if (LocA.Ptr == LocB.Ptr)
+ return LocA.Size == LocB.Size ? MustAlias : PartialAlias;
// Comparisons between global variables and other constants should be
// handled by BasicAA.
- // TODO: ConstantExpr handling -- CFLAA may report NoAlias when comparing
- // a GlobalValue and ConstantExpr, but every query needs to have at least
- // one Value tied to a Function, and neither GlobalValues nor ConstantExprs
- // are.
- if (isa<Constant>(LocA.Ptr) && isa<Constant>(LocB.Ptr)) {
+ // CFLSteensAA may report NoAlias when comparing a GlobalValue and
+ // ConstantExpr, but every query needs to have at least one Value tied to a
+ // Function, and neither GlobalValues nor ConstantExprs are.
+ if (isa<Constant>(LocA.Ptr) && isa<Constant>(LocB.Ptr))
return AAResultBase::alias(LocA, LocB);
- }
AliasResult QueryResult = query(LocA, LocB);
if (QueryResult == MayAlias)
@@ -77,9 +81,19 @@ public:
return QueryResult;
}
+ /// Get the location associated with a pointer argument of a callsite.
+ ModRefInfo getArgModRefInfo(ImmutableCallSite CS, unsigned ArgIdx);
+
+ /// Returns the behavior when calling the given call site.
+ FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS);
+
+ /// Returns the behavior when calling the given function. For use when the
+ /// call site is not known.
+ FunctionModRefBehavior getModRefBehavior(const Function *F);
+
private:
struct FunctionHandle final : public CallbackVH {
- FunctionHandle(Function *Fn, CFLAAResult *Result)
+ FunctionHandle(Function *Fn, CFLSteensAAResult *Result)
: CallbackVH(Fn), Result(Result) {
assert(Fn != nullptr);
assert(Result != nullptr);
@@ -89,7 +103,7 @@ private:
void allUsesReplacedWith(Value *) override { removeSelfFromCache(); }
private:
- CFLAAResult *Result;
+ CFLSteensAAResult *Result;
void removeSelfFromCache() {
assert(Result != nullptr);
@@ -99,6 +113,8 @@ private:
}
};
+ const TargetLibraryInfo &TLI;
+
/// \brief Cached mapping of Functions to their StratifiedSets.
/// If a function's sets are currently being built, it is marked
/// in the cache as an Optional without a value. This way, if we
@@ -114,45 +130,38 @@ private:
///
/// FIXME: We really should refactor CFL to use the analysis more heavily, and
/// in particular to leverage invalidation to trigger re-computation of sets.
-class CFLAA {
-public:
- typedef CFLAAResult Result;
-
- /// \brief Opaque, unique identifier for this analysis pass.
- static void *ID() { return (void *)&PassID; }
-
- CFLAAResult run(Function &F, AnalysisManager<Function> *AM);
+class CFLSteensAA : public AnalysisInfoMixin<CFLSteensAA> {
+ friend AnalysisInfoMixin<CFLSteensAA>;
+ static char PassID;
- /// \brief Provide access to a name for this pass for debugging purposes.
- static StringRef name() { return "CFLAA"; }
+public:
+ typedef CFLSteensAAResult Result;
-private:
- static char PassID;
+ CFLSteensAAResult run(Function &F, AnalysisManager<Function> &AM);
};
-/// Legacy wrapper pass to provide the CFLAAResult object.
-class CFLAAWrapperPass : public ImmutablePass {
- std::unique_ptr<CFLAAResult> Result;
+/// Legacy wrapper pass to provide the CFLSteensAAResult object.
+class CFLSteensAAWrapperPass : public ImmutablePass {
+ std::unique_ptr<CFLSteensAAResult> Result;
public:
static char ID;
- CFLAAWrapperPass();
+ CFLSteensAAWrapperPass();
- CFLAAResult &getResult() { return *Result; }
- const CFLAAResult &getResult() const { return *Result; }
+ CFLSteensAAResult &getResult() { return *Result; }
+ const CFLSteensAAResult &getResult() const { return *Result; }
- bool doInitialization(Module &M) override;
- bool doFinalization(Module &M) override;
+ void initializePass() override;
void getAnalysisUsage(AnalysisUsage &AU) const override;
};
//===--------------------------------------------------------------------===//
//
-// createCFLAAWrapperPass - This pass implements a set-based approach to
+// createCFLSteensAAWrapperPass - This pass implements a set-based approach to
// alias analysis.
//
-ImmutablePass *createCFLAAWrapperPass();
+ImmutablePass *createCFLSteensAAWrapperPass();
}
#endif
diff --git a/include/llvm/Analysis/CGSCCPassManager.h b/include/llvm/Analysis/CGSCCPassManager.h
index e7635eb1ab67..3263ecec4e26 100644
--- a/include/llvm/Analysis/CGSCCPassManager.h
+++ b/include/llvm/Analysis/CGSCCPassManager.h
@@ -11,7 +11,7 @@
/// This header provides classes for managing passes over SCCs of the call
/// graph. These passes form an important component of LLVM's interprocedural
/// optimizations. Because they operate on the SCCs of the call graph, and they
-/// wtraverse the graph in post order, they can effectively do pair-wise
+/// traverse the graph in post order, they can effectively do pair-wise
/// interprocedural optimizations for all call edges in the program. At each
/// call site edge, the callee has already been optimized as much as is
/// possible. This in turn allows very accurate analysis of it for IPO.
@@ -26,6 +26,7 @@
namespace llvm {
+extern template class PassManager<LazyCallGraph::SCC>;
/// \brief The CGSCC pass manager.
///
/// See the documentation for the PassManager template for details. It runs
@@ -33,6 +34,7 @@ namespace llvm {
/// typedef serves as a convenient way to refer to this construct.
typedef PassManager<LazyCallGraph::SCC> CGSCCPassManager;
+extern template class AnalysisManager<LazyCallGraph::SCC>;
/// \brief The CGSCC analysis manager.
///
/// See the documentation for the AnalysisManager template for detail
@@ -41,147 +43,16 @@ typedef PassManager<LazyCallGraph::SCC> CGSCCPassManager;
/// pass manager infrastructure.
typedef AnalysisManager<LazyCallGraph::SCC> CGSCCAnalysisManager;
-/// \brief A module analysis which acts as a proxy for a CGSCC analysis
-/// manager.
-///
-/// This primarily proxies invalidation information from the module analysis
-/// manager and module pass manager to a CGSCC analysis manager. You should
-/// never use a CGSCC analysis manager from within (transitively) a module
-/// pass manager unless your parent module pass has received a proxy result
-/// object for it.
-class CGSCCAnalysisManagerModuleProxy {
-public:
- class Result {
- public:
- explicit Result(CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {}
- // We have to explicitly define all the special member functions because
- // MSVC refuses to generate them.
- Result(const Result &Arg) : CGAM(Arg.CGAM) {}
- Result(Result &&Arg) : CGAM(std::move(Arg.CGAM)) {}
- Result &operator=(Result RHS) {
- std::swap(CGAM, RHS.CGAM);
- return *this;
- }
- ~Result();
-
- /// \brief Accessor for the \c CGSCCAnalysisManager.
- CGSCCAnalysisManager &getManager() { return *CGAM; }
-
- /// \brief Handler for invalidation of the module.
- ///
- /// If this analysis itself is preserved, then we assume that the call
- /// graph of the module hasn't changed and thus we don't need to invalidate
- /// *all* cached data associated with a \c SCC* in the \c
- /// CGSCCAnalysisManager.
- ///
- /// Regardless of whether this analysis is marked as preserved, all of the
- /// analyses in the \c CGSCCAnalysisManager are potentially invalidated
- /// based on the set of preserved analyses.
- bool invalidate(Module &M, const PreservedAnalyses &PA);
-
- private:
- CGSCCAnalysisManager *CGAM;
- };
-
- static void *ID() { return (void *)&PassID; }
-
- static StringRef name() { return "CGSCCAnalysisManagerModuleProxy"; }
-
- explicit CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManager &CGAM)
- : CGAM(&CGAM) {}
- // We have to explicitly define all the special member functions because MSVC
- // refuses to generate them.
- CGSCCAnalysisManagerModuleProxy(const CGSCCAnalysisManagerModuleProxy &Arg)
- : CGAM(Arg.CGAM) {}
- CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManagerModuleProxy &&Arg)
- : CGAM(std::move(Arg.CGAM)) {}
- CGSCCAnalysisManagerModuleProxy &
- operator=(CGSCCAnalysisManagerModuleProxy RHS) {
- std::swap(CGAM, RHS.CGAM);
- return *this;
- }
-
- /// \brief Run the analysis pass and create our proxy result object.
- ///
- /// This doesn't do any interesting work, it is primarily used to insert our
- /// proxy result object into the module analysis cache so that we can proxy
- /// invalidation to the CGSCC analysis manager.
- ///
- /// In debug builds, it will also assert that the analysis manager is empty
- /// as no queries should arrive at the CGSCC analysis manager prior to
- /// this analysis being requested.
- Result run(Module &M);
+extern template class InnerAnalysisManagerProxy<CGSCCAnalysisManager, Module>;
+/// A proxy from a \c CGSCCAnalysisManager to a \c Module.
+typedef InnerAnalysisManagerProxy<CGSCCAnalysisManager, Module>
+ CGSCCAnalysisManagerModuleProxy;
-private:
- static char PassID;
-
- CGSCCAnalysisManager *CGAM;
-};
-
-/// \brief A CGSCC analysis which acts as a proxy for a module analysis
-/// manager.
-///
-/// This primarily provides an accessor to a parent module analysis manager to
-/// CGSCC passes. Only the const interface of the module analysis manager is
-/// provided to indicate that once inside of a CGSCC analysis pass you
-/// cannot request a module analysis to actually run. Instead, the user must
-/// rely on the \c getCachedResult API.
-///
-/// This proxy *doesn't* manage the invalidation in any way. That is handled by
-/// the recursive return path of each layer of the pass manager and the
-/// returned PreservedAnalysis set.
-class ModuleAnalysisManagerCGSCCProxy {
-public:
- /// \brief Result proxy object for \c ModuleAnalysisManagerCGSCCProxy.
- class Result {
- public:
- explicit Result(const ModuleAnalysisManager &MAM) : MAM(&MAM) {}
- // We have to explicitly define all the special member functions because
- // MSVC refuses to generate them.
- Result(const Result &Arg) : MAM(Arg.MAM) {}
- Result(Result &&Arg) : MAM(std::move(Arg.MAM)) {}
- Result &operator=(Result RHS) {
- std::swap(MAM, RHS.MAM);
- return *this;
- }
-
- const ModuleAnalysisManager &getManager() const { return *MAM; }
-
- /// \brief Handle invalidation by ignoring it, this pass is immutable.
- bool invalidate(LazyCallGraph::SCC &) { return false; }
-
- private:
- const ModuleAnalysisManager *MAM;
- };
-
- static void *ID() { return (void *)&PassID; }
-
- static StringRef name() { return "ModuleAnalysisManagerCGSCCProxy"; }
-
- ModuleAnalysisManagerCGSCCProxy(const ModuleAnalysisManager &MAM)
- : MAM(&MAM) {}
- // We have to explicitly define all the special member functions because MSVC
- // refuses to generate them.
- ModuleAnalysisManagerCGSCCProxy(const ModuleAnalysisManagerCGSCCProxy &Arg)
- : MAM(Arg.MAM) {}
- ModuleAnalysisManagerCGSCCProxy(ModuleAnalysisManagerCGSCCProxy &&Arg)
- : MAM(std::move(Arg.MAM)) {}
- ModuleAnalysisManagerCGSCCProxy &
- operator=(ModuleAnalysisManagerCGSCCProxy RHS) {
- std::swap(MAM, RHS.MAM);
- return *this;
- }
-
- /// \brief Run the analysis pass and create our proxy result object.
- /// Nothing to see here, it just forwards the \c MAM reference into the
- /// result.
- Result run(LazyCallGraph::SCC &) { return Result(*MAM); }
-
-private:
- static char PassID;
-
- const ModuleAnalysisManager *MAM;
-};
+extern template class OuterAnalysisManagerProxy<ModuleAnalysisManager,
+ LazyCallGraph::SCC>;
+/// A proxy from a \c ModuleAnalysisManager to an \c SCC.
+typedef OuterAnalysisManagerProxy<ModuleAnalysisManager, LazyCallGraph::SCC>
+ ModuleAnalysisManagerCGSCCProxy;
/// \brief The core module pass which does a post-order walk of the SCCs and
/// runs a CGSCC pass over each one.
@@ -192,21 +63,24 @@ private:
/// \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 <typename CGSCCPassT> class ModuleToPostOrderCGSCCPassAdaptor {
+template <typename CGSCCPassT>
+class ModuleToPostOrderCGSCCPassAdaptor
+ : public PassInfoMixin<ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>> {
public:
- explicit ModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass)
- : Pass(std::move(Pass)) {}
+ explicit ModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass, bool DebugLogging = false)
+ : Pass(std::move(Pass)), DebugLogging(DebugLogging) {}
// We have to explicitly define all the special member functions because MSVC
// refuses to generate them.
ModuleToPostOrderCGSCCPassAdaptor(
const ModuleToPostOrderCGSCCPassAdaptor &Arg)
- : Pass(Arg.Pass) {}
+ : Pass(Arg.Pass), DebugLogging(Arg.DebugLogging) {}
ModuleToPostOrderCGSCCPassAdaptor(ModuleToPostOrderCGSCCPassAdaptor &&Arg)
- : Pass(std::move(Arg.Pass)) {}
+ : Pass(std::move(Arg.Pass)), DebugLogging(Arg.DebugLogging) {}
friend void swap(ModuleToPostOrderCGSCCPassAdaptor &LHS,
ModuleToPostOrderCGSCCPassAdaptor &RHS) {
using std::swap;
swap(LHS.Pass, RHS.Pass);
+ swap(LHS.DebugLogging, RHS.DebugLogging);
}
ModuleToPostOrderCGSCCPassAdaptor &
operator=(ModuleToPostOrderCGSCCPassAdaptor RHS) {
@@ -215,33 +89,36 @@ public:
}
/// \brief Runs the CGSCC pass across every SCC in the module.
- PreservedAnalyses run(Module &M, ModuleAnalysisManager *AM) {
- assert(AM && "We need analyses to compute the call graph!");
-
+ PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) {
// Setup the CGSCC analysis manager from its proxy.
CGSCCAnalysisManager &CGAM =
- AM->getResult<CGSCCAnalysisManagerModuleProxy>(M).getManager();
+ AM.getResult<CGSCCAnalysisManagerModuleProxy>(M).getManager();
// Get the call graph for this module.
- LazyCallGraph &CG = AM->getResult<LazyCallGraphAnalysis>(M);
+ LazyCallGraph &CG = AM.getResult<LazyCallGraphAnalysis>(M);
PreservedAnalyses PA = PreservedAnalyses::all();
- for (LazyCallGraph::SCC &C : CG.postorder_sccs()) {
- PreservedAnalyses PassPA = Pass.run(C, &CGAM);
-
- // We know that the CGSCC pass couldn't have invalidated any other
- // SCC's analyses (that's the contract of a CGSCC pass), so
- // directly handle the CGSCC analysis manager's invalidation here. We
- // also update the preserved set of analyses to reflect that invalidated
- // analyses are now safe to preserve.
- // FIXME: This isn't quite correct. We need to handle the case where the
- // pass updated the CG, particularly some child of the current SCC, and
- // invalidate its analyses.
- PassPA = CGAM.invalidate(C, std::move(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));
+ for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs()) {
+ if (DebugLogging)
+ dbgs() << "Running an SCC pass across the RefSCC: " << RC << "\n";
+
+ for (LazyCallGraph::SCC &C : RC) {
+ PreservedAnalyses PassPA = Pass.run(C, CGAM);
+
+ // We know that the CGSCC pass couldn't have invalidated any other
+ // SCC's analyses (that's the contract of a CGSCC pass), so
+ // directly handle the CGSCC analysis manager's invalidation here. We
+ // also update the preserved set of analyses to reflect that invalidated
+ // analyses are now safe to preserve.
+ // FIXME: This isn't quite correct. We need to handle the case where the
+ // pass updated the CG, particularly some child of the current SCC, and
+ // invalidate its analyses.
+ PassPA = CGAM.invalidate(C, std::move(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));
+ }
}
// By definition we preserve the proxy. This precludes *any* invalidation
@@ -252,163 +129,29 @@ public:
return PA;
}
- static StringRef name() { return "ModuleToPostOrderCGSCCPassAdaptor"; }
-
private:
CGSCCPassT Pass;
+ bool DebugLogging;
};
/// \brief A function to deduce a function pass type and wrap it in the
/// templated adaptor.
template <typename CGSCCPassT>
ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>
-createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass) {
- return ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>(std::move(Pass));
+createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass, bool DebugLogging = false) {
+ return ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>(std::move(Pass), DebugLogging);
}
-/// \brief A CGSCC analysis which acts as a proxy for a function analysis
-/// manager.
-///
-/// This primarily proxies invalidation information from the CGSCC analysis
-/// manager and CGSCC pass manager to a function analysis manager. You should
-/// never use a function analysis manager from within (transitively) a CGSCC
-/// pass manager unless your parent CGSCC pass has received a proxy result
-/// object for it.
-class FunctionAnalysisManagerCGSCCProxy {
-public:
- class Result {
- public:
- explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {}
- // We have to explicitly define all the special member functions because
- // MSVC refuses to generate them.
- Result(const Result &Arg) : FAM(Arg.FAM) {}
- Result(Result &&Arg) : FAM(std::move(Arg.FAM)) {}
- Result &operator=(Result RHS) {
- std::swap(FAM, RHS.FAM);
- return *this;
- }
- ~Result();
-
- /// \brief Accessor for the \c FunctionAnalysisManager.
- FunctionAnalysisManager &getManager() { return *FAM; }
-
- /// \brief Handler for invalidation of the SCC.
- ///
- /// If this analysis itself is preserved, then we assume that the set of \c
- /// Function objects in the \c SCC hasn't changed and thus we don't need
- /// to invalidate *all* cached data associated with a \c Function* in the \c
- /// FunctionAnalysisManager.
- ///
- /// Regardless of whether this analysis is marked as preserved, all of the
- /// analyses in the \c FunctionAnalysisManager are potentially invalidated
- /// based on the set of preserved analyses.
- bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA);
-
- private:
- FunctionAnalysisManager *FAM;
- };
-
- static void *ID() { return (void *)&PassID; }
-
- static StringRef name() { return "FunctionAnalysisManagerCGSCCProxy"; }
-
- explicit FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManager &FAM)
- : FAM(&FAM) {}
- // We have to explicitly define all the special member functions because MSVC
- // refuses to generate them.
- FunctionAnalysisManagerCGSCCProxy(
- const FunctionAnalysisManagerCGSCCProxy &Arg)
- : FAM(Arg.FAM) {}
- FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManagerCGSCCProxy &&Arg)
- : FAM(std::move(Arg.FAM)) {}
- FunctionAnalysisManagerCGSCCProxy &
- operator=(FunctionAnalysisManagerCGSCCProxy RHS) {
- std::swap(FAM, RHS.FAM);
- return *this;
- }
-
- /// \brief Run the analysis pass and create our proxy result object.
- ///
- /// This doesn't do any interesting work, it is primarily used to insert our
- /// proxy result object into the module analysis cache so that we can proxy
- /// invalidation to the function analysis manager.
- ///
- /// In debug builds, it will also assert that the analysis manager is empty
- /// as no queries should arrive at the function analysis manager prior to
- /// this analysis being requested.
- Result run(LazyCallGraph::SCC &C);
-
-private:
- static char PassID;
-
- FunctionAnalysisManager *FAM;
-};
-
-/// \brief A function analysis which acts as a proxy for a CGSCC analysis
-/// manager.
-///
-/// This primarily provides an accessor to a parent CGSCC analysis manager to
-/// function passes. Only the const interface of the CGSCC analysis manager is
-/// provided to indicate that once inside of a function analysis pass you
-/// cannot request a CGSCC analysis to actually run. Instead, the user must
-/// rely on the \c getCachedResult API.
-///
-/// This proxy *doesn't* manage the invalidation in any way. That is handled by
-/// the recursive return path of each layer of the pass manager and the
-/// returned PreservedAnalysis set.
-class CGSCCAnalysisManagerFunctionProxy {
-public:
- /// \brief Result proxy object for \c CGSCCAnalysisManagerFunctionProxy.
- class Result {
- public:
- explicit Result(const CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {}
- // We have to explicitly define all the special member functions because
- // MSVC refuses to generate them.
- Result(const Result &Arg) : CGAM(Arg.CGAM) {}
- Result(Result &&Arg) : CGAM(std::move(Arg.CGAM)) {}
- Result &operator=(Result RHS) {
- std::swap(CGAM, RHS.CGAM);
- return *this;
- }
-
- const CGSCCAnalysisManager &getManager() const { return *CGAM; }
-
- /// \brief Handle invalidation by ignoring it, this pass is immutable.
- bool invalidate(Function &) { return false; }
+extern template class InnerAnalysisManagerProxy<FunctionAnalysisManager,
+ LazyCallGraph::SCC>;
+/// A proxy from a \c FunctionAnalysisManager to an \c SCC.
+typedef InnerAnalysisManagerProxy<FunctionAnalysisManager, LazyCallGraph::SCC>
+ FunctionAnalysisManagerCGSCCProxy;
- private:
- const CGSCCAnalysisManager *CGAM;
- };
-
- static void *ID() { return (void *)&PassID; }
-
- static StringRef name() { return "CGSCCAnalysisManagerFunctionProxy"; }
-
- CGSCCAnalysisManagerFunctionProxy(const CGSCCAnalysisManager &CGAM)
- : CGAM(&CGAM) {}
- // We have to explicitly define all the special member functions because MSVC
- // refuses to generate them.
- CGSCCAnalysisManagerFunctionProxy(
- const CGSCCAnalysisManagerFunctionProxy &Arg)
- : CGAM(Arg.CGAM) {}
- CGSCCAnalysisManagerFunctionProxy(CGSCCAnalysisManagerFunctionProxy &&Arg)
- : CGAM(std::move(Arg.CGAM)) {}
- CGSCCAnalysisManagerFunctionProxy &
- operator=(CGSCCAnalysisManagerFunctionProxy RHS) {
- std::swap(CGAM, RHS.CGAM);
- return *this;
- }
-
- /// \brief Run the analysis pass and create our proxy result object.
- /// Nothing to see here, it just forwards the \c CGAM reference into the
- /// result.
- Result run(Function &) { return Result(*CGAM); }
-
-private:
- static char PassID;
-
- const CGSCCAnalysisManager *CGAM;
-};
+extern template class OuterAnalysisManagerProxy<CGSCCAnalysisManager, Function>;
+/// A proxy from a \c CGSCCAnalysisManager to a \c Function.
+typedef OuterAnalysisManagerProxy<CGSCCAnalysisManager, Function>
+ CGSCCAnalysisManagerFunctionProxy;
/// \brief Adaptor that maps from a SCC to its functions.
///
@@ -418,20 +161,23 @@ private:
/// \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 <typename FunctionPassT> class CGSCCToFunctionPassAdaptor {
+template <typename FunctionPassT>
+class CGSCCToFunctionPassAdaptor
+ : public PassInfoMixin<CGSCCToFunctionPassAdaptor<FunctionPassT>> {
public:
- explicit CGSCCToFunctionPassAdaptor(FunctionPassT Pass)
- : Pass(std::move(Pass)) {}
+ explicit CGSCCToFunctionPassAdaptor(FunctionPassT Pass, bool DebugLogging = false)
+ : Pass(std::move(Pass)), DebugLogging(DebugLogging) {}
// We have to explicitly define all the special member functions because MSVC
// refuses to generate them.
CGSCCToFunctionPassAdaptor(const CGSCCToFunctionPassAdaptor &Arg)
- : Pass(Arg.Pass) {}
+ : Pass(Arg.Pass), DebugLogging(Arg.DebugLogging) {}
CGSCCToFunctionPassAdaptor(CGSCCToFunctionPassAdaptor &&Arg)
- : Pass(std::move(Arg.Pass)) {}
+ : Pass(std::move(Arg.Pass)), DebugLogging(Arg.DebugLogging) {}
friend void swap(CGSCCToFunctionPassAdaptor &LHS,
CGSCCToFunctionPassAdaptor &RHS) {
using std::swap;
swap(LHS.Pass, RHS.Pass);
+ swap(LHS.DebugLogging, RHS.DebugLogging);
}
CGSCCToFunctionPassAdaptor &operator=(CGSCCToFunctionPassAdaptor RHS) {
swap(*this, RHS);
@@ -439,23 +185,24 @@ public:
}
/// \brief Runs the function pass across every function in the module.
- PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager *AM) {
- FunctionAnalysisManager *FAM = nullptr;
- if (AM)
- // Setup the function analysis manager from its proxy.
- FAM = &AM->getResult<FunctionAnalysisManagerCGSCCProxy>(C).getManager();
+ PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM) {
+ // Setup the function analysis manager from its proxy.
+ FunctionAnalysisManager &FAM =
+ AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C).getManager();
+
+ if (DebugLogging)
+ dbgs() << "Running function passes across an SCC: " << C << "\n";
PreservedAnalyses PA = PreservedAnalyses::all();
- for (LazyCallGraph::Node *N : C) {
- PreservedAnalyses PassPA = Pass.run(N->getFunction(), FAM);
+ for (LazyCallGraph::Node &N : C) {
+ PreservedAnalyses PassPA = Pass.run(N.getFunction(), FAM);
// 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.
// Also, update the preserved analyses to reflect that once invalidated
// these can again be preserved.
- if (FAM)
- PassPA = FAM->invalidate(N->getFunction(), std::move(PassPA));
+ PassPA = FAM.invalidate(N.getFunction(), std::move(PassPA));
// Then intersect the preserved set so that invalidation of module
// analyses will eventually occur when the module pass completes.
@@ -472,18 +219,18 @@ public:
return PA;
}
- static StringRef name() { return "CGSCCToFunctionPassAdaptor"; }
-
private:
FunctionPassT Pass;
+ bool DebugLogging;
};
/// \brief A function to deduce a function pass type and wrap it in the
/// templated adaptor.
template <typename FunctionPassT>
CGSCCToFunctionPassAdaptor<FunctionPassT>
-createCGSCCToFunctionPassAdaptor(FunctionPassT Pass) {
- return CGSCCToFunctionPassAdaptor<FunctionPassT>(std::move(Pass));
+createCGSCCToFunctionPassAdaptor(FunctionPassT Pass, bool DebugLogging = false) {
+ return CGSCCToFunctionPassAdaptor<FunctionPassT>(std::move(Pass),
+ DebugLogging);
}
}
diff --git a/include/llvm/Analysis/CallGraph.h b/include/llvm/Analysis/CallGraph.h
index 5562e9b9465f..4ecacb0f0be2 100644
--- a/include/llvm/Analysis/CallGraph.h
+++ b/include/llvm/Analysis/CallGraph.h
@@ -57,6 +57,7 @@
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/PassManager.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Pass.h"
#include <map>
@@ -294,20 +295,27 @@ private:
/// This class implements the concept of an analysis pass used by the \c
/// ModuleAnalysisManager to run an analysis over a module and cache the
/// resulting data.
-class CallGraphAnalysis {
+class CallGraphAnalysis : public AnalysisInfoMixin<CallGraphAnalysis> {
+ friend AnalysisInfoMixin<CallGraphAnalysis>;
+ static char PassID;
+
public:
/// \brief A formulaic typedef to inform clients of the result type.
typedef CallGraph Result;
- static void *ID() { return (void *)&PassID; }
-
/// \brief Compute the \c CallGraph for the module \c M.
///
/// The real work here is done in the \c CallGraph constructor.
- CallGraph run(Module *M) { return CallGraph(*M); }
+ CallGraph run(Module &M, ModuleAnalysisManager &) { return CallGraph(M); }
+};
-private:
- static char PassID;
+/// \brief Printer pass for the \c CallGraphAnalysis results.
+class CallGraphPrinterPass : public PassInfoMixin<CallGraphPrinterPass> {
+ raw_ostream &OS;
+
+public:
+ explicit CallGraphPrinterPass(raw_ostream &OS) : OS(OS) {}
+ PreservedAnalyses run(Module &M, AnalysisManager<Module> &AM);
};
/// \brief The \c ModulePass which wraps up a \c CallGraph and the logic to
diff --git a/include/llvm/Analysis/CallGraphSCCPass.h b/include/llvm/Analysis/CallGraphSCCPass.h
index 9c7f7bd34cce..cb35b3292be7 100644
--- a/include/llvm/Analysis/CallGraphSCCPass.h
+++ b/include/llvm/Analysis/CallGraphSCCPass.h
@@ -23,6 +23,7 @@
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Pass.h"
+#include "llvm/PassSupport.h"
namespace llvm {
@@ -77,15 +78,21 @@ public:
/// the call graph. If the derived class implements this method, it should
/// always explicitly call the implementation here.
void getAnalysisUsage(AnalysisUsage &Info) const override;
+
+protected:
+ /// Optional passes call this function to check whether the pass should be
+ /// skipped. This is the case when optimization bisect is over the limit.
+ bool skipSCC(CallGraphSCC &SCC) const;
};
/// CallGraphSCC - This is a single SCC that a CallGraphSCCPass is run on.
class CallGraphSCC {
+ const CallGraph &CG; // The call graph for this SCC.
void *Context; // The CGPassManager object that is vending this.
std::vector<CallGraphNode*> Nodes;
public:
- CallGraphSCC(void *context) : Context(context) {}
+ CallGraphSCC(CallGraph &cg, void *context) : CG(cg), Context(context) {}
void initialize(CallGraphNode *const *I, CallGraphNode *const *E) {
Nodes.assign(I, E);
@@ -101,6 +108,25 @@ public:
typedef std::vector<CallGraphNode *>::const_iterator iterator;
iterator begin() const { return Nodes.begin(); }
iterator end() const { return Nodes.end(); }
+
+ const CallGraph &getCallGraph() { return CG; }
+};
+
+void initializeDummyCGSCCPassPass(PassRegistry &);
+
+/// This pass is required by interprocedural register allocation. It forces
+/// codegen to follow bottom up order on call graph.
+class DummyCGSCCPass : public CallGraphSCCPass {
+public:
+ static char ID;
+ DummyCGSCCPass() : CallGraphSCCPass(ID) {
+ PassRegistry &Registry = *PassRegistry::getPassRegistry();
+ initializeDummyCGSCCPassPass(Registry);
+ };
+ bool runOnSCC(CallGraphSCC &SCC) override { return false; }
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.setPreservesAll();
+ }
};
} // End llvm namespace
diff --git a/include/llvm/Analysis/CallPrinter.h b/include/llvm/Analysis/CallPrinter.h
index 5f5d160c3ca0..8b697d5aa149 100644
--- a/include/llvm/Analysis/CallPrinter.h
+++ b/include/llvm/Analysis/CallPrinter.h
@@ -17,10 +17,10 @@
namespace llvm {
- class ModulePass;
+class ModulePass;
- ModulePass *createCallGraphViewerPass();
- ModulePass *createCallGraphPrinterPass();
+ModulePass *createCallGraphViewerPass();
+ModulePass *createCallGraphDOTPrinterPass();
} // end namespace llvm
diff --git a/include/llvm/Analysis/CodeMetrics.h b/include/llvm/Analysis/CodeMetrics.h
index 2f5969129e02..f512aca57865 100644
--- a/include/llvm/Analysis/CodeMetrics.h
+++ b/include/llvm/Analysis/CodeMetrics.h
@@ -42,50 +42,48 @@ bool callIsSmall(ImmutableCallSite CS);
struct CodeMetrics {
/// \brief True if this function contains a call to setjmp or other functions
/// with attribute "returns twice" without having the attribute itself.
- bool exposesReturnsTwice;
+ bool exposesReturnsTwice = false;
/// \brief True if this function calls itself.
- bool isRecursive;
+ bool isRecursive = false;
/// \brief True if this function cannot be duplicated.
///
/// True if this function contains one or more indirect branches, or it contains
/// one or more 'noduplicate' instructions.
- bool notDuplicatable;
+ bool notDuplicatable = false;
+
+ /// \brief True if this function contains a call to a convergent function.
+ bool convergent = false;
/// \brief True if this function calls alloca (in the C sense).
- bool usesDynamicAlloca;
+ bool usesDynamicAlloca = false;
/// \brief Number of instructions in the analyzed blocks.
- unsigned NumInsts;
+ unsigned NumInsts = false;
/// \brief Number of analyzed blocks.
- unsigned NumBlocks;
+ unsigned NumBlocks = false;
/// \brief Keeps track of basic block code size estimates.
DenseMap<const BasicBlock *, unsigned> NumBBInsts;
/// \brief Keep track of the number of calls to 'big' functions.
- unsigned NumCalls;
+ unsigned NumCalls = false;
/// \brief The number of calls to internal functions with a single caller.
///
/// These are likely targets for future inlining, likely exposed by
/// interleaved devirtualization.
- unsigned NumInlineCandidates;
+ unsigned NumInlineCandidates = 0;
/// \brief How many instructions produce vector values.
///
/// The inliner is more aggressive with inlining vector kernels.
- unsigned NumVectorInsts;
+ unsigned NumVectorInsts = 0;
/// \brief How many 'ret' instructions the blocks contain.
- unsigned NumRets;
-
- CodeMetrics()
- : exposesReturnsTwice(false), isRecursive(false), notDuplicatable(false),
- usesDynamicAlloca(false), NumInsts(0), NumBlocks(0), NumCalls(0),
- NumInlineCandidates(0), NumVectorInsts(0), NumRets(0) {}
+ unsigned NumRets = 0;
/// \brief Add information about a block to the current state.
void analyzeBasicBlock(const BasicBlock *BB, const TargetTransformInfo &TTI,
diff --git a/include/llvm/Analysis/ConstantFolding.h b/include/llvm/Analysis/ConstantFolding.h
index e8185b3b6307..b1504004d83c 100644
--- a/include/llvm/Analysis/ConstantFolding.h
+++ b/include/llvm/Analysis/ConstantFolding.h
@@ -21,30 +21,46 @@
#define LLVM_ANALYSIS_CONSTANTFOLDING_H
namespace llvm {
- class Constant;
- class ConstantExpr;
- class Instruction;
- class DataLayout;
- class TargetLibraryInfo;
- class Function;
- class Type;
- template<typename T>
- class ArrayRef;
+class APInt;
+template <typename T> class ArrayRef;
+class Constant;
+class ConstantExpr;
+class DataLayout;
+class Function;
+class GlobalValue;
+class Instruction;
+class TargetLibraryInfo;
+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.
+bool IsConstantOffsetFromGlobal(Constant *C, GlobalValue *&GV, APInt &Offset,
+ const DataLayout &DL);
/// ConstantFoldInstruction - Try to constant fold the specified instruction.
/// If successful, the constant result is returned, if not, null is returned.
/// Note that this fails if not all of the operands are constant. Otherwise,
/// this function can only fail when attempting to fold instructions like loads
/// and stores, which have no constant expression form.
- Constant *ConstantFoldInstruction(Instruction *I, const DataLayout &DL,
- const TargetLibraryInfo *TLI = nullptr);
+Constant *ConstantFoldInstruction(Instruction *I, const DataLayout &DL,
+ const TargetLibraryInfo *TLI = nullptr);
/// ConstantFoldConstantExpression - Attempt to fold the constant expression
/// using the specified DataLayout. If successful, the constant result is
/// result is returned, if not, null is returned.
- Constant *
- ConstantFoldConstantExpression(const ConstantExpr *CE, const DataLayout &DL,
- const TargetLibraryInfo *TLI = nullptr);
+Constant *
+ConstantFoldConstantExpression(const ConstantExpr *CE, const DataLayout &DL,
+ const TargetLibraryInfo *TLI = nullptr);
+
+/// ConstantFoldInstOperands - Attempt to constant fold an instruction with the
+/// specified operands. If successful, the constant result is returned, if not,
+/// null is returned. Note that this function can fail when attempting to
+/// fold instructions like loads and stores, which have no constant expression
+/// form.
+///
+Constant *ConstantFoldInstOperands(Instruction *I, ArrayRef<Constant *> Ops,
+ const DataLayout &DL,
+ const TargetLibraryInfo *TLI = nullptr);
/// ConstantFoldInstOperands - Attempt to constant fold an instruction with the
/// specified operands. If successful, the constant result is returned, if not,
@@ -52,19 +68,32 @@ namespace llvm {
/// fold instructions like loads and stores, which have no constant expression
/// form.
///
- Constant *ConstantFoldInstOperands(unsigned Opcode, Type *DestTy,
- ArrayRef<Constant *> Ops,
- const DataLayout &DL,
- const TargetLibraryInfo *TLI = nullptr);
+/// This function doesn't work for compares (use ConstantFoldCompareInstOperands
+/// for this) and GEPs.
+Constant *ConstantFoldInstOperands(unsigned Opcode, Type *DestTy,
+ ArrayRef<Constant *> Ops,
+ const DataLayout &DL,
+ const TargetLibraryInfo *TLI = nullptr);
/// ConstantFoldCompareInstOperands - Attempt to constant fold a compare
/// instruction (icmp/fcmp) with the specified operands. If it fails, it
/// returns a constant expression of the specified operands.
///
- Constant *
- ConstantFoldCompareInstOperands(unsigned Predicate, Constant *LHS,
- Constant *RHS, const DataLayout &DL,
- const TargetLibraryInfo *TLI = nullptr);
+Constant *
+ConstantFoldCompareInstOperands(unsigned Predicate, Constant *LHS,
+ Constant *RHS, const DataLayout &DL,
+ const TargetLibraryInfo *TLI = nullptr);
+
+/// \brief Attempt to constant fold a binary operation with the specified
+/// operands. If it fails, it returns a constant expression of the specified
+/// operands.
+Constant *ConstantFoldBinaryOpOperands(unsigned Opcode, Constant *LHS,
+ Constant *RHS, const DataLayout &DL);
+
+/// \brief Attempt to constant fold a cast with the specified operand. If it
+/// fails, it returns a constant expression of the specified operand.
+Constant *ConstantFoldCastOperand(unsigned Opcode, Constant *C, Type *DestTy,
+ const DataLayout &DL);
/// ConstantFoldInsertValueInstruction - Attempt to constant fold an insertvalue
/// instruction with the specified operands and indices. The constant result is
@@ -86,7 +115,7 @@ Constant *ConstantFoldExtractElementInstruction(Constant *Val, Constant *Idx);
/// ConstantFoldLoadFromConstPtr - Return the value that a load from C would
/// produce if it is constant and determinable. If this is not determinable,
/// return null.
-Constant *ConstantFoldLoadFromConstPtr(Constant *C, const DataLayout &DL);
+Constant *ConstantFoldLoadFromConstPtr(Constant *C, Type *Ty, const DataLayout &DL);
/// ConstantFoldLoadThroughGEPConstantExpr - Given a constant and a
/// getelementptr constantexpr, return the constant value being addressed by the
@@ -98,7 +127,7 @@ Constant *ConstantFoldLoadThroughGEPConstantExpr(Constant *C, ConstantExpr *CE);
/// return the constant value being addressed by a virtual load, or null if
/// something is funny and we can't decide.
Constant *ConstantFoldLoadThroughGEPIndices(Constant *C,
- ArrayRef<Constant*> Indices);
+ ArrayRef<Constant *> Indices);
/// canConstantFoldCallTo - Return true if its even possible to fold a call to
/// the specified function.
diff --git a/include/llvm/Analysis/DemandedBits.h b/include/llvm/Analysis/DemandedBits.h
index 42932bfd3491..fafd5d00b481 100644
--- a/include/llvm/Analysis/DemandedBits.h
+++ b/include/llvm/Analysis/DemandedBits.h
@@ -26,6 +26,7 @@
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/IR/PassManager.h"
namespace llvm {
@@ -35,40 +36,81 @@ class Instruction;
class DominatorTree;
class AssumptionCache;
-struct DemandedBits : public FunctionPass {
- static char ID; // Pass identification, replacement for typeid
- DemandedBits();
+class DemandedBits {
+public:
+ DemandedBits(Function &F, AssumptionCache &AC, DominatorTree &DT) :
+ F(F), AC(AC), DT(DT), Analyzed(false) {}
- bool runOnFunction(Function& F) override;
- void getAnalysisUsage(AnalysisUsage& AU) const override;
- void print(raw_ostream &OS, const Module *M) const override;
-
/// Return the bits demanded from instruction I.
APInt getDemandedBits(Instruction *I);
/// Return true if, during analysis, I could not be reached.
bool isInstructionDead(Instruction *I);
+
+ void print(raw_ostream &OS);
private:
+ Function &F;
+ AssumptionCache &AC;
+ DominatorTree &DT;
+
void performAnalysis();
void determineLiveOperandBits(const Instruction *UserI,
- const Instruction *I, unsigned OperandNo,
- const APInt &AOut, APInt &AB,
- APInt &KnownZero, APInt &KnownOne,
- APInt &KnownZero2, APInt &KnownOne2);
-
- AssumptionCache *AC;
- DominatorTree *DT;
- Function *F;
+ const Instruction *I, unsigned OperandNo,
+ const APInt &AOut, APInt &AB,
+ APInt &KnownZero, APInt &KnownOne,
+ APInt &KnownZero2, APInt &KnownOne2);
+
bool Analyzed;
// The set of visited instructions (non-integer-typed only).
- SmallPtrSet<Instruction*, 128> Visited;
+ SmallPtrSet<Instruction*, 32> Visited;
DenseMap<Instruction *, APInt> AliveBits;
};
+class DemandedBitsWrapperPass : public FunctionPass {
+private:
+ mutable Optional<DemandedBits> DB;
+public:
+ static char ID; // Pass identification, replacement for typeid
+ DemandedBitsWrapperPass();
+
+ bool runOnFunction(Function &F) override;
+ void getAnalysisUsage(AnalysisUsage &AU) const override;
+
+ /// Clean up memory in between runs
+ void releaseMemory() override;
+
+ DemandedBits &getDemandedBits() { return *DB; }
+
+ void print(raw_ostream &OS, const Module *M) const override;
+};
+
+/// An analysis that produces \c DemandedBits for a function.
+class DemandedBitsAnalysis : public AnalysisInfoMixin<DemandedBitsAnalysis> {
+ friend AnalysisInfoMixin<DemandedBitsAnalysis>;
+ static char PassID;
+
+public:
+ /// \brief Provide the result typedef for this analysis pass.
+ typedef DemandedBits Result;
+
+ /// \brief Run the analysis pass over a function and produce demanded bits
+ /// information.
+ DemandedBits run(Function &F, AnalysisManager<Function> &AM);
+};
+
+/// \brief Printer pass for DemandedBits
+class DemandedBitsPrinterPass : public PassInfoMixin<DemandedBitsPrinterPass> {
+ raw_ostream &OS;
+
+public:
+ explicit DemandedBitsPrinterPass(raw_ostream &OS) : OS(OS) {}
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
+};
+
/// Create a demanded bits analysis pass.
-FunctionPass *createDemandedBitsPass();
+FunctionPass *createDemandedBitsWrapperPass();
} // End llvm namespace
diff --git a/include/llvm/Analysis/DependenceAnalysis.h b/include/llvm/Analysis/DependenceAnalysis.h
index 5290552b41dc..32dd367a9c0a 100644
--- a/include/llvm/Analysis/DependenceAnalysis.h
+++ b/include/llvm/Analysis/DependenceAnalysis.h
@@ -41,12 +41,12 @@
#define LLVM_ANALYSIS_DEPENDENCEANALYSIS_H
#include "llvm/ADT/SmallBitVector.h"
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Pass.h"
namespace llvm {
+template <typename T> class ArrayRef;
class Loop;
class LoopInfo;
class ScalarEvolution;
@@ -206,7 +206,7 @@ namespace llvm {
private:
Instruction *Src, *Dst;
const Dependence *NextPredecessor, *NextSuccessor;
- friend class DependenceAnalysis;
+ friend class DependenceInfo;
};
/// FullDependence - This class represents a dependence between two memory
@@ -274,16 +274,17 @@ namespace llvm {
bool LoopIndependent;
bool Consistent; // Init to true, then refine.
std::unique_ptr<DVEntry[]> DV;
- friend class DependenceAnalysis;
+ friend class DependenceInfo;
};
- /// DependenceAnalysis - This class is the main dependence-analysis driver.
+ /// DependenceInfo - This class is the main dependence-analysis driver.
///
- class DependenceAnalysis : public FunctionPass {
- void operator=(const DependenceAnalysis &) = delete;
- DependenceAnalysis(const DependenceAnalysis &) = delete;
-
+ class DependenceInfo {
public:
+ DependenceInfo(Function *F, AliasAnalysis *AA, ScalarEvolution *SE,
+ LoopInfo *LI)
+ : AA(AA), SE(SE), LI(LI), F(F) {}
+
/// depends - Tests for a dependence between the Src and Dst instructions.
/// Returns NULL if no dependence; otherwise, returns a Dependence (or a
/// FullDependence) with as much information as can be gleaned.
@@ -336,6 +337,8 @@ namespace llvm {
/// both loops.
const SCEV *getSplitIteration(const Dependence &Dep, unsigned Level);
+ Function *getFunction() const { return F; }
+
private:
AliasAnalysis *AA;
ScalarEvolution *SE;
@@ -919,22 +922,41 @@ namespace llvm {
bool tryDelinearize(Instruction *Src, Instruction *Dst,
SmallVectorImpl<Subscript> &Pair);
+ }; // class DependenceInfo
+ /// \brief AnalysisPass to compute dependence information in a function
+ class DependenceAnalysis : public AnalysisInfoMixin<DependenceAnalysis> {
+ public:
+ typedef DependenceInfo Result;
+ Result run(Function &F, FunctionAnalysisManager &FAM);
+
+ private:
+ static char PassID;
+ friend struct AnalysisInfoMixin<DependenceAnalysis>;
+ }; // class DependenceAnalysis
+
+ /// \brief Legacy pass manager pass to access dependence information
+ class DependenceAnalysisWrapperPass : public FunctionPass {
public:
static char ID; // Class identification, replacement for typeinfo
- DependenceAnalysis() : FunctionPass(ID) {
- initializeDependenceAnalysisPass(*PassRegistry::getPassRegistry());
+ DependenceAnalysisWrapperPass() : FunctionPass(ID) {
+ initializeDependenceAnalysisWrapperPassPass(
+ *PassRegistry::getPassRegistry());
}
bool runOnFunction(Function &F) override;
void releaseMemory() override;
void getAnalysisUsage(AnalysisUsage &) const override;
void print(raw_ostream &, const Module * = nullptr) const override;
- }; // class DependenceAnalysis
+ DependenceInfo &getDI() const;
+
+ private:
+ std::unique_ptr<DependenceInfo> info;
+ }; // class DependenceAnalysisWrapperPass
/// createDependenceAnalysisPass - This creates an instance of the
- /// DependenceAnalysis pass.
- FunctionPass *createDependenceAnalysisPass();
+ /// DependenceAnalysis wrapper pass.
+ FunctionPass *createDependenceAnalysisWrapperPass();
} // namespace llvm
diff --git a/include/llvm/Analysis/DominanceFrontier.h b/include/llvm/Analysis/DominanceFrontier.h
index fb730054a8e5..79672e4e4225 100644
--- a/include/llvm/Analysis/DominanceFrontier.h
+++ b/include/llvm/Analysis/DominanceFrontier.h
@@ -19,6 +19,7 @@
#define LLVM_ANALYSIS_DOMINANCEFRONTIER_H
#include "llvm/IR/Dominators.h"
+#include "llvm/IR/PassManager.h"
#include <map>
#include <set>
@@ -133,63 +134,24 @@ public:
const DomSetType &calculate(const DomTreeT &DT, const DomTreeNodeT *Node);
};
-class DominanceFrontier : public FunctionPass {
- ForwardDominanceFrontierBase<BasicBlock> Base;
-
+class DominanceFrontier : public ForwardDominanceFrontierBase<BasicBlock> {
public:
typedef DominatorTreeBase<BasicBlock> DomTreeT;
typedef DomTreeNodeBase<BasicBlock> DomTreeNodeT;
typedef DominanceFrontierBase<BasicBlock>::DomSetType DomSetType;
typedef DominanceFrontierBase<BasicBlock>::iterator iterator;
typedef DominanceFrontierBase<BasicBlock>::const_iterator const_iterator;
+};
+class DominanceFrontierWrapperPass : public FunctionPass {
+ DominanceFrontier DF;
+public:
static char ID; // Pass ID, replacement for typeid
- DominanceFrontier();
-
- ForwardDominanceFrontierBase<BasicBlock> &getBase() { return Base; }
-
- inline const std::vector<BasicBlock *> &getRoots() const {
- return Base.getRoots();
- }
-
- BasicBlock *getRoot() const { return Base.getRoot(); }
-
- bool isPostDominator() const { return Base.isPostDominator(); }
-
- iterator begin() { return Base.begin(); }
+ DominanceFrontierWrapperPass();
- const_iterator begin() const { return Base.begin(); }
-
- iterator end() { return Base.end(); }
-
- const_iterator end() const { return Base.end(); }
-
- iterator find(BasicBlock *B) { return Base.find(B); }
-
- const_iterator find(BasicBlock *B) const { return Base.find(B); }
-
- iterator addBasicBlock(BasicBlock *BB, const DomSetType &frontier) {
- return Base.addBasicBlock(BB, frontier);
- }
-
- void removeBlock(BasicBlock *BB) { return Base.removeBlock(BB); }
-
- void addToFrontier(iterator I, BasicBlock *Node) {
- return Base.addToFrontier(I, Node);
- }
-
- void removeFromFrontier(iterator I, BasicBlock *Node) {
- return Base.removeFromFrontier(I, Node);
- }
-
- bool compareDomSet(DomSetType &DS1, const DomSetType &DS2) const {
- return Base.compareDomSet(DS1, DS2);
- }
-
- bool compare(DominanceFrontierBase<BasicBlock> &Other) const {
- return Base.compare(Other);
- }
+ DominanceFrontier &getDominanceFrontier() { return DF; }
+ const DominanceFrontier &getDominanceFrontier() const { return DF; }
void releaseMemory() override;
@@ -205,6 +167,30 @@ public:
extern template class DominanceFrontierBase<BasicBlock>;
extern template class ForwardDominanceFrontierBase<BasicBlock>;
+/// \brief Analysis pass which computes a \c DominanceFrontier.
+class DominanceFrontierAnalysis
+ : public AnalysisInfoMixin<DominanceFrontierAnalysis> {
+ friend AnalysisInfoMixin<DominanceFrontierAnalysis>;
+ static char PassID;
+
+public:
+ /// \brief Provide the result typedef for this analysis pass.
+ typedef DominanceFrontier Result;
+
+ /// \brief Run the analysis pass over a function and produce a dominator tree.
+ DominanceFrontier run(Function &F, AnalysisManager<Function> &AM);
+};
+
+/// \brief Printer pass for the \c DominanceFrontier.
+class DominanceFrontierPrinterPass
+ : public PassInfoMixin<DominanceFrontierPrinterPass> {
+ raw_ostream &OS;
+
+public:
+ explicit DominanceFrontierPrinterPass(raw_ostream &OS);
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
+};
+
} // End llvm namespace
#endif
diff --git a/include/llvm/Analysis/EHPersonalities.h b/include/llvm/Analysis/EHPersonalities.h
index 59e9672b88e5..a26c575cfe10 100644
--- a/include/llvm/Analysis/EHPersonalities.h
+++ b/include/llvm/Analysis/EHPersonalities.h
@@ -23,12 +23,15 @@ enum class EHPersonality {
Unknown,
GNU_Ada,
GNU_C,
+ GNU_C_SjLj,
GNU_CXX,
+ GNU_CXX_SjLj,
GNU_ObjC,
MSVC_X86SEH,
MSVC_Win64SEH,
MSVC_CXX,
- CoreCLR
+ CoreCLR,
+ Rust
};
/// \brief See if the given exception handling personality function is one
diff --git a/include/llvm/Analysis/GlobalsModRef.h b/include/llvm/Analysis/GlobalsModRef.h
index bcd102e7ded2..4c0a98949778 100644
--- a/include/llvm/Analysis/GlobalsModRef.h
+++ b/include/llvm/Analysis/GlobalsModRef.h
@@ -35,6 +35,7 @@ class GlobalsAAResult : public AAResultBase<GlobalsAAResult> {
class FunctionInfo;
const DataLayout &DL;
+ const TargetLibraryInfo &TLI;
/// The globals that do not have their addresses taken.
SmallPtrSet<const GlobalValue *, 8> NonAddressTakenGlobals;
@@ -76,6 +77,7 @@ class GlobalsAAResult : public AAResultBase<GlobalsAAResult> {
public:
GlobalsAAResult(GlobalsAAResult &&Arg);
+ ~GlobalsAAResult();
static GlobalsAAResult analyzeModule(Module &M, const TargetLibraryInfo &TLI,
CallGraph &CG);
@@ -116,20 +118,14 @@ private:
};
/// Analysis pass providing a never-invalidated alias analysis result.
-class GlobalsAA {
+class GlobalsAA : public AnalysisInfoMixin<GlobalsAA> {
+ friend AnalysisInfoMixin<GlobalsAA>;
+ static char PassID;
+
public:
typedef GlobalsAAResult Result;
- /// \brief Opaque, unique identifier for this analysis pass.
- static void *ID() { return (void *)&PassID; }
-
- GlobalsAAResult run(Module &M, AnalysisManager<Module> *AM);
-
- /// \brief Provide access to a name for this pass for debugging purposes.
- static StringRef name() { return "GlobalsAA"; }
-
-private:
- static char PassID;
+ GlobalsAAResult run(Module &M, AnalysisManager<Module> &AM);
};
/// Legacy wrapper pass to provide the GlobalsAAResult object.
diff --git a/include/llvm/Analysis/IVUsers.h b/include/llvm/Analysis/IVUsers.h
index 37d01490dac6..e68a77526b96 100644
--- a/include/llvm/Analysis/IVUsers.h
+++ b/include/llvm/Analysis/IVUsers.h
@@ -117,7 +117,7 @@ private:
mutable ilist_node<IVStrideUse> Sentinel;
};
-class IVUsers : public LoopPass {
+class IVUsers {
friend class IVStrideUse;
Loop *L;
AssumptionCache *AC;
@@ -133,15 +133,9 @@ class IVUsers : public LoopPass {
// Ephemeral values used by @llvm.assume in this function.
SmallPtrSet<const Value *, 32> EphValues;
- void getAnalysisUsage(AnalysisUsage &AU) const override;
-
- bool runOnLoop(Loop *L, LPPassManager &LPM) override;
-
- void releaseMemory() override;
-
public:
- static char ID; // Pass ID, replacement for typeid
- IVUsers();
+ IVUsers(Loop *L, AssumptionCache *AC, LoopInfo *LI, DominatorTree *DT,
+ ScalarEvolution *SE);
Loop *getLoop() const { return L; }
@@ -173,16 +167,58 @@ public:
return Processed.count(Inst);
}
- void print(raw_ostream &OS, const Module* = nullptr) const override;
+ void releaseMemory();
+
+ void print(raw_ostream &OS, const Module * = nullptr) const;
/// dump - This method is used for debugging.
void dump() const;
+
protected:
bool AddUsersImpl(Instruction *I, SmallPtrSetImpl<Loop*> &SimpleLoopNests);
};
Pass *createIVUsersPass();
+class IVUsersWrapperPass : public LoopPass {
+ std::unique_ptr<IVUsers> IU;
+
+public:
+ static char ID;
+
+ IVUsersWrapperPass();
+
+ IVUsers &getIU() { return *IU; }
+ const IVUsers &getIU() const { return *IU; }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override;
+
+ bool runOnLoop(Loop *L, LPPassManager &LPM) override;
+
+ void releaseMemory() override;
+
+ void print(raw_ostream &OS, const Module * = nullptr) const override;
+};
+
+/// Analysis pass that exposes the \c IVUsers for a loop.
+class IVUsersAnalysis : public AnalysisInfoMixin<IVUsersAnalysis> {
+ friend AnalysisInfoMixin<IVUsersAnalysis>;
+ static char PassID;
+
+public:
+ typedef IVUsers Result;
+
+ IVUsers run(Loop &L, AnalysisManager<Loop> &AM);
+};
+
+/// Printer pass for the \c IVUsers for a loop.
+class IVUsersPrinterPass : public PassInfoMixin<IVUsersPrinterPass> {
+ raw_ostream &OS;
+
+public:
+ explicit IVUsersPrinterPass(raw_ostream &OS) : OS(OS) {}
+ PreservedAnalyses run(Loop &L, AnalysisManager<Loop> &AM);
+};
}
#endif
diff --git a/include/llvm/Analysis/IndirectCallPromotionAnalysis.h b/include/llvm/Analysis/IndirectCallPromotionAnalysis.h
new file mode 100644
index 000000000000..007e4d8602fa
--- /dev/null
+++ b/include/llvm/Analysis/IndirectCallPromotionAnalysis.h
@@ -0,0 +1,67 @@
+//===- IndirectCallPromotionAnalysis.h - Indirect call analysis -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// Interface to identify indirect call promotion candidates.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ANALYSIS_INDIRECTCALLPROMOTIONANALYSIS_H
+#define LLVM_ANALYSIS_INDIRECTCALLPROMOTIONANALYSIS_H
+
+#include "llvm/ProfileData/InstrProf.h"
+
+namespace llvm {
+
+class Instruction;
+
+// Class for identifying profitable indirect call promotion candidates when
+// the indirect-call value profile metadata is available.
+class ICallPromotionAnalysis {
+private:
+ // Allocate space to read the profile annotation.
+ std::unique_ptr<InstrProfValueData[]> ValueDataArray;
+
+ // Count is the call count for the direct-call target and
+ // TotalCount is the call count for the indirect-call callsite.
+ // Return true we should promote this indirect-call target.
+ bool isPromotionProfitable(uint64_t Count, uint64_t TotalCount);
+
+ // Returns the number of profitable candidates to promote for the
+ // current ValueDataArray and the given \p Inst.
+ uint32_t getProfitablePromotionCandidates(const Instruction *Inst,
+ uint32_t NumVals,
+ uint64_t TotalCount);
+
+ // Noncopyable
+ ICallPromotionAnalysis(const ICallPromotionAnalysis &other) = delete;
+ ICallPromotionAnalysis &
+ operator=(const ICallPromotionAnalysis &other) = delete;
+
+public:
+ ICallPromotionAnalysis();
+
+ /// \brief Returns reference to array of InstrProfValueData for the given
+ /// instruction \p I.
+ ///
+ /// The \p NumVals, \p TotalCount and \p NumCandidates
+ /// are set to the number of values in the array, the total profile count
+ /// of the indirect call \p I, and the number of profitable candidates
+ /// in the given array (which is sorted in reverse order of profitability).
+ ///
+ /// The returned array space is owned by this class, and overwritten on
+ /// subsequent calls.
+ ArrayRef<InstrProfValueData>
+ getPromotionCandidatesForInstruction(const Instruction *I, uint32_t &NumVals,
+ uint64_t &TotalCount,
+ uint32_t &NumCandidates);
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/include/llvm/Analysis/IndirectCallSiteVisitor.h b/include/llvm/Analysis/IndirectCallSiteVisitor.h
new file mode 100644
index 000000000000..71a8cb886321
--- /dev/null
+++ b/include/llvm/Analysis/IndirectCallSiteVisitor.h
@@ -0,0 +1,43 @@
+//===-- IndirectCallSiteVisitor.h - indirect call-sites visitor -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements defines a visitor class and a helper function that find
+// all indirect call-sites in a function.
+
+#include "llvm/IR/InstVisitor.h"
+#include <vector>
+
+namespace llvm {
+// Visitor class that finds all indirect call sites.
+struct PGOIndirectCallSiteVisitor
+ : public InstVisitor<PGOIndirectCallSiteVisitor> {
+ std::vector<Instruction *> IndirectCallInsts;
+ PGOIndirectCallSiteVisitor() {}
+
+ void visitCallSite(CallSite CS) {
+ if (CS.getCalledFunction() || !CS.getCalledValue())
+ return;
+ Instruction *I = CS.getInstruction();
+ if (CallInst *CI = dyn_cast<CallInst>(I)) {
+ if (CI->isInlineAsm())
+ return;
+ }
+ if (isa<Constant>(CS.getCalledValue()))
+ return;
+ IndirectCallInsts.push_back(I);
+ }
+};
+
+// Helper function that finds all indirect call sites.
+static inline std::vector<Instruction *> findIndirectCallSites(Function &F) {
+ PGOIndirectCallSiteVisitor ICV;
+ ICV.visit(F);
+ return ICV.IndirectCallInsts;
+}
+}
diff --git a/include/llvm/Analysis/InlineCost.h b/include/llvm/Analysis/InlineCost.h
index 35f991cb3f67..2928d2be30e5 100644
--- a/include/llvm/Analysis/InlineCost.h
+++ b/include/llvm/Analysis/InlineCost.h
@@ -23,6 +23,7 @@ class AssumptionCacheTracker;
class CallSite;
class DataLayout;
class Function;
+class ProfileSummaryInfo;
class TargetTransformInfo;
namespace InlineConstants {
@@ -101,25 +102,31 @@ public:
/// \brief Get an InlineCost object representing the cost of inlining this
/// callsite.
///
-/// Note that threshold is passed into this function. Only costs below the
-/// threshold are computed with any accuracy. The threshold can be used to
-/// bound the computation necessary to determine whether the cost is
+/// Note that a default threshold is passed into this function. This threshold
+/// could be modified based on callsite's properties and only costs below this
+/// new threshold are computed with any accuracy. The new threshold can be
+/// used to bound the computation necessary to determine whether the cost is
/// sufficiently low to warrant inlining.
///
/// Also note that calling this function *dynamically* computes the cost of
/// inlining the callsite. It is an expensive, heavyweight call.
-InlineCost getInlineCost(CallSite CS, int Threshold,
+InlineCost getInlineCost(CallSite CS, int DefaultThreshold,
TargetTransformInfo &CalleeTTI,
- AssumptionCacheTracker *ACT);
+ AssumptionCacheTracker *ACT, ProfileSummaryInfo *PSI);
/// \brief Get an InlineCost with the callee explicitly specified.
/// This allows you to calculate the cost of inlining a function via a
/// pointer. This behaves exactly as the version with no explicit callee
/// parameter in all other respects.
//
-InlineCost getInlineCost(CallSite CS, Function *Callee, int Threshold,
+InlineCost getInlineCost(CallSite CS, Function *Callee, int DefaultThreshold,
TargetTransformInfo &CalleeTTI,
- AssumptionCacheTracker *ACT);
+ AssumptionCacheTracker *ACT, ProfileSummaryInfo *PSI);
+
+int computeThresholdFromOptLevels(unsigned OptLevel, unsigned SizeOptLevel);
+
+/// \brief Return the default value of -inline-threshold.
+int getDefaultInlineThreshold();
/// \brief Minimal filter to detect invalid constructs for inlining.
bool isInlineViable(Function &Callee);
diff --git a/include/llvm/Analysis/InstructionSimplify.h b/include/llvm/Analysis/InstructionSimplify.h
index ed313dae9ab1..410fa4165a91 100644
--- a/include/llvm/Analysis/InstructionSimplify.h
+++ b/include/llvm/Analysis/InstructionSimplify.h
@@ -46,8 +46,7 @@ namespace llvm {
class Type;
class Value;
- /// SimplifyAddInst - Given operands for an Add, see if we can
- /// fold the result. If not, this returns null.
+ /// Given operands for an Add, fold the result or return null.
Value *SimplifyAddInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@@ -55,8 +54,7 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
- /// SimplifySubInst - Given operands for a Sub, see if we can
- /// fold the result. If not, this returns null.
+ /// Given operands for a Sub, fold the result or return null.
Value *SimplifySubInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@@ -64,8 +62,7 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
- /// Given operands for an FAdd, see if we can fold the result. If not, this
- /// returns null.
+ /// Given operands for an FAdd, fold the result or return null.
Value *SimplifyFAddInst(Value *LHS, Value *RHS, FastMathFlags FMF,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@@ -73,8 +70,7 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
- /// Given operands for an FSub, see if we can fold the result. If not, this
- /// returns null.
+ /// Given operands for an FSub, fold the result or return null.
Value *SimplifyFSubInst(Value *LHS, Value *RHS, FastMathFlags FMF,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@@ -82,8 +78,7 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
- /// Given operands for an FMul, see if we can fold the result. If not, this
- /// returns null.
+ /// Given operands for an FMul, fold the result or return null.
Value *SimplifyFMulInst(Value *LHS, Value *RHS, FastMathFlags FMF,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@@ -91,32 +86,28 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
- /// SimplifyMulInst - Given operands for a Mul, see if we can
- /// fold the result. If not, this returns null.
+ /// Given operands for a Mul, fold the result or return null.
Value *SimplifyMulInst(Value *LHS, Value *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
- /// SimplifySDivInst - Given operands for an SDiv, see if we can
- /// fold the result. If not, this returns null.
+ /// Given operands for an SDiv, fold the result or return null.
Value *SimplifySDivInst(Value *LHS, Value *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
- /// SimplifyUDivInst - Given operands for a UDiv, see if we can
- /// fold the result. If not, this returns null.
+ /// Given operands for a UDiv, fold the result or return null.
Value *SimplifyUDivInst(Value *LHS, Value *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
- /// SimplifyFDivInst - Given operands for an FDiv, see if we can
- /// fold the result. If not, this returns null.
+ /// Given operands for an FDiv, fold the result or return null.
Value *SimplifyFDivInst(Value *LHS, Value *RHS, FastMathFlags FMF,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@@ -124,24 +115,21 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
- /// SimplifySRemInst - Given operands for an SRem, see if we can
- /// fold the result. If not, this returns null.
+ /// Given operands for an SRem, fold the result or return null.
Value *SimplifySRemInst(Value *LHS, Value *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
- /// SimplifyURemInst - Given operands for a URem, see if we can
- /// fold the result. If not, this returns null.
+ /// Given operands for a URem, fold the result or return null.
Value *SimplifyURemInst(Value *LHS, Value *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
- /// SimplifyFRemInst - Given operands for an FRem, see if we can
- /// fold the result. If not, this returns null.
+ /// Given operands for an FRem, fold the result or return null.
Value *SimplifyFRemInst(Value *LHS, Value *RHS, FastMathFlags FMF,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@@ -149,8 +137,7 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
- /// SimplifyShlInst - Given operands for a Shl, see if we can
- /// fold the result. If not, this returns null.
+ /// Given operands for a Shl, fold the result or return null.
Value *SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@@ -158,8 +145,7 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
- /// SimplifyLShrInst - Given operands for a LShr, see if we can
- /// fold the result. If not, this returns null.
+ /// Given operands for a LShr, fold the result or return null.
Value *SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@@ -167,8 +153,7 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
- /// SimplifyAShrInst - Given operands for a AShr, see if we can
- /// fold the result. If not, this returns null.
+ /// Given operands for a AShr, fold the result or return nulll.
Value *SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@@ -176,32 +161,28 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
- /// SimplifyAndInst - Given operands for an And, see if we can
- /// fold the result. If not, this returns null.
+ /// Given operands for an And, fold the result or return null.
Value *SimplifyAndInst(Value *LHS, Value *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
- /// SimplifyOrInst - Given operands for an Or, see if we can
- /// fold the result. If not, this returns null.
+ /// Given operands for an Or, fold the result or return null.
Value *SimplifyOrInst(Value *LHS, Value *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
- /// SimplifyXorInst - Given operands for a Xor, see if we can
- /// fold the result. If not, this returns null.
+ /// Given operands for an Xor, fold the result or return null.
Value *SimplifyXorInst(Value *LHS, Value *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
- /// SimplifyICmpInst - Given operands for an ICmpInst, see if we can
- /// fold the result. If not, this returns null.
+ /// Given operands for an ICmpInst, fold the result or return null.
Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@@ -209,8 +190,7 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
- /// SimplifyFCmpInst - Given operands for an FCmpInst, see if we can
- /// fold the result. If not, this returns null.
+ /// Given operands for an FCmpInst, fold the result or return null.
Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
FastMathFlags FMF, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@@ -218,8 +198,7 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
- /// SimplifySelectInst - Given operands for a SelectInst, see if we can fold
- /// the result. If not, this returns null.
+ /// Given operands for a SelectInst, fold the result or return null.
Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@@ -227,16 +206,15 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
- /// SimplifyGEPInst - Given operands for an GetElementPtrInst, see if we can
- /// fold the result. If not, this returns null.
- Value *SimplifyGEPInst(ArrayRef<Value *> Ops, const DataLayout &DL,
+ /// Given operands for a GetElementPtrInst, fold the result or return null.
+ Value *SimplifyGEPInst(Type *SrcTy, ArrayRef<Value *> Ops,
+ const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
- /// SimplifyInsertValueInst - Given operands for an InsertValueInst, see if we
- /// can fold the result. If not, this returns null.
+ /// Given operands for an InsertValueInst, fold the result or return null.
Value *SimplifyInsertValueInst(Value *Agg, Value *Val,
ArrayRef<unsigned> Idxs, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@@ -244,8 +222,7 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
- /// \brief Given operands for an ExtractValueInst, see if we can fold the
- /// result. If not, this returns null.
+ /// Given operands for an ExtractValueInst, fold the result or return null.
Value *SimplifyExtractValueInst(Value *Agg, ArrayRef<unsigned> Idxs,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@@ -253,8 +230,7 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
- /// \brief Given operands for an ExtractElementInst, see if we can fold the
- /// result. If not, this returns null.
+ /// Given operands for an ExtractElementInst, fold the result or return null.
Value *SimplifyExtractElementInst(Value *Vec, Value *Idx,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@@ -262,8 +238,7 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
- /// SimplifyTruncInst - Given operands for an TruncInst, see if we can fold
- /// the result. If not, this returns null.
+ /// Given operands for an TruncInst, fold the result or return null.
Value *SimplifyTruncInst(Value *Op, Type *Ty, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
@@ -273,8 +248,7 @@ namespace llvm {
//=== Helper functions for higher up the class hierarchy.
- /// SimplifyCmpInst - Given operands for a CmpInst, see if we can
- /// fold the result. If not, this returns null.
+ /// Given operands for a CmpInst, fold the result or return null.
Value *SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@@ -282,16 +256,15 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
- /// SimplifyBinOp - Given operands for a BinaryOperator, see if we can
- /// fold the result. If not, this returns null.
+ /// Given operands for a BinaryOperator, fold the result or return null.
Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
- /// SimplifyFPBinOp - Given operands for a BinaryOperator, see if we can
- /// fold the result. If not, this returns null.
+
+ /// Given operands for an FP BinaryOperator, fold the result or return null.
/// In contrast to SimplifyBinOp, try to use FastMathFlag when folding the
/// result. In case we don't need FastMathFlags, simply fall to SimplifyBinOp.
Value *SimplifyFPBinOp(unsigned Opcode, Value *LHS, Value *RHS,
@@ -301,10 +274,8 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
- /// \brief Given a function and iterators over arguments, see if we can fold
- /// the result.
- ///
- /// If this call could not be simplified returns null.
+ /// Given a function and iterators over arguments, fold the result or return
+ /// null.
Value *SimplifyCall(Value *V, User::op_iterator ArgBegin,
User::op_iterator ArgEnd, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@@ -312,25 +283,21 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
- /// \brief Given a function and set of arguments, see if we can fold the
- /// result.
- ///
- /// If this call could not be simplified returns null.
+ /// Given a function and set of arguments, fold the result or return null.
Value *SimplifyCall(Value *V, ArrayRef<Value *> Args, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
- /// SimplifyInstruction - See if we can compute a simplified version of this
- /// instruction. If not, this returns null.
+ /// See if we can compute a simplified version of this instruction. If not,
+ /// return null.
Value *SimplifyInstruction(Instruction *I, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr);
- /// \brief Replace all uses of 'I' with 'SimpleV' and simplify the uses
- /// recursively.
+ /// Replace all uses of 'I' with 'SimpleV' and simplify the uses recursively.
///
/// This first performs a normal RAUW of I with SimpleV. It then recursively
/// attempts to simplify those users updated by the operation. The 'I'
@@ -342,7 +309,7 @@ namespace llvm {
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr);
- /// \brief Recursively attempt to simplify an instruction.
+ /// 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
diff --git a/include/llvm/Analysis/Interval.h b/include/llvm/Analysis/Interval.h
index 01eba3f16c01..a904753adaab 100644
--- a/include/llvm/Analysis/Interval.h
+++ b/include/llvm/Analysis/Interval.h
@@ -67,8 +67,9 @@ public:
/// contains - Find out if a basic block is in this interval
inline bool contains(BasicBlock *BB) const {
- for (unsigned i = 0; i < Nodes.size(); ++i)
- if (Nodes[i] == BB) return true;
+ for (BasicBlock *Node : Nodes)
+ if (Node == BB)
+ return true;
return false;
// I don't want the dependency on <algorithm>
//return find(Nodes.begin(), Nodes.end(), BB) != Nodes.end();
@@ -76,8 +77,9 @@ public:
/// isSuccessor - find out if a basic block is a successor of this Interval
inline bool isSuccessor(BasicBlock *BB) const {
- for (unsigned i = 0; i < Successors.size(); ++i)
- if (Successors[i] == BB) return true;
+ for (BasicBlock *Successor : Successors)
+ if (Successor == BB)
+ return true;
return false;
// I don't want the dependency on <algorithm>
//return find(Successors.begin(), Successors.end(), BB) != Successors.end();
diff --git a/include/llvm/Analysis/IteratedDominanceFrontier.h b/include/llvm/Analysis/IteratedDominanceFrontier.h
index a1ded2554d44..37da5617b913 100644
--- a/include/llvm/Analysis/IteratedDominanceFrontier.h
+++ b/include/llvm/Analysis/IteratedDominanceFrontier.h
@@ -24,18 +24,14 @@
#ifndef LLVM_ANALYSIS_IDF_H
#define LLVM_ANALYSIS_IDF_H
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Dominators.h"
namespace llvm {
-class BasicBlock;
-template <class T> class DomTreeNodeBase;
-typedef DomTreeNodeBase<BasicBlock> DomTreeNode;
-template <class T> class DominatorTreeBase;
-
/// \brief Determine the iterated dominance frontier, given a set of defining
/// blocks, and optionally, a set of live-in blocks.
///
@@ -44,6 +40,9 @@ template <class T> class DominatorTreeBase;
/// This algorithm is a linear time computation of Iterated Dominance Frontiers,
/// pruned using the live-in set.
/// By default, liveness is not used to prune the IDF computation.
+/// The template parameters should be either BasicBlock* or Inverse<BasicBlock
+/// *>, depending on if you want the forward or reverse IDF.
+template <class NodeTy>
class IDFCalculator {
public:
@@ -92,5 +91,7 @@ private:
const SmallPtrSetImpl<BasicBlock *> *DefBlocks;
SmallVector<BasicBlock *, 32> PHIBlocks;
};
+typedef IDFCalculator<BasicBlock *> ForwardIDFCalculator;
+typedef IDFCalculator<Inverse<BasicBlock *>> ReverseIDFCalculator;
}
#endif
diff --git a/include/llvm/Analysis/LazyBlockFrequencyInfo.h b/include/llvm/Analysis/LazyBlockFrequencyInfo.h
new file mode 100644
index 000000000000..a2d24bb9eb88
--- /dev/null
+++ b/include/llvm/Analysis/LazyBlockFrequencyInfo.h
@@ -0,0 +1,125 @@
+//===- LazyBlockFrequencyInfo.h - Lazy Block Frequency Analysis -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is an alternative analysis pass to BlockFrequencyInfoWrapperPass. The
+// difference is that with this pass the block frequencies are not computed when
+// the analysis pass is executed but rather when the BFI results is explicitly
+// requested by the analysis client.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ANALYSIS_LAZYBLOCKFREQUENCYINFO_H
+#define LLVM_ANALYSIS_LAZYBLOCKFREQUENCYINFO_H
+
+#include "llvm/Analysis/BlockFrequencyInfo.h"
+#include "llvm/Pass.h"
+
+namespace llvm {
+class AnalysisUsage;
+class BranchProbabilityInfo;
+class Function;
+class LoopInfo;
+
+/// \brief This is an alternative analysis pass to
+/// BlockFrequencyInfoWrapperPass. The difference is that with this pass the
+/// block frequencies are not computed when the analysis pass is executed but
+/// rather when the BFI results is explicitly requested by the analysis client.
+///
+/// There are some additional requirements for any client pass that wants to use
+/// the analysis:
+///
+/// 1. The pass needs to initialize dependent passes with:
+///
+/// INITIALIZE_PASS_DEPENDENCY(LazyBFIPass)
+///
+/// 2. Similarly, getAnalysisUsage should call:
+///
+/// LazyBlockFrequencyInfoPass::getLazyBFIAnalysisUsage(AU)
+///
+/// 3. The computed BFI should be requested with
+/// getAnalysis<LazyBlockFrequencyInfoPass>().getBFI() before either LoopInfo
+/// or BPI could be invalidated for example by changing the CFG.
+///
+/// Note that it is expected that we wouldn't need this functionality for the
+/// new PM since with the new PM, analyses are executed on demand.
+class LazyBlockFrequencyInfoPass : public FunctionPass {
+
+ /// Wraps a BFI to allow lazy computation of the block frequencies.
+ ///
+ /// A pass that only conditionally uses BFI can uncondtionally require the
+ /// analysis without paying for the overhead if BFI doesn't end up being used.
+ class LazyBlockFrequencyInfo {
+ public:
+ LazyBlockFrequencyInfo()
+ : Calculated(false), F(nullptr), BPI(nullptr), LI(nullptr) {}
+
+ /// Set up the per-function input.
+ void setAnalysis(const Function *F, const BranchProbabilityInfo *BPI,
+ const LoopInfo *LI) {
+ this->F = F;
+ this->BPI = BPI;
+ this->LI = LI;
+ }
+
+ /// Retrieve the BFI with the block frequencies computed.
+ BlockFrequencyInfo &getCalculated() {
+ if (!Calculated) {
+ assert(F && BPI && LI && "call setAnalysis");
+ BFI.calculate(*F, *BPI, *LI);
+ Calculated = true;
+ }
+ return BFI;
+ }
+
+ const BlockFrequencyInfo &getCalculated() const {
+ return const_cast<LazyBlockFrequencyInfo *>(this)->getCalculated();
+ }
+
+ void releaseMemory() {
+ BFI.releaseMemory();
+ Calculated = false;
+ setAnalysis(nullptr, nullptr, nullptr);
+ }
+
+ private:
+ BlockFrequencyInfo BFI;
+ bool Calculated;
+ const Function *F;
+ const BranchProbabilityInfo *BPI;
+ const LoopInfo *LI;
+ };
+
+ LazyBlockFrequencyInfo LBFI;
+
+public:
+ static char ID;
+
+ LazyBlockFrequencyInfoPass();
+
+ /// \brief Compute and return the block frequencies.
+ BlockFrequencyInfo &getBFI() { return LBFI.getCalculated(); }
+
+ /// \brief Compute and return the block frequencies.
+ const BlockFrequencyInfo &getBFI() const { return LBFI.getCalculated(); }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override;
+
+ /// Helper for client passes to set up the analysis usage on behalf of this
+ /// pass.
+ static void getLazyBFIAnalysisUsage(AnalysisUsage &AU);
+
+ bool runOnFunction(Function &F) override;
+ void releaseMemory() override;
+ void print(raw_ostream &OS, const Module *M) const override;
+};
+
+/// \brief Helper for client passes to initialize dependent passes for LBFI.
+void initializeLazyBFIPassPass(PassRegistry &Registry);
+}
+#endif
diff --git a/include/llvm/Analysis/LazyCallGraph.h b/include/llvm/Analysis/LazyCallGraph.h
index e02f3ab2de1f..9f62eaa2e9f8 100644
--- a/include/llvm/Analysis/LazyCallGraph.h
+++ b/include/llvm/Analysis/LazyCallGraph.h
@@ -48,7 +48,9 @@
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Support/Allocator.h"
+#include "llvm/Support/raw_ostream.h"
#include <iterator>
+#include <utility>
namespace llvm {
class PreservedAnalyses;
@@ -104,9 +106,85 @@ class LazyCallGraph {
public:
class Node;
class SCC;
- class iterator;
- typedef SmallVector<PointerUnion<Function *, Node *>, 4> NodeVectorT;
- typedef SmallVectorImpl<PointerUnion<Function *, Node *>> NodeVectorImplT;
+ class RefSCC;
+ class edge_iterator;
+ class call_edge_iterator;
+
+ /// A class used to represent edges in the call graph.
+ ///
+ /// The lazy call graph models both *call* edges and *reference* edges. Call
+ /// edges are much what you would expect, and exist when there is a 'call' or
+ /// 'invoke' instruction of some function. Reference edges are also tracked
+ /// along side these, and exist whenever any instruction (transitively
+ /// through its operands) references a function. All call edges are
+ /// inherently reference edges, and so the reference graph forms a superset
+ /// of the formal call graph.
+ ///
+ /// Furthermore, edges also may point to raw \c Function objects when those
+ /// functions have not been scanned and incorporated into the graph (yet).
+ /// This is one of the primary ways in which the graph can be lazy. When
+ /// functions are scanned and fully incorporated into the graph, all of the
+ /// edges referencing them are updated to point to the graph \c Node objects
+ /// instead of to the raw \c Function objects. This class even provides
+ /// methods to trigger this scan on-demand by attempting to get the target
+ /// node of the graph and providing a reference back to the graph in order to
+ /// lazily build it if necessary.
+ ///
+ /// All of these forms of edges are fundamentally represented as outgoing
+ /// edges. The edges are stored in the source node and point at the target
+ /// node. This allows the edge structure itself to be a very compact data
+ /// structure: essentially a tagged pointer.
+ class Edge {
+ public:
+ /// The kind of edge in the graph.
+ enum Kind : bool { Ref = false, Call = true };
+
+ Edge();
+ explicit Edge(Function &F, Kind K);
+ explicit Edge(Node &N, Kind K);
+
+ /// Test whether the edge is null.
+ ///
+ /// This happens when an edge has been deleted. We leave the edge objects
+ /// around but clear them.
+ operator bool() const;
+
+ /// Test whether the edge represents a direct call to a function.
+ ///
+ /// This requires that the edge is not null.
+ bool isCall() const;
+
+ /// Get the function referenced by this edge.
+ ///
+ /// This requires that the edge is not null, but will succeed whether we
+ /// have built a graph node for the function yet or not.
+ Function &getFunction() const;
+
+ /// Get the call graph node referenced by this edge if one exists.
+ ///
+ /// This requires that the edge is not null. If we have built a graph node
+ /// for the function this edge points to, this will return that node,
+ /// otherwise it will return null.
+ Node *getNode() const;
+
+ /// Get the call graph node for this edge, building it if necessary.
+ ///
+ /// This requires that the edge is not null. If we have not yet built
+ /// a graph node for the function this edge points to, this will first ask
+ /// the graph to build that node, inserting it into all the relevant
+ /// structures.
+ Node &getNode(LazyCallGraph &G);
+
+ private:
+ friend class LazyCallGraph::Node;
+
+ PointerIntPair<PointerUnion<Function *, Node *>, 1, Kind> Value;
+
+ void setKind(Kind K) { Value.setInt(K); }
+ };
+
+ typedef SmallVector<Edge, 4> EdgeVectorT;
+ typedef SmallVectorImpl<Edge> EdgeVectorImplT;
/// A node in the call graph.
///
@@ -121,35 +199,65 @@ public:
Function &F;
// We provide for the DFS numbering and Tarjan walk lowlink numbers to be
- // stored directly within the node.
+ // stored directly within the node. These are both '-1' when nodes are part
+ // of an SCC (or RefSCC), or '0' when not yet reached in a DFS walk.
int DFSNumber;
int LowLink;
- mutable NodeVectorT Callees;
- DenseMap<Function *, size_t> CalleeIndexMap;
+ mutable EdgeVectorT Edges;
+ DenseMap<Function *, int> EdgeIndexMap;
- /// Basic constructor implements the scanning of F into Callees and
- /// CalleeIndexMap.
+ /// Basic constructor implements the scanning of F into Edges and
+ /// EdgeIndexMap.
Node(LazyCallGraph &G, Function &F);
- /// Internal helper to insert a callee.
- void insertEdgeInternal(Function &Callee);
+ /// Internal helper to insert an edge to a function.
+ void insertEdgeInternal(Function &ChildF, Edge::Kind EK);
- /// Internal helper to insert a callee.
- void insertEdgeInternal(Node &CalleeN);
+ /// Internal helper to insert an edge to a node.
+ void insertEdgeInternal(Node &ChildN, Edge::Kind EK);
- /// Internal helper to remove a callee from this node.
- void removeEdgeInternal(Function &Callee);
+ /// Internal helper to change an edge kind.
+ void setEdgeKind(Function &ChildF, Edge::Kind EK);
+
+ /// Internal helper to remove the edge to the given function.
+ void removeEdgeInternal(Function &ChildF);
+
+ /// Print the name of this node's function.
+ friend raw_ostream &operator<<(raw_ostream &OS, const Node &N) {
+ return OS << N.F.getName();
+ }
+
+ /// Dump the name of this node's function to stderr.
+ void dump() const;
public:
- typedef LazyCallGraph::iterator iterator;
+ LazyCallGraph &getGraph() const { return *G; }
Function &getFunction() const { return F; }
- iterator begin() const {
- return iterator(*G, Callees.begin(), Callees.end());
+ edge_iterator begin() const {
+ return edge_iterator(Edges.begin(), Edges.end());
+ }
+ edge_iterator end() const { return edge_iterator(Edges.end(), Edges.end()); }
+
+ const Edge &operator[](int i) const { return Edges[i]; }
+ const Edge &operator[](Function &F) const {
+ assert(EdgeIndexMap.find(&F) != EdgeIndexMap.end() && "No such edge!");
+ return Edges[EdgeIndexMap.find(&F)->second];
+ }
+ const Edge &operator[](Node &N) const { return (*this)[N.getFunction()]; }
+
+ call_edge_iterator call_begin() const {
+ return call_edge_iterator(Edges.begin(), Edges.end());
+ }
+ call_edge_iterator call_end() const {
+ return call_edge_iterator(Edges.end(), Edges.end());
+ }
+
+ iterator_range<call_edge_iterator> calls() const {
+ return make_range(call_begin(), call_end());
}
- iterator end() const { return iterator(*G, Callees.end(), Callees.end()); }
/// Equality is defined as address equality.
bool operator==(const Node &N) const { return this == &N; }
@@ -162,101 +270,279 @@ public:
/// be scanned for "calls" or uses of functions and its child information
/// will be constructed. All of these results are accumulated and cached in
/// the graph.
- class iterator
- : public iterator_adaptor_base<iterator, NodeVectorImplT::iterator,
- std::forward_iterator_tag, Node> {
+ class edge_iterator
+ : public iterator_adaptor_base<edge_iterator, EdgeVectorImplT::iterator,
+ std::forward_iterator_tag> {
friend class LazyCallGraph;
friend class LazyCallGraph::Node;
- LazyCallGraph *G;
- NodeVectorImplT::iterator E;
+ EdgeVectorImplT::iterator E;
- // Build the iterator for a specific position in a node list.
- iterator(LazyCallGraph &G, NodeVectorImplT::iterator NI,
- NodeVectorImplT::iterator E)
- : iterator_adaptor_base(NI), G(&G), E(E) {
- while (I != E && I->isNull())
+ // Build the iterator for a specific position in the edge list.
+ edge_iterator(EdgeVectorImplT::iterator BaseI,
+ EdgeVectorImplT::iterator E)
+ : iterator_adaptor_base(BaseI), E(E) {
+ while (I != E && !*I)
++I;
}
public:
- iterator() {}
+ edge_iterator() {}
using iterator_adaptor_base::operator++;
- iterator &operator++() {
+ edge_iterator &operator++() {
do {
++I;
- } while (I != E && I->isNull());
+ } while (I != E && !*I);
return *this;
}
+ };
- reference operator*() const {
- if (I->is<Node *>())
- return *I->get<Node *>();
+ /// A lazy iterator over specifically call edges.
+ ///
+ /// This has the same iteration properties as the \c edge_iterator, but
+ /// restricts itself to edges which represent actual calls.
+ class call_edge_iterator
+ : public iterator_adaptor_base<call_edge_iterator,
+ EdgeVectorImplT::iterator,
+ std::forward_iterator_tag> {
+ friend class LazyCallGraph;
+ friend class LazyCallGraph::Node;
+
+ EdgeVectorImplT::iterator E;
+
+ /// Advance the iterator to the next valid, call edge.
+ void advanceToNextEdge() {
+ while (I != E && (!*I || !I->isCall()))
+ ++I;
+ }
+
+ // Build the iterator for a specific position in the edge list.
+ call_edge_iterator(EdgeVectorImplT::iterator BaseI,
+ EdgeVectorImplT::iterator E)
+ : iterator_adaptor_base(BaseI), E(E) {
+ advanceToNextEdge();
+ }
+
+ public:
+ call_edge_iterator() {}
- Function *F = I->get<Function *>();
- Node &ChildN = G->get(*F);
- *I = &ChildN;
- return ChildN;
+ using iterator_adaptor_base::operator++;
+ call_edge_iterator &operator++() {
+ ++I;
+ advanceToNextEdge();
+ return *this;
}
};
/// An SCC of the call graph.
///
- /// This represents a Strongly Connected Component of the call graph as
+ /// This represents a Strongly Connected Component of the direct call graph
+ /// -- ignoring indirect calls and function references. It stores this as
/// a collection of call graph nodes. While the order of nodes in the SCC is
/// stable, it is not any particular order.
+ ///
+ /// The SCCs are nested within a \c RefSCC, see below for details about that
+ /// outer structure. SCCs do not support mutation of the call graph, that
+ /// must be done through the containing \c RefSCC in order to fully reason
+ /// about the ordering and connections of the graph.
class SCC {
friend class LazyCallGraph;
friend class LazyCallGraph::Node;
- LazyCallGraph *G;
- SmallPtrSet<SCC *, 1> ParentSCCs;
+ RefSCC *OuterRefSCC;
SmallVector<Node *, 1> Nodes;
- SCC(LazyCallGraph &G) : G(&G) {}
+ template <typename NodeRangeT>
+ SCC(RefSCC &OuterRefSCC, NodeRangeT &&Nodes)
+ : OuterRefSCC(&OuterRefSCC), Nodes(std::forward<NodeRangeT>(Nodes)) {}
+
+ void clear() {
+ OuterRefSCC = nullptr;
+ Nodes.clear();
+ }
+
+ /// Print a short descrtiption useful for debugging or logging.
+ ///
+ /// We print the function names in the SCC wrapped in '()'s and skipping
+ /// the middle functions if there are a large number.
+ //
+ // Note: this is defined inline to dodge issues with GCC's interpretation
+ // of enclosing namespaces for friend function declarations.
+ friend raw_ostream &operator<<(raw_ostream &OS, const SCC &C) {
+ OS << '(';
+ int i = 0;
+ for (LazyCallGraph::Node &N : C) {
+ if (i > 0)
+ OS << ", ";
+ // Elide the inner elements if there are too many.
+ if (i > 8) {
+ OS << "..., " << *C.Nodes.back();
+ break;
+ }
+ OS << N;
+ ++i;
+ }
+ OS << ')';
+ return OS;
+ }
- void insert(Node &N);
+ /// Dump a short description of this SCC to stderr.
+ void dump() const;
- void
- internalDFS(SmallVectorImpl<std::pair<Node *, Node::iterator>> &DFSStack,
- SmallVectorImpl<Node *> &PendingSCCStack, Node *N,
- SmallVectorImpl<SCC *> &ResultSCCs);
+#ifndef NDEBUG
+ /// Verify invariants about the SCC.
+ ///
+ /// This will attempt to validate all of the basic invariants within an
+ /// SCC, but not that it is a strongly connected componet per-se. Primarily
+ /// useful while building and updating the graph to check that basic
+ /// properties are in place rather than having inexplicable crashes later.
+ void verify();
+#endif
public:
- typedef SmallVectorImpl<Node *>::const_iterator iterator;
- typedef pointee_iterator<SmallPtrSet<SCC *, 1>::const_iterator>
- parent_iterator;
+ typedef pointee_iterator<SmallVectorImpl<Node *>::const_iterator> iterator;
iterator begin() const { return Nodes.begin(); }
iterator end() const { return Nodes.end(); }
- parent_iterator parent_begin() const { return ParentSCCs.begin(); }
- parent_iterator parent_end() const { return ParentSCCs.end(); }
+ int size() const { return Nodes.size(); }
+
+ RefSCC &getOuterRefSCC() const { return *OuterRefSCC; }
+
+ /// Provide a short name by printing this SCC to a std::string.
+ ///
+ /// This copes with the fact that we don't have a name per-se for an SCC
+ /// while still making the use of this in debugging and logging useful.
+ std::string getName() const {
+ std::string Name;
+ raw_string_ostream OS(Name);
+ OS << *this;
+ OS.flush();
+ return Name;
+ }
+ };
+
+ /// A RefSCC of the call graph.
+ ///
+ /// This models a Strongly Connected Component of function reference edges in
+ /// the call graph. As opposed to actual SCCs, these can be used to scope
+ /// subgraphs of the module which are independent from other subgraphs of the
+ /// module because they do not reference it in any way. This is also the unit
+ /// where we do mutation of the graph in order to restrict mutations to those
+ /// which don't violate this independence.
+ ///
+ /// A RefSCC contains a DAG of actual SCCs. All the nodes within the RefSCC
+ /// are necessarily within some actual SCC that nests within it. Since
+ /// a direct call *is* a reference, there will always be at least one RefSCC
+ /// around any SCC.
+ class RefSCC {
+ friend class LazyCallGraph;
+ friend class LazyCallGraph::Node;
+
+ LazyCallGraph *G;
+ SmallPtrSet<RefSCC *, 1> Parents;
+
+ /// A postorder list of the inner SCCs.
+ SmallVector<SCC *, 4> SCCs;
+
+ /// A map from SCC to index in the postorder list.
+ SmallDenseMap<SCC *, int, 4> SCCIndices;
+
+ /// Fast-path constructor. RefSCCs should instead be constructed by calling
+ /// formRefSCCFast on the graph itself.
+ RefSCC(LazyCallGraph &G);
+
+ /// Print a short description useful for debugging or logging.
+ ///
+ /// We print the SCCs wrapped in '[]'s and skipping the middle SCCs if
+ /// there are a large number.
+ //
+ // Note: this is defined inline to dodge issues with GCC's interpretation
+ // of enclosing namespaces for friend function declarations.
+ friend raw_ostream &operator<<(raw_ostream &OS, const RefSCC &RC) {
+ OS << '[';
+ int i = 0;
+ for (LazyCallGraph::SCC &C : RC) {
+ if (i > 0)
+ OS << ", ";
+ // Elide the inner elements if there are too many.
+ if (i > 4) {
+ OS << "..., " << *RC.SCCs.back();
+ break;
+ }
+ OS << C;
+ ++i;
+ }
+ OS << ']';
+ return OS;
+ }
+
+ /// Dump a short description of this RefSCC to stderr.
+ void dump() const;
+
+#ifndef NDEBUG
+ /// Verify invariants about the RefSCC and all its SCCs.
+ ///
+ /// This will attempt to validate all of the invariants *within* the
+ /// RefSCC, but not that it is a strongly connected component of the larger
+ /// graph. This makes it useful even when partially through an update.
+ ///
+ /// Invariants checked:
+ /// - SCCs and their indices match.
+ /// - The SCCs list is in fact in post-order.
+ void verify();
+#endif
+
+ public:
+ typedef pointee_iterator<SmallVectorImpl<SCC *>::const_iterator> iterator;
+ typedef iterator_range<iterator> range;
+ typedef pointee_iterator<SmallPtrSetImpl<RefSCC *>::const_iterator>
+ parent_iterator;
+
+ iterator begin() const { return SCCs.begin(); }
+ iterator end() const { return SCCs.end(); }
+
+ ssize_t size() const { return SCCs.size(); }
+
+ SCC &operator[](int Idx) { return *SCCs[Idx]; }
+
+ iterator find(SCC &C) const {
+ return SCCs.begin() + SCCIndices.find(&C)->second;
+ }
+
+ parent_iterator parent_begin() const { return Parents.begin(); }
+ parent_iterator parent_end() const { return Parents.end(); }
iterator_range<parent_iterator> parents() const {
return make_range(parent_begin(), parent_end());
}
/// Test if this SCC is a parent of \a C.
- bool isParentOf(const SCC &C) const { return C.isChildOf(*this); }
+ bool isParentOf(const RefSCC &C) const { return C.isChildOf(*this); }
- /// Test if this SCC is an ancestor of \a C.
- bool isAncestorOf(const SCC &C) const { return C.isDescendantOf(*this); }
+ /// Test if this RefSCC is an ancestor of \a C.
+ bool isAncestorOf(const RefSCC &C) const { return C.isDescendantOf(*this); }
- /// Test if this SCC is a child of \a C.
- bool isChildOf(const SCC &C) const {
- return ParentSCCs.count(const_cast<SCC *>(&C));
+ /// Test if this RefSCC is a child of \a C.
+ bool isChildOf(const RefSCC &C) const {
+ return Parents.count(const_cast<RefSCC *>(&C));
}
- /// Test if this SCC is a descendant of \a C.
- bool isDescendantOf(const SCC &C) const;
+ /// Test if this RefSCC is a descendant of \a C.
+ bool isDescendantOf(const RefSCC &C) const;
- /// Short name useful for debugging or logging.
+ /// Provide a short name by printing this SCC to a std::string.
///
- /// We use the name of the first function in the SCC to name the SCC for
- /// the purposes of debugging and logging.
- StringRef getName() const { return (*begin())->getFunction().getName(); }
+ /// This copes with the fact that we don't have a name per-se for an SCC
+ /// while still making the use of this in debugging and logging useful.
+ std::string getName() const {
+ std::string Name;
+ raw_string_ostream OS(Name);
+ OS << *this;
+ OS.flush();
+ return Name;
+ }
///@{
/// \name Mutation API
@@ -267,80 +553,151 @@ public:
/// Note that these methods sometimes have complex runtimes, so be careful
/// how you call them.
- /// Insert an edge from one node in this SCC to another in this SCC.
+ /// Make an existing internal ref edge into a call edge.
+ ///
+ /// This may form a larger cycle and thus collapse SCCs into TargetN's SCC.
+ /// If that happens, the deleted SCC pointers are returned. These SCCs are
+ /// not in a valid state any longer but the pointers will remain valid
+ /// until destruction of the parent graph instance for the purpose of
+ /// clearing cached information.
///
- /// By the definition of an SCC, this does not change the nature or make-up
- /// of any SCCs.
- void insertIntraSCCEdge(Node &CallerN, Node &CalleeN);
+ /// After this operation, both SourceN's SCC and TargetN's SCC may move
+ /// position within this RefSCC's postorder list. Any SCCs merged are
+ /// merged into the TargetN's SCC in order to preserve reachability analyses
+ /// which took place on that SCC.
+ SmallVector<SCC *, 1> switchInternalEdgeToCall(Node &SourceN,
+ Node &TargetN);
+
+ /// Make an existing internal call edge into a ref edge.
+ ///
+ /// If SourceN and TargetN are part of a single SCC, it may be split up due
+ /// to breaking a cycle in the call edges that formed it. If that happens,
+ /// then this routine will insert new SCCs into the postorder list *before*
+ /// the SCC of TargetN (previously the SCC of both). This preserves
+ /// postorder as the TargetN can reach all of the other nodes by definition
+ /// of previously being in a single SCC formed by the cycle from SourceN to
+ /// TargetN. The newly added nodes are added *immediately* and contiguously
+ /// prior to the TargetN SCC and so they may be iterated starting from
+ /// there.
+ void switchInternalEdgeToRef(Node &SourceN, Node &TargetN);
+
+ /// Make an existing outgoing ref edge into a call edge.
+ ///
+ /// Note that this is trivial as there are no cyclic impacts and there
+ /// remains a reference edge.
+ void switchOutgoingEdgeToCall(Node &SourceN, Node &TargetN);
- /// Insert an edge whose tail is in this SCC and head is in some child SCC.
+ /// Make an existing outgoing call edge into a ref edge.
///
- /// There must be an existing path from the caller to the callee. This
- /// operation is inexpensive and does not change the set of SCCs in the
- /// graph.
- void insertOutgoingEdge(Node &CallerN, Node &CalleeN);
+ /// This is trivial as there are no cyclic impacts and there remains
+ /// a reference edge.
+ void switchOutgoingEdgeToRef(Node &SourceN, Node &TargetN);
- /// Insert an edge whose tail is in a descendant SCC and head is in this
- /// SCC.
+ /// Insert a ref edge from one node in this RefSCC to another in this
+ /// RefSCC.
+ ///
+ /// This is always a trivial operation as it doesn't change any part of the
+ /// graph structure besides connecting the two nodes.
+ ///
+ /// Note that we don't support directly inserting internal *call* edges
+ /// because that could change the graph structure and requires returning
+ /// information about what became invalid. As a consequence, the pattern
+ /// should be to first insert the necessary ref edge, and then to switch it
+ /// to a call edge if needed and handle any invalidation that results. See
+ /// the \c switchInternalEdgeToCall routine for details.
+ void insertInternalRefEdge(Node &SourceN, Node &TargetN);
+
+ /// Insert an edge whose parent is in this RefSCC and child is in some
+ /// child RefSCC.
+ ///
+ /// There must be an existing path from the \p SourceN to the \p TargetN.
+ /// This operation is inexpensive and does not change the set of SCCs and
+ /// RefSCCs in the graph.
+ void insertOutgoingEdge(Node &SourceN, Node &TargetN, Edge::Kind EK);
+
+ /// Insert an edge whose source is in a descendant RefSCC and target is in
+ /// this RefSCC.
+ ///
+ /// There must be an existing path from the target to the source in this
+ /// case.
+ ///
+ /// NB! This is has the potential to be a very expensive function. It
+ /// inherently forms a cycle in the prior RefSCC DAG and we have to merge
+ /// RefSCCs to resolve that cycle. But finding all of the RefSCCs which
+ /// participate in the cycle can in the worst case require traversing every
+ /// RefSCC in the graph. Every attempt is made to avoid that, but passes
+ /// must still exercise caution calling this routine repeatedly.
+ ///
+ /// Also note that this can only insert ref edges. In order to insert
+ /// a call edge, first insert a ref edge and then switch it to a call edge.
+ /// These are intentionally kept as separate interfaces because each step
+ /// of the operation invalidates a different set of data structures.
///
- /// There must be an existing path from the callee to the caller in this
- /// case. NB! This is has the potential to be a very expensive function. It
- /// inherently forms a cycle in the prior SCC DAG and we have to merge SCCs
- /// to resolve that cycle. But finding all of the SCCs which participate in
- /// the cycle can in the worst case require traversing every SCC in the
- /// graph. Every attempt is made to avoid that, but passes must still
- /// exercise caution calling this routine repeatedly.
+ /// This returns all the RefSCCs which were merged into the this RefSCC
+ /// (the target's). This allows callers to invalidate any cached
+ /// information.
///
/// FIXME: We could possibly optimize this quite a bit for cases where the
/// caller and callee are very nearby in the graph. See comments in the
/// implementation for details, but that use case might impact users.
- SmallVector<SCC *, 1> insertIncomingEdge(Node &CallerN, Node &CalleeN);
+ SmallVector<RefSCC *, 1> insertIncomingRefEdge(Node &SourceN,
+ Node &TargetN);
- /// Remove an edge whose source is in this SCC and target is *not*.
+ /// Remove an edge whose source is in this RefSCC and target is *not*.
///
- /// This removes an inter-SCC edge. All inter-SCC edges originating from
- /// this SCC have been fully explored by any in-flight DFS SCC formation,
- /// so this is always safe to call once you have the source SCC.
+ /// This removes an inter-RefSCC edge. All inter-RefSCC edges originating
+ /// from this SCC have been fully explored by any in-flight DFS graph
+ /// formation, so this is always safe to call once you have the source
+ /// RefSCC.
///
- /// This operation does not change the set of SCCs or the members of the
- /// SCCs and so is very inexpensive. It may change the connectivity graph
- /// of the SCCs though, so be careful calling this while iterating over
- /// them.
- void removeInterSCCEdge(Node &CallerN, Node &CalleeN);
+ /// This operation does not change the cyclic structure of the graph and so
+ /// is very inexpensive. It may change the connectivity graph of the SCCs
+ /// though, so be careful calling this while iterating over them.
+ void removeOutgoingEdge(Node &SourceN, Node &TargetN);
- /// Remove an edge which is entirely within this SCC.
+ /// Remove a ref edge which is entirely within this RefSCC.
///
- /// Both the \a Caller and the \a Callee must be within this SCC. Removing
- /// such an edge make break cycles that form this SCC and thus this
- /// operation may change the SCC graph significantly. In particular, this
- /// operation will re-form new SCCs based on the remaining connectivity of
- /// the graph. The following invariants are guaranteed to hold after
- /// calling this method:
+ /// Both the \a SourceN and the \a TargetN must be within this RefSCC.
+ /// Removing such an edge may break cycles that form this RefSCC and thus
+ /// this operation may change the RefSCC graph significantly. In
+ /// particular, this operation will re-form new RefSCCs based on the
+ /// remaining connectivity of the graph. The following invariants are
+ /// guaranteed to hold after calling this method:
///
- /// 1) This SCC is still an SCC in the graph.
- /// 2) This SCC will be the parent of any new SCCs. Thus, this SCC is
- /// preserved as the root of any new SCC directed graph formed.
- /// 3) No SCC other than this SCC has its member set changed (this is
+ /// 1) This RefSCC is still a RefSCC in the graph.
+ /// 2) This RefSCC will be the parent of any new RefSCCs. Thus, this RefSCC
+ /// is preserved as the root of any new RefSCC DAG formed.
+ /// 3) No RefSCC other than this RefSCC has its member set changed (this is
/// inherent in the definition of removing such an edge).
- /// 4) All of the parent links of the SCC graph will be updated to reflect
- /// the new SCC structure.
- /// 5) All SCCs formed out of this SCC, excluding this SCC, will be
- /// returned in a vector.
- /// 6) The order of the SCCs in the vector will be a valid postorder
- /// traversal of the new SCCs.
+ /// 4) All of the parent links of the RefSCC graph will be updated to
+ /// reflect the new RefSCC structure.
+ /// 5) All RefSCCs formed out of this RefSCC, excluding this RefSCC, will
+ /// be returned in post-order.
+ /// 6) The order of the RefSCCs in the vector will be a valid postorder
+ /// traversal of the new RefSCCs.
///
/// These invariants are very important to ensure that we can build
- /// optimization pipeliens on top of the CGSCC pass manager which
- /// intelligently update the SCC graph without invalidating other parts of
- /// the SCC graph.
+ /// optimization pipelines on top of the CGSCC pass manager which
+ /// intelligently update the RefSCC graph without invalidating other parts
+ /// of the RefSCC graph.
+ ///
+ /// Note that we provide no routine to remove a *call* edge. Instead, you
+ /// must first switch it to a ref edge using \c switchInternalEdgeToRef.
+ /// This split API is intentional as each of these two steps can invalidate
+ /// a different aspect of the graph structure and needs to have the
+ /// invalidation handled independently.
///
/// The runtime complexity of this method is, in the worst case, O(V+E)
- /// where V is the number of nodes in this SCC and E is the number of edges
- /// leaving the nodes in this SCC. Note that E includes both edges within
- /// this SCC and edges from this SCC to child SCCs. Some effort has been
- /// made to minimize the overhead of common cases such as self-edges and
- /// edge removals which result in a spanning tree with no more cycles.
- SmallVector<SCC *, 1> removeIntraSCCEdge(Node &CallerN, Node &CalleeN);
+ /// where V is the number of nodes in this RefSCC and E is the number of
+ /// edges leaving the nodes in this RefSCC. Note that E includes both edges
+ /// within this RefSCC and edges from this RefSCC to child RefSCCs. Some
+ /// effort has been made to minimize the overhead of common cases such as
+ /// self-edges and edge removals which result in a spanning tree with no
+ /// more cycles. There are also detailed comments within the implementation
+ /// on techniques which could substantially improve this routine's
+ /// efficiency.
+ SmallVector<RefSCC *, 1> removeInternalRefEdge(Node &SourceN,
+ Node &TargetN);
///@}
};
@@ -351,9 +708,9 @@ public:
/// the call graph, walking it lazily in depth-first post-order. That is, it
/// always visits SCCs for a callee prior to visiting the SCC for a caller
/// (when they are in different SCCs).
- class postorder_scc_iterator
- : public iterator_facade_base<postorder_scc_iterator,
- std::forward_iterator_tag, SCC> {
+ class postorder_ref_scc_iterator
+ : public iterator_facade_base<postorder_ref_scc_iterator,
+ std::forward_iterator_tag, RefSCC> {
friend class LazyCallGraph;
friend class LazyCallGraph::Node;
@@ -361,27 +718,27 @@ public:
struct IsAtEndT {};
LazyCallGraph *G;
- SCC *C;
+ RefSCC *C;
// Build the begin iterator for a node.
- postorder_scc_iterator(LazyCallGraph &G) : G(&G) {
- C = G.getNextSCCInPostOrder();
+ postorder_ref_scc_iterator(LazyCallGraph &G) : G(&G) {
+ C = G.getNextRefSCCInPostOrder();
}
// Build the end iterator for a node. This is selected purely by overload.
- postorder_scc_iterator(LazyCallGraph &G, IsAtEndT /*Nonce*/)
+ postorder_ref_scc_iterator(LazyCallGraph &G, IsAtEndT /*Nonce*/)
: G(&G), C(nullptr) {}
public:
- bool operator==(const postorder_scc_iterator &Arg) const {
+ bool operator==(const postorder_ref_scc_iterator &Arg) const {
return G == Arg.G && C == Arg.C;
}
reference operator*() const { return *C; }
using iterator_facade_base::operator++;
- postorder_scc_iterator &operator++() {
- C = G->getNextSCCInPostOrder();
+ postorder_ref_scc_iterator &operator++() {
+ C = G->getNextRefSCCInPostOrder();
return *this;
}
};
@@ -396,20 +753,23 @@ public:
LazyCallGraph(LazyCallGraph &&G);
LazyCallGraph &operator=(LazyCallGraph &&RHS);
- iterator begin() {
- return iterator(*this, EntryNodes.begin(), EntryNodes.end());
+ edge_iterator begin() {
+ return edge_iterator(EntryEdges.begin(), EntryEdges.end());
+ }
+ edge_iterator end() {
+ return edge_iterator(EntryEdges.end(), EntryEdges.end());
}
- iterator end() { return iterator(*this, EntryNodes.end(), EntryNodes.end()); }
- postorder_scc_iterator postorder_scc_begin() {
- return postorder_scc_iterator(*this);
+ postorder_ref_scc_iterator postorder_ref_scc_begin() {
+ return postorder_ref_scc_iterator(*this);
}
- postorder_scc_iterator postorder_scc_end() {
- return postorder_scc_iterator(*this, postorder_scc_iterator::IsAtEndT());
+ postorder_ref_scc_iterator postorder_ref_scc_end() {
+ return postorder_ref_scc_iterator(*this,
+ postorder_ref_scc_iterator::IsAtEndT());
}
- iterator_range<postorder_scc_iterator> postorder_sccs() {
- return make_range(postorder_scc_begin(), postorder_scc_end());
+ iterator_range<postorder_ref_scc_iterator> postorder_ref_sccs() {
+ return make_range(postorder_ref_scc_begin(), postorder_ref_scc_end());
}
/// Lookup a function in the graph which has already been scanned and added.
@@ -421,6 +781,17 @@ public:
/// iterator walk.
SCC *lookupSCC(Node &N) const { return SCCMap.lookup(&N); }
+ /// Lookup a function's RefSCC in the graph.
+ ///
+ /// \returns null if the function hasn't been assigned a RefSCC via the
+ /// RefSCC iterator walk.
+ RefSCC *lookupRefSCC(Node &N) const {
+ if (SCC *C = lookupSCC(N))
+ return &C->getOuterRefSCC();
+
+ return nullptr;
+ }
+
/// Get a graph node for a given function, scanning it to populate the graph
/// data as necessary.
Node &get(Function &F) {
@@ -442,11 +813,11 @@ public:
/// mutation of the graph via the SCC methods.
/// Update the call graph after inserting a new edge.
- void insertEdge(Node &Caller, Function &Callee);
+ void insertEdge(Node &Caller, Function &Callee, Edge::Kind EK);
/// Update the call graph after inserting a new edge.
- void insertEdge(Function &Caller, Function &Callee) {
- return insertEdge(get(Caller), Callee);
+ void insertEdge(Function &Caller, Function &Callee, Edge::Kind EK) {
+ return insertEdge(get(Caller), Callee, EK);
}
/// Update the call graph after deleting an edge.
@@ -460,6 +831,9 @@ public:
///@}
private:
+ typedef SmallVectorImpl<Node *>::reverse_iterator node_stack_iterator;
+ typedef iterator_range<node_stack_iterator> node_stack_range;
+
/// Allocator that holds all the call graph nodes.
SpecificBumpPtrAllocator<Node> BPA;
@@ -470,10 +844,10 @@ private:
///
/// These nodes are reachable through "external" means. Put another way, they
/// escape at the module scope.
- NodeVectorT EntryNodes;
+ EdgeVectorT EntryEdges;
- /// Map of the entry nodes in the graph to their indices in \c EntryNodes.
- DenseMap<Function *, size_t> EntryIndexMap;
+ /// Map of the entry nodes in the graph to their indices in \c EntryEdges.
+ DenseMap<Function *, int> EntryIndexMap;
/// Allocator that holds all the call graph SCCs.
SpecificBumpPtrAllocator<SCC> SCCBPA;
@@ -481,19 +855,22 @@ private:
/// Maps Function -> SCC for fast lookup.
DenseMap<Node *, SCC *> SCCMap;
- /// The leaf SCCs of the graph.
+ /// Allocator that holds all the call graph RefSCCs.
+ SpecificBumpPtrAllocator<RefSCC> RefSCCBPA;
+
+ /// The leaf RefSCCs of the graph.
///
- /// These are all of the SCCs which have no children.
- SmallVector<SCC *, 4> LeafSCCs;
+ /// These are all of the RefSCCs which have no children.
+ SmallVector<RefSCC *, 4> LeafRefSCCs;
/// Stack of nodes in the DFS walk.
- SmallVector<std::pair<Node *, iterator>, 4> DFSStack;
+ SmallVector<std::pair<Node *, edge_iterator>, 4> DFSStack;
- /// Set of entry nodes not-yet-processed into SCCs.
- SmallVector<Function *, 4> SCCEntryNodes;
+ /// Set of entry nodes not-yet-processed into RefSCCs.
+ SmallVector<Function *, 4> RefSCCEntryNodes;
/// Stack of nodes the DFS has walked but not yet put into a SCC.
- SmallVector<Node *, 4> PendingSCCStack;
+ SmallVector<Node *, 4> PendingRefSCCStack;
/// Counter for the next DFS number to assign.
int NextDFSNumber;
@@ -505,18 +882,79 @@ private:
/// Helper to update pointers back to the graph object during moves.
void updateGraphPtrs();
- /// Helper to form a new SCC out of the top of a DFSStack-like
- /// structure.
- SCC *formSCC(Node *RootN, SmallVectorImpl<Node *> &NodeStack);
+ /// Allocates an SCC and constructs it using the graph allocator.
+ ///
+ /// The arguments are forwarded to the constructor.
+ template <typename... Ts> SCC *createSCC(Ts &&... Args) {
+ return new (SCCBPA.Allocate()) SCC(std::forward<Ts>(Args)...);
+ }
+
+ /// Allocates a RefSCC and constructs it using the graph allocator.
+ ///
+ /// The arguments are forwarded to the constructor.
+ template <typename... Ts> RefSCC *createRefSCC(Ts &&... Args) {
+ return new (RefSCCBPA.Allocate()) RefSCC(std::forward<Ts>(Args)...);
+ }
+
+ /// Build the SCCs for a RefSCC out of a list of nodes.
+ void buildSCCs(RefSCC &RC, node_stack_range Nodes);
- /// Retrieve the next node in the post-order SCC walk of the call graph.
- SCC *getNextSCCInPostOrder();
+ /// Connect a RefSCC into the larger graph.
+ ///
+ /// This walks the edges to connect the RefSCC to its children's parent set,
+ /// and updates the root leaf list.
+ void connectRefSCC(RefSCC &RC);
+
+ /// Retrieve the next node in the post-order RefSCC walk of the call graph.
+ RefSCC *getNextRefSCCInPostOrder();
};
+inline LazyCallGraph::Edge::Edge() : Value() {}
+inline LazyCallGraph::Edge::Edge(Function &F, Kind K) : Value(&F, K) {}
+inline LazyCallGraph::Edge::Edge(Node &N, Kind K) : Value(&N, K) {}
+
+inline LazyCallGraph::Edge::operator bool() const {
+ return !Value.getPointer().isNull();
+}
+
+inline bool LazyCallGraph::Edge::isCall() const {
+ assert(*this && "Queried a null edge!");
+ return Value.getInt() == Call;
+}
+
+inline Function &LazyCallGraph::Edge::getFunction() const {
+ assert(*this && "Queried a null edge!");
+ auto P = Value.getPointer();
+ if (auto *F = P.dyn_cast<Function *>())
+ return *F;
+
+ return P.get<Node *>()->getFunction();
+}
+
+inline LazyCallGraph::Node *LazyCallGraph::Edge::getNode() const {
+ assert(*this && "Queried a null edge!");
+ auto P = Value.getPointer();
+ if (auto *N = P.dyn_cast<Node *>())
+ return N;
+
+ return nullptr;
+}
+
+inline LazyCallGraph::Node &LazyCallGraph::Edge::getNode(LazyCallGraph &G) {
+ assert(*this && "Queried a null edge!");
+ auto P = Value.getPointer();
+ if (auto *N = P.dyn_cast<Node *>())
+ return *N;
+
+ Node &N = G.get(*P.get<Function *>());
+ Value.setPointer(&N);
+ return N;
+}
+
// Provide GraphTraits specializations for call graphs.
template <> struct GraphTraits<LazyCallGraph::Node *> {
typedef LazyCallGraph::Node NodeType;
- typedef LazyCallGraph::iterator ChildIteratorType;
+ typedef LazyCallGraph::edge_iterator ChildIteratorType;
static NodeType *getEntryNode(NodeType *N) { return N; }
static ChildIteratorType child_begin(NodeType *N) { return N->begin(); }
@@ -524,7 +962,7 @@ template <> struct GraphTraits<LazyCallGraph::Node *> {
};
template <> struct GraphTraits<LazyCallGraph *> {
typedef LazyCallGraph::Node NodeType;
- typedef LazyCallGraph::iterator ChildIteratorType;
+ typedef LazyCallGraph::edge_iterator ChildIteratorType;
static NodeType *getEntryNode(NodeType *N) { return N; }
static ChildIteratorType child_begin(NodeType *N) { return N->begin(); }
@@ -532,39 +970,48 @@ template <> struct GraphTraits<LazyCallGraph *> {
};
/// An analysis pass which computes the call graph for a module.
-class LazyCallGraphAnalysis {
+class LazyCallGraphAnalysis : public AnalysisInfoMixin<LazyCallGraphAnalysis> {
+ friend AnalysisInfoMixin<LazyCallGraphAnalysis>;
+ static char PassID;
+
public:
/// Inform generic clients of the result type.
typedef LazyCallGraph Result;
- static void *ID() { return (void *)&PassID; }
-
- static StringRef name() { return "Lazy CallGraph Analysis"; }
-
/// Compute the \c LazyCallGraph for the module \c M.
///
/// This just builds the set of entry points to the call graph. The rest is
/// built lazily as it is walked.
- LazyCallGraph run(Module &M) { return LazyCallGraph(M); }
-
-private:
- static char PassID;
+ LazyCallGraph run(Module &M, ModuleAnalysisManager &) {
+ return LazyCallGraph(M);
+ }
};
/// A pass which prints the call graph to a \c raw_ostream.
///
/// This is primarily useful for testing the analysis.
-class LazyCallGraphPrinterPass {
+class LazyCallGraphPrinterPass
+ : public PassInfoMixin<LazyCallGraphPrinterPass> {
raw_ostream &OS;
public:
explicit LazyCallGraphPrinterPass(raw_ostream &OS);
- PreservedAnalyses run(Module &M, ModuleAnalysisManager *AM);
-
- static StringRef name() { return "LazyCallGraphPrinterPass"; }
+ PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
};
+/// A pass which prints the call graph as a DOT file to a \c raw_ostream.
+///
+/// This is primarily useful for visualization purposes.
+class LazyCallGraphDOTPrinterPass
+ : public PassInfoMixin<LazyCallGraphDOTPrinterPass> {
+ raw_ostream &OS;
+
+public:
+ explicit LazyCallGraphDOTPrinterPass(raw_ostream &OS);
+
+ PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
+};
}
#endif
diff --git a/include/llvm/Analysis/LazyValueInfo.h b/include/llvm/Analysis/LazyValueInfo.h
index 42002062dca2..c85cf2c5da56 100644
--- a/include/llvm/Analysis/LazyValueInfo.h
+++ b/include/llvm/Analysis/LazyValueInfo.h
@@ -15,11 +15,13 @@
#ifndef LLVM_ANALYSIS_LAZYVALUEINFO_H
#define LLVM_ANALYSIS_LAZYVALUEINFO_H
+#include "llvm/IR/PassManager.h"
#include "llvm/Pass.h"
namespace llvm {
class AssumptionCache;
class Constant;
+ class ConstantRange;
class DataLayout;
class DominatorTree;
class Instruction;
@@ -27,19 +29,33 @@ namespace llvm {
class Value;
/// This pass computes, caches, and vends lazy value constraint information.
-class LazyValueInfo : public FunctionPass {
- AssumptionCache *AC;
- class TargetLibraryInfo *TLI;
- DominatorTree *DT;
- void *PImpl;
+class LazyValueInfo {
+ friend class LazyValueInfoWrapperPass;
+ AssumptionCache *AC = nullptr;
+ class TargetLibraryInfo *TLI = nullptr;
+ DominatorTree *DT = nullptr;
+ void *PImpl = nullptr;
LazyValueInfo(const LazyValueInfo&) = delete;
void operator=(const LazyValueInfo&) = delete;
public:
- static char ID;
- LazyValueInfo() : FunctionPass(ID), PImpl(nullptr) {
- initializeLazyValueInfoPass(*PassRegistry::getPassRegistry());
+ ~LazyValueInfo();
+ LazyValueInfo() {}
+ LazyValueInfo(AssumptionCache *AC_, TargetLibraryInfo *TLI_,
+ DominatorTree *DT_)
+ : AC(AC_), TLI(TLI_), DT(DT_) {}
+ LazyValueInfo(LazyValueInfo &&Arg)
+ : AC(Arg.AC), TLI(Arg.TLI), DT(Arg.DT), PImpl(Arg.PImpl) {
+ Arg.PImpl = nullptr;
+ }
+ LazyValueInfo &operator=(LazyValueInfo &&Arg) {
+ releaseMemory();
+ AC = Arg.AC;
+ TLI = Arg.TLI;
+ DT = Arg.DT;
+ PImpl = Arg.PImpl;
+ Arg.PImpl = nullptr;
+ return *this;
}
- ~LazyValueInfo() override { assert(!PImpl && "releaseMemory not called"); }
/// This is used to return true/false/dunno results.
enum Tristate {
@@ -65,6 +81,11 @@ public:
/// constant at the end of the specified block. Return null if not.
Constant *getConstant(Value *V, BasicBlock *BB, Instruction *CxtI = nullptr);
+ /// 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
+ /// on integer-typed Values.
+ ConstantRange getConstantRange(Value *V, BasicBlock *BB, Instruction *CxtI = nullptr);
+
/// Determine whether the specified value is known to be a
/// constant on the specified edge. Return null if not.
Constant *getConstantOnEdge(Value *V, BasicBlock *FromBB, BasicBlock *ToBB,
@@ -77,11 +98,41 @@ public:
/// Inform the analysis cache that we have erased a block.
void eraseBlock(BasicBlock *BB);
- // Implementation boilerplate.
+ // For old PM pass. Delete once LazyValueInfoWrapperPass is gone.
+ void releaseMemory();
+};
+
+/// \brief Analysis to compute lazy value information.
+class LazyValueAnalysis : public AnalysisInfoMixin<LazyValueAnalysis> {
+public:
+ typedef LazyValueInfo Result;
+ Result run(Function &F, FunctionAnalysisManager &FAM);
+
+private:
+ static char PassID;
+ friend struct AnalysisInfoMixin<LazyValueAnalysis>;
+};
+
+/// Wrapper around LazyValueInfo.
+class LazyValueInfoWrapperPass : public FunctionPass {
+ LazyValueInfoWrapperPass(const LazyValueInfoWrapperPass&) = delete;
+ void operator=(const LazyValueInfoWrapperPass&) = delete;
+public:
+ static char ID;
+ LazyValueInfoWrapperPass() : FunctionPass(ID) {
+ initializeLazyValueInfoWrapperPassPass(*PassRegistry::getPassRegistry());
+ }
+ ~LazyValueInfoWrapperPass() override {
+ assert(!Info.PImpl && "releaseMemory not called");
+ }
+
+ LazyValueInfo &getLVI();
void getAnalysisUsage(AnalysisUsage &AU) const override;
void releaseMemory() override;
bool runOnFunction(Function &F) override;
+private:
+ LazyValueInfo Info;
};
} // end namespace llvm
diff --git a/include/llvm/Analysis/Loads.h b/include/llvm/Analysis/Loads.h
index 939663b0def1..39f80f489e12 100644
--- a/include/llvm/Analysis/Loads.h
+++ b/include/llvm/Analysis/Loads.h
@@ -23,39 +23,74 @@ namespace llvm {
class DataLayout;
class MDNode;
+/// isDereferenceablePointer - Return true if this is always a dereferenceable
+/// pointer. If the context instruction is specified perform context-sensitive
+/// analysis and return true if the pointer is dereferenceable at the
+/// specified instruction.
+bool isDereferenceablePointer(const Value *V, const DataLayout &DL,
+ const Instruction *CtxI = nullptr,
+ const DominatorTree *DT = nullptr);
+
+/// Returns true if V is always a dereferenceable pointer with alignment
+/// greater or equal than requested. If the context instruction is specified
+/// performs context-sensitive analysis and returns true if the pointer is
+/// dereferenceable at the specified instruction.
+bool isDereferenceableAndAlignedPointer(const Value *V, unsigned Align,
+ const DataLayout &DL,
+ const Instruction *CtxI = nullptr,
+ const DominatorTree *DT = nullptr);
+
/// isSafeToLoadUnconditionally - Return true if we know that executing a load
-/// from this value cannot trap. If it is not obviously safe to load from the
-/// specified pointer, we do a quick local scan of the basic block containing
-/// ScanFrom, to determine if the address is already accessed.
-bool isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom,
- unsigned Align);
+/// from this value cannot trap.
+///
+/// If DT and ScanFrom are specified this method performs context-sensitive
+/// analysis and returns true if it is safe to load immediately before ScanFrom.
+///
+/// If it is not obviously safe to load from the specified pointer, we do a
+/// quick local scan of the basic block containing ScanFrom, to determine if
+/// the address is already accessed.
+bool isSafeToLoadUnconditionally(Value *V, unsigned Align,
+ const DataLayout &DL,
+ Instruction *ScanFrom = nullptr,
+ const DominatorTree *DT = nullptr);
/// DefMaxInstsToScan - the default number of maximum instructions
/// to scan in the block, used by FindAvailableLoadedValue().
extern cl::opt<unsigned> DefMaxInstsToScan;
-/// FindAvailableLoadedValue - Scan the ScanBB block backwards (starting at
-/// the instruction before ScanFrom) checking to see if we have the value at
-/// the memory address *Ptr locally available within a small number of
-/// instructions. If the value is available, return it.
+/// \brief Scan backwards to see if we have the value of the given load
+/// available locally within a small number of instructions.
+///
+/// You can use this function to scan across multiple blocks: after you call
+/// this function, if ScanFrom points at the beginning of the block, it's safe
+/// to continue scanning the predecessors.
///
-/// If not, return the iterator for the last validated instruction that the
-/// value would be live through. If we scanned the entire block and didn't
-/// find something that invalidates *Ptr or provides it, ScanFrom would be
-/// left at begin() and this returns null. ScanFrom could also be left
+/// Note that performing load CSE requires special care to make sure the
+/// metadata is set appropriately. In particular, aliasing metadata needs
+/// to be merged. (This doesn't matter for store-to-load forwarding because
+/// the only relevant load gets deleted.)
///
-/// MaxInstsToScan specifies the maximum instructions to scan in the block.
-/// If it is set to 0, it will scan the whole block. You can also optionally
-/// specify an alias analysis implementation, which makes this more precise.
+/// \param Load The load we want to replace.
+/// \param ScanBB The basic block to scan. FIXME: This is redundant.
+/// \param [in,out] ScanFrom The location to start scanning from. When this
+/// function returns, it points at the last instruction scanned.
+/// \param MaxInstsToScan The maximum number of instructions to scan. If this
+/// is zero, the whole block will be scanned.
+/// \param AA Optional pointer to alias analysis, to make the scan more
+/// precise.
+/// \param [out] AATags The aliasing metadata for the operation which produced
+/// the value. FIXME: This is basically useless.
+/// \param [out] IsLoadCSE Whether the returned value is a load from the same
+/// location in memory, as opposed to the value operand of a store.
///
-/// If AATags is non-null and a load or store is found, the AA tags from the
-/// load or store are recorded there. If there are no AA tags or if no access
-/// is found, it is left unmodified.
-Value *FindAvailableLoadedValue(Value *Ptr, BasicBlock *ScanBB,
+/// \returns The found value, or nullptr if no value is found.
+Value *FindAvailableLoadedValue(LoadInst *Load,
+ BasicBlock *ScanBB,
BasicBlock::iterator &ScanFrom,
unsigned MaxInstsToScan = DefMaxInstsToScan,
AliasAnalysis *AA = nullptr,
- AAMDNodes *AATags = nullptr);
+ AAMDNodes *AATags = nullptr,
+ bool *IsLoadCSE = nullptr);
}
diff --git a/include/llvm/Analysis/LoopAccessAnalysis.h b/include/llvm/Analysis/LoopAccessAnalysis.h
index 871d35e99b74..ceee1be5e1e7 100644
--- a/include/llvm/Analysis/LoopAccessAnalysis.h
+++ b/include/llvm/Analysis/LoopAccessAnalysis.h
@@ -228,7 +228,7 @@ public:
/// \brief The maximum number of bytes of a vector register we can vectorize
/// the accesses safely with.
- unsigned getMaxSafeDepDistBytes() { return MaxSafeDepDistBytes; }
+ uint64_t getMaxSafeDepDistBytes() { return MaxSafeDepDistBytes; }
/// \brief In same cases when the dependency check fails we can still
/// vectorize the loop with a dynamic array access check.
@@ -284,7 +284,7 @@ private:
unsigned AccessIdx;
// We can access this many bytes in parallel safely.
- unsigned MaxSafeDepDistBytes;
+ uint64_t MaxSafeDepDistBytes;
/// \brief If we see a non-constant dependence distance we can still try to
/// vectorize this loop with runtime checks.
@@ -321,7 +321,10 @@ private:
/// \brief Check whether the data dependence could prevent store-load
/// forwarding.
- bool couldPreventStoreLoadForward(unsigned Distance, unsigned TypeByteSize);
+ ///
+ /// \return false if we shouldn't vectorize at all or avoid larger
+ /// vectorization factors by limiting MaxSafeDepDistBytes.
+ bool couldPreventStoreLoadForward(uint64_t Distance, uint64_t TypeByteSize);
};
/// \brief Holds information about the memory runtime legality checks to verify
@@ -363,10 +366,10 @@ public:
}
/// Insert a pointer and calculate the start and end SCEVs.
- /// \p We need Preds in order to compute the SCEV expression of the pointer
+ /// We need \p PSE in order to compute the SCEV expression of the pointer
/// according to the assumptions that we've made during the analysis.
/// The method might also version the pointer stride according to \p Strides,
- /// and change \p Preds.
+ /// and add new predicates to \p PSE.
void insert(Loop *Lp, Value *Ptr, bool WritePtr, unsigned DepSetId,
unsigned ASId, const ValueToValueMap &Strides,
PredicatedScalarEvolution &PSE);
@@ -508,23 +511,53 @@ private:
/// PSE must be emitted in order for the results of this analysis to be valid.
class LoopAccessInfo {
public:
- LoopAccessInfo(Loop *L, ScalarEvolution *SE, const DataLayout &DL,
- const TargetLibraryInfo *TLI, AliasAnalysis *AA,
- DominatorTree *DT, LoopInfo *LI,
- const ValueToValueMap &Strides);
+ LoopAccessInfo(Loop *L, ScalarEvolution *SE, const TargetLibraryInfo *TLI,
+ AliasAnalysis *AA, DominatorTree *DT, LoopInfo *LI);
+
+ // FIXME:
+ // Hack for MSVC 2013 which sems like it can't synthesize this even
+ // with default keyword:
+ // LoopAccessInfo(LoopAccessInfo &&LAI) = default;
+ LoopAccessInfo(LoopAccessInfo &&LAI)
+ : PSE(std::move(LAI.PSE)), PtrRtChecking(std::move(LAI.PtrRtChecking)),
+ DepChecker(std::move(LAI.DepChecker)), TheLoop(LAI.TheLoop),
+ NumLoads(LAI.NumLoads), NumStores(LAI.NumStores),
+ MaxSafeDepDistBytes(LAI.MaxSafeDepDistBytes), CanVecMem(LAI.CanVecMem),
+ StoreToLoopInvariantAddress(LAI.StoreToLoopInvariantAddress),
+ Report(std::move(LAI.Report)),
+ SymbolicStrides(std::move(LAI.SymbolicStrides)),
+ StrideSet(std::move(LAI.StrideSet)) {}
+ // LoopAccessInfo &operator=(LoopAccessInfo &&LAI) = default;
+ LoopAccessInfo &operator=(LoopAccessInfo &&LAI) {
+ assert(this != &LAI);
+
+ PSE = std::move(LAI.PSE);
+ PtrRtChecking = std::move(LAI.PtrRtChecking);
+ DepChecker = std::move(LAI.DepChecker);
+ TheLoop = LAI.TheLoop;
+ NumLoads = LAI.NumLoads;
+ NumStores = LAI.NumStores;
+ MaxSafeDepDistBytes = LAI.MaxSafeDepDistBytes;
+ CanVecMem = LAI.CanVecMem;
+ StoreToLoopInvariantAddress = LAI.StoreToLoopInvariantAddress;
+ Report = std::move(LAI.Report);
+ SymbolicStrides = std::move(LAI.SymbolicStrides);
+ StrideSet = std::move(LAI.StrideSet);
+ return *this;
+ }
/// Return true we can analyze the memory accesses in the loop and there are
/// no memory dependence cycles.
bool canVectorizeMemory() const { return CanVecMem; }
const RuntimePointerChecking *getRuntimePointerChecking() const {
- return &PtrRtChecking;
+ return PtrRtChecking.get();
}
/// \brief Number of memchecks required to prove independence of otherwise
/// may-alias pointers.
unsigned getNumRuntimePointerChecks() const {
- return PtrRtChecking.getNumberOfChecks();
+ return PtrRtChecking->getNumberOfChecks();
}
/// Return true if the block BB needs to be predicated in order for the loop
@@ -535,7 +568,7 @@ public:
/// Returns true if the value V is uniform within the loop.
bool isUniform(Value *V) const;
- unsigned getMaxSafeDepDistBytes() const { return MaxSafeDepDistBytes; }
+ uint64_t getMaxSafeDepDistBytes() const { return MaxSafeDepDistBytes; }
unsigned getNumStores() const { return NumStores; }
unsigned getNumLoads() const { return NumLoads;}
@@ -563,23 +596,25 @@ public:
/// \brief the Memory Dependence Checker which can determine the
/// loop-independent and loop-carried dependences between memory accesses.
- const MemoryDepChecker &getDepChecker() const { return DepChecker; }
+ const MemoryDepChecker &getDepChecker() const { return *DepChecker; }
/// \brief Return the list of instructions that use \p Ptr to read or write
/// memory.
SmallVector<Instruction *, 4> getInstructionsForAccess(Value *Ptr,
bool isWrite) const {
- return DepChecker.getInstructionsForAccess(Ptr, isWrite);
+ return DepChecker->getInstructionsForAccess(Ptr, isWrite);
}
+ /// \brief If an access has a symbolic strides, this maps the pointer value to
+ /// the stride symbol.
+ const ValueToValueMap &getSymbolicStrides() const { return SymbolicStrides; }
+
+ /// \brief Pointer has a symbolic stride.
+ bool hasStride(Value *V) const { return StrideSet.count(V); }
+
/// \brief Print the information about the memory accesses in the loop.
void print(raw_ostream &OS, unsigned Depth = 0) const;
- /// \brief Used to ensure that if the analysis was run with speculating the
- /// value of symbolic strides, the client queries it with the same assumption.
- /// Only used in DEBUG build but we don't want NDEBUG-dependent ABI.
- unsigned NumSymbolicStrides;
-
/// \brief Checks existence of store to invariant address inside loop.
/// If the loop has any store to invariant address, then it returns true,
/// else returns false.
@@ -592,11 +627,12 @@ public:
/// should be re-written (and therefore simplified) according to PSE.
/// A user of LoopAccessAnalysis will need to emit the runtime checks
/// associated with this predicate.
- PredicatedScalarEvolution PSE;
+ const PredicatedScalarEvolution &getPSE() const { return *PSE; }
private:
- /// \brief Analyze the loop. Substitute symbolic strides using Strides.
- void analyzeLoop(const ValueToValueMap &Strides);
+ /// \brief Analyze the loop.
+ void analyzeLoop(AliasAnalysis *AA, LoopInfo *LI,
+ const TargetLibraryInfo *TLI, DominatorTree *DT);
/// \brief Check if the structure of the loop allows it to be analyzed by this
/// pass.
@@ -604,25 +640,28 @@ private:
void emitAnalysis(LoopAccessReport &Message);
+ /// \brief Collect memory access with loop invariant strides.
+ ///
+ /// Looks for accesses like "a[i * StrideA]" where "StrideA" is loop
+ /// invariant.
+ void collectStridedAccess(Value *LoadOrStoreInst);
+
+ std::unique_ptr<PredicatedScalarEvolution> PSE;
+
/// We need to check that all of the pointers in this list are disjoint
- /// at runtime.
- RuntimePointerChecking PtrRtChecking;
+ /// at runtime. Using std::unique_ptr to make using move ctor simpler.
+ std::unique_ptr<RuntimePointerChecking> PtrRtChecking;
/// \brief the Memory Dependence Checker which can determine the
/// loop-independent and loop-carried dependences between memory accesses.
- MemoryDepChecker DepChecker;
+ std::unique_ptr<MemoryDepChecker> DepChecker;
Loop *TheLoop;
- const DataLayout &DL;
- const TargetLibraryInfo *TLI;
- AliasAnalysis *AA;
- DominatorTree *DT;
- LoopInfo *LI;
unsigned NumLoads;
unsigned NumStores;
- unsigned MaxSafeDepDistBytes;
+ uint64_t MaxSafeDepDistBytes;
/// \brief Cache the result of analyzeLoop.
bool CanVecMem;
@@ -634,15 +673,23 @@ private:
/// \brief The diagnostics report generated for the analysis. E.g. why we
/// couldn't analyze the loop.
Optional<LoopAccessReport> Report;
+
+ /// \brief If an access has a symbolic strides, this maps the pointer value to
+ /// the stride symbol.
+ ValueToValueMap SymbolicStrides;
+
+ /// \brief Set of symbolic strides values.
+ SmallPtrSet<Value *, 8> StrideSet;
};
Value *stripIntegerCast(Value *V);
-///\brief Return the SCEV corresponding to a pointer with the symbolic stride
-/// replaced with constant one, assuming \p Preds is true.
+/// \brief Return the SCEV corresponding to a pointer with the symbolic stride
+/// replaced with constant one, assuming the SCEV predicate associated with
+/// \p PSE is true.
///
/// If necessary this method will version the stride of the pointer according
-/// to \p PtrToStride and therefore add a new predicate to \p Preds.
+/// to \p PtrToStride and therefore add further predicates to \p PSE.
///
/// If \p OrigPtr is not null, use it to look up the stride value instead of \p
/// Ptr. \p PtrToStride provides the mapping between the pointer value and its
@@ -651,13 +698,24 @@ const SCEV *replaceSymbolicStrideSCEV(PredicatedScalarEvolution &PSE,
const ValueToValueMap &PtrToStride,
Value *Ptr, Value *OrigPtr = nullptr);
-/// \brief Check the stride of the pointer and ensure that it does not wrap in
-/// the address space, assuming \p Preds is true.
+/// \brief If the pointer has a constant stride return it in units of its
+/// element size. Otherwise return zero.
+///
+/// Ensure that it does not wrap in the address space, assuming the predicate
+/// associated with \p PSE is true.
///
/// If necessary this method will version the stride of the pointer according
-/// to \p PtrToStride and therefore add a new predicate to \p Preds.
-int isStridedPtr(PredicatedScalarEvolution &PSE, Value *Ptr, const Loop *Lp,
- const ValueToValueMap &StridesMap);
+/// to \p PtrToStride and therefore add further predicates to \p PSE.
+/// The \p Assume parameter indicates if we are allowed to make additional
+/// run-time assumptions.
+int64_t getPtrStride(PredicatedScalarEvolution &PSE, Value *Ptr, const Loop *Lp,
+ const ValueToValueMap &StridesMap = ValueToValueMap(),
+ bool Assume = false);
+
+/// \brief Returns true if the memory operations \p A and \p B are consecutive.
+/// This is a simple API that does not depend on the analysis pass.
+bool isConsecutiveAccess(Value *A, Value *B, const DataLayout &DL,
+ ScalarEvolution &SE, bool CheckType = true);
/// \brief This analysis provides dependence information for the memory accesses
/// of a loop.
@@ -666,12 +724,12 @@ int isStridedPtr(PredicatedScalarEvolution &PSE, Value *Ptr, const Loop *Lp,
/// querying the loop access info via LAA::getInfo. getInfo return a
/// LoopAccessInfo object. See this class for the specifics of what information
/// is provided.
-class LoopAccessAnalysis : public FunctionPass {
+class LoopAccessLegacyAnalysis : public FunctionPass {
public:
static char ID;
- LoopAccessAnalysis() : FunctionPass(ID) {
- initializeLoopAccessAnalysisPass(*PassRegistry::getPassRegistry());
+ LoopAccessLegacyAnalysis() : FunctionPass(ID) {
+ initializeLoopAccessLegacyAnalysisPass(*PassRegistry::getPassRegistry());
}
bool runOnFunction(Function &F) override;
@@ -680,11 +738,8 @@ public:
/// \brief Query the result of the loop access information for the loop \p L.
///
- /// If the client speculates (and then issues run-time checks) for the values
- /// of symbolic strides, \p Strides provides the mapping (see
- /// replaceSymbolicStrideSCEV). If there is no cached result available run
- /// the analysis.
- const LoopAccessInfo &getInfo(Loop *L, const ValueToValueMap &Strides);
+ /// If there is no cached result available run the analysis.
+ const LoopAccessInfo &getInfo(Loop *L);
void releaseMemory() override {
// Invalidate the cache when the pass is freed.
@@ -706,6 +761,34 @@ private:
LoopInfo *LI;
};
+/// \brief This analysis provides dependence information for the memory
+/// accesses of a loop.
+///
+/// It runs the analysis for a loop on demand. This can be initiated by
+/// querying the loop access info via AM.getResult<LoopAccessAnalysis>.
+/// getResult return a LoopAccessInfo object. See this class for the
+/// specifics of what information is provided.
+class LoopAccessAnalysis
+ : public AnalysisInfoMixin<LoopAccessAnalysis> {
+ friend AnalysisInfoMixin<LoopAccessAnalysis>;
+ static char PassID;
+
+public:
+ typedef LoopAccessInfo Result;
+ Result run(Loop &, AnalysisManager<Loop> &);
+ static StringRef name() { return "LoopAccessAnalysis"; }
+};
+
+/// \brief Printer pass for the \c LoopAccessInfo results.
+class LoopAccessInfoPrinterPass
+ : public PassInfoMixin<LoopAccessInfoPrinterPass> {
+ raw_ostream &OS;
+
+public:
+ explicit LoopAccessInfoPrinterPass(raw_ostream &OS) : OS(OS) {}
+ PreservedAnalyses run(Loop &L, AnalysisManager<Loop> &AM);
+};
+
inline Instruction *MemoryDepChecker::Dependence::getSource(
const LoopAccessInfo &LAI) const {
return LAI.getDepChecker().getMemoryInstructions()[Source];
diff --git a/include/llvm/Analysis/LoopInfo.h b/include/llvm/Analysis/LoopInfo.h
index 70e636ce1f3d..35dc6bcb6864 100644
--- a/include/llvm/Analysis/LoopInfo.h
+++ b/include/llvm/Analysis/LoopInfo.h
@@ -25,6 +25,12 @@
// * the loop depth
// * etc...
//
+// Note that this analysis specifically identifies *Loops* not cycles or SCCs
+// in the CFG. There can be strongly connected compontents in the CFG which
+// this analysis will not recognize and that will not be represented by a Loop
+// instance. In particular, a Loop might be inside such a non-loop SCC, or a
+// non-loop SCC might contain a sub-SCC which is a Loop.
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_LOOPINFO_H
@@ -38,16 +44,12 @@
#include "llvm/IR/CFG.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
+#include "llvm/IR/PassManager.h"
#include "llvm/Pass.h"
#include <algorithm>
namespace llvm {
-// FIXME: Replace this brittle forward declaration with the include of the new
-// PassManager.h when doing so doesn't break the PassManagerBuilder.
-template <typename IRUnitT> class AnalysisManager;
-class PreservedAnalyses;
-
class DominatorTree;
class LoopInfo;
class Loop;
@@ -346,6 +348,9 @@ raw_ostream& operator<<(raw_ostream &OS, const LoopBase<BlockT, LoopT> &Loop) {
// Implementation in LoopInfoImpl.h
extern template class LoopBase<BasicBlock, Loop>;
+
+/// Represents a single loop in the control flow graph. Note that not all SCCs
+/// in the CFG are neccessarily loops.
class Loop : public LoopBase<BasicBlock, Loop> {
public:
Loop() {}
@@ -452,21 +457,13 @@ public:
/// location by looking at the preheader and header blocks. If it
/// cannot find a terminating instruction with location information,
/// it returns an unknown location.
- DebugLoc getStartLoc() const {
- BasicBlock *HeadBB;
-
- // Try the pre-header first.
- if ((HeadBB = getLoopPreheader()) != nullptr)
- if (DebugLoc DL = HeadBB->getTerminator()->getDebugLoc())
- return DL;
+ DebugLoc getStartLoc() const;
- // If we have no pre-header or there are no instructions with debug
- // info in it, try the header.
- HeadBB = getHeader();
- if (HeadBB)
- return HeadBB->getTerminator()->getDebugLoc();
-
- return DebugLoc();
+ StringRef getName() const {
+ if (BasicBlock *Header = getHeader())
+ if (Header->hasName())
+ return Header->getName();
+ return "<unnamed loop>";
}
private:
@@ -775,30 +772,23 @@ template <> struct GraphTraits<Loop*> {
};
/// \brief Analysis pass that exposes the \c LoopInfo for a function.
-class LoopAnalysis {
+class LoopAnalysis : public AnalysisInfoMixin<LoopAnalysis> {
+ friend AnalysisInfoMixin<LoopAnalysis>;
static char PassID;
public:
typedef LoopInfo Result;
- /// \brief Opaque, unique identifier for this analysis pass.
- static void *ID() { return (void *)&PassID; }
-
- /// \brief Provide a name for the analysis for debugging and logging.
- static StringRef name() { return "LoopAnalysis"; }
-
- LoopInfo run(Function &F, AnalysisManager<Function> *AM);
+ LoopInfo run(Function &F, AnalysisManager<Function> &AM);
};
/// \brief Printer pass for the \c LoopAnalysis results.
-class LoopPrinterPass {
+class LoopPrinterPass : public PassInfoMixin<LoopPrinterPass> {
raw_ostream &OS;
public:
explicit LoopPrinterPass(raw_ostream &OS) : OS(OS) {}
- PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM);
-
- static StringRef name() { return "LoopPrinterPass"; }
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
};
/// \brief The legacy pass manager's analysis pass to compute loop information.
@@ -828,7 +818,7 @@ public:
};
/// \brief Pass for printing a loop's contents as LLVM's text IR assembly.
-class PrintLoopPass {
+class PrintLoopPass : public PassInfoMixin<PrintLoopPass> {
raw_ostream &OS;
std::string Banner;
@@ -836,8 +826,7 @@ public:
PrintLoopPass();
PrintLoopPass(raw_ostream &OS, const std::string &Banner = "");
- PreservedAnalyses run(Loop &L);
- static StringRef name() { return "PrintLoopPass"; }
+ PreservedAnalyses run(Loop &L, AnalysisManager<Loop> &);
};
} // End llvm namespace
diff --git a/include/llvm/Analysis/LoopInfoImpl.h b/include/llvm/Analysis/LoopInfoImpl.h
index 824fc7e8f155..816a15452dae 100644
--- a/include/llvm/Analysis/LoopInfoImpl.h
+++ b/include/llvm/Analysis/LoopInfoImpl.h
@@ -277,7 +277,7 @@ void LoopBase<BlockT, LoopT>::verifyLoop() const {
}
assert(HasInsideLoopPreds && "Loop block has no in-loop predecessors!");
assert(HasInsideLoopSuccs && "Loop block has no in-loop successors!");
- assert(BB != getHeader()->getParent()->begin() &&
+ assert(BB != &getHeader()->getParent()->front() &&
"Loop contains function entry block!");
NumVisited++;
diff --git a/include/llvm/Analysis/LoopPass.h b/include/llvm/Analysis/LoopPass.h
index 2cf734e53bb4..89debec04e94 100644
--- a/include/llvm/Analysis/LoopPass.h
+++ b/include/llvm/Analysis/LoopPass.h
@@ -88,9 +88,10 @@ public:
virtual void deleteAnalysisLoop(Loop *L) {}
protected:
- /// skipOptnoneFunction - Containing function has Attribute::OptimizeNone
- /// and most transformation passes should skip it.
- bool skipOptnoneFunction(const Loop *L) const;
+ /// Optional passes call this function to check whether the pass should be
+ /// skipped. This is the case when Attribute::OptimizeNone is set or when
+ /// optimization bisect is over the limit.
+ bool skipLoop(const Loop *L) const;
};
class LPPassManager : public FunctionPass, public PMDataManager {
diff --git a/include/llvm/Analysis/LoopPassManager.h b/include/llvm/Analysis/LoopPassManager.h
new file mode 100644
index 000000000000..a89551851259
--- /dev/null
+++ b/include/llvm/Analysis/LoopPassManager.h
@@ -0,0 +1,142 @@
+//===- LoopPassManager.h - Loop pass management -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This header provides classes for managing passes over loops in LLVM IR.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ANALYSIS_LOOPPASSMANAGER_H
+#define LLVM_ANALYSIS_LOOPPASSMANAGER_H
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+extern template class PassManager<Loop>;
+/// \brief The loop pass manager.
+///
+/// See the documentation for the PassManager template for details. It runs a
+/// sequency of loop passes over each loop that the manager is run over. This
+/// typedef serves as a convenient way to refer to this construct.
+typedef PassManager<Loop> LoopPassManager;
+
+extern template class AnalysisManager<Loop>;
+/// \brief The loop analysis manager.
+///
+/// See the documentation for the AnalysisManager template for detail
+/// documentation. This typedef serves as a convenient way to refer to this
+/// construct in the adaptors and proxies used to integrate this into the larger
+/// pass manager infrastructure.
+typedef AnalysisManager<Loop> LoopAnalysisManager;
+
+extern template class InnerAnalysisManagerProxy<LoopAnalysisManager, Function>;
+/// A proxy from a \c LoopAnalysisManager to a \c Function.
+typedef InnerAnalysisManagerProxy<LoopAnalysisManager, Function>
+ LoopAnalysisManagerFunctionProxy;
+
+extern template class OuterAnalysisManagerProxy<FunctionAnalysisManager, Loop>;
+/// A proxy from a \c FunctionAnalysisManager to a \c Loop.
+typedef OuterAnalysisManagerProxy<FunctionAnalysisManager, Loop>
+ FunctionAnalysisManagerLoopProxy;
+
+/// Returns the minimum set of Analyses that all loop passes must preserve.
+PreservedAnalyses getLoopPassPreservedAnalyses();
+
+/// \brief Adaptor that maps from a function to its loops.
+///
+/// Designed to allow composition of a LoopPass(Manager) and a
+/// FunctionPassManager. Note that if this pass is constructed with a \c
+/// FunctionAnalysisManager it will run the \c LoopAnalysisManagerFunctionProxy
+/// analysis prior to running the loop passes over the function to enable a \c
+/// LoopAnalysisManager to be used within this run safely.
+template <typename LoopPassT>
+class FunctionToLoopPassAdaptor
+ : public PassInfoMixin<FunctionToLoopPassAdaptor<LoopPassT>> {
+public:
+ explicit FunctionToLoopPassAdaptor(LoopPassT Pass)
+ : Pass(std::move(Pass)) {}
+ // We have to explicitly define all the special member functions because MSVC
+ // refuses to generate them.
+ FunctionToLoopPassAdaptor(const FunctionToLoopPassAdaptor &Arg)
+ : Pass(Arg.Pass) {}
+ FunctionToLoopPassAdaptor(FunctionToLoopPassAdaptor &&Arg)
+ : Pass(std::move(Arg.Pass)) {}
+ friend void swap(FunctionToLoopPassAdaptor &LHS,
+ FunctionToLoopPassAdaptor &RHS) {
+ using std::swap;
+ swap(LHS.Pass, RHS.Pass);
+ }
+ FunctionToLoopPassAdaptor &operator=(FunctionToLoopPassAdaptor RHS) {
+ swap(*this, RHS);
+ return *this;
+ }
+
+ /// \brief Runs the loop passes across every loop in the function.
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
+ // Setup the loop analysis manager from its proxy.
+ LoopAnalysisManager &LAM =
+ AM.getResult<LoopAnalysisManagerFunctionProxy>(F).getManager();
+ // Get the loop structure for this function
+ LoopInfo &LI = AM.getResult<LoopAnalysis>(F);
+
+ PreservedAnalyses PA = PreservedAnalyses::all();
+
+ // We want to visit the loops in reverse post-order. We'll build the stack
+ // of loops to visit in Loops by first walking the loops in pre-order.
+ SmallVector<Loop *, 2> Loops;
+ SmallVector<Loop *, 2> WorkList(LI.begin(), LI.end());
+ while (!WorkList.empty()) {
+ Loop *L = WorkList.pop_back_val();
+ WorkList.insert(WorkList.end(), L->begin(), L->end());
+ Loops.push_back(L);
+ }
+
+ // Now pop each element off of the stack to visit the loops in reverse
+ // post-order.
+ for (auto *L : reverse(Loops)) {
+ PreservedAnalyses PassPA = Pass.run(*L, LAM);
+ assert(PassPA.preserved(getLoopPassPreservedAnalyses()) &&
+ "Loop passes must preserve all relevant analyses");
+
+ // We know that the loop pass couldn't have invalidated any other loop's
+ // analyses (that's the contract of a loop pass), so directly handle the
+ // loop analysis manager's invalidation here. Also, update the
+ // preserved analyses to reflect that once invalidated these can again
+ // be preserved.
+ PassPA = LAM.invalidate(*L, std::move(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));
+ }
+
+ // By definition we preserve the proxy. This precludes *any* invalidation of
+ // loop analyses by the proxy, but that's OK because we've taken care to
+ // invalidate analyses in the loop analysis manager incrementally above.
+ PA.preserve<LoopAnalysisManagerFunctionProxy>();
+ return PA;
+ }
+
+private:
+ LoopPassT Pass;
+};
+
+/// \brief A function to deduce a loop pass type and wrap it in the templated
+/// adaptor.
+template <typename LoopPassT>
+FunctionToLoopPassAdaptor<LoopPassT>
+createFunctionToLoopPassAdaptor(LoopPassT Pass) {
+ return FunctionToLoopPassAdaptor<LoopPassT>(std::move(Pass));
+}
+}
+
+#endif // LLVM_ANALYSIS_LOOPPASSMANAGER_H
diff --git a/include/llvm/Analysis/LoopUnrollAnalyzer.h b/include/llvm/Analysis/LoopUnrollAnalyzer.h
new file mode 100644
index 000000000000..80f3e5fdcd43
--- /dev/null
+++ b/include/llvm/Analysis/LoopUnrollAnalyzer.h
@@ -0,0 +1,95 @@
+//===- llvm/Analysis/LoopUnrollAnalyzer.h - Loop Unroll Analyzer-*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements UnrolledInstAnalyzer class. It's used for predicting
+// potential effects that loop unrolling might have, such as enabling constant
+// propagation and other optimizations.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ANALYSIS_LOOPUNROLLANALYZER_H
+#define LLVM_ANALYSIS_LOOPUNROLLANALYZER_H
+
+#include "llvm/Analysis/InstructionSimplify.h"
+#include "llvm/Analysis/ScalarEvolutionExpressions.h"
+#include "llvm/IR/InstVisitor.h"
+
+// This class is used to get an estimate of the optimization effects that we
+// could get from complete loop unrolling. It comes from the fact that some
+// loads might be replaced with concrete constant values and that could trigger
+// a chain of instruction simplifications.
+//
+// E.g. we might have:
+// int a[] = {0, 1, 0};
+// v = 0;
+// for (i = 0; i < 3; i ++)
+// v += b[i]*a[i];
+// If we completely unroll the loop, we would get:
+// v = b[0]*a[0] + b[1]*a[1] + b[2]*a[2]
+// Which then will be simplified to:
+// v = b[0]* 0 + b[1]* 1 + b[2]* 0
+// And finally:
+// v = b[1]
+namespace llvm {
+class UnrolledInstAnalyzer : private InstVisitor<UnrolledInstAnalyzer, bool> {
+ typedef InstVisitor<UnrolledInstAnalyzer, bool> Base;
+ friend class InstVisitor<UnrolledInstAnalyzer, bool>;
+ struct SimplifiedAddress {
+ Value *Base = nullptr;
+ ConstantInt *Offset = nullptr;
+ };
+
+public:
+ UnrolledInstAnalyzer(unsigned Iteration,
+ DenseMap<Value *, Constant *> &SimplifiedValues,
+ ScalarEvolution &SE, const Loop *L)
+ : SimplifiedValues(SimplifiedValues), SE(SE), L(L) {
+ IterationNumber = SE.getConstant(APInt(64, Iteration));
+ }
+
+ // Allow access to the initial visit method.
+ using Base::visit;
+
+private:
+ /// \brief A cache of pointer bases and constant-folded offsets corresponding
+ /// to GEP (or derived from GEP) instructions.
+ ///
+ /// In order to find the base pointer one needs to perform non-trivial
+ /// traversal of the corresponding SCEV expression, so it's good to have the
+ /// results saved.
+ DenseMap<Value *, SimplifiedAddress> SimplifiedAddresses;
+
+ /// \brief SCEV expression corresponding to number of currently simulated
+ /// iteration.
+ const SCEV *IterationNumber;
+
+ /// \brief A Value->Constant map for keeping values that we managed to
+ /// constant-fold on the given iteration.
+ ///
+ /// While we walk the loop instructions, we build up and maintain a mapping
+ /// of simplified values specific to this iteration. The idea is to propagate
+ /// any special information we have about loads that can be replaced with
+ /// constants after complete unrolling, and account for likely simplifications
+ /// post-unrolling.
+ DenseMap<Value *, Constant *> &SimplifiedValues;
+
+ ScalarEvolution &SE;
+ const Loop *L;
+
+ bool simplifyInstWithSCEV(Instruction *I);
+
+ bool visitInstruction(Instruction &I) { return simplifyInstWithSCEV(&I); }
+ bool visitBinaryOperator(BinaryOperator &I);
+ bool visitLoad(LoadInst &I);
+ bool visitCastInst(CastInst &I);
+ bool visitCmpInst(CmpInst &I);
+ bool visitPHINode(PHINode &PN);
+};
+}
+#endif
diff --git a/include/llvm/Analysis/MemoryBuiltins.h b/include/llvm/Analysis/MemoryBuiltins.h
index 493a99a4b11e..140b731c59de 100644
--- a/include/llvm/Analysis/MemoryBuiltins.h
+++ b/include/llvm/Analysis/MemoryBuiltins.h
@@ -32,6 +32,11 @@ class TargetLibraryInfo;
class Type;
class Value;
+enum class ObjSizeMode {
+ Exact = 0,
+ Min = 1,
+ Max = 2
+};
/// \brief Tests if a value is a call or invoke to a library function that
/// allocates or reallocates memory (either malloc, calloc, realloc, or strdup
@@ -130,8 +135,11 @@ static inline CallInst *isFreeCall(Value *I, const TargetLibraryInfo *TLI) {
/// underlying object pointed to by Ptr.
/// If RoundToAlign is true, then Size is rounded up to the aligment of allocas,
/// byval arguments, and global variables.
+/// If Mode is Min or Max the size will be evaluated even if it depends on
+/// a condition and corresponding value will be returned (min or max).
bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL,
- const TargetLibraryInfo *TLI, bool RoundToAlign = false);
+ const TargetLibraryInfo *TLI, bool RoundToAlign = false,
+ ObjSizeMode Mode = ObjSizeMode::Exact);
typedef std::pair<APInt, APInt> SizeOffsetType;
@@ -143,6 +151,7 @@ class ObjectSizeOffsetVisitor
const DataLayout &DL;
const TargetLibraryInfo *TLI;
bool RoundToAlign;
+ ObjSizeMode Mode;
unsigned IntTyBits;
APInt Zero;
SmallPtrSet<Instruction *, 8> SeenInsts;
@@ -155,19 +164,20 @@ class ObjectSizeOffsetVisitor
public:
ObjectSizeOffsetVisitor(const DataLayout &DL, const TargetLibraryInfo *TLI,
- LLVMContext &Context, bool RoundToAlign = false);
+ LLVMContext &Context, bool RoundToAlign = false,
+ ObjSizeMode Mode = ObjSizeMode::Exact);
SizeOffsetType compute(Value *V);
- bool knownSize(SizeOffsetType &SizeOffset) {
+ static bool knownSize(const SizeOffsetType &SizeOffset) {
return SizeOffset.first.getBitWidth() > 1;
}
- bool knownOffset(SizeOffsetType &SizeOffset) {
+ static bool knownOffset(const SizeOffsetType &SizeOffset) {
return SizeOffset.second.getBitWidth() > 1;
}
- bool bothKnown(SizeOffsetType &SizeOffset) {
+ static bool bothKnown(const SizeOffsetType &SizeOffset) {
return knownSize(SizeOffset) && knownOffset(SizeOffset);
}
@@ -198,7 +208,7 @@ typedef std::pair<Value*, Value*> SizeOffsetEvalType;
class ObjectSizeOffsetEvaluator
: public InstVisitor<ObjectSizeOffsetEvaluator, SizeOffsetEvalType> {
- typedef IRBuilder<true, TargetFolder> BuilderTy;
+ typedef IRBuilder<TargetFolder> BuilderTy;
typedef std::pair<WeakVH, WeakVH> WeakEvalType;
typedef DenseMap<const Value*, WeakEvalType> CacheMapTy;
typedef SmallPtrSet<const Value*, 8> PtrSetTy;
diff --git a/include/llvm/Analysis/MemoryDependenceAnalysis.h b/include/llvm/Analysis/MemoryDependenceAnalysis.h
index daa1ba91c071..b19dabbfc32e 100644
--- a/include/llvm/Analysis/MemoryDependenceAnalysis.h
+++ b/include/llvm/Analysis/MemoryDependenceAnalysis.h
@@ -15,452 +15,493 @@
#define LLVM_ANALYSIS_MEMORYDEPENDENCEANALYSIS_H
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/PointerSumType.h"
+#include "llvm/ADT/PointerEmbeddedInt.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/PassManager.h"
#include "llvm/IR/PredIteratorCache.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Pass.h"
namespace llvm {
- class Function;
- class FunctionPass;
- class Instruction;
- class CallSite;
- class AssumptionCache;
- class MemoryDependenceAnalysis;
- class PredIteratorCache;
- class DominatorTree;
- class PHITransAddr;
-
- /// MemDepResult - A memory dependence query can return one of three different
- /// answers, described below.
- class MemDepResult {
- enum DepType {
- /// Invalid - Clients of MemDep never see this.
- Invalid = 0,
-
- /// Clobber - This is a dependence on the specified instruction which
- /// clobbers the desired value. The pointer member of the MemDepResult
- /// pair holds the instruction that clobbers the memory. For example,
- /// this occurs when we see a may-aliased store to the memory location we
- /// care about.
- ///
- /// There are several cases that may be interesting here:
- /// 1. Loads are clobbered by may-alias stores.
- /// 2. Loads are considered clobbered by partially-aliased loads. The
- /// client may choose to analyze deeper into these cases.
- Clobber,
-
- /// Def - This is a dependence on the specified instruction which
- /// defines/produces the desired memory location. The pointer member of
- /// the MemDepResult pair holds the instruction that defines the memory.
- /// Cases of interest:
- /// 1. This could be a load or store for dependence queries on
- /// load/store. The value loaded or stored is the produced value.
- /// Note that the pointer operand may be different than that of the
- /// queried pointer due to must aliases and phi translation. Note
- /// that the def may not be the same type as the query, the pointers
- /// may just be must aliases.
- /// 2. For loads and stores, this could be an allocation instruction. In
- /// this case, the load is loading an undef value or a store is the
- /// first store to (that part of) the allocation.
- /// 3. Dependence queries on calls return Def only when they are
- /// readonly calls or memory use intrinsics with identical callees
- /// and no intervening clobbers. No validation is done that the
- /// operands to the calls are the same.
- Def,
-
- /// Other - This marker indicates that the query has no known dependency
- /// in the specified block. More detailed state info is encoded in the
- /// upper part of the pair (i.e. the Instruction*)
- Other
- };
- /// If DepType is "Other", the upper part of the pair
- /// (i.e. the Instruction* part) is instead used to encode more detailed
- /// type information as follows
- enum OtherType {
- /// NonLocal - This marker indicates that the query has no dependency in
- /// the specified block. To find out more, the client should query other
- /// predecessor blocks.
- NonLocal = 0x4,
- /// NonFuncLocal - This marker indicates that the query has no
- /// dependency in the specified function.
- NonFuncLocal = 0x8,
- /// Unknown - This marker indicates that the query dependency
- /// is unknown.
- Unknown = 0xc
- };
-
- typedef PointerIntPair<Instruction*, 2, DepType> PairTy;
- PairTy Value;
- explicit MemDepResult(PairTy V) : Value(V) {}
-
- public:
- MemDepResult() : Value(nullptr, Invalid) {}
-
- /// get methods: These are static ctor methods for creating various
- /// MemDepResult kinds.
- static MemDepResult getDef(Instruction *Inst) {
- assert(Inst && "Def requires inst");
- return MemDepResult(PairTy(Inst, Def));
- }
- static MemDepResult getClobber(Instruction *Inst) {
- assert(Inst && "Clobber requires inst");
- return MemDepResult(PairTy(Inst, Clobber));
- }
- static MemDepResult getNonLocal() {
- return MemDepResult(
- PairTy(reinterpret_cast<Instruction*>(NonLocal), Other));
- }
- static MemDepResult getNonFuncLocal() {
- return MemDepResult(
- PairTy(reinterpret_cast<Instruction*>(NonFuncLocal), Other));
- }
- static MemDepResult getUnknown() {
- return MemDepResult(
- PairTy(reinterpret_cast<Instruction*>(Unknown), Other));
- }
-
- /// isClobber - Return true if this MemDepResult represents a query that is
- /// an instruction clobber dependency.
- bool isClobber() const { return Value.getInt() == Clobber; }
-
- /// isDef - Return true if this MemDepResult represents a query that is
- /// an instruction definition dependency.
- bool isDef() const { return Value.getInt() == Def; }
-
- /// isNonLocal - Return true if this MemDepResult represents a query that
- /// is transparent to the start of the block, but where a non-local hasn't
- /// been done.
- bool isNonLocal() const {
- return Value.getInt() == Other
- && Value.getPointer() == reinterpret_cast<Instruction*>(NonLocal);
- }
-
- /// isNonFuncLocal - Return true if this MemDepResult represents a query
- /// that is transparent to the start of the function.
- bool isNonFuncLocal() const {
- return Value.getInt() == Other
- && Value.getPointer() == reinterpret_cast<Instruction*>(NonFuncLocal);
- }
-
- /// isUnknown - Return true if this MemDepResult represents a query which
- /// cannot and/or will not be computed.
- bool isUnknown() const {
- return Value.getInt() == Other
- && Value.getPointer() == reinterpret_cast<Instruction*>(Unknown);
- }
-
- /// getInst() - If this is a normal dependency, return the instruction that
- /// is depended on. Otherwise, return null.
- Instruction *getInst() const {
- if (Value.getInt() == Other) return nullptr;
- return Value.getPointer();
- }
-
- bool operator==(const MemDepResult &M) const { return Value == M.Value; }
- bool operator!=(const MemDepResult &M) const { return Value != M.Value; }
- bool operator<(const MemDepResult &M) const { return Value < M.Value; }
- bool operator>(const MemDepResult &M) const { return Value > M.Value; }
-
- private:
- friend class MemoryDependenceAnalysis;
- /// Dirty - Entries with this marker occur in a LocalDeps map or
- /// NonLocalDeps map when the instruction they previously referenced was
- /// removed from MemDep. In either case, the entry may include an
- /// instruction pointer. If so, the pointer is an instruction in the
- /// block where scanning can start from, saving some work.
+class Function;
+class FunctionPass;
+class Instruction;
+class CallSite;
+class AssumptionCache;
+class MemoryDependenceResults;
+class PredIteratorCache;
+class DominatorTree;
+class PHITransAddr;
+
+/// A memory dependence query can return one of three different answers.
+class MemDepResult {
+ enum DepType {
+ /// Clients of MemDep never see this.
///
- /// In a default-constructed MemDepResult object, the type will be Dirty
- /// and the instruction pointer will be null.
+ /// Entries with this marker occur in a LocalDeps map or NonLocalDeps map
+ /// when the instruction they previously referenced was removed from
+ /// MemDep. In either case, the entry may include an instruction pointer.
+ /// If so, the pointer is an instruction in the block where scanning can
+ /// start from, saving some work.
///
+ /// In a default-constructed MemDepResult object, the type will be Invalid
+ /// and the instruction pointer will be null.
+ Invalid = 0,
- /// isDirty - Return true if this is a MemDepResult in its dirty/invalid.
- /// state.
- bool isDirty() const { return Value.getInt() == Invalid; }
-
- static MemDepResult getDirty(Instruction *Inst) {
- return MemDepResult(PairTy(Inst, Invalid));
- }
+ /// This is a dependence on the specified instruction which clobbers the
+ /// desired value. The pointer member of the MemDepResult pair holds the
+ /// instruction that clobbers the memory. For example, this occurs when we
+ /// see a may-aliased store to the memory location we care about.
+ ///
+ /// There are several cases that may be interesting here:
+ /// 1. Loads are clobbered by may-alias stores.
+ /// 2. Loads are considered clobbered by partially-aliased loads. The
+ /// client may choose to analyze deeper into these cases.
+ Clobber,
+
+ /// This is a dependence on the specified instruction which defines or
+ /// produces the desired memory location. The pointer member of the
+ /// MemDepResult pair holds the instruction that defines the memory.
+ ///
+ /// Cases of interest:
+ /// 1. This could be a load or store for dependence queries on
+ /// load/store. The value loaded or stored is the produced value.
+ /// Note that the pointer operand may be different than that of the
+ /// queried pointer due to must aliases and phi translation. Note
+ /// that the def may not be the same type as the query, the pointers
+ /// may just be must aliases.
+ /// 2. For loads and stores, this could be an allocation instruction. In
+ /// this case, the load is loading an undef value or a store is the
+ /// first store to (that part of) the allocation.
+ /// 3. Dependence queries on calls return Def only when they are readonly
+ /// calls or memory use intrinsics with identical callees and no
+ /// intervening clobbers. No validation is done that the operands to
+ /// the calls are the same.
+ Def,
+
+ /// This marker indicates that the query has no known dependency in the
+ /// specified block.
+ ///
+ /// More detailed state info is encoded in the upper part of the pair (i.e.
+ /// the Instruction*)
+ Other
};
- /// NonLocalDepEntry - This is an entry in the NonLocalDepInfo cache. For
- /// each BasicBlock (the BB entry) it keeps a MemDepResult.
- class NonLocalDepEntry {
- BasicBlock *BB;
- MemDepResult Result;
+ /// If DepType is "Other", the upper part of the sum type is an encoding of
+ /// the following more detailed type information.
+ enum OtherType {
+ /// This marker indicates that the query has no dependency in the specified
+ /// block.
+ ///
+ /// To find out more, the client should query other predecessor blocks.
+ NonLocal = 1,
+ /// This marker indicates that the query has no dependency in the specified
+ /// function.
+ NonFuncLocal,
+ /// This marker indicates that the query dependency is unknown.
+ Unknown
+ };
- public:
- NonLocalDepEntry(BasicBlock *bb, MemDepResult result)
+ typedef PointerSumType<
+ DepType, PointerSumTypeMember<Invalid, Instruction *>,
+ PointerSumTypeMember<Clobber, Instruction *>,
+ PointerSumTypeMember<Def, Instruction *>,
+ PointerSumTypeMember<Other, PointerEmbeddedInt<OtherType, 3>>>
+ ValueTy;
+ ValueTy Value;
+ explicit MemDepResult(ValueTy V) : Value(V) {}
+
+public:
+ MemDepResult() : Value() {}
+
+ /// get methods: These are static ctor methods for creating various
+ /// MemDepResult kinds.
+ static MemDepResult getDef(Instruction *Inst) {
+ assert(Inst && "Def requires inst");
+ return MemDepResult(ValueTy::create<Def>(Inst));
+ }
+ static MemDepResult getClobber(Instruction *Inst) {
+ assert(Inst && "Clobber requires inst");
+ return MemDepResult(ValueTy::create<Clobber>(Inst));
+ }
+ static MemDepResult getNonLocal() {
+ return MemDepResult(ValueTy::create<Other>(NonLocal));
+ }
+ static MemDepResult getNonFuncLocal() {
+ return MemDepResult(ValueTy::create<Other>(NonFuncLocal));
+ }
+ static MemDepResult getUnknown() {
+ return MemDepResult(ValueTy::create<Other>(Unknown));
+ }
+
+ /// Tests if this MemDepResult represents a query that is an instruction
+ /// clobber dependency.
+ bool isClobber() const { return Value.is<Clobber>(); }
+
+ /// Tests if this MemDepResult represents a query that is an instruction
+ /// definition dependency.
+ bool isDef() const { return Value.is<Def>(); }
+
+ /// Tests if this MemDepResult represents a query that is transparent to the
+ /// start of the block, but where a non-local hasn't been done.
+ bool isNonLocal() const {
+ return Value.is<Other>() && Value.cast<Other>() == NonLocal;
+ }
+
+ /// Tests if this MemDepResult represents a query that is transparent to the
+ /// start of the function.
+ bool isNonFuncLocal() const {
+ return Value.is<Other>() && Value.cast<Other>() == NonFuncLocal;
+ }
+
+ /// Tests if this MemDepResult represents a query which cannot and/or will
+ /// not be computed.
+ bool isUnknown() const {
+ return Value.is<Other>() && Value.cast<Other>() == Unknown;
+ }
+
+ /// If this is a normal dependency, returns the instruction that is depended
+ /// on. Otherwise, returns null.
+ Instruction *getInst() const {
+ switch (Value.getTag()) {
+ case Invalid:
+ return Value.cast<Invalid>();
+ case Clobber:
+ return Value.cast<Clobber>();
+ case Def:
+ return Value.cast<Def>();
+ case Other:
+ return nullptr;
+ }
+ llvm_unreachable("Unknown discriminant!");
+ }
+
+ bool operator==(const MemDepResult &M) const { return Value == M.Value; }
+ bool operator!=(const MemDepResult &M) const { return Value != M.Value; }
+ bool operator<(const MemDepResult &M) const { return Value < M.Value; }
+ bool operator>(const MemDepResult &M) const { return Value > M.Value; }
+
+private:
+ friend class MemoryDependenceResults;
+
+ /// Tests if this is a MemDepResult in its dirty/invalid. state.
+ bool isDirty() const { return Value.is<Invalid>(); }
+
+ static MemDepResult getDirty(Instruction *Inst) {
+ return MemDepResult(ValueTy::create<Invalid>(Inst));
+ }
+};
+
+/// This is an entry in the NonLocalDepInfo cache.
+///
+/// For each BasicBlock (the BB entry) it keeps a MemDepResult.
+class NonLocalDepEntry {
+ BasicBlock *BB;
+ MemDepResult Result;
+
+public:
+ NonLocalDepEntry(BasicBlock *bb, MemDepResult result)
: BB(bb), Result(result) {}
- // This is used for searches.
- NonLocalDepEntry(BasicBlock *bb) : BB(bb) {}
+ // This is used for searches.
+ NonLocalDepEntry(BasicBlock *bb) : BB(bb) {}
- // BB is the sort key, it can't be changed.
- BasicBlock *getBB() const { return BB; }
+ // BB is the sort key, it can't be changed.
+ BasicBlock *getBB() const { return BB; }
- void setResult(const MemDepResult &R) { Result = R; }
+ void setResult(const MemDepResult &R) { Result = R; }
- const MemDepResult &getResult() const { return Result; }
+ const MemDepResult &getResult() const { return Result; }
- bool operator<(const NonLocalDepEntry &RHS) const {
- return BB < RHS.BB;
- }
- };
+ bool operator<(const NonLocalDepEntry &RHS) const { return BB < RHS.BB; }
+};
- /// NonLocalDepResult - This is a result from a NonLocal dependence query.
- /// For each BasicBlock (the BB entry) it keeps a MemDepResult and the
- /// (potentially phi translated) address that was live in the block.
- class NonLocalDepResult {
- NonLocalDepEntry Entry;
- Value *Address;
+/// This is a result from a NonLocal dependence query.
+///
+/// For each BasicBlock (the BB entry) it keeps a MemDepResult and the
+/// (potentially phi translated) address that was live in the block.
+class NonLocalDepResult {
+ NonLocalDepEntry Entry;
+ Value *Address;
- public:
- NonLocalDepResult(BasicBlock *bb, MemDepResult result, Value *address)
+public:
+ NonLocalDepResult(BasicBlock *bb, MemDepResult result, Value *address)
: Entry(bb, result), Address(address) {}
- // BB is the sort key, it can't be changed.
- BasicBlock *getBB() const { return Entry.getBB(); }
+ // BB is the sort key, it can't be changed.
+ BasicBlock *getBB() const { return Entry.getBB(); }
- void setResult(const MemDepResult &R, Value *Addr) {
- Entry.setResult(R);
- Address = Addr;
- }
+ void setResult(const MemDepResult &R, Value *Addr) {
+ Entry.setResult(R);
+ Address = Addr;
+ }
- const MemDepResult &getResult() const { return Entry.getResult(); }
+ const MemDepResult &getResult() const { return Entry.getResult(); }
- /// getAddress - Return the address of this pointer in this block. This can
- /// be different than the address queried for the non-local result because
- /// of phi translation. This returns null if the address was not available
- /// in a block (i.e. because phi translation failed) or if this is a cached
- /// result and that address was deleted.
+ /// Returns the address of this pointer in this block.
+ ///
+ /// This can be different than the address queried for the non-local result
+ /// because of phi translation. This returns null if the address was not
+ /// available in a block (i.e. because phi translation failed) or if this is
+ /// a cached result and that address was deleted.
+ ///
+ /// The address is always null for a non-local 'call' dependence.
+ Value *getAddress() const { return Address; }
+};
+
+/// Provides a lazy, caching interface for making common memory aliasing
+/// information queries, backed by LLVM's alias analysis passes.
+///
+/// The dependency information returned is somewhat unusual, but is pragmatic.
+/// If queried about a store or call that might modify memory, the analysis
+/// will return the instruction[s] that may either load from that memory or
+/// store to it. If queried with a load or call that can never modify memory,
+/// the analysis will return calls and stores that might modify the pointer,
+/// but generally does not return loads unless a) they are volatile, or
+/// b) they load from *must-aliased* pointers. Returning a dependence on
+/// must-alias'd pointers instead of all pointers interacts well with the
+/// internal caching mechanism.
+class MemoryDependenceResults {
+ // A map from instructions to their dependency.
+ typedef DenseMap<Instruction *, MemDepResult> LocalDepMapType;
+ LocalDepMapType LocalDeps;
+
+public:
+ typedef std::vector<NonLocalDepEntry> NonLocalDepInfo;
+
+private:
+ /// A pair<Value*, bool> where the bool is true if the dependence is a read
+ /// only dependence, false if read/write.
+ typedef PointerIntPair<const Value *, 1, bool> ValueIsLoadPair;
+
+ /// This pair is used when caching information for a block.
+ ///
+ /// If the pointer is null, the cache value is not a full query that starts
+ /// at the specified block. If non-null, the bool indicates whether or not
+ /// the contents of the block was skipped.
+ typedef PointerIntPair<BasicBlock *, 1, bool> BBSkipFirstBlockPair;
+
+ /// This record is the information kept for each (value, is load) pair.
+ struct NonLocalPointerInfo {
+ /// The pair of the block and the skip-first-block flag.
+ BBSkipFirstBlockPair Pair;
+ /// The results of the query for each relevant block.
+ NonLocalDepInfo NonLocalDeps;
+ /// The maximum size of the dereferences of the pointer.
+ ///
+ /// May be UnknownSize if the sizes are unknown.
+ uint64_t Size;
+ /// The AA tags associated with dereferences of the pointer.
///
- /// The address is always null for a non-local 'call' dependence.
- Value *getAddress() const { return Address; }
+ /// The members may be null if there are no tags or conflicting tags.
+ AAMDNodes AATags;
+
+ NonLocalPointerInfo() : Size(MemoryLocation::UnknownSize) {}
};
- /// MemoryDependenceAnalysis - This is an analysis that determines, for a
- /// given memory operation, what preceding memory operations it depends on.
- /// It builds on alias analysis information, and tries to provide a lazy,
- /// caching interface to a common kind of alias information query.
+ /// This map stores the cached results of doing a pointer lookup at the
+ /// bottom of a block.
///
- /// The dependency information returned is somewhat unusual, but is pragmatic.
- /// If queried about a store or call that might modify memory, the analysis
- /// will return the instruction[s] that may either load from that memory or
- /// store to it. If queried with a load or call that can never modify memory,
- /// the analysis will return calls and stores that might modify the pointer,
- /// but generally does not return loads unless a) they are volatile, or
- /// b) they load from *must-aliased* pointers. Returning a dependence on
- /// must-alias'd pointers instead of all pointers interacts well with the
- /// internal caching mechanism.
+ /// The key of this map is the pointer+isload bit, the value is a list of
+ /// <bb->result> mappings.
+ typedef DenseMap<ValueIsLoadPair, NonLocalPointerInfo>
+ CachedNonLocalPointerInfo;
+ CachedNonLocalPointerInfo NonLocalPointerDeps;
+
+ // A map from instructions to their non-local pointer dependencies.
+ typedef DenseMap<Instruction *, SmallPtrSet<ValueIsLoadPair, 4>>
+ ReverseNonLocalPtrDepTy;
+ ReverseNonLocalPtrDepTy ReverseNonLocalPtrDeps;
+
+ /// This is the instruction we keep for each cached access that we have for
+ /// an instruction.
///
- class MemoryDependenceAnalysis : public FunctionPass {
- // A map from instructions to their dependency.
- typedef DenseMap<Instruction*, MemDepResult> LocalDepMapType;
- LocalDepMapType LocalDeps;
-
- public:
- typedef std::vector<NonLocalDepEntry> NonLocalDepInfo;
-
- private:
- /// ValueIsLoadPair - This is a pair<Value*, bool> where the bool is true if
- /// the dependence is a read only dependence, false if read/write.
- typedef PointerIntPair<const Value*, 1, bool> ValueIsLoadPair;
-
- /// BBSkipFirstBlockPair - This pair is used when caching information for a
- /// block. If the pointer is null, the cache value is not a full query that
- /// starts at the specified block. If non-null, the bool indicates whether
- /// or not the contents of the block was skipped.
- typedef PointerIntPair<BasicBlock*, 1, bool> BBSkipFirstBlockPair;
-
- /// NonLocalPointerInfo - This record is the information kept for each
- /// (value, is load) pair.
- struct NonLocalPointerInfo {
- /// Pair - The pair of the block and the skip-first-block flag.
- BBSkipFirstBlockPair Pair;
- /// NonLocalDeps - The results of the query for each relevant block.
- NonLocalDepInfo NonLocalDeps;
- /// Size - The maximum size of the dereferences of the
- /// pointer. May be UnknownSize if the sizes are unknown.
- uint64_t Size;
- /// AATags - The AA tags associated with dereferences of the
- /// pointer. The members may be null if there are no tags or
- /// conflicting tags.
- AAMDNodes AATags;
-
- NonLocalPointerInfo() : Size(MemoryLocation::UnknownSize) {}
- };
-
- /// CachedNonLocalPointerInfo - This map stores the cached results of doing
- /// a pointer lookup at the bottom of a block. The key of this map is the
- /// pointer+isload bit, the value is a list of <bb->result> mappings.
- typedef DenseMap<ValueIsLoadPair,
- NonLocalPointerInfo> CachedNonLocalPointerInfo;
- CachedNonLocalPointerInfo NonLocalPointerDeps;
-
- // A map from instructions to their non-local pointer dependencies.
- typedef DenseMap<Instruction*,
- SmallPtrSet<ValueIsLoadPair, 4> > ReverseNonLocalPtrDepTy;
- ReverseNonLocalPtrDepTy ReverseNonLocalPtrDeps;
-
- /// PerInstNLInfo - This is the instruction we keep for each cached access
- /// that we have for an instruction. The pointer is an owning pointer and
- /// the bool indicates whether we have any dirty bits in the set.
- typedef std::pair<NonLocalDepInfo, bool> PerInstNLInfo;
-
- // A map from instructions to their non-local dependencies.
- typedef DenseMap<Instruction*, PerInstNLInfo> NonLocalDepMapType;
-
- NonLocalDepMapType NonLocalDeps;
-
- // A reverse mapping from dependencies to the dependees. This is
- // used when removing instructions to keep the cache coherent.
- typedef DenseMap<Instruction*,
- SmallPtrSet<Instruction*, 4> > ReverseDepMapType;
- ReverseDepMapType ReverseLocalDeps;
-
- // A reverse mapping from dependencies to the non-local dependees.
- ReverseDepMapType ReverseNonLocalDeps;
-
- /// Current AA implementation, just a cache.
- AliasAnalysis *AA;
- DominatorTree *DT;
- AssumptionCache *AC;
- const TargetLibraryInfo *TLI;
- PredIteratorCache PredCache;
-
- public:
- MemoryDependenceAnalysis();
- ~MemoryDependenceAnalysis() override;
- static char ID;
-
- /// Pass Implementation stuff. This doesn't do any analysis eagerly.
- bool runOnFunction(Function &) override;
-
- /// Clean up memory in between runs
- void releaseMemory() override;
-
- /// getAnalysisUsage - Does not modify anything. It uses Value Numbering
- /// and Alias Analysis.
- ///
- void getAnalysisUsage(AnalysisUsage &AU) const override;
-
- /// getDependency - Return the instruction on which a memory operation
- /// depends. See the class comment for more details. It is illegal to call
- /// this on non-memory instructions.
- MemDepResult getDependency(Instruction *QueryInst);
+ /// The pointer is an owning pointer and the bool indicates whether we have
+ /// any dirty bits in the set.
+ typedef std::pair<NonLocalDepInfo, bool> PerInstNLInfo;
+
+ // A map from instructions to their non-local dependencies.
+ typedef DenseMap<Instruction *, PerInstNLInfo> NonLocalDepMapType;
+
+ NonLocalDepMapType NonLocalDeps;
+
+ // A reverse mapping from dependencies to the dependees. This is
+ // used when removing instructions to keep the cache coherent.
+ typedef DenseMap<Instruction *, SmallPtrSet<Instruction *, 4>>
+ ReverseDepMapType;
+ ReverseDepMapType ReverseLocalDeps;
+
+ // A reverse mapping from dependencies to the non-local dependees.
+ ReverseDepMapType ReverseNonLocalDeps;
+
+ /// Current AA implementation, just a cache.
+ AliasAnalysis &AA;
+ AssumptionCache &AC;
+ const TargetLibraryInfo &TLI;
+ DominatorTree &DT;
+ PredIteratorCache PredCache;
+
+public:
+ MemoryDependenceResults(AliasAnalysis &AA, AssumptionCache &AC,
+ const TargetLibraryInfo &TLI,
+ DominatorTree &DT)
+ : AA(AA), AC(AC), TLI(TLI), DT(DT) {}
+
+ /// Returns the instruction on which a memory operation depends.
+ ///
+ /// See the class comment for more details. It is illegal to call this on
+ /// non-memory instructions.
+ MemDepResult getDependency(Instruction *QueryInst);
- /// getNonLocalCallDependency - Perform a full dependency query for the
- /// specified call, returning the set of blocks that the value is
- /// potentially live across. The returned set of results will include a
- /// "NonLocal" result for all blocks where the value is live across.
- ///
- /// This method assumes the instruction returns a "NonLocal" dependency
- /// within its own block.
- ///
- /// This returns a reference to an internal data structure that may be
- /// invalidated on the next non-local query or when an instruction is
- /// removed. Clients must copy this data if they want it around longer than
- /// that.
- const NonLocalDepInfo &getNonLocalCallDependency(CallSite QueryCS);
-
- /// getNonLocalPointerDependency - Perform a full dependency query for an
- /// access to the QueryInst's specified memory location, returning the set
- /// of instructions that either define or clobber the value.
- ///
- /// Warning: For a volatile query instruction, the dependencies will be
- /// accurate, and thus usable for reordering, but it is never legal to
- /// remove the query instruction.
- ///
- /// This method assumes the pointer has a "NonLocal" dependency within
- /// QueryInst's parent basic block.
- void getNonLocalPointerDependency(Instruction *QueryInst,
+ /// Perform a full dependency query for the specified call, returning the set
+ /// of blocks that the value is potentially live across.
+ ///
+ /// The returned set of results will include a "NonLocal" result for all
+ /// blocks where the value is live across.
+ ///
+ /// This method assumes the instruction returns a "NonLocal" dependency
+ /// within its own block.
+ ///
+ /// This returns a reference to an internal data structure that may be
+ /// invalidated on the next non-local query or when an instruction is
+ /// removed. Clients must copy this data if they want it around longer than
+ /// that.
+ const NonLocalDepInfo &getNonLocalCallDependency(CallSite QueryCS);
+
+ /// Perform a full dependency query for an access to the QueryInst's
+ /// specified memory location, returning the set of instructions that either
+ /// define or clobber the value.
+ ///
+ /// Warning: For a volatile query instruction, the dependencies will be
+ /// accurate, and thus usable for reordering, but it is never legal to
+ /// remove the query instruction.
+ ///
+ /// This method assumes the pointer has a "NonLocal" dependency within
+ /// QueryInst's parent basic block.
+ void getNonLocalPointerDependency(Instruction *QueryInst,
SmallVectorImpl<NonLocalDepResult> &Result);
- /// removeInstruction - Remove an instruction from the dependence analysis,
- /// updating the dependence of instructions that previously depended on it.
- void removeInstruction(Instruction *InstToRemove);
-
- /// invalidateCachedPointerInfo - This method is used to invalidate cached
- /// information about the specified pointer, because it may be too
- /// conservative in memdep. This is an optional call that can be used when
- /// the client detects an equivalence between the pointer and some other
- /// value and replaces the other value with ptr. This can make Ptr available
- /// in more places that cached info does not necessarily keep.
- void invalidateCachedPointerInfo(Value *Ptr);
-
- /// invalidateCachedPredecessors - Clear the PredIteratorCache info.
- /// This needs to be done when the CFG changes, e.g., due to splitting
- /// critical edges.
- void invalidateCachedPredecessors();
-
- /// \brief Return the instruction on which a memory location depends.
- /// If isLoad is true, this routine ignores may-aliases with read-only
- /// operations. If isLoad is false, this routine ignores may-aliases
- /// with reads from read-only locations. If possible, pass the query
- /// instruction as well; this function may take advantage of the metadata
- /// annotated to the query instruction to refine the result.
- ///
- /// Note that this is an uncached query, and thus may be inefficient.
- ///
- MemDepResult getPointerDependencyFrom(const MemoryLocation &Loc,
- bool isLoad,
- BasicBlock::iterator ScanIt,
- BasicBlock *BB,
- Instruction *QueryInst = nullptr);
-
- MemDepResult getSimplePointerDependencyFrom(const MemoryLocation &MemLoc,
- bool isLoad,
- BasicBlock::iterator ScanIt,
- BasicBlock *BB,
- Instruction *QueryInst);
-
- /// This analysis looks for other loads and stores with invariant.group
- /// metadata and the same pointer operand. Returns Unknown if it does not
- /// find anything, and Def if it can be assumed that 2 instructions load or
- /// store the same value.
- /// FIXME: This analysis works only on single block because of restrictions
- /// at the call site.
- MemDepResult getInvariantGroupPointerDependency(LoadInst *LI,
- BasicBlock *BB);
-
- /// getLoadLoadClobberFullWidthSize - This is a little bit of analysis that
- /// looks at a memory location for a load (specified by MemLocBase, Offs,
- /// and Size) and compares it against a load. If the specified load could
- /// be safely widened to a larger integer load that is 1) still efficient,
- /// 2) safe for the target, and 3) would provide the specified memory
- /// location value, then this function returns the size in bytes of the
- /// load width to use. If not, this returns zero.
- static unsigned getLoadLoadClobberFullWidthSize(const Value *MemLocBase,
- int64_t MemLocOffs,
- unsigned MemLocSize,
- const LoadInst *LI);
-
- private:
- MemDepResult getCallSiteDependencyFrom(CallSite C, bool isReadOnlyCall,
- BasicBlock::iterator ScanIt,
- BasicBlock *BB);
- bool getNonLocalPointerDepFromBB(Instruction *QueryInst,
- const PHITransAddr &Pointer,
- const MemoryLocation &Loc, bool isLoad,
- BasicBlock *BB,
- SmallVectorImpl<NonLocalDepResult> &Result,
- DenseMap<BasicBlock *, Value *> &Visited,
- bool SkipFirstBlock = false);
- MemDepResult GetNonLocalInfoForBlock(Instruction *QueryInst,
- const MemoryLocation &Loc, bool isLoad,
- BasicBlock *BB, NonLocalDepInfo *Cache,
- unsigned NumSortedEntries);
-
- void RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair P);
-
- /// verifyRemoved - Verify that the specified instruction does not occur
- /// in our internal data structures.
- void verifyRemoved(Instruction *Inst) const;
- };
+ /// Removes an instruction from the dependence analysis, updating the
+ /// dependence of instructions that previously depended on it.
+ void removeInstruction(Instruction *InstToRemove);
+
+ /// Invalidates cached information about the specified pointer, because it
+ /// may be too conservative in memdep.
+ ///
+ /// This is an optional call that can be used when the client detects an
+ /// equivalence between the pointer and some other value and replaces the
+ /// other value with ptr. This can make Ptr available in more places that
+ /// cached info does not necessarily keep.
+ void invalidateCachedPointerInfo(Value *Ptr);
+
+ /// Clears the PredIteratorCache info.
+ ///
+ /// This needs to be done when the CFG changes, e.g., due to splitting
+ /// critical edges.
+ void invalidateCachedPredecessors();
+
+ /// Returns the instruction on which a memory location depends.
+ ///
+ /// If isLoad is true, this routine ignores may-aliases with read-only
+ /// operations. If isLoad is false, this routine ignores may-aliases
+ /// with reads from read-only locations. If possible, pass the query
+ /// instruction as well; this function may take advantage of the metadata
+ /// annotated to the query instruction to refine the result.
+ ///
+ /// Note that this is an uncached query, and thus may be inefficient.
+ MemDepResult getPointerDependencyFrom(const MemoryLocation &Loc, bool isLoad,
+ BasicBlock::iterator ScanIt,
+ BasicBlock *BB,
+ Instruction *QueryInst = nullptr);
+
+ MemDepResult getSimplePointerDependencyFrom(const MemoryLocation &MemLoc,
+ bool isLoad,
+ BasicBlock::iterator ScanIt,
+ BasicBlock *BB,
+ Instruction *QueryInst);
+
+ /// This analysis looks for other loads and stores with invariant.group
+ /// metadata and the same pointer operand. Returns Unknown if it does not
+ /// find anything, and Def if it can be assumed that 2 instructions load or
+ /// store the same value.
+ /// FIXME: This analysis works only on single block because of restrictions
+ /// at the call site.
+ MemDepResult getInvariantGroupPointerDependency(LoadInst *LI, BasicBlock *BB);
+
+ /// Looks at a memory location for a load (specified by MemLocBase, Offs, and
+ /// Size) and compares it against a load.
+ ///
+ /// If the specified load could be safely widened to a larger integer load
+ /// that is 1) still efficient, 2) safe for the target, and 3) would provide
+ /// the specified memory location value, then this function returns the size
+ /// in bytes of the load width to use. If not, this returns zero.
+ static unsigned getLoadLoadClobberFullWidthSize(const Value *MemLocBase,
+ int64_t MemLocOffs,
+ unsigned MemLocSize,
+ const LoadInst *LI);
+
+ /// Release memory in caches.
+ void releaseMemory();
+
+private:
+ MemDepResult getCallSiteDependencyFrom(CallSite C, bool isReadOnlyCall,
+ BasicBlock::iterator ScanIt,
+ BasicBlock *BB);
+ bool getNonLocalPointerDepFromBB(Instruction *QueryInst,
+ const PHITransAddr &Pointer,
+ const MemoryLocation &Loc, bool isLoad,
+ BasicBlock *BB,
+ SmallVectorImpl<NonLocalDepResult> &Result,
+ DenseMap<BasicBlock *, Value *> &Visited,
+ bool SkipFirstBlock = false);
+ MemDepResult GetNonLocalInfoForBlock(Instruction *QueryInst,
+ const MemoryLocation &Loc, bool isLoad,
+ BasicBlock *BB, NonLocalDepInfo *Cache,
+ unsigned NumSortedEntries);
+
+ void RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair P);
+
+ void verifyRemoved(Instruction *Inst) const;
+};
+
+/// An analysis that produces \c MemoryDependenceResults for a function.
+///
+/// This is essentially a no-op because the results are computed entirely
+/// lazily.
+class MemoryDependenceAnalysis
+ : public AnalysisInfoMixin<MemoryDependenceAnalysis> {
+ friend AnalysisInfoMixin<MemoryDependenceAnalysis>;
+ static char PassID;
+
+public:
+ typedef MemoryDependenceResults Result;
+
+ MemoryDependenceResults run(Function &F, AnalysisManager<Function> &AM);
+};
+
+/// A wrapper analysis pass for the legacy pass manager that exposes a \c
+/// MemoryDepnedenceResults instance.
+class MemoryDependenceWrapperPass : public FunctionPass {
+ Optional<MemoryDependenceResults> MemDep;
+public:
+ MemoryDependenceWrapperPass();
+ ~MemoryDependenceWrapperPass() override;
+ static char ID;
+
+ /// Pass Implementation stuff. This doesn't do any analysis eagerly.
+ bool runOnFunction(Function &) override;
+
+ /// Clean up memory in between runs
+ void releaseMemory() override;
+
+ /// Does not modify anything. It uses Value Numbering and Alias Analysis.
+ void getAnalysisUsage(AnalysisUsage &AU) const override;
+
+ MemoryDependenceResults &getMemDep() { return *MemDep; }
+};
} // End llvm namespace
diff --git a/include/llvm/Analysis/MemoryLocation.h b/include/llvm/Analysis/MemoryLocation.h
index 426b49a3ecd7..f2cb2a123f2e 100644
--- a/include/llvm/Analysis/MemoryLocation.h
+++ b/include/llvm/Analysis/MemoryLocation.h
@@ -16,7 +16,7 @@
#ifndef LLVM_ANALYSIS_MEMORYLOCATION_H
#define LLVM_ANALYSIS_MEMORYLOCATION_H
-#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Metadata.h"
diff --git a/include/llvm/Analysis/ModuleSummaryAnalysis.h b/include/llvm/Analysis/ModuleSummaryAnalysis.h
new file mode 100644
index 000000000000..9f03610ba5b1
--- /dev/null
+++ b/include/llvm/Analysis/ModuleSummaryAnalysis.h
@@ -0,0 +1,91 @@
+//===- ModuleSummaryAnalysis.h - Module summary index builder ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This is the interface to build a ModuleSummaryIndex for a module.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ANALYSIS_MODULESUMMARYANALYSIS_H
+#define LLVM_ANALYSIS_MODULESUMMARYANALYSIS_H
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/IR/ModuleSummaryIndex.h"
+#include "llvm/Pass.h"
+
+namespace llvm {
+
+class BlockFrequencyInfo;
+
+/// Class to build a module summary index for the given Module, possibly from
+/// a Pass.
+class ModuleSummaryIndexBuilder {
+ /// The index being built
+ std::unique_ptr<ModuleSummaryIndex> Index;
+ /// The module for which we are building an index
+ const Module *M;
+
+public:
+ /// Default constructor
+ ModuleSummaryIndexBuilder() = default;
+
+ /// Constructor that builds an index for the given Module. An optional
+ /// callback can be supplied to obtain the frequency info for a function.
+ ModuleSummaryIndexBuilder(
+ const Module *M,
+ std::function<BlockFrequencyInfo *(const Function &F)> Ftor = nullptr);
+
+ /// Get a reference to the index owned by builder
+ ModuleSummaryIndex &getIndex() const { return *Index; }
+
+ /// Take ownership of the built index
+ std::unique_ptr<ModuleSummaryIndex> takeIndex() { return std::move(Index); }
+
+private:
+ /// Compute summary for given function with optional frequency information
+ void computeFunctionSummary(const Function &F,
+ BlockFrequencyInfo *BFI = nullptr);
+
+ /// Compute summary for given variable with optional frequency information
+ void computeVariableSummary(const GlobalVariable &V);
+};
+
+/// Legacy wrapper pass to provide the ModuleSummaryIndex object.
+class ModuleSummaryIndexWrapperPass : public ModulePass {
+ std::unique_ptr<ModuleSummaryIndexBuilder> IndexBuilder;
+
+public:
+ static char ID;
+
+ ModuleSummaryIndexWrapperPass();
+
+ /// Get the index built by pass
+ ModuleSummaryIndex &getIndex() { return IndexBuilder->getIndex(); }
+ const ModuleSummaryIndex &getIndex() const {
+ return IndexBuilder->getIndex();
+ }
+
+ bool runOnModule(Module &M) override;
+ bool doFinalization(Module &M) override;
+ void getAnalysisUsage(AnalysisUsage &AU) const override;
+};
+
+//===--------------------------------------------------------------------===//
+//
+// createModuleSummaryIndexWrapperPass - This pass builds a ModuleSummaryIndex
+// object for the module, to be written to bitcode or LLVM assembly.
+//
+ModulePass *createModuleSummaryIndexWrapperPass();
+
+/// Returns true if \p M is eligible for ThinLTO promotion.
+///
+/// Currently we check if it has any any InlineASM that uses an internal symbol.
+bool moduleCanBeRenamedForThinLTO(const Module &M);
+}
+
+#endif
diff --git a/include/llvm/Analysis/ObjCARCAliasAnalysis.h b/include/llvm/Analysis/ObjCARCAliasAnalysis.h
index ac01154bac6c..067a964bcce1 100644
--- a/include/llvm/Analysis/ObjCARCAliasAnalysis.h
+++ b/include/llvm/Analysis/ObjCARCAliasAnalysis.h
@@ -24,7 +24,6 @@
#define LLVM_ANALYSIS_OBJCARCALIASANALYSIS_H
#include "llvm/Analysis/AliasAnalysis.h"
-#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Pass.h"
namespace llvm {
@@ -42,8 +41,7 @@ class ObjCARCAAResult : public AAResultBase<ObjCARCAAResult> {
const DataLayout &DL;
public:
- explicit ObjCARCAAResult(const DataLayout &DL, const TargetLibraryInfo &TLI)
- : AAResultBase(TLI), DL(DL) {}
+ explicit ObjCARCAAResult(const DataLayout &DL) : AAResultBase(), DL(DL) {}
ObjCARCAAResult(ObjCARCAAResult &&Arg)
: AAResultBase(std::move(Arg)), DL(Arg.DL) {}
@@ -63,20 +61,14 @@ public:
};
/// Analysis pass providing a never-invalidated alias analysis result.
-class ObjCARCAA {
+class ObjCARCAA : public AnalysisInfoMixin<ObjCARCAA> {
+ friend AnalysisInfoMixin<ObjCARCAA>;
+ static char PassID;
+
public:
typedef ObjCARCAAResult Result;
- /// \brief Opaque, unique identifier for this analysis pass.
- static void *ID() { return (void *)&PassID; }
-
- ObjCARCAAResult run(Function &F, AnalysisManager<Function> *AM);
-
- /// \brief Provide access to a name for this pass for debugging purposes.
- static StringRef name() { return "ObjCARCAA"; }
-
-private:
- static char PassID;
+ ObjCARCAAResult run(Function &F, AnalysisManager<Function> &AM);
};
/// Legacy wrapper pass to provide the ObjCARCAAResult object.
diff --git a/include/llvm/Analysis/ObjCARCAnalysisUtils.h b/include/llvm/Analysis/ObjCARCAnalysisUtils.h
index 29d99c9d316d..5f4d8ecbbfbb 100644
--- a/include/llvm/Analysis/ObjCARCAnalysisUtils.h
+++ b/include/llvm/Analysis/ObjCARCAnalysisUtils.h
@@ -54,6 +54,7 @@ inline bool ModuleHasARC(const Module &M) {
M.getNamedValue("objc_release") ||
M.getNamedValue("objc_autorelease") ||
M.getNamedValue("objc_retainAutoreleasedReturnValue") ||
+ M.getNamedValue("objc_unsafeClaimAutoreleasedReturnValue") ||
M.getNamedValue("objc_retainBlock") ||
M.getNamedValue("objc_autoreleaseReturnValue") ||
M.getNamedValue("objc_autoreleasePoolPush") ||
diff --git a/include/llvm/Analysis/ObjCARCInstKind.h b/include/llvm/Analysis/ObjCARCInstKind.h
index 13efb4b160be..3b37ddf78f58 100644
--- a/include/llvm/Analysis/ObjCARCInstKind.h
+++ b/include/llvm/Analysis/ObjCARCInstKind.h
@@ -30,6 +30,7 @@ namespace objcarc {
enum class ARCInstKind {
Retain, ///< objc_retain
RetainRV, ///< objc_retainAutoreleasedReturnValue
+ ClaimRV, ///< objc_unsafeClaimAutoreleasedReturnValue
RetainBlock, ///< objc_retainBlock
Release, ///< objc_release
Autorelease, ///< objc_autorelease
diff --git a/include/llvm/Analysis/OptimizationDiagnosticInfo.h b/include/llvm/Analysis/OptimizationDiagnosticInfo.h
new file mode 100644
index 000000000000..b455a6527bf6
--- /dev/null
+++ b/include/llvm/Analysis/OptimizationDiagnosticInfo.h
@@ -0,0 +1,104 @@
+//===- OptimizationDiagnosticInfo.h - Optimization Diagnostic ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Optimization diagnostic interfaces. It's packaged as an analysis pass so
+// that by using this service passes become dependent on BFI as well. BFI is
+// used to compute the "hotness" of the diagnostic message.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_OPTIMIZATIONDIAGNOSTICINFO_H
+#define LLVM_IR_OPTIMIZATIONDIAGNOSTICINFO_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/Pass.h"
+
+namespace llvm {
+class BlockFrequencyInfo;
+class DebugLoc;
+class Function;
+class LLVMContext;
+class Loop;
+class Pass;
+class Twine;
+class Value;
+
+class OptimizationRemarkEmitter {
+public:
+ OptimizationRemarkEmitter(Function *F, BlockFrequencyInfo *BFI)
+ : F(F), BFI(BFI) {}
+
+ OptimizationRemarkEmitter(OptimizationRemarkEmitter &&Arg)
+ : F(Arg.F), BFI(Arg.BFI) {}
+
+ OptimizationRemarkEmitter &operator=(OptimizationRemarkEmitter &&RHS) {
+ F = RHS.F;
+ BFI = RHS.BFI;
+ return *this;
+ }
+
+ /// Emit an optimization-missed message.
+ ///
+ /// \p PassName is the name of the pass emitting the message. If
+ /// -Rpass-missed= is given and the name matches the regular expression in
+ /// -Rpass, then the remark will be emitted. \p Fn is the function triggering
+ /// the remark, \p DLoc is the debug location where the diagnostic is
+ /// generated. \p V is the IR Value that identifies the code region. \p Msg is
+ /// the message string to use.
+ void emitOptimizationRemarkMissed(const char *PassName, const DebugLoc &DLoc,
+ Value *V, const Twine &Msg);
+
+ /// \brief Same as above but derives the IR Value for the code region and the
+ /// debug location from the Loop parameter \p L.
+ void emitOptimizationRemarkMissed(const char *PassName, Loop *L,
+ const Twine &Msg);
+
+private:
+ Function *F;
+
+ BlockFrequencyInfo *BFI;
+
+ Optional<uint64_t> computeHotness(Value *V);
+
+ OptimizationRemarkEmitter(const OptimizationRemarkEmitter &) = delete;
+ void operator=(const OptimizationRemarkEmitter &) = delete;
+};
+
+class OptimizationRemarkEmitterWrapperPass : public FunctionPass {
+ std::unique_ptr<OptimizationRemarkEmitter> ORE;
+
+public:
+ OptimizationRemarkEmitterWrapperPass();
+
+ bool runOnFunction(Function &F) override;
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override;
+
+ OptimizationRemarkEmitter &getORE() {
+ assert(ORE && "pass not run yet");
+ return *ORE;
+ }
+
+ static char ID;
+};
+
+class OptimizationRemarkEmitterAnalysis
+ : public AnalysisInfoMixin<OptimizationRemarkEmitterAnalysis> {
+ friend AnalysisInfoMixin<OptimizationRemarkEmitterAnalysis>;
+ static char PassID;
+
+public:
+ /// \brief Provide the result typedef for this analysis pass.
+ typedef OptimizationRemarkEmitter Result;
+
+ /// \brief Run the analysis pass over a function and produce BFI.
+ Result run(Function &F, AnalysisManager<Function> &AM);
+};
+}
+#endif // LLVM_IR_OPTIMIZATIONDIAGNOSTICINFO_H
diff --git a/include/llvm/Analysis/Passes.h b/include/llvm/Analysis/Passes.h
index da17457d3446..6d8f14fa32f9 100644
--- a/include/llvm/Analysis/Passes.h
+++ b/include/llvm/Analysis/Passes.h
@@ -25,13 +25,6 @@ namespace llvm {
//===--------------------------------------------------------------------===//
//
- // createAAEvalPass - This pass implements a simple N^2 alias analysis
- // accuracy evaluator.
- //
- FunctionPass *createAAEvalPass();
-
- //===--------------------------------------------------------------------===//
- //
// createObjCARCAAWrapperPass - This pass implements ObjC-ARC-based
// alias analysis.
//
@@ -47,10 +40,10 @@ namespace llvm {
//===--------------------------------------------------------------------===//
//
- // createDependenceAnalysisPass - This creates an instance of the
- // DependenceAnalysis pass.
+ // createDependenceAnalysisWrapperPass - This creates an instance of the
+ // DependenceAnalysisWrapper pass.
//
- FunctionPass *createDependenceAnalysisPass();
+ FunctionPass *createDependenceAnalysisWrapperPass();
//===--------------------------------------------------------------------===//
//
diff --git a/include/llvm/Analysis/PostDominators.h b/include/llvm/Analysis/PostDominators.h
index 0f7e2b88d2d7..99240a40408e 100644
--- a/include/llvm/Analysis/PostDominators.h
+++ b/include/llvm/Analysis/PostDominators.h
@@ -15,78 +15,71 @@
#define LLVM_ANALYSIS_POSTDOMINATORS_H
#include "llvm/IR/Dominators.h"
+#include "llvm/IR/PassManager.h"
namespace llvm {
/// PostDominatorTree Class - Concrete subclass of DominatorTree that is used to
/// compute the post-dominator tree.
///
-struct PostDominatorTree : public FunctionPass {
- static char ID; // Pass identification, replacement for typeid
- DominatorTreeBase<BasicBlock>* DT;
-
- PostDominatorTree() : FunctionPass(ID) {
- initializePostDominatorTreePass(*PassRegistry::getPassRegistry());
- DT = new DominatorTreeBase<BasicBlock>(true);
- }
+struct PostDominatorTree : public DominatorTreeBase<BasicBlock> {
+ typedef DominatorTreeBase<BasicBlock> Base;
- ~PostDominatorTree() override;
+ PostDominatorTree() : DominatorTreeBase<BasicBlock>(true) {}
- bool runOnFunction(Function &F) override;
-
- void getAnalysisUsage(AnalysisUsage &AU) const override {
- AU.setPreservesAll();
- }
+ PostDominatorTree(PostDominatorTree &&Arg)
+ : Base(std::move(static_cast<Base &>(Arg))) {}
- inline const std::vector<BasicBlock*> &getRoots() const {
- return DT->getRoots();
+ PostDominatorTree &operator=(PostDominatorTree &&RHS) {
+ Base::operator=(std::move(static_cast<Base &>(RHS)));
+ return *this;
}
+};
- inline DomTreeNode *getRootNode() const {
- return DT->getRootNode();
- }
+/// \brief Analysis pass which computes a \c PostDominatorTree.
+class PostDominatorTreeAnalysis
+ : public AnalysisInfoMixin<PostDominatorTreeAnalysis> {
+ friend AnalysisInfoMixin<PostDominatorTreeAnalysis>;
+ static char PassID;
- inline DomTreeNode *operator[](BasicBlock *BB) const {
- return DT->getNode(BB);
- }
+public:
+ /// \brief Provide the result typedef for this analysis pass.
+ typedef PostDominatorTree Result;
- inline DomTreeNode *getNode(BasicBlock *BB) const {
- return DT->getNode(BB);
- }
+ /// \brief Run the analysis pass over a function and produce a post dominator
+ /// tree.
+ PostDominatorTree run(Function &F, FunctionAnalysisManager &);
+};
- inline bool dominates(DomTreeNode* A, DomTreeNode* B) const {
- return DT->dominates(A, B);
- }
+/// \brief Printer pass for the \c PostDominatorTree.
+class PostDominatorTreePrinterPass
+ : public PassInfoMixin<PostDominatorTreePrinterPass> {
+ raw_ostream &OS;
- inline bool dominates(const BasicBlock* A, const BasicBlock* B) const {
- return DT->dominates(A, B);
- }
+public:
+ explicit PostDominatorTreePrinterPass(raw_ostream &OS);
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
+};
- inline bool properlyDominates(const DomTreeNode* A, DomTreeNode* B) const {
- return DT->properlyDominates(A, B);
- }
+struct PostDominatorTreeWrapperPass : public FunctionPass {
+ static char ID; // Pass identification, replacement for typeid
+ PostDominatorTree DT;
- inline bool properlyDominates(BasicBlock* A, BasicBlock* B) const {
- return DT->properlyDominates(A, B);
+ PostDominatorTreeWrapperPass() : FunctionPass(ID) {
+ initializePostDominatorTreeWrapperPassPass(*PassRegistry::getPassRegistry());
}
- inline BasicBlock *findNearestCommonDominator(BasicBlock *A, BasicBlock *B) {
- return DT->findNearestCommonDominator(A, B);
- }
+ PostDominatorTree &getPostDomTree() { return DT; }
+ const PostDominatorTree &getPostDomTree() const { return DT; }
- inline const BasicBlock *findNearestCommonDominator(const BasicBlock *A,
- const BasicBlock *B) {
- return DT->findNearestCommonDominator(A, B);
- }
+ bool runOnFunction(Function &F) override;
- /// Get all nodes post-dominated by R, including R itself.
- void getDescendants(BasicBlock *R,
- SmallVectorImpl<BasicBlock *> &Result) const {
- DT->getDescendants(R, Result);
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.setPreservesAll();
}
void releaseMemory() override {
- DT->releaseMemory();
+ DT.releaseMemory();
}
void print(raw_ostream &OS, const Module*) const override;
diff --git a/include/llvm/Analysis/ProfileSummaryInfo.h b/include/llvm/Analysis/ProfileSummaryInfo.h
new file mode 100644
index 000000000000..cd624c8404da
--- /dev/null
+++ b/include/llvm/Analysis/ProfileSummaryInfo.h
@@ -0,0 +1,113 @@
+//===- llvm/Analysis/ProfileSummaryInfo.h - profile summary ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains a pass that provides access to profile summary
+// information.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ANALYSIS_PROFILE_SUMMARY_INFO_H
+#define LLVM_ANALYSIS_PROFILE_SUMMARY_INFO_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/IR/ProfileSummary.h"
+#include "llvm/IR/ValueHandle.h"
+#include "llvm/Pass.h"
+#include <memory>
+
+namespace llvm {
+class ProfileSummary;
+/// \brief Analysis providing profile information.
+///
+/// This is an immutable analysis pass that provides ability to query global
+/// (program-level) profile information. The main APIs are isHotCount and
+/// isColdCount that tells whether a given profile count is considered hot/cold
+/// based on the profile summary. This also provides convenience methods to
+/// check whether a function is hot or cold.
+
+// FIXME: Provide convenience methods to determine hotness/coldness of other IR
+// units. This would require making this depend on BFI.
+class ProfileSummaryInfo {
+private:
+ Module &M;
+ std::unique_ptr<ProfileSummary> Summary;
+ void computeSummary();
+ void computeThresholds();
+ // Count thresholds to answer isHotCount and isColdCount queries.
+ Optional<uint64_t> HotCountThreshold, ColdCountThreshold;
+
+public:
+ ProfileSummaryInfo(Module &M) : M(M) {}
+ ProfileSummaryInfo(ProfileSummaryInfo &&Arg)
+ : M(Arg.M), Summary(std::move(Arg.Summary)) {}
+ /// \brief Returns true if \p F is a hot function.
+ bool isHotFunction(const Function *F);
+ /// \brief Returns true if \p F is a cold function.
+ bool isColdFunction(const Function *F);
+ /// \brief Returns true if count \p C is considered hot.
+ bool isHotCount(uint64_t C);
+ /// \brief Returns true if count \p C is considered cold.
+ bool isColdCount(uint64_t C);
+};
+
+/// An analysis pass based on legacy pass manager to deliver ProfileSummaryInfo.
+class ProfileSummaryInfoWrapperPass : public ImmutablePass {
+ std::unique_ptr<ProfileSummaryInfo> PSI;
+
+public:
+ static char ID;
+ ProfileSummaryInfoWrapperPass();
+
+ ProfileSummaryInfo *getPSI(Module &M);
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.setPreservesAll();
+ }
+};
+
+/// An analysis pass based on the new PM to deliver ProfileSummaryInfo.
+class ProfileSummaryAnalysis
+ : public AnalysisInfoMixin<ProfileSummaryAnalysis> {
+public:
+ typedef ProfileSummaryInfo Result;
+
+ ProfileSummaryAnalysis() {}
+ ProfileSummaryAnalysis(const ProfileSummaryAnalysis &Arg) {}
+ ProfileSummaryAnalysis(ProfileSummaryAnalysis &&Arg) {}
+ ProfileSummaryAnalysis &operator=(const ProfileSummaryAnalysis &RHS) {
+ return *this;
+ }
+ ProfileSummaryAnalysis &operator=(ProfileSummaryAnalysis &&RHS) {
+ return *this;
+ }
+
+ Result run(Module &M, ModuleAnalysisManager &);
+
+private:
+ friend AnalysisInfoMixin<ProfileSummaryAnalysis>;
+ static char PassID;
+};
+
+/// \brief Printer pass that uses \c ProfileSummaryAnalysis.
+class ProfileSummaryPrinterPass
+ : public PassInfoMixin<ProfileSummaryPrinterPass> {
+ raw_ostream &OS;
+
+public:
+ explicit ProfileSummaryPrinterPass(raw_ostream &OS) : OS(OS) {}
+ PreservedAnalyses run(Module &M, AnalysisManager<Module> &AM);
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/include/llvm/Analysis/RegionInfo.h b/include/llvm/Analysis/RegionInfo.h
index 4988386fdc82..91bfd435f08c 100644
--- a/include/llvm/Analysis/RegionInfo.h
+++ b/include/llvm/Analysis/RegionInfo.h
@@ -41,6 +41,7 @@
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/Dominators.h"
+#include "llvm/IR/PassManager.h"
#include <map>
#include <memory>
#include <set>
@@ -676,6 +677,22 @@ class RegionInfoBase {
RegionInfoBase(const RegionInfoBase &) = delete;
const RegionInfoBase &operator=(const RegionInfoBase &) = delete;
+ RegionInfoBase(RegionInfoBase &&Arg)
+ : DT(std::move(Arg.DT)), PDT(std::move(Arg.PDT)), DF(std::move(Arg.DF)),
+ TopLevelRegion(std::move(Arg.TopLevelRegion)),
+ BBtoRegion(std::move(Arg.BBtoRegion)) {
+ Arg.wipe();
+ }
+ RegionInfoBase &operator=(RegionInfoBase &&RHS) {
+ DT = std::move(RHS.DT);
+ PDT = std::move(RHS.PDT);
+ DF = std::move(RHS.DF);
+ TopLevelRegion = std::move(RHS.TopLevelRegion);
+ BBtoRegion = std::move(RHS.BBtoRegion);
+ RHS.wipe();
+ return *this;
+ }
+
DomTreeT *DT;
PostDomTreeT *PDT;
DomFrontierT *DF;
@@ -687,6 +704,18 @@ private:
/// Map every BB to the smallest region, that contains BB.
BBtoRegionMap BBtoRegion;
+ /// \brief Wipe this region tree's state without releasing any resources.
+ ///
+ /// This is essentially a post-move helper only. It leaves the object in an
+ /// assignable and destroyable state, but otherwise invalid.
+ void wipe() {
+ DT = nullptr;
+ PDT = nullptr;
+ DF = nullptr;
+ TopLevelRegion = nullptr;
+ BBtoRegion.clear();
+ }
+
// Check whether the entries of BBtoRegion for the BBs of region
// SR are correct. Triggers an assertion if not. Calls itself recursively for
// subregions.
@@ -836,10 +865,19 @@ public:
class RegionInfo : public RegionInfoBase<RegionTraits<Function>> {
public:
+ typedef RegionInfoBase<RegionTraits<Function>> Base;
+
explicit RegionInfo();
~RegionInfo() override;
+ RegionInfo(RegionInfo &&Arg)
+ : Base(std::move(static_cast<Base &>(Arg))) {}
+ RegionInfo &operator=(RegionInfo &&RHS) {
+ Base::operator=(std::move(static_cast<Base &>(RHS)));
+ return *this;
+ }
+
// updateStatistics - Update statistic about created regions.
void updateStatistics(Region *R) final;
@@ -884,6 +922,31 @@ public:
//@}
};
+/// \brief Analysis pass that exposes the \c RegionInfo for a function.
+class RegionInfoAnalysis : public AnalysisInfoMixin<RegionInfoAnalysis> {
+ friend AnalysisInfoMixin<RegionInfoAnalysis>;
+ static char PassID;
+
+public:
+ typedef RegionInfo Result;
+
+ RegionInfo run(Function &F, AnalysisManager<Function> &AM);
+};
+
+/// \brief Printer pass for the \c RegionInfo.
+class RegionInfoPrinterPass : public PassInfoMixin<RegionInfoPrinterPass> {
+ raw_ostream &OS;
+
+public:
+ explicit RegionInfoPrinterPass(raw_ostream &OS);
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
+};
+
+/// \brief Verifier pass for the \c RegionInfo.
+struct RegionInfoVerifierPass : PassInfoMixin<RegionInfoVerifierPass> {
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
+};
+
template <>
template <>
inline BasicBlock *
diff --git a/include/llvm/Analysis/RegionInfoImpl.h b/include/llvm/Analysis/RegionInfoImpl.h
index 134cd8f96fbe..15dd1a2000e6 100644
--- a/include/llvm/Analysis/RegionInfoImpl.h
+++ b/include/llvm/Analysis/RegionInfoImpl.h
@@ -18,7 +18,6 @@
#include "llvm/Analysis/PostDominators.h"
#include "llvm/Analysis/RegionInfo.h"
#include "llvm/Analysis/RegionIterator.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
@@ -666,7 +665,7 @@ typename Tr::RegionT *RegionInfoBase<Tr>::createRegion(BlockT *entry,
new RegionT(entry, exit, static_cast<RegionInfoT *>(this), DT);
BBtoRegion.insert(std::make_pair(entry, region));
-#ifdef XDEBUG
+#ifdef EXPENSIVE_CHECKS
region->verifyRegion();
#else
DEBUG(region->verifyRegion());
@@ -765,7 +764,7 @@ void RegionInfoBase<Tr>::buildRegionsTree(DomTreeNodeT *N, RegionT *region) {
}
}
-#ifdef XDEBUG
+#ifdef EXPENSIVE_CHECKS
template <class Tr>
bool RegionInfoBase<Tr>::VerifyRegionInfo = true;
#else
@@ -799,7 +798,7 @@ void RegionInfoBase<Tr>::releaseMemory() {
template <class Tr>
void RegionInfoBase<Tr>::verifyAnalysis() const {
- // Do only verify regions if explicitely activated using XDEBUG or
+ // Do only verify regions if explicitely activated using EXPENSIVE_CHECKS or
// -verify-region-info
if (!RegionInfoBase<Tr>::VerifyRegionInfo)
return;
diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h
index ef9305788849..535b623d31ac 100644
--- a/include/llvm/Analysis/ScalarEvolution.h
+++ b/include/llvm/Analysis/ScalarEvolution.h
@@ -23,17 +23,17 @@
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/SetVector.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/IR/ConstantRange.h"
-#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/ValueHandle.h"
+#include "llvm/IR/ValueMap.h"
#include "llvm/Pass.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/DataTypes.h"
-#include <map>
namespace llvm {
class APInt;
@@ -53,6 +53,7 @@ namespace llvm {
class SCEVExpander;
class SCEVPredicate;
class SCEVUnknown;
+ class Function;
template <> struct FoldingSetTrait<SCEV>;
template <> struct FoldingSetTrait<SCEVPredicate>;
@@ -168,8 +169,8 @@ namespace llvm {
static bool classof(const SCEV *S);
};
- /// SCEVPredicate - This class represents an assumption made using SCEV
- /// expressions which can be checked at run-time.
+ /// This class represents an assumption made using SCEV expressions which can
+ /// be checked at run-time.
class SCEVPredicate : public FoldingSetNode {
friend struct FoldingSetTrait<SCEVPredicate>;
@@ -178,7 +179,7 @@ namespace llvm {
FoldingSetNodeIDRef FastID;
public:
- enum SCEVPredicateKind { P_Union, P_Equal };
+ enum SCEVPredicateKind { P_Union, P_Equal, P_Wrap };
protected:
SCEVPredicateKind Kind;
@@ -191,23 +192,23 @@ namespace llvm {
SCEVPredicateKind getKind() const { return Kind; }
- /// \brief Returns the estimated complexity of this predicate.
- /// This is roughly measured in the number of run-time checks required.
+ /// Returns the estimated complexity of this predicate. This is roughly
+ /// measured in the number of run-time checks required.
virtual unsigned getComplexity() const { return 1; }
- /// \brief Returns true if the predicate is always true. This means that no
+ /// Returns true if the predicate is always true. This means that no
/// assumptions were made and nothing needs to be checked at run-time.
virtual bool isAlwaysTrue() const = 0;
- /// \brief Returns true if this predicate implies \p N.
+ /// Returns true if this predicate implies \p N.
virtual bool implies(const SCEVPredicate *N) const = 0;
- /// \brief Prints a textual representation of this predicate with an
- /// indentation of \p Depth.
+ /// Prints a textual representation of this predicate with an indentation of
+ /// \p Depth.
virtual void print(raw_ostream &OS, unsigned Depth = 0) const = 0;
- /// \brief Returns the SCEV to which this predicate applies, or nullptr
- /// if this is a SCEVUnionPredicate.
+ /// Returns the SCEV to which this predicate applies, or nullptr if this is
+ /// a SCEVUnionPredicate.
virtual const SCEV *getExpr() const = 0;
};
@@ -236,10 +237,9 @@ namespace llvm {
}
};
- /// SCEVEqualPredicate - This class represents an assumption that two SCEV
- /// expressions are equal, and this can be checked at run-time. We assume
- /// that the left hand side is a SCEVUnknown and the right hand side a
- /// constant.
+ /// This class represents an assumption that two SCEV expressions are equal,
+ /// and this can be checked at run-time. We assume that the left hand side is
+ /// a SCEVUnknown and the right hand side a constant.
class SCEVEqualPredicate final : public SCEVPredicate {
/// We assume that LHS == RHS, where LHS is a SCEVUnknown and RHS a
/// constant.
@@ -256,10 +256,10 @@ namespace llvm {
bool isAlwaysTrue() const override;
const SCEV *getExpr() const override;
- /// \brief Returns the left hand side of the equality.
+ /// Returns the left hand side of the equality.
const SCEVUnknown *getLHS() const { return LHS; }
- /// \brief Returns the right hand side of the equality.
+ /// Returns the right hand side of the equality.
const SCEVConstant *getRHS() const { return RHS; }
/// Methods for support type inquiry through isa, cast, and dyn_cast:
@@ -268,9 +268,107 @@ namespace llvm {
}
};
- /// SCEVUnionPredicate - This class represents a composition of other
- /// SCEV predicates, and is the class that most clients will interact with.
- /// This is equivalent to a logical "AND" of all the predicates in the union.
+ /// This class represents an assumption made on an AddRec expression. Given an
+ /// affine AddRec expression {a,+,b}, we assume that it has the nssw or nusw
+ /// flags (defined below) in the first X iterations of the loop, where X is a
+ /// SCEV expression returned by getPredicatedBackedgeTakenCount).
+ ///
+ /// Note that this does not imply that X is equal to the backedge taken
+ /// count. This means that if we have a nusw predicate for i32 {0,+,1} with a
+ /// predicated backedge taken count of X, we only guarantee that {0,+,1} has
+ /// nusw in the first X iterations. {0,+,1} may still wrap in the loop if we
+ /// have more than X iterations.
+ class SCEVWrapPredicate final : public SCEVPredicate {
+ public:
+ /// Similar to SCEV::NoWrapFlags, but with slightly different semantics
+ /// for FlagNUSW. The increment is considered to be signed, and a + b
+ /// (where b is the increment) is considered to wrap if:
+ /// zext(a + b) != zext(a) + sext(b)
+ ///
+ /// If Signed is a function that takes an n-bit tuple and maps to the
+ /// integer domain as the tuples value interpreted as twos complement,
+ /// and Unsigned a function that takes an n-bit tuple and maps to the
+ /// integer domain as as the base two value of input tuple, then a + b
+ /// has IncrementNUSW iff:
+ ///
+ /// 0 <= Unsigned(a) + Signed(b) < 2^n
+ ///
+ /// The IncrementNSSW flag has identical semantics with SCEV::FlagNSW.
+ ///
+ /// Note that the IncrementNUSW flag is not commutative: if base + inc
+ /// has IncrementNUSW, then inc + base doesn't neccessarily have this
+ /// property. The reason for this is that this is used for sign/zero
+ /// extending affine AddRec SCEV expressions when a SCEVWrapPredicate is
+ /// assumed. A {base,+,inc} expression is already non-commutative with
+ /// regards to base and inc, since it is interpreted as:
+ /// (((base + inc) + inc) + inc) ...
+ enum IncrementWrapFlags {
+ IncrementAnyWrap = 0, // No guarantee.
+ IncrementNUSW = (1 << 0), // No unsigned with signed increment wrap.
+ IncrementNSSW = (1 << 1), // No signed with signed increment wrap
+ // (equivalent with SCEV::NSW)
+ IncrementNoWrapMask = (1 << 2) - 1
+ };
+
+ /// Convenient IncrementWrapFlags manipulation methods.
+ static SCEVWrapPredicate::IncrementWrapFlags LLVM_ATTRIBUTE_UNUSED_RESULT
+ clearFlags(SCEVWrapPredicate::IncrementWrapFlags Flags,
+ SCEVWrapPredicate::IncrementWrapFlags OffFlags) {
+ assert((Flags & IncrementNoWrapMask) == Flags && "Invalid flags value!");
+ assert((OffFlags & IncrementNoWrapMask) == OffFlags &&
+ "Invalid flags value!");
+ return (SCEVWrapPredicate::IncrementWrapFlags)(Flags & ~OffFlags);
+ }
+
+ static SCEVWrapPredicate::IncrementWrapFlags LLVM_ATTRIBUTE_UNUSED_RESULT
+ maskFlags(SCEVWrapPredicate::IncrementWrapFlags Flags, int Mask) {
+ assert((Flags & IncrementNoWrapMask) == Flags && "Invalid flags value!");
+ assert((Mask & IncrementNoWrapMask) == Mask && "Invalid mask value!");
+
+ return (SCEVWrapPredicate::IncrementWrapFlags)(Flags & Mask);
+ }
+
+ static SCEVWrapPredicate::IncrementWrapFlags LLVM_ATTRIBUTE_UNUSED_RESULT
+ setFlags(SCEVWrapPredicate::IncrementWrapFlags Flags,
+ SCEVWrapPredicate::IncrementWrapFlags OnFlags) {
+ assert((Flags & IncrementNoWrapMask) == Flags && "Invalid flags value!");
+ assert((OnFlags & IncrementNoWrapMask) == OnFlags &&
+ "Invalid flags value!");
+
+ return (SCEVWrapPredicate::IncrementWrapFlags)(Flags | OnFlags);
+ }
+
+ /// Returns the set of SCEVWrapPredicate no wrap flags implied by a
+ /// SCEVAddRecExpr.
+ static SCEVWrapPredicate::IncrementWrapFlags
+ getImpliedFlags(const SCEVAddRecExpr *AR, ScalarEvolution &SE);
+
+ private:
+ const SCEVAddRecExpr *AR;
+ IncrementWrapFlags Flags;
+
+ public:
+ explicit SCEVWrapPredicate(const FoldingSetNodeIDRef ID,
+ const SCEVAddRecExpr *AR,
+ IncrementWrapFlags Flags);
+
+ /// Returns the set assumed no overflow flags.
+ IncrementWrapFlags getFlags() const { return Flags; }
+ /// Implementation of the SCEVPredicate interface
+ const SCEV *getExpr() const override;
+ bool implies(const SCEVPredicate *N) const override;
+ void print(raw_ostream &OS, unsigned Depth = 0) const override;
+ bool isAlwaysTrue() const override;
+
+ /// Methods for support type inquiry through isa, cast, and dyn_cast:
+ static inline bool classof(const SCEVPredicate *P) {
+ return P->getKind() == P_Wrap;
+ }
+ };
+
+ /// This class represents a composition of other SCEV predicates, and is the
+ /// class that most clients will interact with. This is equivalent to a
+ /// logical "AND" of all the predicates in the union.
class SCEVUnionPredicate final : public SCEVPredicate {
private:
typedef DenseMap<const SCEV *, SmallVector<const SCEVPredicate *, 4>>
@@ -288,11 +386,11 @@ namespace llvm {
return Preds;
}
- /// \brief Adds a predicate to this union.
+ /// Adds a predicate to this union.
void add(const SCEVPredicate *N);
- /// \brief Returns a reference to a vector containing all predicates
- /// which apply to \p Expr.
+ /// Returns a reference to a vector containing all predicates which apply to
+ /// \p Expr.
ArrayRef<const SCEVPredicate *> getPredicatesForExpr(const SCEV *Expr);
/// Implementation of the SCEVPredicate interface
@@ -301,8 +399,8 @@ namespace llvm {
void print(raw_ostream &OS, unsigned Depth) const override;
const SCEV *getExpr() const override;
- /// \brief We estimate the complexity of a union predicate as the size
- /// number of predicates in the union.
+ /// We estimate the complexity of a union predicate as the size number of
+ /// predicates in the union.
unsigned getComplexity() const override { return Preds.size(); }
/// Methods for support type inquiry through isa, cast, and dyn_cast:
@@ -364,6 +462,12 @@ namespace llvm {
///
Function &F;
+ /// Does the module have any calls to the llvm.experimental.guard intrinsic
+ /// at all? If this is false, we avoid doing work that will only help if
+ /// thare are guards present in the IR.
+ ///
+ bool HasGuards;
+
/// The target library information for the target we are targeting.
///
TargetLibraryInfo &TLI;
@@ -382,6 +486,21 @@ namespace llvm {
/// This SCEV is used to represent unknown trip counts and things.
std::unique_ptr<SCEVCouldNotCompute> CouldNotCompute;
+ /// The typedef for HasRecMap.
+ ///
+ typedef DenseMap<const SCEV *, bool> HasRecMapType;
+
+ /// This is a cache to record whether a SCEV contains any scAddRecExpr.
+ HasRecMapType HasRecMap;
+
+ /// The typedef for ExprValueMap.
+ ///
+ typedef DenseMap<const SCEV *, SetVector<Value *>> ExprValueMapType;
+
+ /// ExprValueMap -- This map records the original values from which
+ /// the SCEV expr is generated from.
+ ExprValueMapType ExprValueMap;
+
/// The typedef for ValueExprMap.
///
typedef DenseMap<SCEVCallbackVH, const SCEV *, DenseMapInfo<Value *> >
@@ -410,9 +529,14 @@ namespace llvm {
const SCEV *Exact;
const SCEV *Max;
+ /// A predicate union guard for this ExitLimit. The result is only
+ /// valid if this predicate evaluates to 'true' at run-time.
+ SCEVUnionPredicate Pred;
+
/*implicit*/ ExitLimit(const SCEV *E) : Exact(E), Max(E) {}
- ExitLimit(const SCEV *E, const SCEV *M) : Exact(E), Max(M) {
+ ExitLimit(const SCEV *E, const SCEV *M, SCEVUnionPredicate &P)
+ : Exact(E), Max(M), Pred(P) {
assert((isa<SCEVCouldNotCompute>(Exact) ||
!isa<SCEVCouldNotCompute>(Max)) &&
"Exact is not allowed to be less precise than Max");
@@ -424,30 +548,147 @@ namespace llvm {
return !isa<SCEVCouldNotCompute>(Exact) ||
!isa<SCEVCouldNotCompute>(Max);
}
+
+ /// Test whether this ExitLimit contains all information.
+ bool hasFullInfo() const { return !isa<SCEVCouldNotCompute>(Exact); }
};
+ /// Forward declaration of ExitNotTakenExtras
+ struct ExitNotTakenExtras;
+
/// Information about the number of times a particular loop exit may be
/// reached before exiting the loop.
struct ExitNotTakenInfo {
AssertingVH<BasicBlock> ExitingBlock;
const SCEV *ExactNotTaken;
- PointerIntPair<ExitNotTakenInfo*, 1> NextExit;
- ExitNotTakenInfo() : ExitingBlock(nullptr), ExactNotTaken(nullptr) {}
+ ExitNotTakenExtras *ExtraInfo;
+ bool Complete;
+
+ ExitNotTakenInfo()
+ : ExitingBlock(nullptr), ExactNotTaken(nullptr), ExtraInfo(nullptr),
+ Complete(true) {}
+
+ ExitNotTakenInfo(BasicBlock *ExitBlock, const SCEV *Expr,
+ ExitNotTakenExtras *Ptr)
+ : ExitingBlock(ExitBlock), ExactNotTaken(Expr), ExtraInfo(Ptr),
+ Complete(true) {}
/// Return true if all loop exits are computable.
- bool isCompleteList() const {
- return NextExit.getInt() == 0;
+ bool isCompleteList() const { return Complete; }
+
+ /// Sets the incomplete property, indicating that one of the loop exits
+ /// doesn't have a corresponding ExitNotTakenInfo entry.
+ void setIncomplete() { Complete = false; }
+
+ /// Returns a pointer to the predicate associated with this information,
+ /// or nullptr if this doesn't exist (meaning always true).
+ SCEVUnionPredicate *getPred() const {
+ if (ExtraInfo)
+ return &ExtraInfo->Pred;
+
+ return nullptr;
}
- void setIncomplete() { NextExit.setInt(1); }
+ /// Return true if the SCEV predicate associated with this information
+ /// is always true.
+ bool hasAlwaysTruePred() const {
+ return !getPred() || getPred()->isAlwaysTrue();
+ }
- /// Return a pointer to the next exit's not-taken info.
- ExitNotTakenInfo *getNextExit() const {
- return NextExit.getPointer();
+ /// Defines a simple forward iterator for ExitNotTakenInfo.
+ class ExitNotTakenInfoIterator
+ : public std::iterator<std::forward_iterator_tag, ExitNotTakenInfo> {
+ const ExitNotTakenInfo *Start;
+ unsigned Position;
+
+ public:
+ ExitNotTakenInfoIterator(const ExitNotTakenInfo *Start,
+ unsigned Position)
+ : Start(Start), Position(Position) {}
+
+ const ExitNotTakenInfo &operator*() const {
+ if (Position == 0)
+ return *Start;
+
+ return Start->ExtraInfo->Exits[Position - 1];
+ }
+
+ const ExitNotTakenInfo *operator->() const {
+ if (Position == 0)
+ return Start;
+
+ return &Start->ExtraInfo->Exits[Position - 1];
+ }
+
+ bool operator==(const ExitNotTakenInfoIterator &RHS) const {
+ return Start == RHS.Start && Position == RHS.Position;
+ }
+
+ bool operator!=(const ExitNotTakenInfoIterator &RHS) const {
+ return Start != RHS.Start || Position != RHS.Position;
+ }
+
+ ExitNotTakenInfoIterator &operator++() { // Preincrement
+ if (!Start)
+ return *this;
+
+ unsigned Elements =
+ Start->ExtraInfo ? Start->ExtraInfo->Exits.size() + 1 : 1;
+
+ ++Position;
+
+ // We've run out of elements.
+ if (Position == Elements) {
+ Start = nullptr;
+ Position = 0;
+ }
+
+ return *this;
+ }
+ ExitNotTakenInfoIterator operator++(int) { // Postincrement
+ ExitNotTakenInfoIterator Tmp = *this;
+ ++*this;
+ return Tmp;
+ }
+ };
+
+ /// Iterators
+ ExitNotTakenInfoIterator begin() const {
+ return ExitNotTakenInfoIterator(this, 0);
+ }
+ ExitNotTakenInfoIterator end() const {
+ return ExitNotTakenInfoIterator(nullptr, 0);
}
+ };
- void setNextExit(ExitNotTakenInfo *ENT) { NextExit.setPointer(ENT); }
+ /// Describes the extra information that a ExitNotTakenInfo can have.
+ struct ExitNotTakenExtras {
+ /// The predicate associated with the ExitNotTakenInfo struct.
+ SCEVUnionPredicate Pred;
+
+ /// The extra exits in the loop. Only the ExitNotTakenExtras structure
+ /// pointed to by the first ExitNotTakenInfo struct (associated with the
+ /// first loop exit) will populate this vector to prevent having
+ /// redundant information.
+ SmallVector<ExitNotTakenInfo, 4> Exits;
+ };
+
+ /// A struct containing the information attached to a backedge.
+ struct EdgeInfo {
+ EdgeInfo(BasicBlock *Block, const SCEV *Taken, SCEVUnionPredicate &P) :
+ ExitBlock(Block), Taken(Taken), Pred(std::move(P)) {}
+
+ /// The exit basic block.
+ BasicBlock *ExitBlock;
+
+ /// The (exact) number of time we take the edge back.
+ const SCEV *Taken;
+
+ /// The SCEV predicated associated with Taken. If Pred doesn't evaluate
+ /// to true, the information in Taken is not valid (or equivalent with
+ /// a CouldNotCompute.
+ SCEVUnionPredicate Pred;
};
/// Information about the backedge-taken count of a loop. This currently
@@ -459,16 +700,16 @@ namespace llvm {
ExitNotTakenInfo ExitNotTaken;
/// An expression indicating the least maximum backedge-taken count of the
- /// loop that is known, or a SCEVCouldNotCompute.
+ /// loop that is known, or a SCEVCouldNotCompute. This expression is only
+ /// valid if the predicates associated with all loop exits are true.
const SCEV *Max;
public:
BackedgeTakenInfo() : Max(nullptr) {}
/// Initialize BackedgeTakenInfo from a list of exact exit counts.
- BackedgeTakenInfo(
- SmallVectorImpl< std::pair<BasicBlock *, const SCEV *> > &ExitCounts,
- bool Complete, const SCEV *MaxCount);
+ BackedgeTakenInfo(SmallVectorImpl<EdgeInfo> &ExitCounts, bool Complete,
+ const SCEV *MaxCount);
/// Test whether this BackedgeTakenInfo contains any computed information,
/// or whether it's all SCEVCouldNotCompute values.
@@ -476,11 +717,27 @@ namespace llvm {
return ExitNotTaken.ExitingBlock || !isa<SCEVCouldNotCompute>(Max);
}
+ /// Test whether this BackedgeTakenInfo contains complete information.
+ bool hasFullInfo() const { return ExitNotTaken.isCompleteList(); }
+
/// Return an expression indicating the exact backedge-taken count of the
- /// loop if it is known, or SCEVCouldNotCompute otherwise. This is the
+ /// loop if it is known or SCEVCouldNotCompute otherwise. This is the
/// number of times the loop header can be guaranteed to execute, minus
/// one.
- const SCEV *getExact(ScalarEvolution *SE) const;
+ ///
+ /// If the SCEV predicate associated with the answer can be different
+ /// from AlwaysTrue, we must add a (non null) Predicates argument.
+ /// The SCEV predicate associated with the answer will be added to
+ /// Predicates. A run-time check needs to be emitted for the SCEV
+ /// predicate in order for the answer to be valid.
+ ///
+ /// Note that we should always know if we need to pass a predicate
+ /// argument or not from the way the ExitCounts vector was computed.
+ /// If we allowed SCEV predicates to be generated when populating this
+ /// vector, this information can contain them and therefore a
+ /// SCEVPredicate argument should be added to getExact.
+ const SCEV *getExact(ScalarEvolution *SE,
+ SCEVUnionPredicate *Predicates = nullptr) const;
/// Return the number of times this loop exit may fall through to the back
/// edge, or SCEVCouldNotCompute. The loop is guaranteed not to exit via
@@ -501,7 +758,11 @@ namespace llvm {
/// Cache the backedge-taken count of the loops for this function as they
/// are computed.
- DenseMap<const Loop*, BackedgeTakenInfo> BackedgeTakenCounts;
+ DenseMap<const Loop *, BackedgeTakenInfo> BackedgeTakenCounts;
+
+ /// Cache the predicated backedge-taken count of the loops for this
+ /// function as they are computed.
+ DenseMap<const Loop *, BackedgeTakenInfo> PredicatedBackedgeTakenCounts;
/// This map contains entries for all of the PHI instructions that we
/// attempt to compute constant evolutions for. This allows us to avoid
@@ -520,6 +781,16 @@ namespace llvm {
SmallVector<PointerIntPair<const Loop *, 2, LoopDisposition>, 2>>
LoopDispositions;
+ /// Cache for \c loopHasNoAbnormalExits.
+ DenseMap<const Loop *, bool> LoopHasNoAbnormalExits;
+
+ /// Returns true if \p L contains no instruction that can abnormally exit
+ /// the loop (i.e. via throwing an exception, by terminating the thread
+ /// cleanly or by infinite looping in a called function). Strictly
+ /// speaking, the last one is not leaving the loop, but is identical to
+ /// leaving the loop for reasoning about undefined behavior.
+ bool loopHasNoAbnormalExits(const Loop *L);
+
/// Compute a LoopDisposition value.
LoopDisposition computeLoopDisposition(const SCEV *S, const Loop *L);
@@ -547,8 +818,7 @@ namespace llvm {
DenseMap<const SCEV *, ConstantRange> &Cache =
Hint == HINT_RANGE_UNSIGNED ? UnsignedRanges : SignedRanges;
- std::pair<DenseMap<const SCEV *, ConstantRange>::iterator, bool> Pair =
- Cache.insert(std::make_pair(S, CR));
+ auto Pair = Cache.insert({S, CR});
if (!Pair.second)
Pair.first->second = CR;
return Pair.first->second;
@@ -557,6 +827,19 @@ namespace llvm {
/// Determine the range for a particular SCEV.
ConstantRange getRange(const SCEV *S, RangeSignHint Hint);
+ /// Determines the range for the affine SCEVAddRecExpr {\p Start,+,\p Stop}.
+ /// Helper for \c getRange.
+ ConstantRange getRangeForAffineAR(const SCEV *Start, const SCEV *Stop,
+ const SCEV *MaxBECount,
+ unsigned BitWidth);
+
+ /// 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.
+ ConstantRange getRangeViaFactoring(const SCEV *Start, const SCEV *Stop,
+ const SCEV *MaxBECount,
+ unsigned BitWidth);
+
/// We know that there is no SCEV for the specified value. Analyze the
/// expression.
const SCEV *createSCEV(Value *V);
@@ -588,36 +871,59 @@ namespace llvm {
/// This looks up computed SCEV values for all instructions that depend on
/// the given instruction and removes them from the ValueExprMap map if they
/// reference SymName. This is used during PHI resolution.
- void ForgetSymbolicName(Instruction *I, const SCEV *SymName);
+ void forgetSymbolicName(Instruction *I, const SCEV *SymName);
/// Return the BackedgeTakenInfo for the given loop, lazily computing new
- /// values if the loop hasn't been analyzed yet.
+ /// values if the loop hasn't been analyzed yet. The returned result is
+ /// guaranteed not to be predicated.
const BackedgeTakenInfo &getBackedgeTakenInfo(const Loop *L);
+ /// Similar to getBackedgeTakenInfo, but will add predicates as required
+ /// with the purpose of returning complete information.
+ const BackedgeTakenInfo &getPredicatedBackedgeTakenInfo(const Loop *L);
+
/// Compute the number of times the specified loop will iterate.
- BackedgeTakenInfo computeBackedgeTakenCount(const Loop *L);
+ /// If AllowPredicates is set, we will create new SCEV predicates as
+ /// necessary in order to return an exact answer.
+ BackedgeTakenInfo computeBackedgeTakenCount(const Loop *L,
+ bool AllowPredicates = false);
/// Compute the number of times the backedge of the specified loop will
- /// execute if it exits via the specified block.
- ExitLimit computeExitLimit(const Loop *L, BasicBlock *ExitingBlock);
+ /// execute if it exits via the specified block. If AllowPredicates is set,
+ /// this call will try to use a minimal set of SCEV predicates in order to
+ /// return an exact answer.
+ ExitLimit computeExitLimit(const Loop *L, BasicBlock *ExitingBlock,
+ bool AllowPredicates = false);
/// Compute the number of times the backedge of the specified loop will
/// execute if its exit condition were a conditional branch of ExitCond,
/// TBB, and FBB.
+ ///
+ /// \p ControlsExit is true if ExitCond directly controls the exit
+ /// branch. In this case, we can assume that the loop exits only if the
+ /// condition is true and can infer that failing to meet the condition prior
+ /// to integer wraparound results in undefined behavior.
+ ///
+ /// If \p AllowPredicates is set, this call will try to use a minimal set of
+ /// SCEV predicates in order to return an exact answer.
ExitLimit computeExitLimitFromCond(const Loop *L,
Value *ExitCond,
BasicBlock *TBB,
BasicBlock *FBB,
- bool IsSubExpr);
+ bool ControlsExit,
+ bool AllowPredicates = false);
/// Compute the number of times the backedge of the specified loop will
/// execute if its exit condition were a conditional branch of the ICmpInst
- /// ExitCond, TBB, and FBB.
+ /// ExitCond, TBB, and FBB. If AllowPredicates is set, this call will try
+ /// to use a minimal set of SCEV predicates in order to return an exact
+ /// answer.
ExitLimit computeExitLimitFromICmp(const Loop *L,
ICmpInst *ExitCond,
BasicBlock *TBB,
BasicBlock *FBB,
- bool IsSubExpr);
+ bool IsSubExpr,
+ bool AllowPredicates = false);
/// Compute the number of times the backedge of the specified loop will
/// execute if its exit condition were a switch with a single exiting case
@@ -655,20 +961,35 @@ namespace llvm {
/// Return the number of times an exit condition comparing the specified
/// value to zero will execute. If not computable, return CouldNotCompute.
- ExitLimit HowFarToZero(const SCEV *V, const Loop *L, bool IsSubExpr);
+ /// If AllowPredicates is set, this call will try to use a minimal set of
+ /// SCEV predicates in order to return an exact answer.
+ ExitLimit howFarToZero(const SCEV *V, const Loop *L, bool IsSubExpr,
+ bool AllowPredicates = false);
/// Return the number of times an exit condition checking the specified
/// value for nonzero will execute. If not computable, return
/// CouldNotCompute.
- ExitLimit HowFarToNonZero(const SCEV *V, const Loop *L);
+ ExitLimit howFarToNonZero(const SCEV *V, const Loop *L);
/// Return the number of times an exit condition containing the specified
/// less-than comparison will execute. If not computable, return
- /// CouldNotCompute. isSigned specifies whether the less-than is signed.
- ExitLimit HowManyLessThans(const SCEV *LHS, const SCEV *RHS,
- const Loop *L, bool isSigned, bool IsSubExpr);
- ExitLimit HowManyGreaterThans(const SCEV *LHS, const SCEV *RHS,
- const Loop *L, bool isSigned, bool IsSubExpr);
+ /// CouldNotCompute.
+ ///
+ /// \p isSigned specifies whether the less-than is signed.
+ ///
+ /// \p ControlsExit is true when the LHS < RHS condition directly controls
+ /// the branch (loops exits only if condition is true). In this case, we can
+ /// use NoWrapFlags to skip overflow checks.
+ ///
+ /// If \p AllowPredicates is set, this call will try to use a minimal set of
+ /// SCEV predicates in order to return an exact answer.
+ ExitLimit howManyLessThans(const SCEV *LHS, const SCEV *RHS, const Loop *L,
+ bool isSigned, bool ControlsExit,
+ bool AllowPredicates = false);
+
+ ExitLimit howManyGreaterThans(const SCEV *LHS, const SCEV *RHS,
+ const Loop *L, bool isSigned, bool IsSubExpr,
+ bool AllowPredicates = false);
/// 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
@@ -707,12 +1028,18 @@ namespace llvm {
/// Test whether the condition described by Pred, LHS, and RHS is true
/// whenever the condition described by Pred, FoundLHS, and FoundRHS is
- /// true. Utility function used by isImpliedCondOperands.
+ /// true. Utility function used by isImpliedCondOperands. Tries to get
+ /// cases like "X `sgt` 0 => X - 1 `sgt` -1".
bool isImpliedCondOperandsViaRanges(ICmpInst::Predicate Pred,
const SCEV *LHS, const SCEV *RHS,
const SCEV *FoundLHS,
const SCEV *FoundRHS);
+ /// Return true if the condition denoted by \p LHS \p Pred \p RHS is implied
+ /// by a call to \c @llvm.experimental.guard in \p BB.
+ bool isImpliedViaGuard(BasicBlock *BB, ICmpInst::Predicate Pred,
+ const SCEV *LHS, const SCEV *RHS);
+
/// Test whether the condition described by Pred, LHS, and RHS is true
/// whenever the condition described by Pred, FoundLHS, and FoundRHS is
/// true.
@@ -733,8 +1060,8 @@ namespace llvm {
/// Test if the given expression is known to satisfy the condition described
/// by Pred and the known constant ranges of LHS and RHS.
///
- bool isKnownPredicateWithRanges(ICmpInst::Predicate Pred,
- const SCEV *LHS, const SCEV *RHS);
+ bool isKnownPredicateViaConstantRanges(ICmpInst::Predicate Pred,
+ const SCEV *LHS, const SCEV *RHS);
/// Try to prove the condition described by "LHS Pred RHS" by ruling out
/// integer overflow.
@@ -778,6 +1105,9 @@ namespace llvm {
bool proveNoWrapByVaryingStart(const SCEV *Start, const SCEV *Step,
const Loop *L);
+ /// 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);
@@ -793,11 +1123,35 @@ namespace llvm {
bool isMonotonicPredicate(const SCEVAddRecExpr *LHS,
ICmpInst::Predicate Pred, bool &Increasing);
- // 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) would trigger undefined behavior on overflow.
+ /// 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)
+ /// would trigger undefined behavior on overflow.
SCEV::NoWrapFlags getNoWrapFlagsFromUB(const Value *V);
+ /// Return true if the SCEV corresponding to \p I is never poison. Proving
+ /// this is more complex than proving that just \p I is never poison, since
+ /// SCEV commons expressions across control flow, and you can have cases
+ /// like:
+ ///
+ /// idx0 = a + b;
+ /// ptr[idx0] = 100;
+ /// if (<condition>) {
+ /// idx1 = a +nsw b;
+ /// ptr[idx1] = 200;
+ /// }
+ ///
+ /// where the SCEV expression (+ a b) is guaranteed to not be poison (and
+ /// hence not sign-overflow) only if "<condition>" is true. Since both
+ /// `idx0` and `idx1` will be mapped to the same SCEV expression, (+ a b),
+ /// it is not okay to annotate (+ a b) with <nsw> in the above example.
+ bool isSCEVExprNeverPoison(const Instruction *I);
+
+ /// This is like \c isSCEVExprNeverPoison but it specifically works for
+ /// instructions that will get mapped to SCEV add recurrences. Return true
+ /// if \p I will never generate poison under the assumption that \p I is an
+ /// add recurrence on the loop \p L.
+ bool isAddRecNeverPoison(const Instruction *I, const Loop *L);
+
public:
ScalarEvolution(Function &F, TargetLibraryInfo &TLI, AssumptionCache &AC,
DominatorTree &DT, LoopInfo &LI);
@@ -821,6 +1175,17 @@ namespace llvm {
/// return true. For pointer types, this is the pointer-sized integer type.
Type *getEffectiveSCEVType(Type *Ty) const;
+ /// Return true if the SCEV is a scAddRecExpr or it contains
+ /// scAddRecExpr. The result will be cached in HasRecMap.
+ ///
+ bool containsAddRecurrence(const SCEV *S);
+
+ /// Return the Value set from which the SCEV expr is generated.
+ SetVector<Value *> *getSCEVValues(const SCEV *S);
+
+ /// Erase Value from ValueExprMap and ExprValueMap.
+ void eraseValueFromMap(Value *V);
+
/// Return a SCEV expression for the full generality of the specified
/// expression.
const SCEV *getSCEV(Value *V);
@@ -867,7 +1232,7 @@ namespace llvm {
SmallVector<const SCEV *, 4> NewOp(Operands.begin(), Operands.end());
return getAddRecExpr(NewOp, L, Flags);
}
- /// \brief Returns an expression for a GEP
+ /// Returns an expression for a GEP
///
/// \p PointeeType The type used as the basis for the pointer arithmetics
/// \p BaseExpr The expression for the pointer operand.
@@ -885,10 +1250,10 @@ namespace llvm {
const SCEV *getUnknown(Value *V);
const SCEV *getCouldNotCompute();
- /// \brief Return a SCEV for the constant 0 of a specific type.
+ /// Return a SCEV for the constant 0 of a specific type.
const SCEV *getZero(Type *Ty) { return getConstant(Ty, 0); }
- /// \brief Return a SCEV for the constant 1 of a specific type.
+ /// 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
@@ -981,7 +1346,7 @@ namespace llvm {
bool isLoopBackedgeGuardedByCond(const Loop *L, ICmpInst::Predicate Pred,
const SCEV *LHS, const SCEV *RHS);
- /// \brief Returns the maximum trip count of the loop if it is a single-exit
+ /// Returns the maximum trip count of the loop if it is a single-exit
/// loop and we can compute a small maximum for that loop.
///
/// Implemented in terms of the \c getSmallConstantTripCount overload with
@@ -997,7 +1362,7 @@ namespace llvm {
/// prematurely via another branch.
unsigned getSmallConstantTripCount(Loop *L, BasicBlock *ExitingBlock);
- /// \brief Returns the largest constant divisor of the trip count of the
+ /// Returns the largest constant divisor of the trip count of the
/// loop if it is a single-exit loop and we can compute a small maximum for
/// that loop.
///
@@ -1031,6 +1396,13 @@ namespace llvm {
///
const SCEV *getBackedgeTakenCount(const Loop *L);
+ /// Similar to getBackedgeTakenCount, except it will add a set of
+ /// SCEV predicates to Predicates that are required to be true in order for
+ /// the answer to be correct. Predicates can be checked with run-time
+ /// checks and can be used to perform loop versioning.
+ const SCEV *getPredicatedBackedgeTakenCount(const Loop *L,
+ SCEVUnionPredicate &Predicates);
+
/// Similar to getBackedgeTakenCount, except return the least SCEV value
/// that is known never to be less than the actual backedge taken count.
const SCEV *getMaxBackedgeTakenCount(const Loop *L);
@@ -1050,7 +1422,7 @@ namespace llvm {
/// def-use chain linking it to a loop.
void forgetValue(Value *V);
- /// \brief Called when the client has changed the disposition of values in
+ /// Called when the client has changed the disposition of values in
/// this loop.
///
/// We don't have a way to invalidate per-loop dispositions. Clear and
@@ -1154,7 +1526,8 @@ namespace llvm {
const SCEV *getElementSize(Instruction *Inst);
/// Compute the array dimensions Sizes from the set of Terms extracted from
- /// the memory access function of this SCEVAddRecExpr.
+ /// the memory access function of this SCEVAddRecExpr (second step of
+ /// delinearization).
void findArrayDimensions(SmallVectorImpl<const SCEV *> &Terms,
SmallVectorImpl<const SCEV *> &Sizes,
const SCEV *ElementSize) const;
@@ -1162,13 +1535,15 @@ namespace llvm {
void print(raw_ostream &OS) const;
void verify() const;
- /// Collect parametric terms occurring in step expressions.
+ /// Collect parametric terms occurring in step expressions (first step of
+ /// delinearization).
void collectParametricTerms(const SCEV *Expr,
SmallVectorImpl<const SCEV *> &Terms);
- /// Return in Subscripts the access functions for each dimension in Sizes.
+ /// Return in Subscripts the access functions for each dimension in Sizes
+ /// (third step of delinearization).
void computeAccessFunctions(const SCEV *Expr,
SmallVectorImpl<const SCEV *> &Subscripts,
SmallVectorImpl<const SCEV *> &Sizes);
@@ -1251,8 +1626,18 @@ namespace llvm {
const SCEVPredicate *getEqualPredicate(const SCEVUnknown *LHS,
const SCEVConstant *RHS);
- /// Re-writes the SCEV according to the Predicates in \p Preds.
- const SCEV *rewriteUsingPredicate(const SCEV *Scev, SCEVUnionPredicate &A);
+ const SCEVPredicate *
+ getWrapPredicate(const SCEVAddRecExpr *AR,
+ SCEVWrapPredicate::IncrementWrapFlags AddedFlags);
+
+ /// Re-writes the SCEV according to the Predicates in \p A.
+ const SCEV *rewriteUsingPredicate(const SCEV *S, const Loop *L,
+ SCEVUnionPredicate &A);
+ /// Tries to convert the \p S expression to an AddRec expression,
+ /// adding additional predicates to \p Preds as required.
+ const SCEVAddRecExpr *
+ convertSCEVToAddRecWithPredicates(const SCEV *S, const Loop *L,
+ SCEVUnionPredicate &Preds);
private:
/// Compute the backedge taken count knowing the interval difference, the
@@ -1283,31 +1668,26 @@ namespace llvm {
SCEVUnknown *FirstUnknown;
};
- /// \brief Analysis pass that exposes the \c ScalarEvolution for a function.
- class ScalarEvolutionAnalysis {
+ /// Analysis pass that exposes the \c ScalarEvolution for a function.
+ class ScalarEvolutionAnalysis
+ : public AnalysisInfoMixin<ScalarEvolutionAnalysis> {
+ friend AnalysisInfoMixin<ScalarEvolutionAnalysis>;
static char PassID;
public:
typedef ScalarEvolution Result;
- /// \brief Opaque, unique identifier for this analysis pass.
- static void *ID() { return (void *)&PassID; }
-
- /// \brief Provide a name for the analysis for debugging and logging.
- static StringRef name() { return "ScalarEvolutionAnalysis"; }
-
- ScalarEvolution run(Function &F, AnalysisManager<Function> *AM);
+ ScalarEvolution run(Function &F, AnalysisManager<Function> &AM);
};
- /// \brief Printer pass for the \c ScalarEvolutionAnalysis results.
- class ScalarEvolutionPrinterPass {
+ /// Printer pass for the \c ScalarEvolutionAnalysis results.
+ class ScalarEvolutionPrinterPass
+ : public PassInfoMixin<ScalarEvolutionPrinterPass> {
raw_ostream &OS;
public:
explicit ScalarEvolutionPrinterPass(raw_ostream &OS) : OS(OS) {}
- PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM);
-
- static StringRef name() { return "ScalarEvolutionPrinterPass"; }
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
};
class ScalarEvolutionWrapperPass : public FunctionPass {
@@ -1343,42 +1723,81 @@ namespace llvm {
/// - lowers the number of expression rewrites.
class PredicatedScalarEvolution {
public:
- PredicatedScalarEvolution(ScalarEvolution &SE);
+ PredicatedScalarEvolution(ScalarEvolution &SE, Loop &L);
const SCEVUnionPredicate &getUnionPredicate() const;
- /// \brief Returns the SCEV expression of V, in the context of the current
- /// SCEV predicate.
- /// The order of transformations applied on the expression of V returned
- /// by ScalarEvolution is guaranteed to be preserved, even when adding new
- /// predicates.
+
+ /// Returns the SCEV expression of V, in the context of the current SCEV
+ /// predicate. The order of transformations applied on the expression of V
+ /// returned by ScalarEvolution is guaranteed to be preserved, even when
+ /// adding new predicates.
const SCEV *getSCEV(Value *V);
- /// \brief Adds a new predicate.
+
+ /// Get the (predicated) backedge count for the analyzed loop.
+ const SCEV *getBackedgeTakenCount();
+
+ /// Adds a new predicate.
void addPredicate(const SCEVPredicate &Pred);
- /// \brief Returns the ScalarEvolution analysis used.
+
+ /// Attempts to produce an AddRecExpr for V by adding additional SCEV
+ /// predicates. If we can't transform the expression into an AddRecExpr we
+ /// return nullptr and not add additional SCEV predicates to the current
+ /// context.
+ const SCEVAddRecExpr *getAsAddRec(Value *V);
+
+ /// Proves that V doesn't overflow by adding SCEV predicate.
+ void setNoOverflow(Value *V, SCEVWrapPredicate::IncrementWrapFlags Flags);
+
+ /// Returns true if we've proved that V doesn't wrap by means of a SCEV
+ /// predicate.
+ bool hasNoOverflow(Value *V, SCEVWrapPredicate::IncrementWrapFlags Flags);
+
+ /// Returns the ScalarEvolution analysis used.
ScalarEvolution *getSE() const { return &SE; }
+ /// We need to explicitly define the copy constructor because of FlagsMap.
+ PredicatedScalarEvolution(const PredicatedScalarEvolution&);
+
+ /// Print the SCEV mappings done by the Predicated Scalar Evolution.
+ /// The printed text is indented by \p Depth.
+ void print(raw_ostream &OS, unsigned Depth) const;
+
private:
- /// \brief Increments the version number of the predicate.
- /// This needs to be called every time the SCEV predicate changes.
+ /// Increments the version number of the predicate. This needs to be called
+ /// every time the SCEV predicate changes.
void updateGeneration();
+
/// Holds a SCEV and the version number of the SCEV predicate used to
/// perform the rewrite of the expression.
typedef std::pair<unsigned, const SCEV *> RewriteEntry;
+
/// Maps a SCEV to the rewrite result of that SCEV at a certain version
/// number. If this number doesn't match the current Generation, we will
/// need to do a rewrite. To preserve the transformation order of previous
/// rewrites, we will rewrite the previous result instead of the original
/// SCEV.
DenseMap<const SCEV *, RewriteEntry> RewriteMap;
+
+ /// Records what NoWrap flags we've added to a Value *.
+ ValueMap<Value *, SCEVWrapPredicate::IncrementWrapFlags> FlagsMap;
+
/// The ScalarEvolution analysis.
ScalarEvolution &SE;
+
+ /// The analyzed Loop.
+ const Loop &L;
+
/// The SCEVPredicate that forms our context. We will rewrite all
/// expressions assuming that this predicate true.
SCEVUnionPredicate Preds;
+
/// Marks the version of the SCEV predicate used. When rewriting a SCEV
/// expression we mark it with the version of the predicate. We use this to
/// figure out if the predicate has changed from the last rewrite of the
/// SCEV. If so, we need to perform a new rewrite.
unsigned Generation;
+
+ /// The backedge taken count.
+ const SCEV *BackedgeCount;
};
}
diff --git a/include/llvm/Analysis/ScalarEvolutionAliasAnalysis.h b/include/llvm/Analysis/ScalarEvolutionAliasAnalysis.h
index 7bbbf5562047..ac10370b4131 100644
--- a/include/llvm/Analysis/ScalarEvolutionAliasAnalysis.h
+++ b/include/llvm/Analysis/ScalarEvolutionAliasAnalysis.h
@@ -28,8 +28,7 @@ class SCEVAAResult : public AAResultBase<SCEVAAResult> {
ScalarEvolution &SE;
public:
- explicit SCEVAAResult(const TargetLibraryInfo &TLI, ScalarEvolution &SE)
- : AAResultBase(TLI), SE(SE) {}
+ explicit SCEVAAResult(ScalarEvolution &SE) : AAResultBase(), SE(SE) {}
SCEVAAResult(SCEVAAResult &&Arg) : AAResultBase(std::move(Arg)), SE(Arg.SE) {}
AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB);
@@ -39,20 +38,14 @@ private:
};
/// Analysis pass providing a never-invalidated alias analysis result.
-class SCEVAA {
+class SCEVAA : public AnalysisInfoMixin<SCEVAA> {
+ friend AnalysisInfoMixin<SCEVAA>;
+ static char PassID;
+
public:
typedef SCEVAAResult Result;
- /// \brief Opaque, unique identifier for this analysis pass.
- static void *ID() { return (void *)&PassID; }
-
- SCEVAAResult run(Function &F, AnalysisManager<Function> *AM);
-
- /// \brief Provide access to a name for this pass for debugging purposes.
- static StringRef name() { return "SCEVAA"; }
-
-private:
- static char PassID;
+ SCEVAAResult run(Function &F, AnalysisManager<Function> &AM);
};
/// Legacy wrapper pass to provide the SCEVAAResult object.
diff --git a/include/llvm/Analysis/ScalarEvolutionExpander.h b/include/llvm/Analysis/ScalarEvolutionExpander.h
index b9939168a99d..2fa856a32f7d 100644
--- a/include/llvm/Analysis/ScalarEvolutionExpander.h
+++ b/include/llvm/Analysis/ScalarEvolutionExpander.h
@@ -80,9 +80,49 @@ namespace llvm {
/// already in "expanded" form.
bool LSRMode;
- typedef IRBuilder<true, TargetFolder> BuilderType;
+ typedef IRBuilder<TargetFolder> BuilderType;
BuilderType Builder;
+ // RAII object that stores the current insertion point and restores it when
+ // the object is destroyed. This includes the debug location. Duplicated
+ // from InsertPointGuard to add SetInsertPoint() which is used to updated
+ // InsertPointGuards stack when insert points are moved during SCEV
+ // expansion.
+ class SCEVInsertPointGuard {
+ IRBuilderBase &Builder;
+ AssertingVH<BasicBlock> Block;
+ BasicBlock::iterator Point;
+ DebugLoc DbgLoc;
+ SCEVExpander *SE;
+
+ SCEVInsertPointGuard(const SCEVInsertPointGuard &) = delete;
+ SCEVInsertPointGuard &operator=(const SCEVInsertPointGuard &) = delete;
+
+ public:
+ SCEVInsertPointGuard(IRBuilderBase &B, SCEVExpander *SE)
+ : Builder(B), Block(B.GetInsertBlock()), Point(B.GetInsertPoint()),
+ DbgLoc(B.getCurrentDebugLocation()), SE(SE) {
+ SE->InsertPointGuards.push_back(this);
+ }
+
+ ~SCEVInsertPointGuard() {
+ // These guards should always created/destroyed in FIFO order since they
+ // are used to guard lexically scoped blocks of code in
+ // ScalarEvolutionExpander.
+ assert(SE->InsertPointGuards.back() == this);
+ SE->InsertPointGuards.pop_back();
+ Builder.restoreIP(IRBuilderBase::InsertPoint(Block, Point));
+ Builder.SetCurrentDebugLocation(DbgLoc);
+ }
+
+ BasicBlock::iterator GetInsertPoint() const { return Point; }
+ void SetInsertPoint(BasicBlock::iterator I) { Point = I; }
+ };
+
+ /// Stack of pointers to saved insert points, used to keep insert points
+ /// consistent when instructions are moved.
+ SmallVector<SCEVInsertPointGuard *, 8> InsertPointGuards;
+
#ifndef NDEBUG
const char *DebugType;
#endif
@@ -101,6 +141,11 @@ namespace llvm {
#endif
}
+ ~SCEVExpander() {
+ // Make sure the insert point guard stack is consistent.
+ assert(InsertPointGuards.empty());
+ }
+
#ifndef NDEBUG
void setDebugType(const char* s) { DebugType = s; }
#endif
@@ -162,6 +207,15 @@ namespace llvm {
Value *expandEqualPredicate(const SCEVEqualPredicate *Pred,
Instruction *Loc);
+ /// \brief Generates code that evaluates if the \p AR expression will
+ /// overflow.
+ Value *generateOverflowCheck(const SCEVAddRecExpr *AR, Instruction *Loc,
+ bool Signed);
+
+ /// \brief A specialized variant of expandCodeForPredicate, handling the
+ /// case when we are expanding code for a SCEVWrapPredicate.
+ Value *expandWrapPredicate(const SCEVWrapPredicate *P, Instruction *Loc);
+
/// \brief A specialized variant of expandCodeForPredicate, handling the
/// case when we are expanding code for a SCEVUnionPredicate.
Value *expandUnionPredicate(const SCEVUnionPredicate *Pred,
@@ -254,6 +308,9 @@ namespace llvm {
const SCEV *const *op_end,
PointerType *PTy, Type *Ty, Value *V);
+ /// \brief Find a previous Value in ExprValueMap for expand.
+ Value *FindValueInExprValueMap(const SCEV *S, const Instruction *InsertPt);
+
Value *expand(const SCEV *S);
/// \brief Insert code to directly compute the specified SCEV expression
@@ -306,6 +363,11 @@ namespace llvm {
bool &InvertStep);
Value *expandIVInc(PHINode *PN, Value *StepV, const Loop *L,
Type *ExpandTy, Type *IntTy, bool useSubtract);
+
+ void hoistBeforePos(DominatorTree *DT, Instruction *InstToHoist,
+ Instruction *Pos, PHINode *LoopPhi);
+
+ void fixupInsertPoints(Instruction *I);
};
}
diff --git a/include/llvm/Analysis/ScalarEvolutionExpressions.h b/include/llvm/Analysis/ScalarEvolutionExpressions.h
index 16992680577c..ff24cafbe680 100644
--- a/include/llvm/Analysis/ScalarEvolutionExpressions.h
+++ b/include/llvm/Analysis/ScalarEvolutionExpressions.h
@@ -32,9 +32,7 @@ namespace llvm {
scUnknown, scCouldNotCompute
};
- //===--------------------------------------------------------------------===//
- /// SCEVConstant - This class represents a constant integer value.
- ///
+ /// This class represents a constant integer value.
class SCEVConstant : public SCEV {
friend class ScalarEvolution;
@@ -53,9 +51,7 @@ namespace llvm {
}
};
- //===--------------------------------------------------------------------===//
- /// SCEVCastExpr - This is the base class for unary cast operator classes.
- ///
+ /// This is the base class for unary cast operator classes.
class SCEVCastExpr : public SCEV {
protected:
const SCEV *Op;
@@ -76,10 +72,8 @@ namespace llvm {
}
};
- //===--------------------------------------------------------------------===//
- /// SCEVTruncateExpr - This class represents a truncation of an integer value
- /// to a smaller integer value.
- ///
+ /// This class represents a truncation of an integer value to a
+ /// smaller integer value.
class SCEVTruncateExpr : public SCEVCastExpr {
friend class ScalarEvolution;
@@ -93,10 +87,8 @@ namespace llvm {
}
};
- //===--------------------------------------------------------------------===//
- /// SCEVZeroExtendExpr - This class represents a zero extension of a small
- /// integer value to a larger integer value.
- ///
+ /// This class represents a zero extension of a small integer value
+ /// to a larger integer value.
class SCEVZeroExtendExpr : public SCEVCastExpr {
friend class ScalarEvolution;
@@ -110,10 +102,8 @@ namespace llvm {
}
};
- //===--------------------------------------------------------------------===//
- /// SCEVSignExtendExpr - This class represents a sign extension of a small
- /// integer value to a larger integer value.
- ///
+ /// This class represents a sign extension of a small integer value
+ /// to a larger integer value.
class SCEVSignExtendExpr : public SCEVCastExpr {
friend class ScalarEvolution;
@@ -128,10 +118,8 @@ namespace llvm {
};
- //===--------------------------------------------------------------------===//
- /// SCEVNAryExpr - This node is a base class providing common
- /// functionality for n'ary operators.
- ///
+ /// This node is a base class providing common functionality for
+ /// n'ary operators.
class SCEVNAryExpr : public SCEV {
protected:
// Since SCEVs are immutable, ScalarEvolution allocates operand
@@ -166,6 +154,18 @@ namespace llvm {
return (NoWrapFlags)(SubclassData & Mask);
}
+ bool hasNoUnsignedWrap() const {
+ return getNoWrapFlags(FlagNUW) != FlagAnyWrap;
+ }
+
+ bool hasNoSignedWrap() const {
+ return getNoWrapFlags(FlagNSW) != FlagAnyWrap;
+ }
+
+ bool hasNoSelfWrap() const {
+ return getNoWrapFlags(FlagNW) != FlagAnyWrap;
+ }
+
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEV *S) {
return S->getSCEVType() == scAddExpr ||
@@ -176,10 +176,7 @@ namespace llvm {
}
};
- //===--------------------------------------------------------------------===//
- /// SCEVCommutativeExpr - This node is the base class for n'ary commutative
- /// operators.
- ///
+ /// This node is the base class for n'ary commutative operators.
class SCEVCommutativeExpr : public SCEVNAryExpr {
protected:
SCEVCommutativeExpr(const FoldingSetNodeIDRef ID,
@@ -202,9 +199,7 @@ namespace llvm {
};
- //===--------------------------------------------------------------------===//
- /// SCEVAddExpr - This node represents an addition of some number of SCEVs.
- ///
+ /// This node represents an addition of some number of SCEVs.
class SCEVAddExpr : public SCEVCommutativeExpr {
friend class ScalarEvolution;
@@ -227,9 +222,8 @@ namespace llvm {
}
};
- //===--------------------------------------------------------------------===//
- /// SCEVMulExpr - This node represents multiplication of some number of SCEVs.
- ///
+
+ /// This node represents multiplication of some number of SCEVs.
class SCEVMulExpr : public SCEVCommutativeExpr {
friend class ScalarEvolution;
@@ -246,9 +240,7 @@ namespace llvm {
};
- //===--------------------------------------------------------------------===//
- /// SCEVUDivExpr - This class represents a binary unsigned division operation.
- ///
+ /// This class represents a binary unsigned division operation.
class SCEVUDivExpr : public SCEV {
friend class ScalarEvolution;
@@ -277,12 +269,11 @@ namespace llvm {
};
- //===--------------------------------------------------------------------===//
- /// SCEVAddRecExpr - This node represents a polynomial recurrence on the trip
- /// count of the specified loop. This is the primary focus of the
- /// ScalarEvolution framework; all the other SCEV subclasses are mostly just
- /// supporting infrastructure to allow SCEVAddRecExpr expressions to be
- /// created and analyzed.
+ /// This node represents a polynomial recurrence on the trip count
+ /// of the specified loop. This is the primary focus of the
+ /// ScalarEvolution framework; all the other SCEV subclasses are
+ /// mostly just supporting infrastructure to allow SCEVAddRecExpr
+ /// expressions to be created and analyzed.
///
/// All operands of an AddRec are required to be loop invariant.
///
@@ -299,10 +290,10 @@ namespace llvm {
const SCEV *getStart() const { return Operands[0]; }
const Loop *getLoop() const { return L; }
- /// getStepRecurrence - This method constructs and returns the recurrence
- /// indicating how much this expression steps by. If this is a polynomial
- /// of degree N, it returns a chrec of degree N-1.
- /// We cannot determine whether the step recurrence has self-wraparound.
+ /// Constructs and returns the recurrence indicating how much this
+ /// expression steps by. If this is a polynomial of degree N, it
+ /// returns a chrec of degree N-1. We cannot determine whether
+ /// the step recurrence has self-wraparound.
const SCEV *getStepRecurrence(ScalarEvolution &SE) const {
if (isAffine()) return getOperand(1);
return SE.getAddRecExpr(SmallVector<const SCEV *, 3>(op_begin()+1,
@@ -310,17 +301,17 @@ namespace llvm {
getLoop(), FlagAnyWrap);
}
- /// isAffine - Return true if this represents an expression
- /// A + B*x where A and B are loop invariant values.
+ /// Return true if this represents an expression A + B*x where A
+ /// and B are loop invariant values.
bool isAffine() const {
// We know that the start value is invariant. This expression is thus
// affine iff the step is also invariant.
return getNumOperands() == 2;
}
- /// isQuadratic - Return true if this represents an expression
- /// A + B*x + C*x^2 where A, B and C are loop invariant values.
- /// This corresponds to an addrec of the form {L,+,M,+,N}
+ /// Return true if this represents an expression A + B*x + C*x^2
+ /// where A, B and C are loop invariant values. This corresponds
+ /// to an addrec of the form {L,+,M,+,N}
bool isQuadratic() const {
return getNumOperands() == 3;
}
@@ -334,21 +325,21 @@ namespace llvm {
SubclassData |= Flags;
}
- /// evaluateAtIteration - Return the value of this chain of recurrences at
- /// the specified iteration number.
+ /// Return the value of this chain of recurrences at the specified
+ /// iteration number.
const SCEV *evaluateAtIteration(const SCEV *It, ScalarEvolution &SE) const;
- /// getNumIterationsInRange - Return the number of iterations of this loop
- /// that produce values in the specified constant range. Another way of
- /// looking at this is that it returns the first iteration number where the
- /// value is not in the condition, thus computing the exit count. If the
- /// iteration count can't be computed, an instance of SCEVCouldNotCompute is
- /// returned.
- const SCEV *getNumIterationsInRange(ConstantRange Range,
- ScalarEvolution &SE) const;
-
- /// getPostIncExpr - Return an expression representing the value of
- /// this expression one iteration of the loop ahead.
+ /// Return the number of iterations of this loop that produce
+ /// values in the specified constant range. Another way of
+ /// looking at this is that it returns the first iteration number
+ /// where the value is not in the condition, thus computing the
+ /// exit count. If the iteration count can't be computed, an
+ /// instance of SCEVCouldNotCompute is returned.
+ const SCEV *getNumIterationsInRange(const ConstantRange &Range,
+ ScalarEvolution &SE) const;
+
+ /// Return an expression representing the value of this expression
+ /// one iteration of the loop ahead.
const SCEVAddRecExpr *getPostIncExpr(ScalarEvolution &SE) const {
return cast<SCEVAddRecExpr>(SE.getAddExpr(this, getStepRecurrence(SE)));
}
@@ -359,9 +350,7 @@ namespace llvm {
}
};
- //===--------------------------------------------------------------------===//
- /// SCEVSMaxExpr - This class represents a signed maximum selection.
- ///
+ /// This class represents a signed maximum selection.
class SCEVSMaxExpr : public SCEVCommutativeExpr {
friend class ScalarEvolution;
@@ -380,9 +369,7 @@ namespace llvm {
};
- //===--------------------------------------------------------------------===//
- /// SCEVUMaxExpr - This class represents an unsigned maximum selection.
- ///
+ /// This class represents an unsigned maximum selection.
class SCEVUMaxExpr : public SCEVCommutativeExpr {
friend class ScalarEvolution;
@@ -400,11 +387,9 @@ namespace llvm {
}
};
- //===--------------------------------------------------------------------===//
- /// SCEVUnknown - This means that we are dealing with an entirely unknown SCEV
- /// value, and only represent it as its LLVM Value. This is the "bottom"
- /// value for the analysis.
- ///
+ /// This means that we are dealing with an entirely unknown SCEV
+ /// value, and only represent it as its LLVM Value. This is the
+ /// "bottom" value for the analysis.
class SCEVUnknown final : public SCEV, private CallbackVH {
friend class ScalarEvolution;
@@ -412,13 +397,13 @@ namespace llvm {
void deleted() override;
void allUsesReplacedWith(Value *New) override;
- /// SE - The parent ScalarEvolution value. This is used to update
- /// the parent's maps when the value associated with a SCEVUnknown
- /// is deleted or RAUW'd.
+ /// The parent ScalarEvolution value. This is used to update the
+ /// parent's maps when the value associated with a SCEVUnknown is
+ /// deleted or RAUW'd.
ScalarEvolution *SE;
- /// Next - The next pointer in the linked list of all
- /// SCEVUnknown instances owned by a ScalarEvolution.
+ /// The next pointer in the linked list of all SCEVUnknown
+ /// instances owned by a ScalarEvolution.
SCEVUnknown *Next;
SCEVUnknown(const FoldingSetNodeIDRef ID, Value *V,
@@ -428,15 +413,17 @@ namespace llvm {
public:
Value *getValue() const { return getValPtr(); }
- /// isSizeOf, isAlignOf, isOffsetOf - Test whether this is a special
- /// constant representing a type size, alignment, or field offset in
- /// a target-independent manner, and hasn't happened to have been
- /// folded with other operations into something unrecognizable. This
- /// is mainly only useful for pretty-printing and other situations
- /// where it isn't absolutely required for these to succeed.
+ /// @{
+ /// Test whether this is a special constant representing a type
+ /// size, alignment, or field offset in a target-independent
+ /// manner, and hasn't happened to have been folded with other
+ /// operations into something unrecognizable. This is mainly only
+ /// useful for pretty-printing and other situations where it isn't
+ /// absolutely required for these to succeed.
bool isSizeOf(Type *&AllocTy) const;
bool isAlignOf(Type *&AllocTy) const;
bool isOffsetOf(Type *&STy, Constant *&FieldNo) const;
+ /// @}
Type *getType() const { return getValPtr()->getType(); }
@@ -446,8 +433,8 @@ namespace llvm {
}
};
- /// SCEVVisitor - This class defines a simple visitor class that may be used
- /// for various SCEV analysis purposes.
+ /// This class defines a simple visitor class that may be used for
+ /// various SCEV analysis purposes.
template<typename SC, typename RetVal=void>
struct SCEVVisitor {
RetVal visit(const SCEV *S) {
@@ -524,14 +511,10 @@ namespace llvm {
case scMulExpr:
case scSMaxExpr:
case scUMaxExpr:
- case scAddRecExpr: {
- const SCEVNAryExpr *NAry = cast<SCEVNAryExpr>(S);
- for (SCEVNAryExpr::op_iterator I = NAry->op_begin(),
- E = NAry->op_end(); I != E; ++I) {
- push(*I);
- }
+ case scAddRecExpr:
+ for (const auto *Op : cast<SCEVNAryExpr>(S)->operands())
+ push(Op);
break;
- }
case scUDivExpr: {
const SCEVUDivExpr *UDiv = cast<SCEVUDivExpr>(S);
push(UDiv->getLHS());
@@ -697,13 +680,6 @@ namespace llvm {
private:
LoopToScevMapT &Map;
};
-
-/// Applies the Map (Loop -> SCEV) to the given Scev.
-static inline const SCEV *apply(const SCEV *Scev, LoopToScevMapT &Map,
- ScalarEvolution &SE) {
- return SCEVLoopAddRecRewriter::rewrite(Scev, Map, SE);
-}
-
}
#endif
diff --git a/include/llvm/Analysis/ScopedNoAliasAA.h b/include/llvm/Analysis/ScopedNoAliasAA.h
index 175561687157..87b85d4e6635 100644
--- a/include/llvm/Analysis/ScopedNoAliasAA.h
+++ b/include/llvm/Analysis/ScopedNoAliasAA.h
@@ -27,8 +27,7 @@ class ScopedNoAliasAAResult : public AAResultBase<ScopedNoAliasAAResult> {
friend AAResultBase<ScopedNoAliasAAResult>;
public:
- explicit ScopedNoAliasAAResult(const TargetLibraryInfo &TLI)
- : AAResultBase(TLI) {}
+ explicit ScopedNoAliasAAResult() : AAResultBase() {}
ScopedNoAliasAAResult(ScopedNoAliasAAResult &&Arg)
: AAResultBase(std::move(Arg)) {}
@@ -48,20 +47,14 @@ private:
};
/// Analysis pass providing a never-invalidated alias analysis result.
-class ScopedNoAliasAA {
+class ScopedNoAliasAA : public AnalysisInfoMixin<ScopedNoAliasAA> {
+ friend AnalysisInfoMixin<ScopedNoAliasAA>;
+ static char PassID;
+
public:
typedef ScopedNoAliasAAResult Result;
- /// \brief Opaque, unique identifier for this analysis pass.
- static void *ID() { return (void *)&PassID; }
-
- ScopedNoAliasAAResult run(Function &F, AnalysisManager<Function> *AM);
-
- /// \brief Provide access to a name for this pass for debugging purposes.
- static StringRef name() { return "ScopedNoAliasAA"; }
-
-private:
- static char PassID;
+ ScopedNoAliasAAResult run(Function &F, AnalysisManager<Function> &AM);
};
/// Legacy wrapper pass to provide the ScopedNoAliasAAResult object.
diff --git a/include/llvm/Analysis/SparsePropagation.h b/include/llvm/Analysis/SparsePropagation.h
index 2c7f5dd73547..d1a54171d8bd 100644
--- a/include/llvm/Analysis/SparsePropagation.h
+++ b/include/llvm/Analysis/SparsePropagation.h
@@ -17,6 +17,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/IR/BasicBlock.h"
#include <set>
#include <vector>
diff --git a/include/llvm/Analysis/TargetLibraryInfo.def b/include/llvm/Analysis/TargetLibraryInfo.def
index 7798e3c88248..b2a593d67dca 100644
--- a/include/llvm/Analysis/TargetLibraryInfo.def
+++ b/include/llvm/Analysis/TargetLibraryInfo.def
@@ -195,6 +195,11 @@ TLI_DEFINE_STRING_INTERNAL("__memmove_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")
+
+// int __nvvm_reflect(const char *)
+TLI_DEFINE_ENUM_INTERNAL(nvvm_reflect)
+TLI_DEFINE_STRING_INTERNAL("__nvvm_reflect")
+
/// double __sincospi_stret(double x);
TLI_DEFINE_ENUM_INTERNAL(sincospi_stret)
TLI_DEFINE_STRING_INTERNAL("__sincospi_stret")
diff --git a/include/llvm/Analysis/TargetLibraryInfo.h b/include/llvm/Analysis/TargetLibraryInfo.h
index 7becdf033dd2..7efa6f059707 100644
--- a/include/llvm/Analysis/TargetLibraryInfo.h
+++ b/include/llvm/Analysis/TargetLibraryInfo.h
@@ -11,15 +11,17 @@
#define LLVM_ANALYSIS_TARGETLIBRARYINFO_H
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/Triple.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
#include "llvm/Pass.h"
namespace llvm {
-/// VecDesc - Describes a possible vectorization of a function.
+template <typename T> class ArrayRef;
+
+/// Describes a possible vectorization of a function.
/// Function 'VectorFnName' is equivalent to 'ScalarFnName' vectorized
/// by a factor 'VectorizationFactor'.
struct VecDesc {
@@ -27,7 +29,6 @@ struct VecDesc {
const char *VectorFnName;
unsigned VectorizationFactor;
};
-class PreservedAnalyses;
namespace LibFunc {
enum Func {
@@ -38,7 +39,7 @@ class PreservedAnalyses;
};
}
-/// \brief Implementation of the target library information.
+/// Implementation of the target library information.
///
/// This class constructs tables that hold the target library information and
/// make it available. However, it is somewhat expensive to compute and only
@@ -70,8 +71,13 @@ class TargetLibraryInfoImpl {
/// on VectorFnName rather than ScalarFnName.
std::vector<VecDesc> ScalarDescs;
+ /// Return true if the function type FTy is valid for the library function
+ /// F, regardless of whether the function is available.
+ bool isValidProtoForLibFunc(const FunctionType &FTy, LibFunc::Func F,
+ const DataLayout *DL) const;
+
public:
- /// \brief List of known vector-functions libraries.
+ /// List of known vector-functions libraries.
///
/// The vector-functions library defines, which functions are vectorizable
/// and with which factor. The library can be specified by either frontend,
@@ -92,24 +98,31 @@ public:
TargetLibraryInfoImpl &operator=(const TargetLibraryInfoImpl &TLI);
TargetLibraryInfoImpl &operator=(TargetLibraryInfoImpl &&TLI);
- /// \brief Searches for a particular function name.
+ /// Searches for a particular function name.
///
/// If it is one of the known library functions, return true and set F to the
/// corresponding value.
bool getLibFunc(StringRef funcName, LibFunc::Func &F) const;
- /// \brief Forces a function to be marked as unavailable.
+ /// Searches for a particular function name, also checking that its type is
+ /// valid for the library function matching that name.
+ ///
+ /// If it is one of the known library functions, return true and set F to the
+ /// corresponding value.
+ bool getLibFunc(const Function &FDecl, LibFunc::Func &F) const;
+
+ /// Forces a function to be marked as unavailable.
void setUnavailable(LibFunc::Func F) {
setState(F, Unavailable);
}
- /// \brief Forces a function to be marked as available.
+ /// Forces a function to be marked as available.
void setAvailable(LibFunc::Func F) {
setState(F, StandardName);
}
- /// \brief Forces a function to be marked as available and provide an
- /// alternate name that must be used.
+ /// Forces a function to be marked as available and provide an alternate name
+ /// that must be used.
void setAvailableWithName(LibFunc::Func F, StringRef Name) {
if (StandardNames[F] != Name) {
setState(F, CustomName);
@@ -120,48 +133,47 @@ public:
}
}
- /// \brief Disables all builtins.
+ /// Disables all builtins.
///
/// This can be used for options like -fno-builtin.
void disableAllFunctions();
- /// addVectorizableFunctions - Add a set of scalar -> vector mappings,
- /// queryable via getVectorizedFunction and getScalarizedFunction.
+ /// Add a set of scalar -> vector mappings, queryable via
+ /// getVectorizedFunction and getScalarizedFunction.
void addVectorizableFunctions(ArrayRef<VecDesc> Fns);
/// Calls addVectorizableFunctions with a known preset of functions for the
/// given vector library.
void addVectorizableFunctionsFromVecLib(enum VectorLibrary VecLib);
- /// isFunctionVectorizable - Return true if the function F has a
- /// vector equivalent with vectorization factor VF.
+ /// Return true if the function F has a vector equivalent with vectorization
+ /// factor VF.
bool isFunctionVectorizable(StringRef F, unsigned VF) const {
return !getVectorizedFunction(F, VF).empty();
}
- /// isFunctionVectorizable - Return true if the function F has a
- /// vector equivalent with any vectorization factor.
+ /// Return true if the function F has a vector equivalent with any
+ /// vectorization factor.
bool isFunctionVectorizable(StringRef F) const;
- /// getVectorizedFunction - Return the name of the equivalent of
- /// F, vectorized with factor VF. If no such mapping exists,
- /// return the empty string.
+ /// Return the name of the equivalent of F, vectorized with factor VF. If no
+ /// such mapping exists, return the empty string.
StringRef getVectorizedFunction(StringRef F, unsigned VF) const;
- /// isFunctionScalarizable - Return true if the function F has a
- /// scalar equivalent, and set VF to be the vectorization factor.
+ /// Return true if the function F has a scalar equivalent, and set VF to be
+ /// the vectorization factor.
bool isFunctionScalarizable(StringRef F, unsigned &VF) const {
return !getScalarizedFunction(F, VF).empty();
}
- /// getScalarizedFunction - Return the name of the equivalent of
- /// F, scalarized. If no such mapping exists, return the empty string.
+ /// Return the name of the equivalent of F, scalarized. If no such mapping
+ /// exists, return the empty string.
///
/// Set VF to the vectorization factor.
StringRef getScalarizedFunction(StringRef F, unsigned &VF) const;
};
-/// \brief Provides information about what library functions are available for
+/// Provides information about what library functions are available for
/// the current target.
///
/// This both allows optimizations to handle them specially and frontends to
@@ -187,7 +199,7 @@ public:
return *this;
}
- /// \brief Searches for a particular function name.
+ /// Searches for a particular function name.
///
/// If it is one of the known library functions, return true and set F to the
/// corresponding value.
@@ -195,7 +207,11 @@ public:
return Impl->getLibFunc(funcName, F);
}
- /// \brief Tests whether a library function is available.
+ bool getLibFunc(const Function &FDecl, LibFunc::Func &F) const {
+ return Impl->getLibFunc(FDecl, F);
+ }
+
+ /// Tests whether a library function is available.
bool has(LibFunc::Func F) const {
return Impl->getState(F) != TargetLibraryInfoImpl::Unavailable;
}
@@ -209,8 +225,8 @@ public:
return Impl->getVectorizedFunction(F, VF);
}
- /// \brief Tests if the function is both available and a candidate for
- /// optimized code generation.
+ /// Tests if the function is both available and a candidate for optimized code
+ /// generation.
bool hasOptimizedCodeGen(LibFunc::Func F) const {
if (Impl->getState(F) == TargetLibraryInfoImpl::Unavailable)
return false;
@@ -251,31 +267,28 @@ public:
return Impl->CustomNames.find(F)->second;
}
- /// \brief Handle invalidation from the pass manager.
+ /// Handle invalidation from the pass manager.
///
/// If we try to invalidate this info, just return false. It cannot become
/// invalid even if the module changes.
bool invalidate(Module &, const PreservedAnalyses &) { return false; }
};
-/// \brief Analysis pass providing the \c TargetLibraryInfo.
+/// Analysis pass providing the \c TargetLibraryInfo.
///
/// Note that this pass's result cannot be invalidated, it is immutable for the
/// life of the module.
-class TargetLibraryAnalysis {
+class TargetLibraryAnalysis : public AnalysisInfoMixin<TargetLibraryAnalysis> {
public:
typedef TargetLibraryInfo Result;
- /// \brief Opaque, unique identifier for this analysis pass.
- static void *ID() { return (void *)&PassID; }
-
- /// \brief Default construct the library analysis.
+ /// Default construct the library analysis.
///
/// This will use the module's triple to construct the library info for that
/// module.
TargetLibraryAnalysis() {}
- /// \brief Construct a library analysis with preset info.
+ /// Construct a library analysis with preset info.
///
/// This will directly copy the preset info into the result without
/// consulting the module's triple.
@@ -291,20 +304,18 @@ public:
return *this;
}
- TargetLibraryInfo run(Module &M);
- TargetLibraryInfo run(Function &F);
-
- /// \brief Provide access to a name for this pass for debugging purposes.
- static StringRef name() { return "TargetLibraryAnalysis"; }
+ TargetLibraryInfo run(Module &M, ModuleAnalysisManager &);
+ TargetLibraryInfo run(Function &F, FunctionAnalysisManager &);
private:
+ friend AnalysisInfoMixin<TargetLibraryAnalysis>;
static char PassID;
Optional<TargetLibraryInfoImpl> PresetInfoImpl;
StringMap<std::unique_ptr<TargetLibraryInfoImpl>> Impls;
- TargetLibraryInfoImpl &lookupInfoImpl(Triple T);
+ TargetLibraryInfoImpl &lookupInfoImpl(const Triple &T);
};
class TargetLibraryInfoWrapperPass : public ImmutablePass {
diff --git a/include/llvm/Analysis/TargetTransformInfo.h b/include/llvm/Analysis/TargetTransformInfo.h
index 3913cc3f107c..7570d22a803c 100644
--- a/include/llvm/Analysis/TargetTransformInfo.h
+++ b/include/llvm/Analysis/TargetTransformInfo.h
@@ -25,6 +25,8 @@
#include "llvm/ADT/Optional.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/Operator.h"
+#include "llvm/IR/PassManager.h"
#include "llvm/Pass.h"
#include "llvm/Support/DataTypes.h"
#include <functional>
@@ -34,7 +36,6 @@ namespace llvm {
class Function;
class GlobalValue;
class Loop;
-class PreservedAnalyses;
class Type;
class User;
class Value;
@@ -165,6 +166,14 @@ public:
/// This overload allows specifying a set of candidate argument values.
int getCallCost(const Function *F, ArrayRef<const Value *> Arguments) const;
+ /// \returns A value by which our inlining threshold should be multiplied.
+ /// This is primarily used to bump up the inlining threshold wholesale on
+ /// targets where calls are unusually expensive.
+ ///
+ /// TODO: This is a rather blunt instrument. Perhaps altering the costs of
+ /// individual classes of instructions would be better.
+ unsigned getInliningThresholdMultiplier() const;
+
/// \brief Estimate the cost of an intrinsic when lowered.
///
/// Mirrors the \c getCallCost method but uses an intrinsic identifier.
@@ -260,6 +269,10 @@ public:
// (set to UINT_MAX to disable). This does not apply in cases where the
// loop is being fully unrolled.
unsigned MaxCount;
+ /// Set the maximum unrolling factor for full unrolling. Like MaxCount, but
+ /// applies even if full unrolling is selected. This allows a target to fall
+ /// back to Partial unrolling if full unrolling is above FullUnrollMaxCount.
+ unsigned FullUnrollMaxCount;
/// Allow partial unrolling (unrolling of loops to expand the size of the
/// loop body, not only to eliminate small constant-trip-count loops).
bool Partial;
@@ -267,9 +280,14 @@ public:
/// loop body even when the number of loop iterations is not known at
/// compile time).
bool Runtime;
+ /// Allow generation of a loop remainder (extra iterations after unroll).
+ bool AllowRemainder;
/// Allow emitting expensive instructions (such as divisions) when computing
/// the trip count of a loop for runtime unrolling.
bool AllowExpensiveTripCount;
+ /// Apply loop unroll on any kind of loop
+ /// (mainly to loops that fail runtime unrolling).
+ bool Force;
};
/// \brief Get target-customized preferences for the generic loop unrolling
@@ -313,8 +331,7 @@ public:
unsigned AddrSpace = 0) const;
/// \brief Return true if the target supports masked load/store
- /// AVX2 and AVX-512 targets allow masks for consecutive load and store for
- /// 32 and 64 bit elements.
+ /// AVX2 and AVX-512 targets allow masks for consecutive load and store
bool isLegalMaskedStore(Type *DataType) const;
bool isLegalMaskedLoad(Type *DataType) const;
@@ -362,6 +379,20 @@ public:
/// \brief Enable matching of interleaved access groups.
bool enableInterleavedAccessVectorization() const;
+ /// \brief Indicate that it is potentially unsafe to automatically vectorize
+ /// floating-point operations because the semantics of vector and scalar
+ /// floating-point semantics may differ. For example, ARM NEON v7 SIMD math
+ /// does not support IEEE-754 denormal numbers, while depending on the
+ /// platform, scalar floating-point math does.
+ /// This applies to floating-point math operations and calls, not memory
+ /// operations, shuffles, or casts.
+ bool isFPVectorizationPotentiallyUnsafe() const;
+
+ /// \brief Determine if the target supports unaligned memory accesses.
+ bool allowsMisalignedMemoryAccesses(unsigned BitWidth, unsigned AddressSpace = 0,
+ unsigned Alignment = 1,
+ bool *Fast = nullptr) const;
+
/// \brief Return hardware support for population count.
PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) const;
@@ -383,6 +414,16 @@ public:
Type *Ty) const;
int getIntImmCost(Intrinsic::ID IID, unsigned Idx, const APInt &Imm,
Type *Ty) const;
+
+ /// \brief Return the expected cost for the given integer when optimising
+ /// for size. This is different than the other integer immediate cost
+ /// functions in that it is subtarget agnostic. This is useful when you e.g.
+ /// target one ISA such as Aarch32 but smaller encodings could be possible
+ /// with another such as Thumb. This return value is used as a penalty when
+ /// the total costs for a constant is calculated (the bigger the cost, the
+ /// more beneficial constant hoisting is).
+ int getIntImmCodeSizeCost(unsigned Opc, unsigned Idx, const APInt &Imm,
+ Type *Ty) const;
/// @}
/// \name Vector Target Information
@@ -416,6 +457,27 @@ public:
/// \return The width of the largest scalar or vector register type.
unsigned getRegisterBitWidth(bool Vector) const;
+ /// \return The bitwidth of the largest vector type that should be used to
+ /// load/store in the given address space.
+ unsigned getLoadStoreVecRegBitWidth(unsigned AddrSpace) const;
+
+ /// \return The size of a cache line in bytes.
+ unsigned getCacheLineSize() const;
+
+ /// \return How much before a load we should place the prefetch instruction.
+ /// This is currently measured in number of instructions.
+ unsigned getPrefetchDistance() const;
+
+ /// \return Some HW prefetchers can handle accesses up to a certain constant
+ /// stride. This is the minimum stride in bytes where it makes sense to start
+ /// adding SW prefetches. The default is 1, i.e. prefetch with any stride.
+ unsigned getMinPrefetchStride() const;
+
+ /// \return The maximum number of iterations to prefetch ahead. If the
+ /// required number of iterations is more than this number, no prefetching is
+ /// performed.
+ unsigned getMaxPrefetchIterationsAhead() const;
+
/// \return The maximum interleave factor that any transform should try to
/// perform for this target. This number depends on the level of parallelism
/// and the number of execution units in the CPU.
@@ -438,6 +500,11 @@ public:
/// zext, etc.
int getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) const;
+ /// \return The expected cost of a sign- or zero-extended vector extract. Use
+ /// -1 to indicate that there is no information about the index value.
+ int getExtractWithExtendCost(unsigned Opcode, Type *Dst, VectorType *VecTy,
+ unsigned Index = -1) const;
+
/// \return The expected cost of control-flow related instructions such as
/// Phi, Ret, Br.
int getCFInstrCost(unsigned Opcode) const;
@@ -497,11 +564,11 @@ public:
/// \returns The cost of Intrinsic instructions. Types analysis only.
int getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
- ArrayRef<Type *> Tys) const;
+ ArrayRef<Type *> Tys, FastMathFlags FMF) const;
/// \returns The cost of Intrinsic instructions. Analyses the real arguments.
int getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
- ArrayRef<Value *> Args) const;
+ ArrayRef<Value *> Args, FastMathFlags FMF) const;
/// \returns The cost of Call instructions.
int getCallInstrCost(Function *F, Type *RetTy, ArrayRef<Type *> Tys) const;
@@ -569,6 +636,7 @@ public:
virtual int getCallCost(const Function *F, int NumArgs) = 0;
virtual int getCallCost(const Function *F,
ArrayRef<const Value *> Arguments) = 0;
+ virtual unsigned getInliningThresholdMultiplier() = 0;
virtual int getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
ArrayRef<Type *> ParamTys) = 0;
virtual int getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
@@ -599,9 +667,16 @@ public:
virtual bool shouldBuildLookupTables() = 0;
virtual bool enableAggressiveInterleaving(bool LoopHasReductions) = 0;
virtual bool enableInterleavedAccessVectorization() = 0;
+ virtual bool isFPVectorizationPotentiallyUnsafe() = 0;
+ virtual bool allowsMisalignedMemoryAccesses(unsigned BitWidth,
+ unsigned AddressSpace,
+ unsigned Alignment,
+ bool *Fast) = 0;
virtual PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) = 0;
virtual bool haveFastSqrt(Type *Ty) = 0;
virtual int getFPOpCost(Type *Ty) = 0;
+ virtual int getIntImmCodeSizeCost(unsigned Opc, unsigned Idx, const APInt &Imm,
+ Type *Ty) = 0;
virtual int getIntImmCost(const APInt &Imm, Type *Ty) = 0;
virtual int getIntImmCost(unsigned Opc, unsigned Idx, const APInt &Imm,
Type *Ty) = 0;
@@ -609,6 +684,11 @@ public:
Type *Ty) = 0;
virtual unsigned getNumberOfRegisters(bool Vector) = 0;
virtual unsigned getRegisterBitWidth(bool Vector) = 0;
+ virtual unsigned getLoadStoreVecRegBitWidth(unsigned AddrSpace) = 0;
+ virtual unsigned getCacheLineSize() = 0;
+ virtual unsigned getPrefetchDistance() = 0;
+ virtual unsigned getMinPrefetchStride() = 0;
+ virtual unsigned getMaxPrefetchIterationsAhead() = 0;
virtual unsigned getMaxInterleaveFactor(unsigned VF) = 0;
virtual unsigned
getArithmeticInstrCost(unsigned Opcode, Type *Ty, OperandValueKind Opd1Info,
@@ -618,6 +698,8 @@ public:
virtual int getShuffleCost(ShuffleKind Kind, Type *Tp, int Index,
Type *SubTp) = 0;
virtual int getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) = 0;
+ virtual int getExtractWithExtendCost(unsigned Opcode, Type *Dst,
+ VectorType *VecTy, unsigned Index) = 0;
virtual int getCFInstrCost(unsigned Opcode) = 0;
virtual int getCmpSelInstrCost(unsigned Opcode, Type *ValTy,
Type *CondTy) = 0;
@@ -639,9 +721,11 @@ public:
virtual int getReductionCost(unsigned Opcode, Type *Ty,
bool IsPairwiseForm) = 0;
virtual int getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
- ArrayRef<Type *> Tys) = 0;
+ ArrayRef<Type *> Tys,
+ FastMathFlags FMF) = 0;
virtual int getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
- ArrayRef<Value *> Args) = 0;
+ ArrayRef<Value *> Args,
+ FastMathFlags FMF) = 0;
virtual int getCallInstrCost(Function *F, Type *RetTy,
ArrayRef<Type *> Tys) = 0;
virtual unsigned getNumberOfParts(Type *Tp) = 0;
@@ -684,6 +768,9 @@ public:
ArrayRef<const Value *> Arguments) override {
return Impl.getCallCost(F, Arguments);
}
+ unsigned getInliningThresholdMultiplier() override {
+ return Impl.getInliningThresholdMultiplier();
+ }
int getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
ArrayRef<Type *> ParamTys) override {
return Impl.getIntrinsicCost(IID, RetTy, ParamTys);
@@ -751,6 +838,14 @@ public:
bool enableInterleavedAccessVectorization() override {
return Impl.enableInterleavedAccessVectorization();
}
+ bool isFPVectorizationPotentiallyUnsafe() override {
+ return Impl.isFPVectorizationPotentiallyUnsafe();
+ }
+ bool allowsMisalignedMemoryAccesses(unsigned BitWidth, unsigned AddressSpace,
+ unsigned Alignment, bool *Fast) override {
+ return Impl.allowsMisalignedMemoryAccesses(BitWidth, AddressSpace,
+ Alignment, Fast);
+ }
PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) override {
return Impl.getPopcntSupport(IntTyWidthInBit);
}
@@ -758,6 +853,10 @@ public:
int getFPOpCost(Type *Ty) override { return Impl.getFPOpCost(Ty); }
+ int getIntImmCodeSizeCost(unsigned Opc, unsigned Idx, const APInt &Imm,
+ Type *Ty) override {
+ return Impl.getIntImmCodeSizeCost(Opc, Idx, Imm, Ty);
+ }
int getIntImmCost(const APInt &Imm, Type *Ty) override {
return Impl.getIntImmCost(Imm, Ty);
}
@@ -775,6 +874,21 @@ public:
unsigned getRegisterBitWidth(bool Vector) override {
return Impl.getRegisterBitWidth(Vector);
}
+
+ unsigned getLoadStoreVecRegBitWidth(unsigned AddrSpace) override {
+ return Impl.getLoadStoreVecRegBitWidth(AddrSpace);
+ }
+
+ unsigned getCacheLineSize() override {
+ return Impl.getCacheLineSize();
+ }
+ unsigned getPrefetchDistance() override { return Impl.getPrefetchDistance(); }
+ unsigned getMinPrefetchStride() override {
+ return Impl.getMinPrefetchStride();
+ }
+ unsigned getMaxPrefetchIterationsAhead() override {
+ return Impl.getMaxPrefetchIterationsAhead();
+ }
unsigned getMaxInterleaveFactor(unsigned VF) override {
return Impl.getMaxInterleaveFactor(VF);
}
@@ -793,6 +907,10 @@ public:
int getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) override {
return Impl.getCastInstrCost(Opcode, Dst, Src);
}
+ int getExtractWithExtendCost(unsigned Opcode, Type *Dst, VectorType *VecTy,
+ unsigned Index) override {
+ return Impl.getExtractWithExtendCost(Opcode, Dst, VecTy, Index);
+ }
int getCFInstrCost(unsigned Opcode) override {
return Impl.getCFInstrCost(Opcode);
}
@@ -826,13 +944,14 @@ public:
bool IsPairwiseForm) override {
return Impl.getReductionCost(Opcode, Ty, IsPairwiseForm);
}
- int getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
- ArrayRef<Type *> Tys) override {
- return Impl.getIntrinsicInstrCost(ID, RetTy, Tys);
+ int getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, ArrayRef<Type *> Tys,
+ FastMathFlags FMF) override {
+ return Impl.getIntrinsicInstrCost(ID, RetTy, Tys, FMF);
}
int getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
- ArrayRef<Value *> Args) override {
- return Impl.getIntrinsicInstrCost(ID, RetTy, Args);
+ ArrayRef<Value *> Args,
+ FastMathFlags FMF) override {
+ return Impl.getIntrinsicInstrCost(ID, RetTy, Args, FMF);
}
int getCallInstrCost(Function *F, Type *RetTy,
ArrayRef<Type *> Tys) override {
@@ -876,16 +995,10 @@ TargetTransformInfo::TargetTransformInfo(T Impl)
/// is done in a subtarget specific way and LLVM supports compiling different
/// functions targeting different subtargets in order to support runtime
/// dispatch according to the observed subtarget.
-class TargetIRAnalysis {
+class TargetIRAnalysis : public AnalysisInfoMixin<TargetIRAnalysis> {
public:
typedef TargetTransformInfo Result;
- /// \brief Opaque, unique identifier for this analysis pass.
- static void *ID() { return (void *)&PassID; }
-
- /// \brief Provide access to a name for this pass for debugging purposes.
- static StringRef name() { return "TargetIRAnalysis"; }
-
/// \brief Default construct a target IR analysis.
///
/// This will use the module's datalayout to construct a baseline
@@ -912,9 +1025,10 @@ public:
return *this;
}
- Result run(const Function &F);
+ Result run(const Function &F, AnalysisManager<Function> &);
private:
+ friend AnalysisInfoMixin<TargetIRAnalysis>;
static char PassID;
/// \brief The callback used to produce a result.
diff --git a/include/llvm/Analysis/TargetTransformInfoImpl.h b/include/llvm/Analysis/TargetTransformInfoImpl.h
index 43815234051e..a97624bc2ab0 100644
--- a/include/llvm/Analysis/TargetTransformInfoImpl.h
+++ b/include/llvm/Analysis/TargetTransformInfoImpl.h
@@ -102,8 +102,8 @@ public:
}
}
- unsigned getGEPCost(Type *PointeeType, const Value *Ptr,
- ArrayRef<const Value *> Operands) {
+ int getGEPCost(Type *PointeeType, const Value *Ptr,
+ ArrayRef<const Value *> Operands) {
// 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)
@@ -128,6 +128,8 @@ public:
return TTI::TCC_Basic * (NumArgs + 1);
}
+ unsigned getInliningThresholdMultiplier() { return 1; }
+
unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
ArrayRef<Type *> ParamTys) {
switch (IID) {
@@ -240,6 +242,13 @@ public:
bool enableInterleavedAccessVectorization() { return false; }
+ bool isFPVectorizationPotentiallyUnsafe() { return false; }
+
+ bool allowsMisalignedMemoryAccesses(unsigned BitWidth,
+ unsigned AddressSpace,
+ unsigned Alignment,
+ bool *Fast) { return false; }
+
TTI::PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) {
return TTI::PSK_Software;
}
@@ -248,6 +257,11 @@ public:
unsigned getFPOpCost(Type *Ty) { return TargetTransformInfo::TCC_Basic; }
+ int getIntImmCodeSizeCost(unsigned Opcode, unsigned Idx, const APInt &Imm,
+ Type *Ty) {
+ return 0;
+ }
+
unsigned getIntImmCost(const APInt &Imm, Type *Ty) { return TTI::TCC_Basic; }
unsigned getIntImmCost(unsigned Opcode, unsigned Idx, const APInt &Imm,
@@ -264,6 +278,16 @@ public:
unsigned getRegisterBitWidth(bool Vector) { return 32; }
+ unsigned getLoadStoreVecRegBitWidth(unsigned AddrSpace) { return 128; }
+
+ unsigned getCacheLineSize() { return 0; }
+
+ unsigned getPrefetchDistance() { return 0; }
+
+ unsigned getMinPrefetchStride() { return 1; }
+
+ unsigned getMaxPrefetchIterationsAhead() { return UINT_MAX; }
+
unsigned getMaxInterleaveFactor(unsigned VF) { return 1; }
unsigned getArithmeticInstrCost(unsigned Opcode, Type *Ty,
@@ -281,6 +305,11 @@ public:
unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) { return 1; }
+ unsigned getExtractWithExtendCost(unsigned Opcode, Type *Dst,
+ VectorType *VecTy, unsigned Index) {
+ return 1;
+ }
+
unsigned getCFInstrCost(unsigned Opcode) { return 1; }
unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy) {
@@ -316,11 +345,11 @@ public:
}
unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
- ArrayRef<Type *> Tys) {
+ ArrayRef<Type *> Tys, FastMathFlags FMF) {
return 1;
}
unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
- ArrayRef<Value *> Args) {
+ ArrayRef<Value *> Args, FastMathFlags FMF) {
return 1;
}
@@ -404,8 +433,8 @@ public:
using BaseT::getGEPCost;
- unsigned getGEPCost(Type *PointeeType, const Value *Ptr,
- ArrayRef<const Value *> Operands) {
+ int getGEPCost(Type *PointeeType, const Value *Ptr,
+ ArrayRef<const Value *> Operands) {
const GlobalValue *BaseGV = nullptr;
if (Ptr != nullptr) {
// TODO: will remove this when pointers have an opaque type.
@@ -421,7 +450,7 @@ public:
// Assumes the address space is 0 when Ptr is nullptr.
unsigned AS =
(Ptr == nullptr ? 0 : Ptr->getType()->getPointerAddressSpace());
- auto GTI = gep_type_begin(PointerType::get(PointeeType, AS), Operands);
+ auto GTI = gep_type_begin(PointeeType, AS, Operands);
for (auto I = Operands.begin(); I != Operands.end(); ++I, ++GTI) {
// We assume that the cost of Scalar GEP with constant index and the
// cost of Vector GEP with splat constant index are the same.
diff --git a/include/llvm/Analysis/TypeBasedAliasAnalysis.h b/include/llvm/Analysis/TypeBasedAliasAnalysis.h
index 7b44ac73f1fa..229b0f97b983 100644
--- a/include/llvm/Analysis/TypeBasedAliasAnalysis.h
+++ b/include/llvm/Analysis/TypeBasedAliasAnalysis.h
@@ -27,8 +27,7 @@ class TypeBasedAAResult : public AAResultBase<TypeBasedAAResult> {
friend AAResultBase<TypeBasedAAResult>;
public:
- explicit TypeBasedAAResult(const TargetLibraryInfo &TLI)
- : AAResultBase(TLI) {}
+ explicit TypeBasedAAResult() {}
TypeBasedAAResult(TypeBasedAAResult &&Arg) : AAResultBase(std::move(Arg)) {}
/// Handle invalidation events from the new pass manager.
@@ -49,20 +48,14 @@ private:
};
/// Analysis pass providing a never-invalidated alias analysis result.
-class TypeBasedAA {
+class TypeBasedAA : public AnalysisInfoMixin<TypeBasedAA> {
+ friend AnalysisInfoMixin<TypeBasedAA>;
+ static char PassID;
+
public:
typedef TypeBasedAAResult Result;
- /// \brief Opaque, unique identifier for this analysis pass.
- static void *ID() { return (void *)&PassID; }
-
- TypeBasedAAResult run(Function &F, AnalysisManager<Function> *AM);
-
- /// \brief Provide access to a name for this pass for debugging purposes.
- static StringRef name() { return "TypeBasedAA"; }
-
-private:
- static char PassID;
+ TypeBasedAAResult run(Function &F, AnalysisManager<Function> &AM);
};
/// Legacy wrapper pass to provide the TypeBasedAAResult object.
diff --git a/include/llvm/Analysis/TypeMetadataUtils.h b/include/llvm/Analysis/TypeMetadataUtils.h
new file mode 100644
index 000000000000..c3f688f5d7f1
--- /dev/null
+++ b/include/llvm/Analysis/TypeMetadataUtils.h
@@ -0,0 +1,45 @@
+//===- TypeMetadataUtils.h - Utilities related to type metadata --*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains functions that make it easier to manipulate type metadata
+// for devirtualization.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ANALYSIS_TYPEMETADATAUTILS_H
+#define LLVM_ANALYSIS_TYPEMETADATAUTILS_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/CallSite.h"
+
+namespace llvm {
+
+/// A call site that could be devirtualized.
+struct DevirtCallSite {
+ /// The offset from the address point to the virtual function.
+ uint64_t Offset;
+ /// The call site itself.
+ CallSite CS;
+};
+
+/// Given a call to the intrinsic @llvm.type.test, find all devirtualizable
+/// call sites based on the call and return them in DevirtCalls.
+void findDevirtualizableCallsForTypeTest(
+ SmallVectorImpl<DevirtCallSite> &DevirtCalls,
+ SmallVectorImpl<CallInst *> &Assumes, CallInst *CI);
+
+/// Given a call to the intrinsic @llvm.type.checked.load, find all
+/// devirtualizable call sites based on the call and return them in DevirtCalls.
+void findDevirtualizableCallsForTypeCheckedLoad(
+ SmallVectorImpl<DevirtCallSite> &DevirtCalls,
+ SmallVectorImpl<Instruction *> &LoadedPtrs,
+ SmallVectorImpl<Instruction *> &Preds, bool &HasNonCallUses, CallInst *CI);
+}
+
+#endif
diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h
index 8e0291068472..2c6221d4933f 100644
--- a/include/llvm/Analysis/ValueTracking.h
+++ b/include/llvm/Analysis/ValueTracking.h
@@ -15,17 +15,20 @@
#ifndef LLVM_ANALYSIS_VALUETRACKING_H
#define LLVM_ANALYSIS_VALUETRACKING_H
-#include "llvm/ADT/ArrayRef.h"
+#include "llvm/IR/CallSite.h"
#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/Instruction.h"
+#include "llvm/IR/IntrinsicInst.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
+template <typename T> class ArrayRef;
class APInt;
class AddOperator;
class AssumptionCache;
class DataLayout;
class DominatorTree;
+ class GEPOperator;
class Instruction;
class Loop;
class LoopInfo;
@@ -34,6 +37,10 @@ namespace llvm {
class TargetLibraryInfo;
class Value;
+ namespace Intrinsic {
+ enum ID : unsigned;
+ }
+
/// Determine which bits of V are known to be either zero or one and return
/// them in the KnownZero/KnownOne bit sets.
///
@@ -58,29 +65,29 @@ namespace llvm {
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
- /// ComputeSignBit - Determine whether the sign bit is known to be zero or
- /// one. Convenience wrapper around computeKnownBits.
+ /// Determine whether the sign bit is known to be zero or one. Convenience
+ /// wrapper around computeKnownBits.
void ComputeSignBit(Value *V, bool &KnownZero, bool &KnownOne,
const DataLayout &DL, unsigned Depth = 0,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
- /// isKnownToBeAPowerOfTwo - Return true if the given value is known to have
- /// exactly one bit set when defined. For vectors return true if every
- /// element is known to be a power of two when defined. Supports values with
- /// integer or pointer type and vectors of integers. If 'OrZero' is set then
- /// return true if the given value is either a power of two or zero.
+ /// Return true if the given value is known to have exactly one bit set when
+ /// defined. For vectors return true if every element is known to be a power
+ /// of two when defined. Supports values with integer or pointer type and
+ /// vectors of integers. If 'OrZero' is set, then return true if the given
+ /// value is either a power of two or zero.
bool isKnownToBeAPowerOfTwo(Value *V, const DataLayout &DL,
bool OrZero = false, unsigned Depth = 0,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
- /// isKnownNonZero - Return true if the given value is known to be non-zero
- /// when defined. For vectors return true if every element is known to be
- /// non-zero when defined. Supports values with integer or pointer type and
- /// vectors of integers.
+ /// Return true if the given value is known to be non-zero when defined. For
+ /// vectors, return true if every element is known to be non-zero when
+ /// defined. Supports values with integer or pointer type and vectors of
+ /// integers.
bool isKnownNonZero(Value *V, const DataLayout &DL, unsigned Depth = 0,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
@@ -92,16 +99,30 @@ namespace llvm {
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
- /// isKnownNonEqual - Return true if the given values are known to be
- /// non-equal when defined. Supports scalar integer types only.
+ /// Returns true if the given value is known be positive (i.e. non-negative
+ /// and non-zero).
+ bool isKnownPositive(Value *V, const DataLayout &DL, unsigned Depth = 0,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr,
+ const DominatorTree *DT = nullptr);
+
+ /// Returns true if the given value is known be negative (i.e. non-positive
+ /// and non-zero).
+ bool isKnownNegative(Value *V, const DataLayout &DL, unsigned Depth = 0,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr,
+ const DominatorTree *DT = nullptr);
+
+ /// Return true if the given values are known to be non-equal when defined.
+ /// Supports scalar integer types only.
bool isKnownNonEqual(Value *V1, Value *V2, const DataLayout &DL,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
- /// MaskedValueIsZero - Return true if 'V & Mask' is known to be zero. We use
- /// this predicate to simplify operations downstream. Mask is known to be
- /// zero for bits that V cannot have.
+ /// Return true if 'V & Mask' is known to be zero. We use this predicate to
+ /// simplify operations downstream. Mask is known to be zero for bits that V
+ /// cannot have.
///
/// This function is defined on values with integer type, values with pointer
/// type, and vectors of integers. In the case
@@ -113,48 +134,52 @@ namespace llvm {
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
- /// ComputeNumSignBits - Return the number of times the sign bit of the
- /// register is replicated into the other bits. We know that at least 1 bit
- /// is always equal to the sign bit (itself), but other cases can give us
- /// information. For example, immediately after an "ashr X, 2", we know that
- /// the top 3 bits are all equal to each other, so we return 3.
- ///
- /// 'Op' must have a scalar integer type.
- ///
+ /// Return the number of times the sign bit of the register is replicated into
+ /// the other bits. We know that at least 1 bit is always equal to the sign
+ /// bit (itself), but other cases can give us information. For example,
+ /// immediately after an "ashr X, 2", we know that the top 3 bits are all
+ /// equal to each other, so we return 3. For vectors, return the number of
+ /// sign bits for the vector element with the mininum number of known sign
+ /// bits.
unsigned ComputeNumSignBits(Value *Op, const DataLayout &DL,
unsigned Depth = 0, AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
- /// ComputeMultiple - This function computes the integer multiple of Base that
- /// equals V. If successful, it returns true and returns the multiple in
- /// Multiple. If unsuccessful, it returns false. Also, if V can be
- /// simplified to an integer, then the simplified V is returned in Val. Look
- /// through sext only if LookThroughSExt=true.
+ /// This function computes the integer multiple of Base that equals V. If
+ /// successful, it returns true and returns the multiple in Multiple. If
+ /// unsuccessful, it returns false. Also, if V can be simplified to an
+ /// integer, then the simplified V is returned in Val. Look through sext only
+ /// if LookThroughSExt=true.
bool ComputeMultiple(Value *V, unsigned Base, Value *&Multiple,
bool LookThroughSExt = false,
unsigned Depth = 0);
- /// CannotBeNegativeZero - Return true if we can prove that the specified FP
- /// value is never equal to -0.0.
- ///
- bool CannotBeNegativeZero(const Value *V, unsigned Depth = 0);
-
- /// CannotBeOrderedLessThanZero - Return true if we can prove that the
- /// specified FP value is either a NaN or never less than 0.0.
- ///
- bool CannotBeOrderedLessThanZero(const Value *V, unsigned Depth = 0);
-
- /// isBytewiseValue - If the specified value can be set by repeating the same
- /// byte in memory, return the i8 value that it is represented with. This is
- /// true for all i8 values obviously, but is also true for i32 0, i32 -1,
- /// i16 0xF0F0, double 0.0 etc. If the value can't be handled with a repeated
- /// byte store (e.g. i16 0x1234), return null.
+ /// Map a call instruction to an intrinsic ID. Libcalls which have equivalent
+ /// intrinsics are treated as-if they were intrinsics.
+ Intrinsic::ID getIntrinsicForCallSite(ImmutableCallSite ICS,
+ const TargetLibraryInfo *TLI);
+
+ /// Return true if we can prove that the specified FP value is never equal to
+ /// -0.0.
+ bool CannotBeNegativeZero(const Value *V, const TargetLibraryInfo *TLI,
+ unsigned Depth = 0);
+
+ /// Return true if we can prove that the specified FP value is either a NaN or
+ /// never less than 0.0.
+ bool CannotBeOrderedLessThanZero(const Value *V, const TargetLibraryInfo *TLI,
+ unsigned Depth = 0);
+
+ /// If the specified value can be set by repeating the same byte in memory,
+ /// return the i8 value that it is represented with. This is true for all i8
+ /// values obviously, but is also true for i32 0, i32 -1, i16 0xF0F0, double
+ /// 0.0 etc. If the value can't be handled with a repeated byte store (e.g.
+ /// i16 0x1234), return null.
Value *isBytewiseValue(Value *V);
- /// FindInsertedValue - Given an aggregrate and an sequence of indices, see if
- /// the scalar value indexed is already around as a register, for example if
- /// it were inserted directly into the aggregrate.
+ /// Given an aggregrate and an sequence of indices, see if the scalar value
+ /// indexed is already around as a register, for example if it were inserted
+ /// directly into the aggregrate.
///
/// If InsertBefore is not null, this function will duplicate (modified)
/// insertvalues when a part of a nested struct is extracted.
@@ -162,9 +187,8 @@ namespace llvm {
ArrayRef<unsigned> idx_range,
Instruction *InsertBefore = nullptr);
- /// GetPointerBaseWithConstantOffset - Analyze the specified pointer to see if
- /// it can be expressed as a base pointer plus a constant offset. Return the
- /// base and offset to the caller.
+ /// Analyze the specified pointer to see if it can be expressed as a base
+ /// pointer plus a constant offset. Return the base and offset to the caller.
Value *GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset,
const DataLayout &DL);
static inline const Value *
@@ -174,24 +198,28 @@ namespace llvm {
DL);
}
- /// getConstantStringInfo - This function computes the length of a
- /// null-terminated C string pointed to by V. If successful, it returns true
- /// and returns the string in Str. If unsuccessful, it returns false. This
- /// does not include the trailing nul character by default. If TrimAtNul is
- /// set to false, then this returns any trailing nul characters as well as any
- /// other characters that come after it.
+ /// Returns true if the GEP is based on a pointer to a string (array of i8),
+ /// and is indexing into this string.
+ bool isGEPBasedOnPointerToString(const GEPOperator *GEP);
+
+ /// This function computes the length of a null-terminated C string pointed to
+ /// by V. If successful, it returns true and returns the string in Str. If
+ /// unsuccessful, it returns false. This does not include the trailing null
+ /// character by default. If TrimAtNul is set to false, then this returns any
+ /// trailing null characters as well as any other characters that come after
+ /// it.
bool getConstantStringInfo(const Value *V, StringRef &Str,
uint64_t Offset = 0, bool TrimAtNul = true);
- /// GetStringLength - If we can compute the length of the string pointed to by
- /// the specified pointer, return 'len+1'. If we can't, return 0.
+ /// If we can compute the length of the string pointed to by the specified
+ /// pointer, return 'len+1'. If we can't, return 0.
uint64_t GetStringLength(Value *V);
- /// GetUnderlyingObject - This method strips off any GEP address adjustments
- /// and pointer casts from the specified value, returning the original object
- /// being addressed. Note 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.
+ /// This method strips off any GEP address adjustments and pointer casts from
+ /// the specified value, returning the original object being addressed. Note
+ /// 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);
static inline const Value *GetUnderlyingObject(const Value *V,
@@ -232,32 +260,11 @@ namespace llvm {
const DataLayout &DL, LoopInfo *LI = nullptr,
unsigned MaxLookup = 6);
- /// onlyUsedByLifetimeMarkers - Return true if the only users of this pointer
- /// are lifetime markers.
+ /// Return true if the only users of this pointer are lifetime markers.
bool onlyUsedByLifetimeMarkers(const Value *V);
- /// isDereferenceablePointer - Return true if this is always a dereferenceable
- /// pointer. If the context instruction is specified perform context-sensitive
- /// analysis and return true if the pointer is dereferenceable at the
- /// specified instruction.
- bool isDereferenceablePointer(const Value *V, const DataLayout &DL,
- const Instruction *CtxI = nullptr,
- const DominatorTree *DT = nullptr,
- const TargetLibraryInfo *TLI = nullptr);
-
- /// Returns true if V is always a dereferenceable pointer with alignment
- /// greater or equal than requested. If the context instruction is specified
- /// performs context-sensitive analysis and returns true if the pointer is
- /// dereferenceable at the specified instruction.
- bool isDereferenceableAndAlignedPointer(const Value *V, unsigned Align,
- const DataLayout &DL,
- const Instruction *CtxI = nullptr,
- const DominatorTree *DT = nullptr,
- const TargetLibraryInfo *TLI = nullptr);
-
- /// isSafeToSpeculativelyExecute - Return true if the instruction does not
- /// have any effects besides calculating the result and does not have
- /// undefined behavior.
+ /// Return true if the instruction does not have any effects besides
+ /// calculating the result and does not have undefined behavior.
///
/// This method never returns true for an instruction that returns true for
/// mayHaveSideEffects; however, this method also does some other checks in
@@ -281,8 +288,7 @@ namespace llvm {
/// for such instructions, moving them may change the resulting value.
bool isSafeToSpeculativelyExecute(const Value *V,
const Instruction *CtxI = nullptr,
- const DominatorTree *DT = nullptr,
- const TargetLibraryInfo *TLI = nullptr);
+ const DominatorTree *DT = nullptr);
/// Returns true if the result or effects of the given instructions \p I
/// depend on or influence global memory.
@@ -294,19 +300,18 @@ namespace llvm {
/// operands are not memory dependent.
bool mayBeMemoryDependent(const Instruction &I);
- /// isKnownNonNull - Return true if this pointer couldn't possibly be null by
- /// its definition. This returns true for allocas, non-extern-weak globals
- /// and byval arguments.
- bool isKnownNonNull(const Value *V, const TargetLibraryInfo *TLI = nullptr);
+ /// Return true if this pointer couldn't possibly be null by its definition.
+ /// This returns true for allocas, non-extern-weak globals, and byval
+ /// arguments.
+ bool isKnownNonNull(const Value *V);
- /// isKnownNonNullAt - Return true if this pointer couldn't possibly be null.
- /// If the context instruction is specified perform context-sensitive analysis
- /// and return true if the pointer couldn't possibly be null at the specified
+ /// Return true if this pointer couldn't possibly be null. If the context
+ /// instruction is specified, perform context-sensitive analysis and return
+ /// true if the pointer couldn't possibly be null at the specified
/// instruction.
bool isKnownNonNullAt(const Value *V,
const Instruction *CtxI = nullptr,
- const DominatorTree *DT = nullptr,
- const TargetLibraryInfo *TLI = nullptr);
+ const DominatorTree *DT = nullptr);
/// Return true if it is valid to use the assumptions provided by an
/// assume intrinsic, I, at the point in the control-flow identified by the
@@ -337,6 +342,11 @@ namespace llvm {
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
+ /// Returns true if the arithmetic part of the \p II 's result is
+ /// used only along the paths control dependent on the computation
+ /// not overflowing, \p II being an <op>.with.overflow intrinsic.
+ bool isOverflowIntrinsicNoWrap(IntrinsicInst *II, DominatorTree &DT);
+
/// Return true if this function can prove that the instruction I will
/// always transfer execution to one of its successors (including the next
/// instruction that follows within a basic block). E.g. this is not
@@ -441,18 +451,20 @@ namespace llvm {
/// E.g. if RangeMD is !{i32 0, i32 10, i32 15, i32 20} then return [0, 20).
ConstantRange getConstantRangeFromMetadata(MDNode &RangeMD);
- /// Return true if RHS is known to be implied by LHS. A & B must be i1
- /// (boolean) values or a vector of such values. Note that the truth table for
- /// implication is the same as <=u on i1 values (but not <=s!). The truth
- /// table for both is:
+ /// 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.
+ /// A & B must be i1 (boolean) values or a vector of such values. Note that
+ /// the truth table for implication is the same as <=u on i1 values (but not
+ /// <=s!). The truth table for both is:
/// | T | F (B)
/// T | T | F
/// F | T | T
/// (A)
- bool isImpliedCondition(Value *LHS, Value *RHS, const DataLayout &DL,
- unsigned Depth = 0, AssumptionCache *AC = nullptr,
- const Instruction *CxtI = nullptr,
- const DominatorTree *DT = nullptr);
+ Optional<bool> isImpliedCondition(
+ Value *LHS, Value *RHS, const DataLayout &DL, bool InvertAPred = false,
+ unsigned Depth = 0, AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr);
} // end namespace llvm
#endif
diff --git a/include/llvm/Analysis/VectorUtils.h b/include/llvm/Analysis/VectorUtils.h
index 531803adf5e4..eaa068b89c77 100644
--- a/include/llvm/Analysis/VectorUtils.h
+++ b/include/llvm/Analysis/VectorUtils.h
@@ -14,15 +14,13 @@
#ifndef LLVM_TRANSFORMS_UTILS_VECTORUTILS_H
#define LLVM_TRANSFORMS_UTILS_VECTORUTILS_H
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
-#include "llvm/IR/IntrinsicInst.h"
-#include "llvm/IR/Intrinsics.h"
namespace llvm {
-struct DemandedBits;
+template <typename T> class ArrayRef;
+class DemandedBits;
class GetElementPtrInst;
class Loop;
class ScalarEvolution;
@@ -30,6 +28,10 @@ class TargetTransformInfo;
class Type;
class Value;
+namespace Intrinsic {
+enum ID : unsigned;
+}
+
/// \brief Identify if the intrinsic is trivially vectorizable.
/// This method returns true if the intrinsic's argument types are all
/// scalars for the scalar form of the intrinsic and all vectors for
@@ -40,26 +42,11 @@ bool isTriviallyVectorizable(Intrinsic::ID ID);
/// ctlz,cttz and powi special intrinsics whose argument is scalar.
bool hasVectorInstrinsicScalarOpd(Intrinsic::ID ID, unsigned ScalarOpdIdx);
-/// \brief Identify if call has a unary float signature
-/// It returns input intrinsic ID if call has a single argument,
-/// argument type and call instruction type should be floating
-/// point type and call should only reads memory.
-/// else return not_intrinsic.
-Intrinsic::ID checkUnaryFloatSignature(const CallInst &I,
- Intrinsic::ID ValidIntrinsicID);
-
-/// \brief Identify if call has a binary float signature
-/// It returns input intrinsic ID if call has two arguments,
-/// arguments type and call instruction type should be floating
-/// point type and call should only reads memory.
-/// else return not_intrinsic.
-Intrinsic::ID checkBinaryFloatSignature(const CallInst &I,
- Intrinsic::ID ValidIntrinsicID);
-
/// \brief Returns intrinsic ID for call.
/// For the input call instruction it finds mapping intrinsic and returns
/// its intrinsic ID, in case it does not found it return not_intrinsic.
-Intrinsic::ID getIntrinsicIDForCall(CallInst *CI, const TargetLibraryInfo *TLI);
+Intrinsic::ID getVectorIntrinsicIDForCall(const CallInst *CI,
+ const TargetLibraryInfo *TLI);
/// \brief Find the operand of the GEP that should be checked for consecutive
/// stores. This ignores trailing indices that have no effect on the final
@@ -126,7 +113,16 @@ MapVector<Instruction*, uint64_t>
computeMinimumValueSizes(ArrayRef<BasicBlock*> Blocks,
DemandedBits &DB,
const TargetTransformInfo *TTI=nullptr);
-
+
+/// Specifically, let Kinds = [MD_tbaa, MD_alias_scope, MD_noalias, MD_fpmath,
+/// MD_nontemporal]. For K in Kinds, we get the MDNode for K from each of the
+/// elements of VL, compute their "intersection" (i.e., the most generic
+/// metadata value that covers all of the individual values), and set I's
+/// metadata for M equal to the intersection value.
+///
+/// This function always sets a (possibly null) value for each K in Kinds.
+Instruction *propagateMetadata(Instruction *I, ArrayRef<Value *> VL);
+
} // llvm namespace
#endif
diff --git a/include/llvm/AsmParser/Parser.h b/include/llvm/AsmParser/Parser.h
index 96a15c1ec45c..768b089b8a2a 100644
--- a/include/llvm/AsmParser/Parser.h
+++ b/include/llvm/AsmParser/Parser.h
@@ -23,6 +23,7 @@ class LLVMContext;
class Module;
struct SlotMapping;
class SMDiagnostic;
+class Type;
/// This function is the main interface to the LLVM Assembly Parser. It parses
/// an ASCII file that (presumably) contains LLVM Assembly code. It returns a
@@ -91,6 +92,24 @@ bool parseAssemblyInto(MemoryBufferRef F, Module &M, SMDiagnostic &Err,
Constant *parseConstantValue(StringRef Asm, SMDiagnostic &Err, const Module &M,
const SlotMapping *Slots = nullptr);
+/// Parse a type in the given string.
+///
+/// \param Slots The optional slot mapping that will restore the parsing state
+/// of the module.
+/// \return null on error.
+Type *parseType(StringRef Asm, SMDiagnostic &Err, const Module &M,
+ const SlotMapping *Slots = nullptr);
+
+/// Parse a string \p Asm that starts with a type.
+/// \p Read[out] gives the number of characters that have been read to parse
+/// the type in \p Asm.
+///
+/// \param Slots The optional slot mapping that will restore the parsing state
+/// of the module.
+/// \return null on error.
+Type *parseTypeAtBeginning(StringRef Asm, unsigned &Read, SMDiagnostic &Err,
+ const Module &M, const SlotMapping *Slots = nullptr);
+
} // End llvm namespace
#endif
diff --git a/include/llvm/Bitcode/BitCodes.h b/include/llvm/Bitcode/BitCodes.h
index 96c420151858..66400b697c5c 100644
--- a/include/llvm/Bitcode/BitCodes.h
+++ b/include/llvm/Bitcode/BitCodes.h
@@ -147,12 +147,8 @@ public:
static char DecodeChar6(unsigned V) {
assert((V & ~63) == 0 && "Not a Char6 encoded character!");
- if (V < 26) return V+'a';
- if (V < 26+26) return V-26+'A';
- if (V < 26+26+10) return V-26-26+'0';
- if (V == 62) return '.';
- if (V == 63) return '_';
- llvm_unreachable("Not a value Char6 character!");
+ return "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789._"
+ [V];
}
};
diff --git a/include/llvm/Bitcode/BitcodeWriterPass.h b/include/llvm/Bitcode/BitcodeWriterPass.h
index a1272cf156e5..946255b878a6 100644
--- a/include/llvm/Bitcode/BitcodeWriterPass.h
+++ b/include/llvm/Bitcode/BitcodeWriterPass.h
@@ -16,12 +16,12 @@
#define LLVM_BITCODE_BITCODEWRITERPASS_H
#include "llvm/ADT/StringRef.h"
+#include "llvm/IR/PassManager.h"
namespace llvm {
class Module;
class ModulePass;
class raw_ostream;
-class PreservedAnalyses;
/// \brief Create and return a pass that writes the module to the specified
/// ostream. Note that this pass is designed for use with the legacy pass
@@ -30,11 +30,15 @@ class PreservedAnalyses;
/// If \c ShouldPreserveUseListOrder, encode use-list order so it can be
/// reproduced when deserialized.
///
-/// If \c EmitFunctionSummary, emit the function summary index (currently
-/// for use in ThinLTO optimization).
+/// If \c EmitSummaryIndex, emit the summary index (currently for use in ThinLTO
+/// optimization).
+///
+/// If \c EmitModuleHash, compute and emit the module hash in the bitcode
+/// (currently for use in ThinLTO incremental build).
ModulePass *createBitcodeWriterPass(raw_ostream &Str,
bool ShouldPreserveUseListOrder = false,
- bool EmitFunctionSummary = false);
+ bool EmitSummaryIndex = false,
+ bool EmitModuleHash = false);
/// \brief Pass for writing a module of IR out to a bitcode file.
///
@@ -43,7 +47,8 @@ ModulePass *createBitcodeWriterPass(raw_ostream &Str,
class BitcodeWriterPass {
raw_ostream &OS;
bool ShouldPreserveUseListOrder;
- bool EmitFunctionSummary;
+ bool EmitSummaryIndex;
+ bool EmitModuleHash;
public:
/// \brief Construct a bitcode writer pass around a particular output stream.
@@ -51,17 +56,18 @@ public:
/// If \c ShouldPreserveUseListOrder, encode use-list order so it can be
/// reproduced when deserialized.
///
- /// If \c EmitFunctionSummary, emit the function summary index (currently
+ /// If \c EmitSummaryIndex, emit the summary index (currently
/// for use in ThinLTO optimization).
explicit BitcodeWriterPass(raw_ostream &OS,
bool ShouldPreserveUseListOrder = false,
- bool EmitFunctionSummary = false)
+ bool EmitSummaryIndex = false,
+ bool EmitModuleHash = false)
: OS(OS), ShouldPreserveUseListOrder(ShouldPreserveUseListOrder),
- EmitFunctionSummary(EmitFunctionSummary) {}
+ EmitSummaryIndex(EmitSummaryIndex), EmitModuleHash(EmitModuleHash) {}
/// \brief Run the bitcode writer pass, and output the module to the selected
/// output stream.
- PreservedAnalyses run(Module &M);
+ PreservedAnalyses run(Module &M, ModuleAnalysisManager &);
static StringRef name() { return "BitcodeWriterPass"; }
};
diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h
index c0cf6cde887f..b331ceea051c 100644
--- a/include/llvm/Bitcode/BitstreamReader.h
+++ b/include/llvm/Bitcode/BitstreamReader.h
@@ -17,6 +17,7 @@
#include "llvm/Bitcode/BitCodes.h"
#include "llvm/Support/Endian.h"
+#include "llvm/Support/MathExtras.h"
#include "llvm/Support/StreamingMemoryObject.h"
#include <climits>
#include <string>
@@ -128,175 +129,64 @@ public:
}
};
-/// When advancing through a bitstream cursor, each advance can discover a few
-/// different kinds of entries:
-struct BitstreamEntry {
- enum {
- Error, // Malformed bitcode was found.
- EndBlock, // We've reached the end of the current block, (or the end of the
- // file, which is treated like a series of EndBlock records.
- SubBlock, // This is the start of a new subblock of a specific ID.
- Record // This is a record with a specific AbbrevID.
- } Kind;
-
- unsigned ID;
-
- static BitstreamEntry getError() {
- BitstreamEntry E; E.Kind = Error; return E;
- }
- static BitstreamEntry getEndBlock() {
- BitstreamEntry E; E.Kind = EndBlock; return E;
- }
- static BitstreamEntry getSubBlock(unsigned ID) {
- BitstreamEntry E; E.Kind = SubBlock; E.ID = ID; return E;
- }
- static BitstreamEntry getRecord(unsigned AbbrevID) {
- BitstreamEntry E; E.Kind = Record; E.ID = AbbrevID; return E;
- }
-};
-
-/// This represents a position within a bitcode file. There may be multiple
-/// independent cursors reading within one bitstream, each maintaining their own
-/// local state.
-///
-/// Unlike iterators, BitstreamCursors are heavy-weight objects that should not
-/// be passed by value.
-class BitstreamCursor {
- BitstreamReader *BitStream;
- size_t NextChar;
+/// This represents a position within a bitstream. There may be multiple
+/// independent cursors reading within one bitstream, each maintaining their
+/// own local state.
+class SimpleBitstreamCursor {
+ BitstreamReader *R = nullptr;
+ size_t NextChar = 0;
// The size of the bicode. 0 if we don't know it yet.
- size_t Size;
+ size_t Size = 0;
/// This is the current data we have pulled from the stream but have not
/// returned to the client. This is specifically and intentionally defined to
/// follow the word size of the host machine for efficiency. We use word_t in
/// places that are aware of this to make it perfectly explicit what is going
/// on.
+public:
typedef size_t word_t;
- word_t CurWord;
+
+private:
+ word_t CurWord = 0;
/// This is the number of bits in CurWord that are valid. This is always from
/// [0...bits_of(size_t)-1] inclusive.
- unsigned BitsInCurWord;
-
- // This is the declared size of code values used for the current block, in
- // bits.
- unsigned CurCodeSize;
-
- /// Abbrevs installed at in this block.
- std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> CurAbbrevs;
-
- struct Block {
- unsigned PrevCodeSize;
- std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> PrevAbbrevs;
- explicit Block(unsigned PCS) : PrevCodeSize(PCS) {}
- };
-
- /// This tracks the codesize of parent blocks.
- SmallVector<Block, 8> BlockScope;
-
+ unsigned BitsInCurWord = 0;
public:
static const size_t MaxChunkSize = sizeof(word_t) * 8;
- BitstreamCursor() { init(nullptr); }
-
- explicit BitstreamCursor(BitstreamReader &R) { init(&R); }
+ SimpleBitstreamCursor() = default;
- void init(BitstreamReader *R) {
- freeState();
-
- BitStream = R;
- NextChar = 0;
- Size = 0;
- BitsInCurWord = 0;
- CurCodeSize = 2;
- }
-
- void freeState();
+ explicit SimpleBitstreamCursor(BitstreamReader &R) : R(&R) {}
+ explicit SimpleBitstreamCursor(BitstreamReader *R) : R(R) {}
bool canSkipToPos(size_t pos) const {
// pos can be skipped to if it is a valid address or one byte past the end.
- return pos == 0 || BitStream->getBitcodeBytes().isValidAddress(
- static_cast<uint64_t>(pos - 1));
+ return pos == 0 ||
+ R->getBitcodeBytes().isValidAddress(static_cast<uint64_t>(pos - 1));
}
bool AtEndOfStream() {
if (BitsInCurWord != 0)
return false;
if (Size != 0)
- return Size == NextChar;
+ return Size <= NextChar;
fillCurWord();
return BitsInCurWord == 0;
}
- /// Return the number of bits used to encode an abbrev #.
- unsigned getAbbrevIDWidth() const { return CurCodeSize; }
-
/// Return the bit # of the bit we are reading.
uint64_t GetCurrentBitNo() const {
return NextChar*CHAR_BIT - BitsInCurWord;
}
- BitstreamReader *getBitStreamReader() {
- return BitStream;
- }
- const BitstreamReader *getBitStreamReader() const {
- return BitStream;
- }
-
- /// Flags that modify the behavior of advance().
- enum {
- /// If this flag is used, the advance() method does not automatically pop
- /// the block scope when the end of a block is reached.
- AF_DontPopBlockAtEnd = 1,
-
- /// If this flag is used, abbrev entries are returned just like normal
- /// records.
- AF_DontAutoprocessAbbrevs = 2
- };
-
- /// Advance the current bitstream, returning the next entry in the stream.
- BitstreamEntry advance(unsigned Flags = 0) {
- while (1) {
- unsigned Code = ReadCode();
- if (Code == bitc::END_BLOCK) {
- // Pop the end of the block unless Flags tells us not to.
- if (!(Flags & AF_DontPopBlockAtEnd) && ReadBlockEnd())
- return BitstreamEntry::getError();
- return BitstreamEntry::getEndBlock();
- }
-
- if (Code == bitc::ENTER_SUBBLOCK)
- return BitstreamEntry::getSubBlock(ReadSubBlockID());
-
- if (Code == bitc::DEFINE_ABBREV &&
- !(Flags & AF_DontAutoprocessAbbrevs)) {
- // We read and accumulate abbrev's, the client can't do anything with
- // them anyway.
- ReadAbbrevRecord();
- continue;
- }
-
- return BitstreamEntry::getRecord(Code);
- }
- }
+ // Return the byte # of the current bit.
+ uint64_t getCurrentByteNo() const { return GetCurrentBitNo() / 8; }
- /// This is a convenience function for clients that don't expect any
- /// subblocks. This just skips over them automatically.
- BitstreamEntry advanceSkippingSubblocks(unsigned Flags = 0) {
- while (1) {
- // If we found a normal entry, return it.
- BitstreamEntry Entry = advance(Flags);
- if (Entry.Kind != BitstreamEntry::SubBlock)
- return Entry;
-
- // If we found a sub-block, just skip over it and check the next entry.
- if (SkipBlock())
- return BitstreamEntry::getError();
- }
- }
+ BitstreamReader *getBitStreamReader() { return R; }
+ const BitstreamReader *getBitStreamReader() const { return R; }
/// Reset the stream to the specified bit number.
void JumpToBit(uint64_t BitNo) {
@@ -313,6 +203,37 @@ public:
Read(WordBitNo);
}
+ /// Reset the stream to the bit pointed at by the specified pointer.
+ ///
+ /// The pointer must be a dereferenceable pointer into the bytes in the
+ /// underlying memory object.
+ void jumpToPointer(const uint8_t *Pointer) {
+ auto *Pointer0 = getPointerToByte(0, 1);
+ assert((intptr_t)Pointer0 <= (intptr_t)Pointer &&
+ "Expected pointer into bitstream");
+
+ JumpToBit(8 * (Pointer - Pointer0));
+ assert((intptr_t)getPointerToByte(getCurrentByteNo(), 1) ==
+ (intptr_t)Pointer &&
+ "Expected to reach pointer");
+ }
+ void jumpToPointer(const char *Pointer) {
+ jumpToPointer((const uint8_t *)Pointer);
+ }
+
+ /// Get a pointer into the bitstream at the specified byte offset.
+ const uint8_t *getPointerToByte(uint64_t ByteNo, uint64_t NumBytes) {
+ return R->getBitcodeBytes().getPointer(ByteNo, NumBytes);
+ }
+
+ /// Get a pointer into the bitstream at the specified bit offset.
+ ///
+ /// The bit offset must be on a byte boundary.
+ const uint8_t *getPointerToBit(uint64_t BitNo, uint64_t NumBytes) {
+ assert(!(BitNo % 8) && "Expected bit on byte boundary");
+ return getPointerToByte(BitNo / 8, NumBytes);
+ }
+
void fillCurWord() {
if (Size != 0 && NextChar >= Size)
report_fatal_error("Unexpected end of file");
@@ -321,7 +242,7 @@ public:
uint8_t Array[sizeof(word_t)] = {0};
uint64_t BytesRead =
- BitStream->getBitcodeBytes().readBytes(Array, sizeof(Array), NextChar);
+ R->getBitcodeBytes().readBytes(Array, sizeof(Array), NextChar);
// If we run out of data, stop at the end of the stream.
if (BytesRead == 0) {
@@ -416,7 +337,6 @@ public:
}
}
-private:
void SkipToFourByteBoundary() {
// If word_t is 64-bits and if we've read less than 32 bits, just dump
// the bits we have up to the next 32-bit boundary.
@@ -429,7 +349,166 @@ private:
BitsInCurWord = 0;
}
+
+ /// Skip to the end of the file.
+ void skipToEnd() { NextChar = R->getBitcodeBytes().getExtent(); }
+
+ /// Prevent the cursor from reading past a byte boundary.
+ ///
+ /// Prevent the cursor from requesting byte reads past \c Limit. This is
+ /// useful when working with a cursor on a StreamingMemoryObject, when it's
+ /// desirable to avoid invalidating the result of getPointerToByte().
+ ///
+ /// If \c Limit is on a word boundary, AtEndOfStream() will return true if
+ /// the cursor position reaches or exceeds \c Limit, regardless of the true
+ /// number of available bytes. Otherwise, AtEndOfStream() returns true when
+ /// it reaches or exceeds the next word boundary.
+ void setArtificialByteLimit(uint64_t Limit) {
+ assert(getCurrentByteNo() < Limit && "Move cursor before lowering limit");
+
+ // Round to word boundary.
+ Limit = alignTo(Limit, sizeof(word_t));
+
+ // Only change size if the new one is lower.
+ if (!Size || Size > Limit)
+ Size = Limit;
+ }
+
+ /// Return the Size, if known.
+ uint64_t getSizeIfKnown() const { return Size; }
+};
+
+/// When advancing through a bitstream cursor, each advance can discover a few
+/// different kinds of entries:
+struct BitstreamEntry {
+ enum {
+ Error, // Malformed bitcode was found.
+ EndBlock, // We've reached the end of the current block, (or the end of the
+ // file, which is treated like a series of EndBlock records.
+ SubBlock, // This is the start of a new subblock of a specific ID.
+ Record // This is a record with a specific AbbrevID.
+ } Kind;
+
+ unsigned ID;
+
+ static BitstreamEntry getError() {
+ BitstreamEntry E; E.Kind = Error; return E;
+ }
+ static BitstreamEntry getEndBlock() {
+ BitstreamEntry E; E.Kind = EndBlock; return E;
+ }
+ static BitstreamEntry getSubBlock(unsigned ID) {
+ BitstreamEntry E; E.Kind = SubBlock; E.ID = ID; return E;
+ }
+ static BitstreamEntry getRecord(unsigned AbbrevID) {
+ BitstreamEntry E; E.Kind = Record; E.ID = AbbrevID; return E;
+ }
+};
+
+/// This represents a position within a bitcode file, implemented on top of a
+/// SimpleBitstreamCursor.
+///
+/// Unlike iterators, BitstreamCursors are heavy-weight objects that should not
+/// be passed by value.
+class BitstreamCursor : SimpleBitstreamCursor {
+ // This is the declared size of code values used for the current block, in
+ // bits.
+ unsigned CurCodeSize = 2;
+
+ /// Abbrevs installed at in this block.
+ std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> CurAbbrevs;
+
+ struct Block {
+ unsigned PrevCodeSize;
+ std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> PrevAbbrevs;
+ explicit Block(unsigned PCS) : PrevCodeSize(PCS) {}
+ };
+
+ /// This tracks the codesize of parent blocks.
+ SmallVector<Block, 8> BlockScope;
+
+
public:
+ static const size_t MaxChunkSize = sizeof(word_t) * 8;
+
+ BitstreamCursor() = default;
+
+ explicit BitstreamCursor(BitstreamReader &R) { init(&R); }
+
+ void init(BitstreamReader *R) {
+ freeState();
+ SimpleBitstreamCursor::operator=(SimpleBitstreamCursor(R));
+ CurCodeSize = 2;
+ }
+
+ void freeState();
+
+ using SimpleBitstreamCursor::canSkipToPos;
+ using SimpleBitstreamCursor::AtEndOfStream;
+ using SimpleBitstreamCursor::GetCurrentBitNo;
+ using SimpleBitstreamCursor::getCurrentByteNo;
+ using SimpleBitstreamCursor::getPointerToByte;
+ using SimpleBitstreamCursor::getBitStreamReader;
+ using SimpleBitstreamCursor::JumpToBit;
+ using SimpleBitstreamCursor::fillCurWord;
+ using SimpleBitstreamCursor::Read;
+ using SimpleBitstreamCursor::ReadVBR;
+ using SimpleBitstreamCursor::ReadVBR64;
+
+ /// Return the number of bits used to encode an abbrev #.
+ unsigned getAbbrevIDWidth() const { return CurCodeSize; }
+
+ /// Flags that modify the behavior of advance().
+ enum {
+ /// If this flag is used, the advance() method does not automatically pop
+ /// the block scope when the end of a block is reached.
+ AF_DontPopBlockAtEnd = 1,
+
+ /// If this flag is used, abbrev entries are returned just like normal
+ /// records.
+ AF_DontAutoprocessAbbrevs = 2
+ };
+
+ /// Advance the current bitstream, returning the next entry in the stream.
+ BitstreamEntry advance(unsigned Flags = 0) {
+ while (1) {
+ unsigned Code = ReadCode();
+ if (Code == bitc::END_BLOCK) {
+ // Pop the end of the block unless Flags tells us not to.
+ if (!(Flags & AF_DontPopBlockAtEnd) && ReadBlockEnd())
+ return BitstreamEntry::getError();
+ return BitstreamEntry::getEndBlock();
+ }
+
+ if (Code == bitc::ENTER_SUBBLOCK)
+ return BitstreamEntry::getSubBlock(ReadSubBlockID());
+
+ if (Code == bitc::DEFINE_ABBREV &&
+ !(Flags & AF_DontAutoprocessAbbrevs)) {
+ // We read and accumulate abbrev's, the client can't do anything with
+ // them anyway.
+ ReadAbbrevRecord();
+ continue;
+ }
+
+ return BitstreamEntry::getRecord(Code);
+ }
+ }
+
+ /// This is a convenience function for clients that don't expect any
+ /// subblocks. This just skips over them automatically.
+ BitstreamEntry advanceSkippingSubblocks(unsigned Flags = 0) {
+ while (1) {
+ // If we found a normal entry, return it.
+ BitstreamEntry Entry = advance(Flags);
+ if (Entry.Kind != BitstreamEntry::SubBlock)
+ return Entry;
+
+ // If we found a sub-block, just skip over it and check the next entry.
+ if (SkipBlock())
+ return BitstreamEntry::getError();
+ }
+ }
unsigned ReadCode() {
return Read(CurCodeSize);
diff --git a/include/llvm/Bitcode/BitstreamWriter.h b/include/llvm/Bitcode/BitstreamWriter.h
index 438f4a6fb69b..d613f5e18954 100644
--- a/include/llvm/Bitcode/BitstreamWriter.h
+++ b/include/llvm/Bitcode/BitstreamWriter.h
@@ -361,36 +361,17 @@ private:
// If this record has blob data, emit it, otherwise we must have record
// entries to encode this way.
- // Emit a vbr6 to indicate the number of elements present.
if (BlobData) {
- EmitVBR(static_cast<uint32_t>(BlobLen), 6);
assert(RecordIdx == Vals.size() &&
"Blob data and record entries specified for blob operand!");
- } else {
- EmitVBR(static_cast<uint32_t>(Vals.size()-RecordIdx), 6);
- }
-
- // Flush to a 32-bit alignment boundary.
- FlushToWord();
-
- // Emit each field as a literal byte.
- if (BlobData) {
- for (unsigned i = 0; i != BlobLen; ++i)
- WriteByte((unsigned char)BlobData[i]);
- // Know that blob data is consumed for assertion below.
+ assert(Blob.data() == BlobData && "BlobData got moved");
+ assert(Blob.size() == BlobLen && "BlobLen got changed");
+ emitBlob(Blob);
BlobData = nullptr;
} else {
- for (unsigned e = Vals.size(); RecordIdx != e; ++RecordIdx) {
- assert(isUInt<8>(Vals[RecordIdx]) &&
- "Value too large to emit as blob");
- WriteByte((unsigned char)Vals[RecordIdx]);
- }
+ emitBlob(Vals.slice(RecordIdx));
}
-
- // Align end to 32-bits.
- while (GetBufferOffset() & 3)
- WriteByte(0);
} else { // Single scalar field.
assert(RecordIdx < Vals.size() && "Invalid abbrev/record");
EmitAbbreviatedField(Op, Vals[RecordIdx]);
@@ -403,6 +384,30 @@ private:
}
public:
+ /// Emit a blob, including flushing before and tail-padding.
+ template <class UIntTy>
+ void emitBlob(ArrayRef<UIntTy> Bytes, bool ShouldEmitSize = true) {
+ // Emit a vbr6 to indicate the number of elements present.
+ if (ShouldEmitSize)
+ EmitVBR(static_cast<uint32_t>(Bytes.size()), 6);
+
+ // Flush to a 32-bit alignment boundary.
+ FlushToWord();
+
+ // Emit literal bytes.
+ for (const auto &B : Bytes) {
+ assert(isUInt<8>(B) && "Value too large to emit as byte");
+ WriteByte((unsigned char)B);
+ }
+
+ // Align end to 32-bits.
+ while (GetBufferOffset() & 3)
+ WriteByte(0);
+ }
+ void emitBlob(StringRef Bytes, bool ShouldEmitSize = true) {
+ emitBlob(makeArrayRef((const uint8_t *)Bytes.data(), Bytes.size()),
+ ShouldEmitSize);
+ }
/// EmitRecord - Emit the specified record to the stream, using an abbrev if
/// we have one to compress the output.
diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h
index bcc84bedbed0..52d4f01b7985 100644
--- a/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/include/llvm/Bitcode/LLVMBitCodes.h
@@ -22,7 +22,7 @@
namespace llvm {
namespace bitc {
- // The only top-level block type defined is for a module.
+// The only top-level block type defined is for a module.
enum BlockIDs {
// Blocks
MODULE_BLOCK_ID = FIRST_APPLICATION_BLOCKID,
@@ -48,7 +48,7 @@ enum BlockIDs {
USELIST_BLOCK_ID,
MODULE_STRTAB_BLOCK_ID,
- FUNCTION_SUMMARY_BLOCK_ID,
+ GLOBALVAL_SUMMARY_BLOCK_ID,
OPERAND_BUNDLE_TAGS_BLOCK_ID,
@@ -70,431 +70,468 @@ enum IdentificationCodes {
/// also accepts N-1.
enum { BITCODE_CURRENT_EPOCH = 0 };
- /// MODULE blocks have a number of optional fields and subblocks.
- enum ModuleCodes {
- MODULE_CODE_VERSION = 1, // VERSION: [version#]
- MODULE_CODE_TRIPLE = 2, // TRIPLE: [strchr x N]
- MODULE_CODE_DATALAYOUT = 3, // DATALAYOUT: [strchr x N]
- MODULE_CODE_ASM = 4, // ASM: [strchr x N]
- MODULE_CODE_SECTIONNAME = 5, // SECTIONNAME: [strchr x N]
-
- // FIXME: Remove DEPLIB in 4.0.
- MODULE_CODE_DEPLIB = 6, // DEPLIB: [strchr x N]
-
- // GLOBALVAR: [pointer type, isconst, initid,
- // linkage, alignment, section, visibility, threadlocal]
- MODULE_CODE_GLOBALVAR = 7,
-
- // FUNCTION: [type, callingconv, isproto, linkage, paramattrs, alignment,
- // section, visibility, gc, unnamed_addr]
- MODULE_CODE_FUNCTION = 8,
-
- // ALIAS: [alias type, aliasee val#, linkage, visibility]
- MODULE_CODE_ALIAS_OLD = 9,
-
- // MODULE_CODE_PURGEVALS: [numvals]
- MODULE_CODE_PURGEVALS = 10,
-
- MODULE_CODE_GCNAME = 11, // GCNAME: [strchr x N]
- MODULE_CODE_COMDAT = 12, // COMDAT: [selection_kind, name]
-
- MODULE_CODE_VSTOFFSET = 13, // VSTOFFSET: [offset]
-
- // ALIAS: [alias value type, addrspace, aliasee val#, linkage, visibility]
- MODULE_CODE_ALIAS = 14,
-
- // METADATA_VALUES: [numvals]
- MODULE_CODE_METADATA_VALUES = 15,
- };
-
- /// PARAMATTR blocks have code for defining a parameter attribute set.
- enum AttributeCodes {
- // FIXME: Remove `PARAMATTR_CODE_ENTRY_OLD' in 4.0
- PARAMATTR_CODE_ENTRY_OLD = 1, // ENTRY: [paramidx0, attr0,
- // paramidx1, attr1...]
- PARAMATTR_CODE_ENTRY = 2, // ENTRY: [paramidx0, attrgrp0,
- // paramidx1, attrgrp1, ...]
- PARAMATTR_GRP_CODE_ENTRY = 3 // ENTRY: [id, attr0, att1, ...]
- };
-
- /// TYPE blocks have codes for each type primitive they use.
- enum TypeCodes {
- TYPE_CODE_NUMENTRY = 1, // NUMENTRY: [numentries]
-
- // Type Codes
- TYPE_CODE_VOID = 2, // VOID
- TYPE_CODE_FLOAT = 3, // FLOAT
- TYPE_CODE_DOUBLE = 4, // DOUBLE
- TYPE_CODE_LABEL = 5, // LABEL
- TYPE_CODE_OPAQUE = 6, // OPAQUE
- TYPE_CODE_INTEGER = 7, // INTEGER: [width]
- TYPE_CODE_POINTER = 8, // POINTER: [pointee type]
-
- TYPE_CODE_FUNCTION_OLD = 9, // FUNCTION: [vararg, attrid, retty,
- // paramty x N]
-
- TYPE_CODE_HALF = 10, // HALF
-
- TYPE_CODE_ARRAY = 11, // ARRAY: [numelts, eltty]
- TYPE_CODE_VECTOR = 12, // VECTOR: [numelts, eltty]
-
- // These are not with the other floating point types because they're
- // a late addition, and putting them in the right place breaks
- // binary compatibility.
- TYPE_CODE_X86_FP80 = 13, // X86 LONG DOUBLE
- TYPE_CODE_FP128 = 14, // LONG DOUBLE (112 bit mantissa)
- TYPE_CODE_PPC_FP128= 15, // PPC LONG DOUBLE (2 doubles)
-
- TYPE_CODE_METADATA = 16, // METADATA
-
- TYPE_CODE_X86_MMX = 17, // X86 MMX
-
- TYPE_CODE_STRUCT_ANON = 18, // STRUCT_ANON: [ispacked, eltty x N]
- TYPE_CODE_STRUCT_NAME = 19, // STRUCT_NAME: [strchr x N]
- TYPE_CODE_STRUCT_NAMED = 20,// STRUCT_NAMED: [ispacked, eltty x N]
-
- TYPE_CODE_FUNCTION = 21, // FUNCTION: [vararg, retty, paramty x N]
-
- TYPE_CODE_TOKEN = 22 // TOKEN
- };
-
- enum OperandBundleTagCode {
- OPERAND_BUNDLE_TAG = 1, // TAG: [strchr x N]
- };
-
- // The type symbol table only has one code (TST_ENTRY_CODE).
- enum TypeSymtabCodes {
- TST_CODE_ENTRY = 1 // TST_ENTRY: [typeid, namechar x N]
- };
-
- // Value symbol table codes.
- enum ValueSymtabCodes {
- VST_CODE_ENTRY = 1, // VST_ENTRY: [valueid, namechar x N]
- VST_CODE_BBENTRY = 2, // VST_BBENTRY: [bbid, namechar x N]
- VST_CODE_FNENTRY = 3, // VST_FNENTRY: [valueid, offset, namechar x N]
- // VST_COMBINED_FNENTRY: [offset, namechar x N]
- VST_CODE_COMBINED_FNENTRY = 4
- };
-
- // The module path symbol table only has one code (MST_CODE_ENTRY).
- enum ModulePathSymtabCodes {
- MST_CODE_ENTRY = 1, // MST_ENTRY: [modid, namechar x N]
- };
-
- // The function summary section uses different codes in the per-module
- // and combined index cases.
- enum FunctionSummarySymtabCodes {
- FS_CODE_PERMODULE_ENTRY = 1, // FS_ENTRY: [valueid, islocal, instcount]
- FS_CODE_COMBINED_ENTRY = 2, // FS_ENTRY: [modid, instcount]
- };
-
- enum MetadataCodes {
- METADATA_STRING = 1, // MDSTRING: [values]
- METADATA_VALUE = 2, // VALUE: [type num, value num]
- METADATA_NODE = 3, // NODE: [n x md num]
- METADATA_NAME = 4, // STRING: [values]
- METADATA_DISTINCT_NODE = 5, // DISTINCT_NODE: [n x md num]
- METADATA_KIND = 6, // [n x [id, name]]
- METADATA_LOCATION = 7, // [distinct, line, col, scope, inlined-at?]
- METADATA_OLD_NODE = 8, // OLD_NODE: [n x (type num, value num)]
- METADATA_OLD_FN_NODE = 9, // OLD_FN_NODE: [n x (type num, value num)]
- METADATA_NAMED_NODE = 10, // NAMED_NODE: [n x mdnodes]
- METADATA_ATTACHMENT = 11, // [m x [value, [n x [id, mdnode]]]
- METADATA_GENERIC_DEBUG = 12, // [distinct, tag, vers, header, n x md num]
- METADATA_SUBRANGE = 13, // [distinct, count, lo]
- METADATA_ENUMERATOR = 14, // [distinct, value, name]
- METADATA_BASIC_TYPE = 15, // [distinct, tag, name, size, align, enc]
- METADATA_FILE = 16, // [distinct, filename, directory]
- METADATA_DERIVED_TYPE = 17, // [distinct, ...]
- METADATA_COMPOSITE_TYPE= 18, // [distinct, ...]
- METADATA_SUBROUTINE_TYPE=19, // [distinct, flags, types]
- METADATA_COMPILE_UNIT = 20, // [distinct, ...]
- METADATA_SUBPROGRAM = 21, // [distinct, ...]
- METADATA_LEXICAL_BLOCK = 22, // [distinct, scope, file, line, column]
- METADATA_LEXICAL_BLOCK_FILE=23,//[distinct, scope, file, discriminator]
- METADATA_NAMESPACE = 24, // [distinct, scope, file, name, line]
- METADATA_TEMPLATE_TYPE = 25, // [distinct, scope, name, type, ...]
- METADATA_TEMPLATE_VALUE= 26, // [distinct, scope, name, type, value, ...]
- METADATA_GLOBAL_VAR = 27, // [distinct, ...]
- METADATA_LOCAL_VAR = 28, // [distinct, ...]
- METADATA_EXPRESSION = 29, // [distinct, n x element]
- METADATA_OBJC_PROPERTY = 30, // [distinct, name, file, line, ...]
- METADATA_IMPORTED_ENTITY=31, // [distinct, tag, scope, entity, line, name]
- METADATA_MODULE = 32, // [distinct, scope, name, ...]
- METADATA_MACRO = 33, // [distinct, macinfo, line, name, value]
- METADATA_MACRO_FILE = 34, // [distinct, macinfo, line, file, ...]
- };
-
- // The constants block (CONSTANTS_BLOCK_ID) describes emission for each
- // constant and maintains an implicit current type value.
- enum ConstantsCodes {
- CST_CODE_SETTYPE = 1, // SETTYPE: [typeid]
- CST_CODE_NULL = 2, // NULL
- CST_CODE_UNDEF = 3, // UNDEF
- CST_CODE_INTEGER = 4, // INTEGER: [intval]
- CST_CODE_WIDE_INTEGER = 5, // WIDE_INTEGER: [n x intval]
- CST_CODE_FLOAT = 6, // FLOAT: [fpval]
- CST_CODE_AGGREGATE = 7, // AGGREGATE: [n x value number]
- CST_CODE_STRING = 8, // STRING: [values]
- CST_CODE_CSTRING = 9, // CSTRING: [values]
- CST_CODE_CE_BINOP = 10, // CE_BINOP: [opcode, opval, opval]
- CST_CODE_CE_CAST = 11, // CE_CAST: [opcode, opty, opval]
- CST_CODE_CE_GEP = 12, // CE_GEP: [n x operands]
- CST_CODE_CE_SELECT = 13, // CE_SELECT: [opval, opval, opval]
- CST_CODE_CE_EXTRACTELT = 14, // CE_EXTRACTELT: [opty, opval, opval]
- CST_CODE_CE_INSERTELT = 15, // CE_INSERTELT: [opval, opval, opval]
- CST_CODE_CE_SHUFFLEVEC = 16, // CE_SHUFFLEVEC: [opval, opval, opval]
- CST_CODE_CE_CMP = 17, // CE_CMP: [opty, opval, opval, pred]
- CST_CODE_INLINEASM_OLD = 18, // INLINEASM: [sideeffect|alignstack,
- // asmstr,conststr]
- CST_CODE_CE_SHUFVEC_EX = 19, // SHUFVEC_EX: [opty, opval, opval, opval]
- CST_CODE_CE_INBOUNDS_GEP = 20,// INBOUNDS_GEP: [n x operands]
- CST_CODE_BLOCKADDRESS = 21, // CST_CODE_BLOCKADDRESS [fnty, fnval, bb#]
- CST_CODE_DATA = 22, // DATA: [n x elements]
- CST_CODE_INLINEASM = 23 // INLINEASM: [sideeffect|alignstack|
- // asmdialect,asmstr,conststr]
- };
-
- /// CastOpcodes - These are values used in the bitcode files to encode which
- /// cast a CST_CODE_CE_CAST or a XXX refers to. The values of these enums
- /// have no fixed relation to the LLVM IR enum values. Changing these will
- /// break compatibility with old files.
- enum CastOpcodes {
- CAST_TRUNC = 0,
- CAST_ZEXT = 1,
- CAST_SEXT = 2,
- CAST_FPTOUI = 3,
- CAST_FPTOSI = 4,
- CAST_UITOFP = 5,
- CAST_SITOFP = 6,
- CAST_FPTRUNC = 7,
- CAST_FPEXT = 8,
- CAST_PTRTOINT = 9,
- CAST_INTTOPTR = 10,
- CAST_BITCAST = 11,
- CAST_ADDRSPACECAST = 12
- };
-
- /// BinaryOpcodes - These are values used in the bitcode files to encode which
- /// binop a CST_CODE_CE_BINOP or a XXX refers to. The values of these enums
- /// have no fixed relation to the LLVM IR enum values. Changing these will
- /// break compatibility with old files.
- enum BinaryOpcodes {
- BINOP_ADD = 0,
- BINOP_SUB = 1,
- BINOP_MUL = 2,
- BINOP_UDIV = 3,
- BINOP_SDIV = 4, // overloaded for FP
- BINOP_UREM = 5,
- BINOP_SREM = 6, // overloaded for FP
- BINOP_SHL = 7,
- BINOP_LSHR = 8,
- BINOP_ASHR = 9,
- BINOP_AND = 10,
- BINOP_OR = 11,
- BINOP_XOR = 12
- };
-
- /// These are values used in the bitcode files to encode AtomicRMW operations.
- /// The values of these enums have no fixed relation to the LLVM IR enum
- /// values. Changing these will break compatibility with old files.
- enum RMWOperations {
- RMW_XCHG = 0,
- RMW_ADD = 1,
- RMW_SUB = 2,
- RMW_AND = 3,
- RMW_NAND = 4,
- RMW_OR = 5,
- RMW_XOR = 6,
- RMW_MAX = 7,
- RMW_MIN = 8,
- RMW_UMAX = 9,
- RMW_UMIN = 10
- };
-
- /// OverflowingBinaryOperatorOptionalFlags - Flags for serializing
- /// OverflowingBinaryOperator's SubclassOptionalData contents.
- enum OverflowingBinaryOperatorOptionalFlags {
- OBO_NO_UNSIGNED_WRAP = 0,
- OBO_NO_SIGNED_WRAP = 1
- };
-
- /// PossiblyExactOperatorOptionalFlags - Flags for serializing
- /// PossiblyExactOperator's SubclassOptionalData contents.
- enum PossiblyExactOperatorOptionalFlags {
- PEO_EXACT = 0
- };
-
- /// Encoded AtomicOrdering values.
- enum AtomicOrderingCodes {
- ORDERING_NOTATOMIC = 0,
- ORDERING_UNORDERED = 1,
- ORDERING_MONOTONIC = 2,
- ORDERING_ACQUIRE = 3,
- ORDERING_RELEASE = 4,
- ORDERING_ACQREL = 5,
- ORDERING_SEQCST = 6
- };
-
- /// Encoded SynchronizationScope values.
- enum AtomicSynchScopeCodes {
- SYNCHSCOPE_SINGLETHREAD = 0,
- SYNCHSCOPE_CROSSTHREAD = 1
- };
-
- /// Markers and flags for call instruction.
- enum CallMarkersFlags {
- CALL_TAIL = 0,
- CALL_CCONV = 1,
- CALL_MUSTTAIL = 14,
- CALL_EXPLICIT_TYPE = 15,
- CALL_NOTAIL = 16,
- CALL_FMF = 17 // Call has optional fast-math-flags.
- };
-
- // The function body block (FUNCTION_BLOCK_ID) describes function bodies. It
- // can contain a constant block (CONSTANTS_BLOCK_ID).
- enum FunctionCodes {
- FUNC_CODE_DECLAREBLOCKS = 1, // DECLAREBLOCKS: [n]
-
- FUNC_CODE_INST_BINOP = 2, // BINOP: [opcode, ty, opval, opval]
- FUNC_CODE_INST_CAST = 3, // CAST: [opcode, ty, opty, opval]
- FUNC_CODE_INST_GEP_OLD = 4, // GEP: [n x operands]
- FUNC_CODE_INST_SELECT = 5, // SELECT: [ty, opval, opval, opval]
- FUNC_CODE_INST_EXTRACTELT = 6, // EXTRACTELT: [opty, opval, opval]
- FUNC_CODE_INST_INSERTELT = 7, // INSERTELT: [ty, opval, opval, opval]
- FUNC_CODE_INST_SHUFFLEVEC = 8, // SHUFFLEVEC: [ty, opval, opval, opval]
- FUNC_CODE_INST_CMP = 9, // CMP: [opty, opval, opval, pred]
-
- FUNC_CODE_INST_RET = 10, // RET: [opty,opval<both optional>]
- FUNC_CODE_INST_BR = 11, // BR: [bb#, bb#, cond] or [bb#]
- FUNC_CODE_INST_SWITCH = 12, // SWITCH: [opty, op0, op1, ...]
- FUNC_CODE_INST_INVOKE = 13, // INVOKE: [attr, fnty, op0,op1, ...]
- // 14 is unused.
- FUNC_CODE_INST_UNREACHABLE = 15, // UNREACHABLE
-
- FUNC_CODE_INST_PHI = 16, // PHI: [ty, val0,bb0, ...]
- // 17 is unused.
- // 18 is unused.
- FUNC_CODE_INST_ALLOCA = 19, // ALLOCA: [instty, opty, op, align]
- FUNC_CODE_INST_LOAD = 20, // LOAD: [opty, op, align, vol]
- // 21 is unused.
- // 22 is unused.
- FUNC_CODE_INST_VAARG = 23, // VAARG: [valistty, valist, instty]
- // This store code encodes the pointer type, rather than the value type
- // this is so information only available in the pointer type (e.g. address
- // spaces) is retained.
- FUNC_CODE_INST_STORE_OLD = 24, // STORE: [ptrty,ptr,val, align, vol]
- // 25 is unused.
- FUNC_CODE_INST_EXTRACTVAL = 26, // EXTRACTVAL: [n x operands]
- FUNC_CODE_INST_INSERTVAL = 27, // INSERTVAL: [n x operands]
- // fcmp/icmp returning Int1TY or vector of Int1Ty. Same as CMP, exists to
- // support legacy vicmp/vfcmp instructions.
- FUNC_CODE_INST_CMP2 = 28, // CMP2: [opty, opval, opval, pred]
- // new select on i1 or [N x i1]
- FUNC_CODE_INST_VSELECT = 29, // VSELECT: [ty,opval,opval,predty,pred]
- FUNC_CODE_INST_INBOUNDS_GEP_OLD = 30, // INBOUNDS_GEP: [n x operands]
- FUNC_CODE_INST_INDIRECTBR = 31, // INDIRECTBR: [opty, op0, op1, ...]
- // 32 is unused.
- FUNC_CODE_DEBUG_LOC_AGAIN = 33, // DEBUG_LOC_AGAIN
-
- FUNC_CODE_INST_CALL = 34, // CALL: [attr, cc, fnty, fnid, args...]
-
- 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_ATOMICRMW = 38, // ATOMICRMW: [ptrty,ptr,val, operation,
- // align, vol,
- // ordering, synchscope]
- FUNC_CODE_INST_RESUME = 39, // RESUME: [opval]
- FUNC_CODE_INST_LANDINGPAD_OLD = 40, // LANDINGPAD: [ty,val,val,num,id0,val0...]
- FUNC_CODE_INST_LOADATOMIC = 41, // LOAD: [opty, op, align, vol,
- // ordering, synchscope]
- FUNC_CODE_INST_STOREATOMIC_OLD = 42, // STORE: [ptrty,ptr,val, align, vol
- // ordering, synchscope]
- 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_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#]
- FUNC_CODE_INST_CATCHPAD = 50, // CATCHPAD: [bb#,bb#,num,args...]
- FUNC_CODE_INST_CLEANUPPAD = 51, // CLEANUPPAD: [num,args...]
- FUNC_CODE_INST_CATCHSWITCH = 52, // CATCHSWITCH: [num,args...] or [num,args...,bb]
- // 53 is unused.
- // 54 is unused.
- FUNC_CODE_OPERAND_BUNDLE = 55, // OPERAND_BUNDLE: [tag#, value...]
- };
-
- enum UseListCodes {
- USELIST_CODE_DEFAULT = 1, // DEFAULT: [index..., value-id]
- USELIST_CODE_BB = 2 // BB: [index..., bb-id]
- };
-
- enum AttributeKindCodes {
- // = 0 is unused
- ATTR_KIND_ALIGNMENT = 1,
- ATTR_KIND_ALWAYS_INLINE = 2,
- ATTR_KIND_BY_VAL = 3,
- ATTR_KIND_INLINE_HINT = 4,
- ATTR_KIND_IN_REG = 5,
- ATTR_KIND_MIN_SIZE = 6,
- ATTR_KIND_NAKED = 7,
- ATTR_KIND_NEST = 8,
- ATTR_KIND_NO_ALIAS = 9,
- ATTR_KIND_NO_BUILTIN = 10,
- ATTR_KIND_NO_CAPTURE = 11,
- ATTR_KIND_NO_DUPLICATE = 12,
- ATTR_KIND_NO_IMPLICIT_FLOAT = 13,
- ATTR_KIND_NO_INLINE = 14,
- ATTR_KIND_NON_LAZY_BIND = 15,
- ATTR_KIND_NO_RED_ZONE = 16,
- ATTR_KIND_NO_RETURN = 17,
- ATTR_KIND_NO_UNWIND = 18,
- ATTR_KIND_OPTIMIZE_FOR_SIZE = 19,
- ATTR_KIND_READ_NONE = 20,
- ATTR_KIND_READ_ONLY = 21,
- ATTR_KIND_RETURNED = 22,
- ATTR_KIND_RETURNS_TWICE = 23,
- ATTR_KIND_S_EXT = 24,
- ATTR_KIND_STACK_ALIGNMENT = 25,
- ATTR_KIND_STACK_PROTECT = 26,
- ATTR_KIND_STACK_PROTECT_REQ = 27,
- ATTR_KIND_STACK_PROTECT_STRONG = 28,
- ATTR_KIND_STRUCT_RET = 29,
- ATTR_KIND_SANITIZE_ADDRESS = 30,
- ATTR_KIND_SANITIZE_THREAD = 31,
- ATTR_KIND_SANITIZE_MEMORY = 32,
- ATTR_KIND_UW_TABLE = 33,
- ATTR_KIND_Z_EXT = 34,
- ATTR_KIND_BUILTIN = 35,
- ATTR_KIND_COLD = 36,
- ATTR_KIND_OPTIMIZE_NONE = 37,
- ATTR_KIND_IN_ALLOCA = 38,
- ATTR_KIND_NON_NULL = 39,
- ATTR_KIND_JUMP_TABLE = 40,
- ATTR_KIND_DEREFERENCEABLE = 41,
- ATTR_KIND_DEREFERENCEABLE_OR_NULL = 42,
- ATTR_KIND_CONVERGENT = 43,
- ATTR_KIND_SAFESTACK = 44,
- ATTR_KIND_ARGMEMONLY = 45,
- ATTR_KIND_SWIFT_SELF = 46,
- ATTR_KIND_SWIFT_ERROR = 47,
- ATTR_KIND_NO_RECURSE = 48,
- ATTR_KIND_INACCESSIBLEMEM_ONLY = 49,
- ATTR_KIND_INACCESSIBLEMEM_OR_ARGMEMONLY = 50
- };
-
- enum ComdatSelectionKindCodes {
- COMDAT_SELECTION_KIND_ANY = 1,
- COMDAT_SELECTION_KIND_EXACT_MATCH = 2,
- COMDAT_SELECTION_KIND_LARGEST = 3,
- COMDAT_SELECTION_KIND_NO_DUPLICATES = 4,
- COMDAT_SELECTION_KIND_SAME_SIZE = 5,
- };
+/// MODULE blocks have a number of optional fields and subblocks.
+enum ModuleCodes {
+ MODULE_CODE_VERSION = 1, // VERSION: [version#]
+ MODULE_CODE_TRIPLE = 2, // TRIPLE: [strchr x N]
+ MODULE_CODE_DATALAYOUT = 3, // DATALAYOUT: [strchr x N]
+ MODULE_CODE_ASM = 4, // ASM: [strchr x N]
+ MODULE_CODE_SECTIONNAME = 5, // SECTIONNAME: [strchr x N]
+
+ // FIXME: Remove DEPLIB in 4.0.
+ MODULE_CODE_DEPLIB = 6, // DEPLIB: [strchr x N]
+
+ // GLOBALVAR: [pointer type, isconst, initid,
+ // linkage, alignment, section, visibility, threadlocal]
+ MODULE_CODE_GLOBALVAR = 7,
+
+ // FUNCTION: [type, callingconv, isproto, linkage, paramattrs, alignment,
+ // section, visibility, gc, unnamed_addr]
+ MODULE_CODE_FUNCTION = 8,
+
+ // ALIAS: [alias type, aliasee val#, linkage, visibility]
+ MODULE_CODE_ALIAS_OLD = 9,
+
+ // MODULE_CODE_PURGEVALS: [numvals]
+ MODULE_CODE_PURGEVALS = 10,
+
+ MODULE_CODE_GCNAME = 11, // GCNAME: [strchr x N]
+ MODULE_CODE_COMDAT = 12, // COMDAT: [selection_kind, name]
+
+ MODULE_CODE_VSTOFFSET = 13, // VSTOFFSET: [offset]
+
+ // ALIAS: [alias value type, addrspace, aliasee val#, linkage, visibility]
+ MODULE_CODE_ALIAS = 14,
+
+ MODULE_CODE_METADATA_VALUES_UNUSED = 15,
+
+ // SOURCE_FILENAME: [namechar x N]
+ MODULE_CODE_SOURCE_FILENAME = 16,
+
+ // HASH: [5*i32]
+ MODULE_CODE_HASH = 17,
+
+ // IFUNC: [ifunc value type, addrspace, resolver val#, linkage, visibility]
+ MODULE_CODE_IFUNC = 18,
+};
+
+/// PARAMATTR blocks have code for defining a parameter attribute set.
+enum AttributeCodes {
+ // FIXME: Remove `PARAMATTR_CODE_ENTRY_OLD' in 4.0
+ PARAMATTR_CODE_ENTRY_OLD = 1, // ENTRY: [paramidx0, attr0,
+ // paramidx1, attr1...]
+ PARAMATTR_CODE_ENTRY = 2, // ENTRY: [paramidx0, attrgrp0,
+ // paramidx1, attrgrp1, ...]
+ PARAMATTR_GRP_CODE_ENTRY = 3 // ENTRY: [id, attr0, att1, ...]
+};
+
+/// TYPE blocks have codes for each type primitive they use.
+enum TypeCodes {
+ TYPE_CODE_NUMENTRY = 1, // NUMENTRY: [numentries]
+
+ // Type Codes
+ TYPE_CODE_VOID = 2, // VOID
+ TYPE_CODE_FLOAT = 3, // FLOAT
+ TYPE_CODE_DOUBLE = 4, // DOUBLE
+ TYPE_CODE_LABEL = 5, // LABEL
+ TYPE_CODE_OPAQUE = 6, // OPAQUE
+ TYPE_CODE_INTEGER = 7, // INTEGER: [width]
+ TYPE_CODE_POINTER = 8, // POINTER: [pointee type]
+
+ TYPE_CODE_FUNCTION_OLD = 9, // FUNCTION: [vararg, attrid, retty,
+ // paramty x N]
+
+ TYPE_CODE_HALF = 10, // HALF
+
+ TYPE_CODE_ARRAY = 11, // ARRAY: [numelts, eltty]
+ TYPE_CODE_VECTOR = 12, // VECTOR: [numelts, eltty]
+
+ // These are not with the other floating point types because they're
+ // a late addition, and putting them in the right place breaks
+ // binary compatibility.
+ TYPE_CODE_X86_FP80 = 13, // X86 LONG DOUBLE
+ TYPE_CODE_FP128 = 14, // LONG DOUBLE (112 bit mantissa)
+ TYPE_CODE_PPC_FP128 = 15, // PPC LONG DOUBLE (2 doubles)
+
+ TYPE_CODE_METADATA = 16, // METADATA
+
+ TYPE_CODE_X86_MMX = 17, // X86 MMX
+
+ TYPE_CODE_STRUCT_ANON = 18, // STRUCT_ANON: [ispacked, eltty x N]
+ TYPE_CODE_STRUCT_NAME = 19, // STRUCT_NAME: [strchr x N]
+ TYPE_CODE_STRUCT_NAMED = 20, // STRUCT_NAMED: [ispacked, eltty x N]
+
+ TYPE_CODE_FUNCTION = 21, // FUNCTION: [vararg, retty, paramty x N]
+
+ TYPE_CODE_TOKEN = 22 // TOKEN
+};
+
+enum OperandBundleTagCode {
+ OPERAND_BUNDLE_TAG = 1, // TAG: [strchr x N]
+};
+
+// The type symbol table only has one code (TST_ENTRY_CODE).
+enum TypeSymtabCodes {
+ TST_CODE_ENTRY = 1 // TST_ENTRY: [typeid, namechar x N]
+};
+
+// Value symbol table codes.
+enum ValueSymtabCodes {
+ VST_CODE_ENTRY = 1, // VST_ENTRY: [valueid, namechar x N]
+ VST_CODE_BBENTRY = 2, // VST_BBENTRY: [bbid, namechar x N]
+ VST_CODE_FNENTRY = 3, // VST_FNENTRY: [valueid, offset, namechar x N]
+ // VST_COMBINED_ENTRY: [valueid, refguid]
+ VST_CODE_COMBINED_ENTRY = 5
+};
+
+// The module path symbol table only has one code (MST_CODE_ENTRY).
+enum ModulePathSymtabCodes {
+ MST_CODE_ENTRY = 1, // MST_ENTRY: [modid, namechar x N]
+ MST_CODE_HASH = 2, // MST_HASH: [5*i32]
+};
+
+// The summary section uses different codes in the per-module
+// and combined index cases.
+enum GlobalValueSummarySymtabCodes {
+ // PERMODULE: [valueid, flags, instcount, numrefs, numrefs x valueid,
+ // n x (valueid, callsitecount)]
+ FS_PERMODULE = 1,
+ // PERMODULE_PROFILE: [valueid, flags, instcount, numrefs,
+ // numrefs x valueid,
+ // n x (valueid, callsitecount, profilecount)]
+ FS_PERMODULE_PROFILE = 2,
+ // PERMODULE_GLOBALVAR_INIT_REFS: [valueid, flags, n x valueid]
+ FS_PERMODULE_GLOBALVAR_INIT_REFS = 3,
+ // COMBINED: [valueid, modid, flags, instcount, numrefs, numrefs x valueid,
+ // n x (valueid, callsitecount)]
+ FS_COMBINED = 4,
+ // COMBINED_PROFILE: [valueid, modid, flags, instcount, numrefs,
+ // numrefs x valueid,
+ // n x (valueid, callsitecount, profilecount)]
+ FS_COMBINED_PROFILE = 5,
+ // COMBINED_GLOBALVAR_INIT_REFS: [valueid, modid, flags, n x valueid]
+ FS_COMBINED_GLOBALVAR_INIT_REFS = 6,
+ // ALIAS: [valueid, flags, valueid]
+ FS_ALIAS = 7,
+ // COMBINED_ALIAS: [valueid, modid, flags, valueid]
+ FS_COMBINED_ALIAS = 8,
+ // COMBINED_ORIGINAL_NAME: [original_name_hash]
+ FS_COMBINED_ORIGINAL_NAME = 9,
+ // VERSION of the summary, bumped when adding flags for instance.
+ FS_VERSION = 10,
+};
+
+enum MetadataCodes {
+ METADATA_STRING_OLD = 1, // MDSTRING: [values]
+ METADATA_VALUE = 2, // VALUE: [type num, value num]
+ METADATA_NODE = 3, // NODE: [n x md num]
+ METADATA_NAME = 4, // STRING: [values]
+ METADATA_DISTINCT_NODE = 5, // DISTINCT_NODE: [n x md num]
+ METADATA_KIND = 6, // [n x [id, name]]
+ METADATA_LOCATION = 7, // [distinct, line, col, scope, inlined-at?]
+ METADATA_OLD_NODE = 8, // OLD_NODE: [n x (type num, value num)]
+ METADATA_OLD_FN_NODE = 9, // OLD_FN_NODE: [n x (type num, value num)]
+ METADATA_NAMED_NODE = 10, // NAMED_NODE: [n x mdnodes]
+ METADATA_ATTACHMENT = 11, // [m x [value, [n x [id, mdnode]]]
+ METADATA_GENERIC_DEBUG = 12, // [distinct, tag, vers, header, n x md num]
+ METADATA_SUBRANGE = 13, // [distinct, count, lo]
+ METADATA_ENUMERATOR = 14, // [distinct, value, name]
+ METADATA_BASIC_TYPE = 15, // [distinct, tag, name, size, align, enc]
+ METADATA_FILE = 16, // [distinct, filename, directory]
+ METADATA_DERIVED_TYPE = 17, // [distinct, ...]
+ METADATA_COMPOSITE_TYPE = 18, // [distinct, ...]
+ METADATA_SUBROUTINE_TYPE = 19, // [distinct, flags, types, cc]
+ METADATA_COMPILE_UNIT = 20, // [distinct, ...]
+ METADATA_SUBPROGRAM = 21, // [distinct, ...]
+ METADATA_LEXICAL_BLOCK = 22, // [distinct, scope, file, line, column]
+ METADATA_LEXICAL_BLOCK_FILE = 23, //[distinct, scope, file, discriminator]
+ METADATA_NAMESPACE = 24, // [distinct, scope, file, name, line]
+ METADATA_TEMPLATE_TYPE = 25, // [distinct, scope, name, type, ...]
+ METADATA_TEMPLATE_VALUE = 26, // [distinct, scope, name, type, value, ...]
+ METADATA_GLOBAL_VAR = 27, // [distinct, ...]
+ METADATA_LOCAL_VAR = 28, // [distinct, ...]
+ METADATA_EXPRESSION = 29, // [distinct, n x element]
+ METADATA_OBJC_PROPERTY = 30, // [distinct, name, file, line, ...]
+ METADATA_IMPORTED_ENTITY = 31, // [distinct, tag, scope, entity, line, name]
+ METADATA_MODULE = 32, // [distinct, scope, name, ...]
+ METADATA_MACRO = 33, // [distinct, macinfo, line, name, value]
+ METADATA_MACRO_FILE = 34, // [distinct, macinfo, line, file, ...]
+ METADATA_STRINGS = 35, // [count, offset] blob([lengths][chars])
+ METADATA_GLOBAL_DECL_ATTACHMENT = 36, // [valueid, n x [id, mdnode]]
+};
+
+// The constants block (CONSTANTS_BLOCK_ID) describes emission for each
+// constant and maintains an implicit current type value.
+enum ConstantsCodes {
+ CST_CODE_SETTYPE = 1, // SETTYPE: [typeid]
+ CST_CODE_NULL = 2, // NULL
+ CST_CODE_UNDEF = 3, // UNDEF
+ CST_CODE_INTEGER = 4, // INTEGER: [intval]
+ CST_CODE_WIDE_INTEGER = 5, // WIDE_INTEGER: [n x intval]
+ CST_CODE_FLOAT = 6, // FLOAT: [fpval]
+ CST_CODE_AGGREGATE = 7, // AGGREGATE: [n x value number]
+ CST_CODE_STRING = 8, // STRING: [values]
+ CST_CODE_CSTRING = 9, // CSTRING: [values]
+ CST_CODE_CE_BINOP = 10, // CE_BINOP: [opcode, opval, opval]
+ CST_CODE_CE_CAST = 11, // CE_CAST: [opcode, opty, opval]
+ CST_CODE_CE_GEP = 12, // CE_GEP: [n x operands]
+ CST_CODE_CE_SELECT = 13, // CE_SELECT: [opval, opval, opval]
+ CST_CODE_CE_EXTRACTELT = 14, // CE_EXTRACTELT: [opty, opval, opval]
+ CST_CODE_CE_INSERTELT = 15, // CE_INSERTELT: [opval, opval, opval]
+ CST_CODE_CE_SHUFFLEVEC = 16, // CE_SHUFFLEVEC: [opval, opval, opval]
+ CST_CODE_CE_CMP = 17, // CE_CMP: [opty, opval, opval, pred]
+ CST_CODE_INLINEASM_OLD = 18, // INLINEASM: [sideeffect|alignstack,
+ // asmstr,conststr]
+ CST_CODE_CE_SHUFVEC_EX = 19, // SHUFVEC_EX: [opty, opval, opval, opval]
+ CST_CODE_CE_INBOUNDS_GEP = 20, // INBOUNDS_GEP: [n x operands]
+ CST_CODE_BLOCKADDRESS = 21, // CST_CODE_BLOCKADDRESS [fnty, fnval, bb#]
+ CST_CODE_DATA = 22, // DATA: [n x elements]
+ CST_CODE_INLINEASM = 23 // INLINEASM: [sideeffect|alignstack|
+ // asmdialect,asmstr,conststr]
+};
+
+/// CastOpcodes - These are values used in the bitcode files to encode which
+/// cast a CST_CODE_CE_CAST or a XXX refers to. The values of these enums
+/// have no fixed relation to the LLVM IR enum values. Changing these will
+/// break compatibility with old files.
+enum CastOpcodes {
+ CAST_TRUNC = 0,
+ CAST_ZEXT = 1,
+ CAST_SEXT = 2,
+ CAST_FPTOUI = 3,
+ CAST_FPTOSI = 4,
+ CAST_UITOFP = 5,
+ CAST_SITOFP = 6,
+ CAST_FPTRUNC = 7,
+ CAST_FPEXT = 8,
+ CAST_PTRTOINT = 9,
+ CAST_INTTOPTR = 10,
+ CAST_BITCAST = 11,
+ CAST_ADDRSPACECAST = 12
+};
+
+/// BinaryOpcodes - These are values used in the bitcode files to encode which
+/// binop a CST_CODE_CE_BINOP or a XXX refers to. The values of these enums
+/// have no fixed relation to the LLVM IR enum values. Changing these will
+/// break compatibility with old files.
+enum BinaryOpcodes {
+ BINOP_ADD = 0,
+ BINOP_SUB = 1,
+ BINOP_MUL = 2,
+ BINOP_UDIV = 3,
+ BINOP_SDIV = 4, // overloaded for FP
+ BINOP_UREM = 5,
+ BINOP_SREM = 6, // overloaded for FP
+ BINOP_SHL = 7,
+ BINOP_LSHR = 8,
+ BINOP_ASHR = 9,
+ BINOP_AND = 10,
+ BINOP_OR = 11,
+ BINOP_XOR = 12
+};
+
+/// These are values used in the bitcode files to encode AtomicRMW operations.
+/// The values of these enums have no fixed relation to the LLVM IR enum
+/// values. Changing these will break compatibility with old files.
+enum RMWOperations {
+ RMW_XCHG = 0,
+ RMW_ADD = 1,
+ RMW_SUB = 2,
+ RMW_AND = 3,
+ RMW_NAND = 4,
+ RMW_OR = 5,
+ RMW_XOR = 6,
+ RMW_MAX = 7,
+ RMW_MIN = 8,
+ RMW_UMAX = 9,
+ RMW_UMIN = 10
+};
+
+/// OverflowingBinaryOperatorOptionalFlags - Flags for serializing
+/// OverflowingBinaryOperator's SubclassOptionalData contents.
+enum OverflowingBinaryOperatorOptionalFlags {
+ OBO_NO_UNSIGNED_WRAP = 0,
+ OBO_NO_SIGNED_WRAP = 1
+};
+
+/// PossiblyExactOperatorOptionalFlags - Flags for serializing
+/// PossiblyExactOperator's SubclassOptionalData contents.
+enum PossiblyExactOperatorOptionalFlags { PEO_EXACT = 0 };
+
+/// Encoded AtomicOrdering values.
+enum AtomicOrderingCodes {
+ ORDERING_NOTATOMIC = 0,
+ ORDERING_UNORDERED = 1,
+ ORDERING_MONOTONIC = 2,
+ ORDERING_ACQUIRE = 3,
+ ORDERING_RELEASE = 4,
+ ORDERING_ACQREL = 5,
+ ORDERING_SEQCST = 6
+};
+
+/// Encoded SynchronizationScope values.
+enum AtomicSynchScopeCodes {
+ SYNCHSCOPE_SINGLETHREAD = 0,
+ SYNCHSCOPE_CROSSTHREAD = 1
+};
+
+/// Markers and flags for call instruction.
+enum CallMarkersFlags {
+ CALL_TAIL = 0,
+ CALL_CCONV = 1,
+ CALL_MUSTTAIL = 14,
+ CALL_EXPLICIT_TYPE = 15,
+ CALL_NOTAIL = 16,
+ CALL_FMF = 17 // Call has optional fast-math-flags.
+};
+
+// The function body block (FUNCTION_BLOCK_ID) describes function bodies. It
+// can contain a constant block (CONSTANTS_BLOCK_ID).
+enum FunctionCodes {
+ FUNC_CODE_DECLAREBLOCKS = 1, // DECLAREBLOCKS: [n]
+
+ FUNC_CODE_INST_BINOP = 2, // BINOP: [opcode, ty, opval, opval]
+ FUNC_CODE_INST_CAST = 3, // CAST: [opcode, ty, opty, opval]
+ FUNC_CODE_INST_GEP_OLD = 4, // GEP: [n x operands]
+ FUNC_CODE_INST_SELECT = 5, // SELECT: [ty, opval, opval, opval]
+ FUNC_CODE_INST_EXTRACTELT = 6, // EXTRACTELT: [opty, opval, opval]
+ FUNC_CODE_INST_INSERTELT = 7, // INSERTELT: [ty, opval, opval, opval]
+ FUNC_CODE_INST_SHUFFLEVEC = 8, // SHUFFLEVEC: [ty, opval, opval, opval]
+ FUNC_CODE_INST_CMP = 9, // CMP: [opty, opval, opval, pred]
+
+ FUNC_CODE_INST_RET = 10, // RET: [opty,opval<both optional>]
+ FUNC_CODE_INST_BR = 11, // BR: [bb#, bb#, cond] or [bb#]
+ FUNC_CODE_INST_SWITCH = 12, // SWITCH: [opty, op0, op1, ...]
+ FUNC_CODE_INST_INVOKE = 13, // INVOKE: [attr, fnty, op0,op1, ...]
+ // 14 is unused.
+ FUNC_CODE_INST_UNREACHABLE = 15, // UNREACHABLE
+
+ FUNC_CODE_INST_PHI = 16, // PHI: [ty, val0,bb0, ...]
+ // 17 is unused.
+ // 18 is unused.
+ FUNC_CODE_INST_ALLOCA = 19, // ALLOCA: [instty, opty, op, align]
+ FUNC_CODE_INST_LOAD = 20, // LOAD: [opty, op, align, vol]
+ // 21 is unused.
+ // 22 is unused.
+ FUNC_CODE_INST_VAARG = 23, // VAARG: [valistty, valist, instty]
+ // This store code encodes the pointer type, rather than the value type
+ // this is so information only available in the pointer type (e.g. address
+ // spaces) is retained.
+ FUNC_CODE_INST_STORE_OLD = 24, // STORE: [ptrty,ptr,val, align, vol]
+ // 25 is unused.
+ FUNC_CODE_INST_EXTRACTVAL = 26, // EXTRACTVAL: [n x operands]
+ FUNC_CODE_INST_INSERTVAL = 27, // INSERTVAL: [n x operands]
+ // fcmp/icmp returning Int1TY or vector of Int1Ty. Same as CMP, exists to
+ // support legacy vicmp/vfcmp instructions.
+ FUNC_CODE_INST_CMP2 = 28, // CMP2: [opty, opval, opval, pred]
+ // new select on i1 or [N x i1]
+ FUNC_CODE_INST_VSELECT = 29, // VSELECT: [ty,opval,opval,predty,pred]
+ FUNC_CODE_INST_INBOUNDS_GEP_OLD = 30, // INBOUNDS_GEP: [n x operands]
+ FUNC_CODE_INST_INDIRECTBR = 31, // INDIRECTBR: [opty, op0, op1, ...]
+ // 32 is unused.
+ FUNC_CODE_DEBUG_LOC_AGAIN = 33, // DEBUG_LOC_AGAIN
+
+ FUNC_CODE_INST_CALL = 34, // CALL: [attr, cc, fnty, fnid, args...]
+
+ 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_ATOMICRMW = 38, // ATOMICRMW: [ptrty,ptr,val, operation,
+ // align, vol,
+ // ordering, synchscope]
+ FUNC_CODE_INST_RESUME = 39, // RESUME: [opval]
+ FUNC_CODE_INST_LANDINGPAD_OLD =
+ 40, // LANDINGPAD: [ty,val,val,num,id0,val0...]
+ FUNC_CODE_INST_LOADATOMIC = 41, // LOAD: [opty, op, align, vol,
+ // ordering, synchscope]
+ FUNC_CODE_INST_STOREATOMIC_OLD = 42, // STORE: [ptrty,ptr,val, align, vol
+ // ordering, synchscope]
+ 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_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#]
+ FUNC_CODE_INST_CATCHPAD = 50, // CATCHPAD: [bb#,bb#,num,args...]
+ FUNC_CODE_INST_CLEANUPPAD = 51, // CLEANUPPAD: [num,args...]
+ FUNC_CODE_INST_CATCHSWITCH =
+ 52, // CATCHSWITCH: [num,args...] or [num,args...,bb]
+ // 53 is unused.
+ // 54 is unused.
+ FUNC_CODE_OPERAND_BUNDLE = 55, // OPERAND_BUNDLE: [tag#, value...]
+};
+
+enum UseListCodes {
+ USELIST_CODE_DEFAULT = 1, // DEFAULT: [index..., value-id]
+ USELIST_CODE_BB = 2 // BB: [index..., bb-id]
+};
+
+enum AttributeKindCodes {
+ // = 0 is unused
+ ATTR_KIND_ALIGNMENT = 1,
+ ATTR_KIND_ALWAYS_INLINE = 2,
+ ATTR_KIND_BY_VAL = 3,
+ ATTR_KIND_INLINE_HINT = 4,
+ ATTR_KIND_IN_REG = 5,
+ ATTR_KIND_MIN_SIZE = 6,
+ ATTR_KIND_NAKED = 7,
+ ATTR_KIND_NEST = 8,
+ ATTR_KIND_NO_ALIAS = 9,
+ ATTR_KIND_NO_BUILTIN = 10,
+ ATTR_KIND_NO_CAPTURE = 11,
+ ATTR_KIND_NO_DUPLICATE = 12,
+ ATTR_KIND_NO_IMPLICIT_FLOAT = 13,
+ ATTR_KIND_NO_INLINE = 14,
+ ATTR_KIND_NON_LAZY_BIND = 15,
+ ATTR_KIND_NO_RED_ZONE = 16,
+ ATTR_KIND_NO_RETURN = 17,
+ ATTR_KIND_NO_UNWIND = 18,
+ ATTR_KIND_OPTIMIZE_FOR_SIZE = 19,
+ ATTR_KIND_READ_NONE = 20,
+ ATTR_KIND_READ_ONLY = 21,
+ ATTR_KIND_RETURNED = 22,
+ ATTR_KIND_RETURNS_TWICE = 23,
+ ATTR_KIND_S_EXT = 24,
+ ATTR_KIND_STACK_ALIGNMENT = 25,
+ ATTR_KIND_STACK_PROTECT = 26,
+ ATTR_KIND_STACK_PROTECT_REQ = 27,
+ ATTR_KIND_STACK_PROTECT_STRONG = 28,
+ ATTR_KIND_STRUCT_RET = 29,
+ ATTR_KIND_SANITIZE_ADDRESS = 30,
+ ATTR_KIND_SANITIZE_THREAD = 31,
+ ATTR_KIND_SANITIZE_MEMORY = 32,
+ ATTR_KIND_UW_TABLE = 33,
+ ATTR_KIND_Z_EXT = 34,
+ ATTR_KIND_BUILTIN = 35,
+ ATTR_KIND_COLD = 36,
+ ATTR_KIND_OPTIMIZE_NONE = 37,
+ ATTR_KIND_IN_ALLOCA = 38,
+ ATTR_KIND_NON_NULL = 39,
+ ATTR_KIND_JUMP_TABLE = 40,
+ ATTR_KIND_DEREFERENCEABLE = 41,
+ ATTR_KIND_DEREFERENCEABLE_OR_NULL = 42,
+ ATTR_KIND_CONVERGENT = 43,
+ ATTR_KIND_SAFESTACK = 44,
+ ATTR_KIND_ARGMEMONLY = 45,
+ ATTR_KIND_SWIFT_SELF = 46,
+ ATTR_KIND_SWIFT_ERROR = 47,
+ ATTR_KIND_NO_RECURSE = 48,
+ ATTR_KIND_INACCESSIBLEMEM_ONLY = 49,
+ ATTR_KIND_INACCESSIBLEMEM_OR_ARGMEMONLY = 50,
+ ATTR_KIND_ALLOC_SIZE = 51,
+ ATTR_KIND_WRITEONLY = 52
+};
+
+enum ComdatSelectionKindCodes {
+ COMDAT_SELECTION_KIND_ANY = 1,
+ COMDAT_SELECTION_KIND_EXACT_MATCH = 2,
+ COMDAT_SELECTION_KIND_LARGEST = 3,
+ COMDAT_SELECTION_KIND_NO_DUPLICATES = 4,
+ COMDAT_SELECTION_KIND_SAME_SIZE = 5,
+};
} // End bitc namespace
} // End llvm namespace
diff --git a/include/llvm/Bitcode/ReaderWriter.h b/include/llvm/Bitcode/ReaderWriter.h
index 60d865fd2355..76a60a0b8d25 100644
--- a/include/llvm/Bitcode/ReaderWriter.h
+++ b/include/llvm/Bitcode/ReaderWriter.h
@@ -15,7 +15,7 @@
#define LLVM_BITCODE_READERWRITER_H
#include "llvm/IR/DiagnosticInfo.h"
-#include "llvm/IR/FunctionInfo.h"
+#include "llvm/IR/ModuleSummaryIndex.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -30,6 +30,14 @@ namespace llvm {
class ModulePass;
class raw_ostream;
+ /// Offsets of the 32-bit fields of bitcode wrapper header.
+ static const unsigned BWH_MagicField = 0*4;
+ static const unsigned BWH_VersionField = 1*4;
+ static const unsigned BWH_OffsetField = 2*4;
+ static const unsigned BWH_SizeField = 3*4;
+ static const unsigned BWH_CPUTypeField = 4*4;
+ static const unsigned BWH_HeaderSize = 5*4;
+
/// Read the header of the specified bitcode buffer and prepare for lazy
/// deserialization of function bodies. If ShouldLazyLoadMetadata is true,
/// lazily load metadata as well. If successful, this moves Buffer. On
@@ -52,6 +60,11 @@ namespace llvm {
std::string getBitcodeTargetTriple(MemoryBufferRef Buffer,
LLVMContext &Context);
+ /// Return true if \p Buffer contains a bitcode file with ObjC code (category
+ /// or class) in it.
+ bool isBitcodeContainingObjCCategory(MemoryBufferRef Buffer,
+ LLVMContext &Context);
+
/// Read the header of the specified bitcode buffer and extract just the
/// producer string information. If successful, this returns a string. On
/// error, this returns "".
@@ -62,29 +75,15 @@ namespace llvm {
ErrorOr<std::unique_ptr<Module>> parseBitcodeFile(MemoryBufferRef Buffer,
LLVMContext &Context);
- /// Check if the given bitcode buffer contains a function summary block.
- bool hasFunctionSummary(MemoryBufferRef Buffer,
- DiagnosticHandlerFunction DiagnosticHandler);
-
- /// Parse the specified bitcode buffer, returning the function info index.
- /// If IsLazy is true, parse the entire function summary into
- /// the index. Otherwise skip the function summary section, and only create
- /// an index object with a map from function name to function summary offset.
- /// The index is used to perform lazy function summary reading later.
- ErrorOr<std::unique_ptr<FunctionInfoIndex>>
- getFunctionInfoIndex(MemoryBufferRef Buffer,
- DiagnosticHandlerFunction DiagnosticHandler,
- bool IsLazy = false);
-
- /// This method supports lazy reading of function summary data from the
- /// combined index during function importing. When reading the combined index
- /// file, getFunctionInfoIndex is first invoked with IsLazy=true.
- /// Then this method is called for each function considered for importing,
- /// to parse the summary information for the given function name into
- /// the index.
- std::error_code readFunctionSummary(
- MemoryBufferRef Buffer, DiagnosticHandlerFunction DiagnosticHandler,
- StringRef FunctionName, std::unique_ptr<FunctionInfoIndex> Index);
+ /// Check if the given bitcode buffer contains a summary block.
+ bool
+ hasGlobalValueSummary(MemoryBufferRef Buffer,
+ const DiagnosticHandlerFunction &DiagnosticHandler);
+
+ /// Parse the specified bitcode buffer, returning the module summary index.
+ ErrorOr<std::unique_ptr<ModuleSummaryIndex>>
+ getModuleSummaryIndex(MemoryBufferRef Buffer,
+ const DiagnosticHandlerFunction &DiagnosticHandler);
/// \brief Write the specified module to the specified raw output stream.
///
@@ -95,17 +94,21 @@ namespace llvm {
/// Value in \c M. These will be reconstructed exactly when \a M is
/// deserialized.
///
- /// If \c EmitFunctionSummary, emit the function summary index (currently
+ /// If \c EmitSummaryIndex, emit the module's summary index (currently
/// for use in ThinLTO optimization).
void WriteBitcodeToFile(const Module *M, raw_ostream &Out,
bool ShouldPreserveUseListOrder = false,
- bool EmitFunctionSummary = false);
+ const ModuleSummaryIndex *Index = nullptr,
+ bool GenerateHash = false);
- /// Write the specified function summary index to the given raw output stream,
+ /// Write the specified module summary index to the given raw output stream,
/// where it will be written in a new bitcode block. This is used when
- /// writing the combined index file for ThinLTO.
- void WriteFunctionSummaryToFile(const FunctionInfoIndex &Index,
- raw_ostream &Out);
+ /// writing the combined index file for ThinLTO. When writing a subset of the
+ /// index for a distributed backend, provide the \p ModuleToSummariesForIndex
+ /// map.
+ void WriteIndexToFile(const ModuleSummaryIndex &Index, raw_ostream &Out,
+ std::map<std::string, GVSummaryMapTy>
+ *ModuleToSummariesForIndex = nullptr);
/// isBitcodeWrapper - Return true if the given bytes are the magic bytes
/// for an LLVM IR bitcode wrapper.
@@ -163,20 +166,16 @@ namespace llvm {
inline bool SkipBitcodeWrapperHeader(const unsigned char *&BufPtr,
const unsigned char *&BufEnd,
bool VerifyBufferSize) {
- enum {
- KnownHeaderSize = 4*4, // Size of header we read.
- OffsetField = 2*4, // Offset in bytes to Offset field.
- SizeField = 3*4 // Offset in bytes to Size field.
- };
-
- // Must contain the header!
- if (BufEnd-BufPtr < KnownHeaderSize) return true;
+ // Must contain the offset and size field!
+ if (unsigned(BufEnd - BufPtr) < BWH_SizeField + 4)
+ return true;
- unsigned Offset = support::endian::read32le(&BufPtr[OffsetField]);
- unsigned Size = support::endian::read32le(&BufPtr[SizeField]);
+ unsigned Offset = support::endian::read32le(&BufPtr[BWH_OffsetField]);
+ unsigned Size = support::endian::read32le(&BufPtr[BWH_SizeField]);
+ uint64_t BitcodeOffsetEnd = (uint64_t)Offset + (uint64_t)Size;
// Verify that Offset+Size fits in the file.
- if (VerifyBufferSize && Offset+Size > unsigned(BufEnd-BufPtr))
+ if (VerifyBufferSize && BitcodeOffsetEnd > uint64_t(BufEnd-BufPtr))
return true;
BufPtr += Offset;
BufEnd = BufPtr+Size;
diff --git a/include/llvm/CodeGen/Analysis.h b/include/llvm/CodeGen/Analysis.h
index 38e64ad3be29..2e4dc49a1e26 100644
--- a/include/llvm/CodeGen/Analysis.h
+++ b/include/llvm/CodeGen/Analysis.h
@@ -17,10 +17,12 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/Instructions.h"
+#include "llvm/Support/CodeGen.h"
namespace llvm {
class GlobalValue;
diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h
index cf29fc9ef889..de618d173573 100644
--- a/include/llvm/CodeGen/AsmPrinter.h
+++ b/include/llvm/CodeGen/AsmPrinter.h
@@ -34,6 +34,7 @@ class ConstantArray;
class DIE;
class DIEAbbrev;
class GCMetadataPrinter;
+class GlobalIndirectSymbol;
class GlobalValue;
class GlobalVariable;
class MachineBasicBlock;
@@ -147,6 +148,8 @@ public:
DwarfDebug *getDwarfDebug() { return DD; }
DwarfDebug *getDwarfDebug() const { return DD; }
+ bool isPositionIndependent() const;
+
/// Return true if assembly output should contain comments.
///
bool isVerbose() const { return VerboseAsm; }
@@ -238,11 +241,6 @@ public:
///
virtual void EmitJumpTableInfo();
- /// Emit the control variable for an emulated TLS variable.
- virtual void EmitEmulatedTLSControlVariable(const GlobalVariable *GV,
- MCSymbol *EmittedSym,
- bool AllZeroInitValue);
-
/// Emit the specified global variable to the .s file.
virtual void EmitGlobalVariable(const GlobalVariable *GV);
@@ -551,6 +549,9 @@ private:
void EmitXXStructorList(const DataLayout &DL, const Constant *List,
bool isCtor);
GCMetadataPrinter *GetOrCreateGCPrinter(GCStrategy &C);
+ /// Emit GlobalAlias or GlobalIFunc.
+ void emitGlobalIndirectSymbol(Module &M,
+ const GlobalIndirectSymbol& GIS);
};
}
diff --git a/include/llvm/CodeGen/BasicTTIImpl.h b/include/llvm/CodeGen/BasicTTIImpl.h
index d99054eb6f36..69951afb623c 100644
--- a/include/llvm/CodeGen/BasicTTIImpl.h
+++ b/include/llvm/CodeGen/BasicTTIImpl.h
@@ -105,6 +105,11 @@ public:
/// \name Scalar TTI Implementations
/// @{
+ bool allowsMisalignedMemoryAccesses(unsigned BitWidth, unsigned AddressSpace,
+ unsigned Alignment, bool *Fast) const {
+ MVT M = MVT::getIntegerVT(BitWidth);
+ return getTLI()->allowsMisalignedMemoryAccesses(M, AddressSpace, Alignment, Fast);
+ }
bool hasBranchDivergence() { return false; }
@@ -152,6 +157,11 @@ public:
return getTLI()->isTypeLegal(VT);
}
+ int getGEPCost(Type *PointeeType, const Value *Ptr,
+ ArrayRef<const Value *> Operands) {
+ return BaseT::getGEPCost(PointeeType, Ptr, Operands);
+ }
+
unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
ArrayRef<const Value *> Arguments) {
return BaseT::getIntrinsicCost(IID, RetTy, Arguments);
@@ -216,6 +226,8 @@ public:
return BaseT::getOperationCost(Opcode, Ty, OpTy);
}
+ unsigned getInliningThresholdMultiplier() { return 1; }
+
void getUnrollingPreferences(Loop *L, TTI::UnrollingPreferences &UP) {
// This unrolling functionality is target independent, but to provide some
// motivation for its intended use, for x86:
@@ -307,12 +319,14 @@ public:
}
if (!TLI->isOperationExpand(ISD, LT.second)) {
- // If the operation is custom lowered then assume
- // thare the code is twice as expensive.
+ // If the operation is custom lowered, then assume that the code is twice
+ // as expensive.
return LT.first * 2 * OpCost;
}
// Else, assume that we need to scalarize this op.
+ // TODO: If one of the types get legalized by splitting, handle this
+ // similarly to what getCastInstrCost() does.
if (Ty->isVectorTy()) {
unsigned Num = Ty->getVectorNumElements();
unsigned Cost = static_cast<T *>(this)
@@ -359,6 +373,11 @@ public:
TLI->isZExtFree(SrcLT.second, DstLT.second))
return 0;
+ if (Opcode == Instruction::AddrSpaceCast &&
+ TLI->isNoopAddrSpaceCast(Src->getPointerAddressSpace(),
+ Dst->getPointerAddressSpace()))
+ return 0;
+
// If the cast is marked as legal (or promote) then assume low cost.
if (SrcLT.first == DstLT.first &&
TLI->isOperationLegalOrPromote(ISD, DstLT.second))
@@ -402,9 +421,25 @@ public:
return SrcLT.first * 1;
}
- // If we are converting vectors and the operation is illegal, or
- // if the vectors are legalized to different types, estimate the
- // scalarization costs.
+ // If we are legalizing by splitting, query the concrete TTI for the cost
+ // of casting the original vector twice. We also need to factor int the
+ // cost of the split itself. Count that as 1, to be consistent with
+ // TLI->getTypeLegalizationCost().
+ if ((TLI->getTypeAction(Src->getContext(), TLI->getValueType(DL, Src)) ==
+ TargetLowering::TypeSplitVector) ||
+ (TLI->getTypeAction(Dst->getContext(), TLI->getValueType(DL, Dst)) ==
+ TargetLowering::TypeSplitVector)) {
+ Type *SplitDst = VectorType::get(Dst->getVectorElementType(),
+ Dst->getVectorNumElements() / 2);
+ Type *SplitSrc = VectorType::get(Src->getVectorElementType(),
+ Src->getVectorNumElements() / 2);
+ T *TTI = static_cast<T *>(this);
+ return TTI->getVectorSplitCost() +
+ (2 * TTI->getCastInstrCost(Opcode, SplitDst, SplitSrc));
+ }
+
+ // In other cases where the source or destination are illegal, assume
+ // the operation will get scalarized.
unsigned Num = Dst->getVectorNumElements();
unsigned Cost = static_cast<T *>(this)->getCastInstrCost(
Opcode, Dst->getScalarType(), Src->getScalarType());
@@ -428,6 +463,14 @@ public:
llvm_unreachable("Unhandled cast");
}
+ unsigned getExtractWithExtendCost(unsigned Opcode, Type *Dst,
+ VectorType *VecTy, unsigned Index) {
+ return static_cast<T *>(this)->getVectorInstrCost(
+ Instruction::ExtractElement, VecTy, Index) +
+ static_cast<T *>(this)->getCastInstrCost(Opcode, Dst,
+ VecTy->getElementType());
+ }
+
unsigned getCFInstrCost(unsigned Opcode) {
// Branches are assumed to be predicted.
return 0;
@@ -454,6 +497,8 @@ public:
}
// Otherwise, assume that the cast is scalarized.
+ // TODO: If one of the types get legalized by splitting, handle this
+ // similarly to what getCastInstrCost() does.
if (ValTy->isVectorTy()) {
unsigned Num = ValTy->getVectorNumElements();
if (CondTy)
@@ -462,8 +507,7 @@ public:
Opcode, ValTy->getScalarType(), CondTy);
// Return the cost of multiple scalar invocation plus the cost of
- // inserting
- // and extracting the values.
+ // inserting and extracting the values.
return getScalarizationOverhead(ValTy, true, false) + Num * Cost;
}
@@ -527,6 +571,51 @@ public:
unsigned Cost = static_cast<T *>(this)->getMemoryOpCost(
Opcode, VecTy, Alignment, AddressSpace);
+ // Legalize the vector type, and get the legalized and unlegalized type
+ // sizes.
+ MVT VecTyLT = getTLI()->getTypeLegalizationCost(DL, VecTy).second;
+ unsigned VecTySize =
+ static_cast<T *>(this)->getDataLayout().getTypeStoreSize(VecTy);
+ unsigned VecTyLTSize = VecTyLT.getStoreSize();
+
+ // Return the ceiling of dividing A by B.
+ auto ceil = [](unsigned A, unsigned B) { return (A + B - 1) / B; };
+
+ // Scale the cost of the memory operation by the fraction of legalized
+ // instructions that will actually be used. We shouldn't account for the
+ // cost of dead instructions since they will be removed.
+ //
+ // E.g., An interleaved load of factor 8:
+ // %vec = load <16 x i64>, <16 x i64>* %ptr
+ // %v0 = shufflevector %vec, undef, <0, 8>
+ //
+ // If <16 x i64> is legalized to 8 v2i64 loads, only 2 of the loads will be
+ // used (those corresponding to elements [0:1] and [8:9] of the unlegalized
+ // type). The other loads are unused.
+ //
+ // We only scale the cost of loads since interleaved store groups aren't
+ // allowed to have gaps.
+ if (Opcode == Instruction::Load && VecTySize > VecTyLTSize) {
+
+ // The number of loads of a legal type it will take to represent a load
+ // of the unlegalized vector type.
+ unsigned NumLegalInsts = ceil(VecTySize, VecTyLTSize);
+
+ // The number of elements of the unlegalized type that correspond to a
+ // single legal instruction.
+ unsigned NumEltsPerLegalInst = ceil(NumElts, NumLegalInsts);
+
+ // Determine which legal instructions will be used.
+ BitVector UsedInsts(NumLegalInsts, false);
+ for (unsigned Index : Indices)
+ for (unsigned Elt = 0; Elt < NumSubElts; ++Elt)
+ UsedInsts.set((Index + Elt * Factor) / NumEltsPerLegalInst);
+
+ // Scale the cost of the load by the fraction of legal instructions that
+ // will be used.
+ Cost *= UsedInsts.count() / NumLegalInsts;
+ }
+
// Then plus the cost of interleave operation.
if (Opcode == Instruction::Load) {
// The interleave cost is similar to extract sub vectors' elements
@@ -582,13 +671,14 @@ public:
/// Get intrinsic cost based on arguments
unsigned getIntrinsicInstrCost(Intrinsic::ID IID, Type *RetTy,
- ArrayRef<Value *> Args) {
+ ArrayRef<Value *> Args, FastMathFlags FMF) {
switch (IID) {
default: {
SmallVector<Type *, 4> Types;
for (Value *Op : Args)
Types.push_back(Op->getType());
- return getIntrinsicInstrCost(IID, RetTy, Types);
+ return static_cast<T *>(this)->getIntrinsicInstrCost(IID, RetTy, Types,
+ FMF);
}
case Intrinsic::masked_scatter: {
Value *Mask = Args[3];
@@ -614,8 +704,9 @@ public:
/// Get intrinsic cost based on argument types
unsigned getIntrinsicInstrCost(Intrinsic::ID IID, Type *RetTy,
- ArrayRef<Type *> Tys) {
- unsigned ISD = 0;
+ ArrayRef<Type *> Tys, FastMathFlags FMF) {
+ SmallVector<unsigned, 2> ISDs;
+ unsigned SingleCallCost = 10; // Library call cost. Make it expensive.
switch (IID) {
default: {
// Assume that we need to scalarize this intrinsic.
@@ -641,74 +732,78 @@ public:
return 1; // Return cost of a scalar intrinsic. Assume it to be cheap.
unsigned ScalarCost = static_cast<T *>(this)->getIntrinsicInstrCost(
- IID, ScalarRetTy, ScalarTys);
+ IID, ScalarRetTy, ScalarTys, FMF);
return ScalarCalls * ScalarCost + ScalarizationCost;
}
// Look for intrinsics that can be lowered directly or turned into a scalar
// intrinsic call.
case Intrinsic::sqrt:
- ISD = ISD::FSQRT;
+ ISDs.push_back(ISD::FSQRT);
break;
case Intrinsic::sin:
- ISD = ISD::FSIN;
+ ISDs.push_back(ISD::FSIN);
break;
case Intrinsic::cos:
- ISD = ISD::FCOS;
+ ISDs.push_back(ISD::FCOS);
break;
case Intrinsic::exp:
- ISD = ISD::FEXP;
+ ISDs.push_back(ISD::FEXP);
break;
case Intrinsic::exp2:
- ISD = ISD::FEXP2;
+ ISDs.push_back(ISD::FEXP2);
break;
case Intrinsic::log:
- ISD = ISD::FLOG;
+ ISDs.push_back(ISD::FLOG);
break;
case Intrinsic::log10:
- ISD = ISD::FLOG10;
+ ISDs.push_back(ISD::FLOG10);
break;
case Intrinsic::log2:
- ISD = ISD::FLOG2;
+ ISDs.push_back(ISD::FLOG2);
break;
case Intrinsic::fabs:
- ISD = ISD::FABS;
+ ISDs.push_back(ISD::FABS);
break;
case Intrinsic::minnum:
- ISD = ISD::FMINNUM;
+ ISDs.push_back(ISD::FMINNUM);
+ if (FMF.noNaNs())
+ ISDs.push_back(ISD::FMINNAN);
break;
case Intrinsic::maxnum:
- ISD = ISD::FMAXNUM;
+ ISDs.push_back(ISD::FMAXNUM);
+ if (FMF.noNaNs())
+ ISDs.push_back(ISD::FMAXNAN);
break;
case Intrinsic::copysign:
- ISD = ISD::FCOPYSIGN;
+ ISDs.push_back(ISD::FCOPYSIGN);
break;
case Intrinsic::floor:
- ISD = ISD::FFLOOR;
+ ISDs.push_back(ISD::FFLOOR);
break;
case Intrinsic::ceil:
- ISD = ISD::FCEIL;
+ ISDs.push_back(ISD::FCEIL);
break;
case Intrinsic::trunc:
- ISD = ISD::FTRUNC;
+ ISDs.push_back(ISD::FTRUNC);
break;
case Intrinsic::nearbyint:
- ISD = ISD::FNEARBYINT;
+ ISDs.push_back(ISD::FNEARBYINT);
break;
case Intrinsic::rint:
- ISD = ISD::FRINT;
+ ISDs.push_back(ISD::FRINT);
break;
case Intrinsic::round:
- ISD = ISD::FROUND;
+ ISDs.push_back(ISD::FROUND);
break;
case Intrinsic::pow:
- ISD = ISD::FPOW;
+ ISDs.push_back(ISD::FPOW);
break;
case Intrinsic::fma:
- ISD = ISD::FMA;
+ ISDs.push_back(ISD::FMA);
break;
case Intrinsic::fmuladd:
- ISD = ISD::FMA;
+ ISDs.push_back(ISD::FMA);
break;
// FIXME: We should return 0 whenever getIntrinsicCost == TCC_Free.
case Intrinsic::lifetime_start:
@@ -720,27 +815,49 @@ public:
case Intrinsic::masked_load:
return static_cast<T *>(this)
->getMaskedMemoryOpCost(Instruction::Load, RetTy, 0, 0);
+ case Intrinsic::ctpop:
+ ISDs.push_back(ISD::CTPOP);
+ // In case of legalization use TCC_Expensive. This is cheaper than a
+ // library call but still not a cheap instruction.
+ SingleCallCost = TargetTransformInfo::TCC_Expensive;
+ break;
+ // FIXME: ctlz, cttz, ...
}
const TargetLoweringBase *TLI = getTLI();
std::pair<unsigned, MVT> LT = TLI->getTypeLegalizationCost(DL, RetTy);
- if (TLI->isOperationLegalOrPromote(ISD, LT.second)) {
- // The operation is legal. Assume it costs 1.
- // If the type is split to multiple registers, assume that there is some
- // overhead to this.
- // TODO: Once we have extract/insert subvector cost we need to use them.
- if (LT.first > 1)
- return LT.first * 2;
- return LT.first * 1;
- }
+ SmallVector<unsigned, 2> LegalCost;
+ SmallVector<unsigned, 2> CustomCost;
+ for (unsigned ISD : ISDs) {
+ if (TLI->isOperationLegalOrPromote(ISD, LT.second)) {
+ if (IID == Intrinsic::fabs && TLI->isFAbsFree(LT.second)) {
+ return 0;
+ }
- if (!TLI->isOperationExpand(ISD, LT.second)) {
- // If the operation is custom lowered then assume
- // thare the code is twice as expensive.
- return LT.first * 2;
+ // The operation is legal. Assume it costs 1.
+ // If the type is split to multiple registers, assume that there is some
+ // overhead to this.
+ // TODO: Once we have extract/insert subvector cost we need to use them.
+ if (LT.first > 1)
+ LegalCost.push_back(LT.first * 2);
+ else
+ LegalCost.push_back(LT.first * 1);
+ } else if (!TLI->isOperationExpand(ISD, LT.second)) {
+ // If the operation is custom lowered then assume
+ // that the code is twice as expensive.
+ CustomCost.push_back(LT.first * 2);
+ }
}
+ auto MinLegalCostI = std::min_element(LegalCost.begin(), LegalCost.end());
+ if (MinLegalCostI != LegalCost.end())
+ return *MinLegalCostI;
+
+ auto MinCustomCostI = std::min_element(CustomCost.begin(), CustomCost.end());
+ if (MinCustomCostI != CustomCost.end())
+ return *MinCustomCostI;
+
// If we can't lower fmuladd into an FMA estimate the cost as a floating
// point mul followed by an add.
if (IID == Intrinsic::fmuladd)
@@ -763,7 +880,7 @@ public:
ScalarTys.push_back(Ty);
}
unsigned ScalarCost = static_cast<T *>(this)->getIntrinsicInstrCost(
- IID, RetTy->getScalarType(), ScalarTys);
+ IID, RetTy->getScalarType(), ScalarTys, FMF);
for (unsigned i = 0, ie = Tys.size(); i != ie; ++i) {
if (Tys[i]->isVectorTy()) {
ScalarizationCost += getScalarizationOverhead(Tys[i], false, true);
@@ -775,7 +892,7 @@ public:
}
// This is going to be turned into a library call, make it expensive.
- return 10;
+ return SingleCallCost;
}
/// \brief Compute a cost of the given call instruction.
@@ -815,6 +932,8 @@ public:
return ShuffleCost + ArithCost + getScalarizationOverhead(Ty, false, true);
}
+ unsigned getVectorSplitCost() { return 1; }
+
/// @}
};
diff --git a/include/llvm/CodeGen/CallingConvLower.h b/include/llvm/CodeGen/CallingConvLower.h
index 415abb90da57..92e58564e040 100644
--- a/include/llvm/CodeGen/CallingConvLower.h
+++ b/include/llvm/CodeGen/CallingConvLower.h
@@ -195,6 +195,7 @@ class CCState {
private:
CallingConv::ID CallingConv;
bool IsVarArg;
+ bool AnalyzingMustTailForwardedRegs = false;
MachineFunction &MF;
const TargetRegisterInfo &TRI;
SmallVectorImpl<CCValAssign> &Locs;
@@ -281,7 +282,7 @@ public:
/// be able to store all arguments and such that the alignment requirement
/// of each of the arguments is satisfied.
unsigned getAlignedCallFrameSize() const {
- return RoundUpToAlignment(StackOffset, MaxStackArgAlign);
+ return alignTo(StackOffset, MaxStackArgAlign);
}
/// isAllocated - Return true if the specified register (or an alias) is
@@ -412,14 +413,19 @@ public:
/// and alignment.
unsigned AllocateStack(unsigned Size, unsigned Align) {
assert(Align && ((Align - 1) & Align) == 0); // Align is power of 2.
- StackOffset = RoundUpToAlignment(StackOffset, Align);
+ StackOffset = alignTo(StackOffset, Align);
unsigned Result = StackOffset;
StackOffset += Size;
MaxStackArgAlign = std::max(Align, MaxStackArgAlign);
- MF.getFrameInfo()->ensureMaxAlignment(Align);
+ ensureMaxAlignment(Align);
return Result;
}
+ void ensureMaxAlignment(unsigned Align) {
+ if (!AnalyzingMustTailForwardedRegs)
+ MF.getFrameInfo()->ensureMaxAlignment(Align);
+ }
+
/// Version of AllocateStack with extra register to be shadowed.
unsigned AllocateStack(unsigned Size, unsigned Align, unsigned ShadowReg) {
MarkAllocated(ShadowReg);
@@ -507,6 +513,14 @@ public:
SmallVectorImpl<ForwardedRegister> &Forwards, ArrayRef<MVT> RegParmTypes,
CCAssignFn Fn);
+ /// Returns true if the results of the two calling conventions are compatible.
+ /// This is usually part of the check for tailcall eligibility.
+ static bool resultsCompatible(CallingConv::ID CalleeCC,
+ CallingConv::ID CallerCC, MachineFunction &MF,
+ LLVMContext &C,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ CCAssignFn CalleeFn, CCAssignFn CallerFn);
+
private:
/// MarkAllocated - Mark a register and all of its aliases as allocated.
void MarkAllocated(unsigned Reg);
diff --git a/include/llvm/CodeGen/CommandFlags.h b/include/llvm/CodeGen/CommandFlags.h
index 0d37dc00422f..6376c06768b3 100644
--- a/include/llvm/CodeGen/CommandFlags.h
+++ b/include/llvm/CodeGen/CommandFlags.h
@@ -46,20 +46,23 @@ MAttrs("mattr",
cl::desc("Target specific attributes (-mattr=help for details)"),
cl::value_desc("a1,+a2,-a3,..."));
-cl::opt<Reloc::Model>
-RelocModel("relocation-model",
- cl::desc("Choose relocation model"),
- cl::init(Reloc::Default),
- cl::values(
- clEnumValN(Reloc::Default, "default",
- "Target default relocation model"),
- clEnumValN(Reloc::Static, "static",
- "Non-relocatable code"),
- clEnumValN(Reloc::PIC_, "pic",
- "Fully relocatable, position independent code"),
- clEnumValN(Reloc::DynamicNoPIC, "dynamic-no-pic",
- "Relocatable external references, non-relocatable code"),
- clEnumValEnd));
+cl::opt<Reloc::Model> RelocModel(
+ "relocation-model", cl::desc("Choose relocation model"),
+ cl::values(
+ clEnumValN(Reloc::Static, "static", "Non-relocatable code"),
+ clEnumValN(Reloc::PIC_, "pic",
+ "Fully relocatable, position independent code"),
+ clEnumValN(Reloc::DynamicNoPIC, "dynamic-no-pic",
+ "Relocatable external references, non-relocatable code"),
+ clEnumValEnd));
+
+static inline Optional<Reloc::Model> getRelocModel() {
+ if (RelocModel.getNumOccurrences()) {
+ Reloc::Model R = RelocModel;
+ return R;
+ }
+ return None;
+}
cl::opt<ThreadModel::Model>
TMModel("thread-model",
@@ -87,6 +90,22 @@ CMModel("code-model",
"Large code model"),
clEnumValEnd));
+cl::opt<llvm::ExceptionHandling>
+ExceptionModel("exception-model",
+ cl::desc("exception model"),
+ cl::init(ExceptionHandling::None),
+ cl::values(clEnumValN(ExceptionHandling::None, "default",
+ "default exception handling model"),
+ clEnumValN(ExceptionHandling::DwarfCFI, "dwarf",
+ "DWARF-like CFI based exception handling"),
+ clEnumValN(ExceptionHandling::SjLj, "sjlj",
+ "SjLj exception handling"),
+ clEnumValN(ExceptionHandling::ARM, "arm",
+ "ARM EHABI exceptions"),
+ clEnumValN(ExceptionHandling::WinEH, "wineh",
+ "Windows exception model"),
+ clEnumValEnd));
+
cl::opt<TargetMachine::CodeGenFileType>
FileType("filetype", cl::init(TargetMachine::CGFT_AssemblyFile),
cl::desc("Choose a file type (not all types are supported by all targets):"),
@@ -177,6 +196,11 @@ DisableTailCalls("disable-tail-calls",
cl::desc("Never emit tail calls"),
cl::init(false));
+cl::opt<bool>
+StackSymbolOrdering("stack-symbol-ordering",
+ cl::desc("Order local stack symbols."),
+ cl::init(true));
+
cl::opt<unsigned>
OverrideStackAlignment("stack-alignment",
cl::desc("Override default stack alignment"),
@@ -193,11 +217,6 @@ TrapFuncName("trap-func", cl::Hidden,
cl::init(""));
cl::opt<bool>
-EnablePIE("enable-pie",
- cl::desc("Assume the creation of a position independent executable."),
- cl::init(false));
-
-cl::opt<bool>
UseCtors("use-ctors",
cl::desc("Use .ctors instead of .init_array."),
cl::init(false));
@@ -211,10 +230,6 @@ cl::opt<std::string> StartAfter("start-after",
cl::value_desc("pass-name"),
cl::init(""));
-cl::opt<std::string>
- RunPass("run-pass", cl::desc("Run compiler only for one specific pass"),
- cl::value_desc("pass-name"), cl::init(""));
-
cl::opt<bool> DataSections("data-sections",
cl::desc("Emit data into separate sections"),
cl::init(false));
@@ -284,12 +299,13 @@ static inline TargetOptions InitTargetOptionsFromCodeGenFlags() {
Options.NoZerosInBSS = DontPlaceZerosInBSS;
Options.GuaranteedTailCallOpt = EnableGuaranteedTailCallOpt;
Options.StackAlignmentOverride = OverrideStackAlignment;
- Options.PositionIndependentExecutable = EnablePIE;
+ Options.StackSymbolOrdering = StackSymbolOrdering;
Options.UseInitArray = !UseCtors;
Options.DataSections = DataSections;
Options.FunctionSections = FunctionSections;
Options.UniqueSectionNames = UniqueSectionNames;
Options.EmulatedTLS = EmulatedTLS;
+ Options.ExceptionModel = ExceptionModel;
Options.MCOptions = InitMCTargetOptionsFromFlags();
Options.JTType = JTableType;
diff --git a/include/llvm/CodeGen/DFAPacketizer.h b/include/llvm/CodeGen/DFAPacketizer.h
index 40ec201107e8..8de140e91bf3 100644
--- a/include/llvm/CodeGen/DFAPacketizer.h
+++ b/include/llvm/CodeGen/DFAPacketizer.h
@@ -28,6 +28,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/ScheduleDAGMutation.h"
#include <map>
namespace llvm {
@@ -80,7 +81,7 @@ private:
// CachedTable is a map from <FromState, Input> to ToState.
DenseMap<UnsignPair, unsigned> CachedTable;
- // ReadTable - Read the DFA transition table and update CachedTable.
+ // Read the DFA transition table and update CachedTable.
void ReadTable(unsigned state);
public:
@@ -92,38 +93,39 @@ public:
CurrentState = 0;
}
- // getInsnInput - Return the DFAInput for an instruction class.
+ // Return the DFAInput for an instruction class.
DFAInput getInsnInput(unsigned InsnClass);
- // getInsnInput - Return the DFAInput for an instruction class input vector.
+ // Return the DFAInput for an instruction class input vector.
static DFAInput getInsnInput(const std::vector<unsigned> &InsnClass);
- // canReserveResources - Check if the resources occupied by a MCInstrDesc
- // are available in the current state.
+ // Check if the resources occupied by a MCInstrDesc are available in
+ // the current state.
bool canReserveResources(const llvm::MCInstrDesc *MID);
- // reserveResources - Reserve the resources occupied by a MCInstrDesc and
- // change the current state to reflect that change.
+ // Reserve the resources occupied by a MCInstrDesc and change the current
+ // state to reflect that change.
void reserveResources(const llvm::MCInstrDesc *MID);
- // canReserveResources - Check if the resources occupied by a machine
- // instruction are available in the current state.
- bool canReserveResources(llvm::MachineInstr *MI);
+ // Check if the resources occupied by a machine instruction are available
+ // in the current state.
+ bool canReserveResources(llvm::MachineInstr &MI);
- // reserveResources - Reserve the resources occupied by a machine
- // instruction and change the current state to reflect that change.
- void reserveResources(llvm::MachineInstr *MI);
+ // Reserve the resources occupied by a machine instruction and change the
+ // current state to reflect that change.
+ void reserveResources(llvm::MachineInstr &MI);
const InstrItineraryData *getInstrItins() const { return InstrItins; }
};
-// VLIWPacketizerList - Implements a simple VLIW packetizer using DFA. The
-// packetizer works on machine basic blocks. For each instruction I in BB, the
-// packetizer consults the DFA to see if machine resources are available to
-// execute I. If so, the packetizer checks if I depends on any instruction J in
-// the current packet. If no dependency is found, I is added to current packet
-// and machine resource is marked as taken. If any dependency is found, a target
-// API call is made to prune the dependence.
+
+// VLIWPacketizerList implements a simple VLIW packetizer using DFA. The
+// packetizer works on machine basic blocks. For each instruction I in BB,
+// the packetizer consults the DFA to see if machine resources are available
+// to execute I. If so, the packetizer checks if I depends on any instruction
+// in the current packet. If no dependency is found, I is added to current
+// packet and the machine resource is marked as taken. If any dependency is
+// found, a target API call is made to prune the dependence.
class VLIWPacketizerList {
protected:
MachineFunction &MF;
@@ -132,13 +134,11 @@ protected:
// The VLIW Scheduler.
DefaultVLIWScheduler *VLIWScheduler;
-
// Vector of instructions assigned to the current packet.
std::vector<MachineInstr*> CurrentPacketMIs;
// DFA resource tracker.
DFAPacketizer *ResourceTracker;
-
- // Generate MI -> SU map.
+ // Map: MI -> SU.
std::map<MachineInstr*, SUnit*> MIToSUnit;
public:
@@ -148,43 +148,40 @@ public:
virtual ~VLIWPacketizerList();
- // PacketizeMIs - Implement this API in the backend to bundle instructions.
+ // Implement this API in the backend to bundle instructions.
void PacketizeMIs(MachineBasicBlock *MBB,
MachineBasicBlock::iterator BeginItr,
MachineBasicBlock::iterator EndItr);
- // getResourceTracker - return ResourceTracker
+ // Return the ResourceTracker.
DFAPacketizer *getResourceTracker() {return ResourceTracker;}
// addToPacket - Add MI to the current packet.
- virtual MachineBasicBlock::iterator addToPacket(MachineInstr *MI) {
- MachineBasicBlock::iterator MII = MI;
- CurrentPacketMIs.push_back(MI);
+ virtual MachineBasicBlock::iterator addToPacket(MachineInstr &MI) {
+ CurrentPacketMIs.push_back(&MI);
ResourceTracker->reserveResources(MI);
- return MII;
+ return MI;
}
// End the current packet and reset the state of the packetizer.
// Overriding this function allows the target-specific packetizer
// to perform custom finalization.
- virtual void endPacket(MachineBasicBlock *MBB, MachineInstr *MI);
+ virtual void endPacket(MachineBasicBlock *MBB,
+ MachineBasicBlock::iterator MI);
- // initPacketizerState - perform initialization before packetizing
- // an instruction. This function is supposed to be overrided by
- // the target dependent packetizer.
- virtual void initPacketizerState() { return; }
+ // Perform initialization before packetizing an instruction. This
+ // function is supposed to be overrided by the target dependent packetizer.
+ virtual void initPacketizerState() {}
- // ignorePseudoInstruction - Ignore bundling of pseudo instructions.
- virtual bool ignorePseudoInstruction(const MachineInstr *I,
+ // Check if the given instruction I should be ignored by the packetizer.
+ virtual bool ignorePseudoInstruction(const MachineInstr &I,
const MachineBasicBlock *MBB) {
return false;
}
- // isSoloInstruction - return true if instruction MI can not be packetized
- // with any other instruction, which means that MI itself is a packet.
- virtual bool isSoloInstruction(const MachineInstr *MI) {
- return true;
- }
+ // Return true if instruction MI can not be packetized with any other
+ // instruction, which means that MI itself is a packet.
+ virtual bool isSoloInstruction(const MachineInstr &MI) { return true; }
// Check if the packetizer should try to add the given instruction to
// the current packet. One reasons for which it may not be desirable
@@ -192,23 +189,22 @@ public:
// would cause a stall.
// If this function returns "false", the current packet will be ended,
// and the instruction will be added to the next packet.
- virtual bool shouldAddToPacket(const MachineInstr *MI) {
- return true;
- }
+ virtual bool shouldAddToPacket(const MachineInstr &MI) { return true; }
- // isLegalToPacketizeTogether - Is it legal to packetize SUI and SUJ
- // together.
+ // Check if it is legal to packetize SUI and SUJ together.
virtual bool isLegalToPacketizeTogether(SUnit *SUI, SUnit *SUJ) {
return false;
}
- // isLegalToPruneDependencies - Is it legal to prune dependece between SUI
- // and SUJ.
+ // Check if it is legal to prune dependece between SUI and SUJ.
virtual bool isLegalToPruneDependencies(SUnit *SUI, SUnit *SUJ) {
return false;
}
+ // Add a DAG mutation to be done before the packetization begins.
+ void addMutation(std::unique_ptr<ScheduleDAGMutation> Mutation);
};
-}
+
+} // namespace llvm
#endif
diff --git a/include/llvm/CodeGen/DIE.h b/include/llvm/CodeGen/DIE.h
index 72b3adc7de99..7d6e66fa6ec2 100644
--- a/include/llvm/CodeGen/DIE.h
+++ b/include/llvm/CodeGen/DIE.h
@@ -20,7 +20,6 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/DwarfStringPoolEntry.h"
#include "llvm/Support/Dwarf.h"
-#include <vector>
namespace llvm {
class AsmPrinter;
@@ -29,48 +28,6 @@ class MCSymbol;
class raw_ostream;
class DwarfTypeUnit;
-// AsmStreamerBase - A base abstract interface class defines methods that
-// can be implemented to stream objects or can be implemented to
-// calculate the size of the streamed objects.
-// The derived classes will use an AsmPrinter to implement the methods.
-//
-// TODO: complete this interface and use it to merge EmitValue and SizeOf
-// methods in the DIE classes below.
-class AsmStreamerBase {
-protected:
- const AsmPrinter *AP;
- AsmStreamerBase(const AsmPrinter *AP) : AP(AP) {}
-
-public:
- virtual ~AsmStreamerBase() {}
- virtual unsigned emitULEB128(uint64_t Value, const char *Desc = nullptr,
- unsigned PadTo = 0) = 0;
- virtual unsigned emitInt8(unsigned char Value) = 0;
- virtual unsigned emitBytes(StringRef Data) = 0;
-};
-
-/// EmittingAsmStreamer - Implements AbstractAsmStreamer to stream objects.
-/// Notice that the return value is not the actual size of the streamed object.
-/// For size calculation use SizeReporterAsmStreamer.
-class EmittingAsmStreamer : public AsmStreamerBase {
-public:
- EmittingAsmStreamer(const AsmPrinter *AP) : AsmStreamerBase(AP) {}
- unsigned emitULEB128(uint64_t Value, const char *Desc = nullptr,
- unsigned PadTo = 0) override;
- unsigned emitInt8(unsigned char Value) override;
- unsigned emitBytes(StringRef Data) override;
-};
-
-/// SizeReporterAsmStreamer - Only reports the size of the streamed objects.
-class SizeReporterAsmStreamer : public AsmStreamerBase {
-public:
- SizeReporterAsmStreamer(const AsmPrinter *AP) : AsmStreamerBase(AP) {}
- unsigned emitULEB128(uint64_t Value, const char *Desc = nullptr,
- unsigned PadTo = 0) override;
- unsigned emitInt8(unsigned char Value) override;
- unsigned emitBytes(StringRef Data) override;
-};
-
//===--------------------------------------------------------------------===//
/// DIEAbbrevData - Dwarf abbreviation data, describes one attribute of a
/// Dwarf abbreviation.
@@ -286,25 +243,6 @@ public:
};
//===--------------------------------------------------------------------===//
-/// \brief A signature reference to a type unit.
-class DIETypeSignature {
- const DwarfTypeUnit *Unit;
-
- DIETypeSignature() = delete;
-
-public:
- explicit DIETypeSignature(const DwarfTypeUnit &Unit) : Unit(&Unit) {}
-
- void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
- unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
- assert(Form == dwarf::DW_FORM_ref_sig8);
- return 8;
- }
-
- void print(raw_ostream &O) const;
-};
-
-//===--------------------------------------------------------------------===//
/// DIELocList - Represents a pointer to a location list in the debug_loc
/// section.
//
@@ -350,8 +288,9 @@ private:
/// All values that aren't standard layout (or are larger than 8 bytes)
/// should be stored by reference instead of by value.
typedef AlignedCharArrayUnion<DIEInteger, DIEString, DIEExpr, DIELabel,
- DIEDelta *, DIEEntry, DIETypeSignature,
- DIEBlock *, DIELoc *, DIELocList> ValTy;
+ DIEDelta *, DIEEntry, DIEBlock *, DIELoc *,
+ DIELocList>
+ ValTy;
static_assert(sizeof(ValTy) <= sizeof(uint64_t) ||
sizeof(ValTy) <= sizeof(void *),
"Expected all large types to be stored via pointer");
@@ -626,7 +565,7 @@ public:
typedef iterator_range<value_iterator> value_range;
typedef iterator_range<const_value_iterator> const_value_range;
- value_iterator addValue(BumpPtrAllocator &Alloc, DIEValue V) {
+ value_iterator addValue(BumpPtrAllocator &Alloc, const DIEValue &V) {
List.push_back(*new (Alloc) Node(V));
return value_iterator(ListTy::toIterator(List.back()));
}
diff --git a/include/llvm/CodeGen/DIEValue.def b/include/llvm/CodeGen/DIEValue.def
index 2cfae7b608c6..c5ff4010b2e4 100644
--- a/include/llvm/CodeGen/DIEValue.def
+++ b/include/llvm/CodeGen/DIEValue.def
@@ -37,7 +37,6 @@ HANDLE_DIEVALUE_SMALL(Expr)
HANDLE_DIEVALUE_SMALL(Label)
HANDLE_DIEVALUE_LARGE(Delta)
HANDLE_DIEVALUE_SMALL(Entry)
-HANDLE_DIEVALUE_SMALL(TypeSignature)
HANDLE_DIEVALUE_LARGE(Block)
HANDLE_DIEVALUE_LARGE(Loc)
HANDLE_DIEVALUE_SMALL(LocList)
diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h
index cc4e37059bb8..4bff48de38e4 100644
--- a/include/llvm/CodeGen/FastISel.h
+++ b/include/llvm/CodeGen/FastISel.h
@@ -16,7 +16,6 @@
#define LLVM_CODEGEN_FASTISEL_H
#include "llvm/ADT/DenseMap.h"
-#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/IntrinsicInst.h"
@@ -24,6 +23,8 @@
namespace llvm {
+class MachineConstantPool;
+
/// \brief This is a fast-path instruction selection class that generates poor
/// code and doesn't support illegal types or non-trivial lowering, but runs
/// quickly.
@@ -40,12 +41,15 @@ public:
bool IsByVal : 1;
bool IsInAlloca : 1;
bool IsReturned : 1;
+ bool IsSwiftSelf : 1;
+ bool IsSwiftError : 1;
uint16_t Alignment;
ArgListEntry()
: Val(nullptr), Ty(nullptr), IsSExt(false), IsZExt(false),
IsInReg(false), IsSRet(false), IsNest(false), IsByVal(false),
- IsInAlloca(false), IsReturned(false), Alignment(0) {}
+ IsInAlloca(false), IsReturned(false), IsSwiftSelf(false),
+ IsSwiftError(false), Alignment(0) {}
/// \brief Set CallLoweringInfo attribute flags based on a call instruction
/// and called function attributes.
@@ -448,7 +452,7 @@ protected:
/// \brief Emit an unconditional branch to the given block, unless it is the
/// immediate (fall-through) successor, and update the CFG.
- void fastEmitBranch(MachineBasicBlock *MBB, DebugLoc DL);
+ void fastEmitBranch(MachineBasicBlock *MBB, const DebugLoc &DL);
/// Emit an unconditional branch to \p FalseMBB, obtains the branch weight
/// and adds TrueMBB and FalseMBB to the successor list.
diff --git a/include/llvm/CodeGen/FaultMaps.h b/include/llvm/CodeGen/FaultMaps.h
index f4b646322143..9b5a3e1ba050 100644
--- a/include/llvm/CodeGen/FaultMaps.h
+++ b/include/llvm/CodeGen/FaultMaps.h
@@ -10,7 +10,6 @@
#ifndef LLVM_CODEGEN_FAULTMAPS_H
#define LLVM_CODEGEN_FAULTMAPS_H
-#include "llvm/ADT/DenseMap.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Format.h"
diff --git a/include/llvm/CodeGen/FunctionLoweringInfo.h b/include/llvm/CodeGen/FunctionLoweringInfo.h
index 09a9991912da..010e34179efc 100644
--- a/include/llvm/CodeGen/FunctionLoweringInfo.h
+++ b/include/llvm/CodeGen/FunctionLoweringInfo.h
@@ -72,6 +72,37 @@ public:
/// MBBMap - A mapping from LLVM basic blocks to their machine code entry.
DenseMap<const BasicBlock*, MachineBasicBlock *> MBBMap;
+ typedef SmallVector<unsigned, 1> SwiftErrorVRegs;
+ typedef SmallVector<const Value*, 1> SwiftErrorValues;
+ /// A function can only have a single swifterror argument. And if it does
+ /// have a swifterror argument, it must be the first entry in
+ /// SwiftErrorVals.
+ SwiftErrorValues SwiftErrorVals;
+
+ /// Track the virtual register for each swifterror value in a given basic
+ /// block. Entries in SwiftErrorVRegs have the same ordering as entries
+ /// in SwiftErrorVals.
+ /// Note that another choice that is more straight-forward is to use
+ /// Map<const MachineBasicBlock*, Map<Value*, unsigned/*VReg*/>>. It
+ /// maintains a map from swifterror values to virtual registers for each
+ /// machine basic block. This choice does not require a one-to-one
+ /// correspondence between SwiftErrorValues and SwiftErrorVRegs. But because
+ /// of efficiency concern, we do not choose it.
+ llvm::DenseMap<const MachineBasicBlock*, SwiftErrorVRegs> SwiftErrorMap;
+
+ /// Track the virtual register for each swifterror value at the end of a basic
+ /// block when we need the assignment of a virtual register before the basic
+ /// block is visited. When we actually visit the basic block, we will make
+ /// sure the swifterror value is in the correct virtual register.
+ llvm::DenseMap<const MachineBasicBlock*, SwiftErrorVRegs>
+ SwiftErrorWorklist;
+
+ /// Find the swifterror virtual register in SwiftErrorMap. We will assert
+ /// failure when the value does not exist in swifterror map.
+ unsigned findSwiftErrorVReg(const MachineBasicBlock*, const Value*) const;
+ /// Set the swifterror virtual register in SwiftErrorMap.
+ void setSwiftErrorVReg(const MachineBasicBlock *MBB, const Value*, unsigned);
+
/// ValueMap - Since we emit code for the function a basic block at a time,
/// we must remember which virtual registers hold the values for
/// cross-basic-block values.
@@ -80,15 +111,36 @@ public:
/// Track virtual registers created for exception pointers.
DenseMap<const Value *, unsigned> CatchPadExceptionPointers;
- // Keep track of frame indices allocated for statepoints as they could be used
- // across basic block boundaries.
- // Key of the map is statepoint instruction, value is a map from spilled
- // llvm Value to the optional stack stack slot index.
- // If optional is unspecified it means that we have visited this value
- // but didn't spill it.
- typedef DenseMap<const Value*, Optional<int>> StatepointSpilledValueMapTy;
- DenseMap<const Instruction*, StatepointSpilledValueMapTy>
- StatepointRelocatedValues;
+ /// Keep track of frame indices allocated for statepoints as they could be
+ /// used across basic block boundaries. This struct is more complex than a
+ /// simple map because the stateopint lowering code de-duplicates gc pointers
+ /// based on their SDValue (so %p and (bitcast %p to T) will get the same
+ /// slot), and we track that here.
+
+ struct StatepointSpillMap {
+ typedef DenseMap<const Value *, Optional<int>> SlotMapTy;
+
+ /// 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).
+ SlotMapTy SlotMap;
+
+ /// Maps llvm IR values to the values they were de-duplicated to.
+ DenseMap<const Value *, const Value *> DuplicateMap;
+
+ SlotMapTy::const_iterator find(const Value *V) const {
+ auto DuplIt = DuplicateMap.find(V);
+ if (DuplIt != DuplicateMap.end())
+ V = DuplIt->second;
+ return SlotMap.find(V);
+ }
+
+ SlotMapTy::const_iterator end() const { return SlotMap.end(); }
+ };
+
+ /// Maps gc.statepoint instructions to their corresponding StatepointSpillMap
+ /// instances.
+ DenseMap<const Instruction *, StatepointSpillMap> StatepointSpillMaps;
/// StaticAllocaMap - Keep track of frame indices for fixed sized allocas in
/// the entry block. This allows the allocas to be efficiently referenced
@@ -119,7 +171,7 @@ public:
struct LiveOutInfo {
unsigned NumSignBits : 31;
- bool IsValid : 1;
+ unsigned IsValid : 1;
APInt KnownOne, KnownZero;
LiveOutInfo() : NumSignBits(0), IsValid(true), KnownOne(1, 0),
KnownZero(1, 0) {}
diff --git a/include/llvm/CodeGen/GCMetadata.h b/include/llvm/CodeGen/GCMetadata.h
index 163117b0781c..e6afcbc8ded2 100644
--- a/include/llvm/CodeGen/GCMetadata.h
+++ b/include/llvm/CodeGen/GCMetadata.h
@@ -40,6 +40,7 @@
#include "llvm/IR/DebugLoc.h"
#include "llvm/Pass.h"
#include <memory>
+#include <utility>
namespace llvm {
class AsmPrinter;
@@ -54,7 +55,7 @@ struct GCPoint {
DebugLoc Loc;
GCPoint(GC::PointKind K, MCSymbol *L, DebugLoc DL)
- : Kind(K), Label(L), Loc(DL) {}
+ : Kind(K), Label(L), Loc(std::move(DL)) {}
};
/// GCRoot - Metadata for a pointer to an object managed by the garbage
@@ -120,7 +121,7 @@ public:
/// addSafePoint - Notes the existence of a safe point. Num is the ID of the
/// label just prior to the safe point (if the code generator is using
/// MachineModuleInfo).
- void addSafePoint(GC::PointKind Kind, MCSymbol *Label, DebugLoc DL) {
+ void addSafePoint(GC::PointKind Kind, MCSymbol *Label, const DebugLoc &DL) {
SafePoints.emplace_back(Kind, Label, DL);
}
diff --git a/include/llvm/CodeGen/GlobalISel/CallLowering.h b/include/llvm/CodeGen/GlobalISel/CallLowering.h
new file mode 100644
index 000000000000..bbd0b6d88593
--- /dev/null
+++ b/include/llvm/CodeGen/GlobalISel/CallLowering.h
@@ -0,0 +1,72 @@
+//===-- llvm/CodeGen/GlobalISel/CallLowering.h - Call lowering --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file describes how to lower LLVM calls to machine code calls.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_GLOBALISEL_CALLLOWERING_H
+#define LLVM_CODEGEN_GLOBALISEL_CALLLOWERING_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/Function.h"
+
+namespace llvm {
+// Forward declarations.
+class MachineIRBuilder;
+class TargetLowering;
+class Value;
+
+class CallLowering {
+ const TargetLowering *TLI;
+ protected:
+ /// Getter for generic TargetLowering class.
+ const TargetLowering *getTLI() const {
+ return TLI;
+ }
+
+ /// Getter for target specific TargetLowering class.
+ template <class XXXTargetLowering>
+ const XXXTargetLowering *getTLI() const {
+ return static_cast<const XXXTargetLowering *>(TLI);
+ }
+ public:
+ CallLowering(const TargetLowering *TLI) : TLI(TLI) {}
+ virtual ~CallLowering() {}
+
+ /// This hook must be implemented to lower outgoing return values, described
+ /// by \p Val, into the specified virtual register \p VReg.
+ /// This hook is used by GlobalISel.
+ ///
+ /// \return True if the lowering succeeds, false otherwise.
+ virtual bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val,
+ unsigned VReg) const {
+ return false;
+ }
+
+ /// This hook must be implemented to lower the incoming (formal)
+ /// arguments, described by \p Args, for GlobalISel. Each argument
+ /// must end up in the related virtual register described by VRegs.
+ /// In other words, the first argument should end up in VRegs[0],
+ /// the second in VRegs[1], and so on.
+ /// \p MIRBuilder is set to the proper insertion for the argument
+ /// lowering.
+ ///
+ /// \return True if the lowering succeeded, false otherwise.
+ virtual bool
+ lowerFormalArguments(MachineIRBuilder &MIRBuilder,
+ const Function::ArgumentListType &Args,
+ const SmallVectorImpl<unsigned> &VRegs) const {
+ return false;
+ }
+};
+} // End namespace llvm.
+
+#endif
diff --git a/include/llvm/CodeGen/GlobalISel/GISelAccessor.h b/include/llvm/CodeGen/GlobalISel/GISelAccessor.h
new file mode 100644
index 000000000000..7c5ec9f3adc0
--- /dev/null
+++ b/include/llvm/CodeGen/GlobalISel/GISelAccessor.h
@@ -0,0 +1,33 @@
+//===-- GISelAccessor.h - GISel Accessor ------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// This file declares the API to access the various APIs related
+/// to GlobalISel.
+//
+//===----------------------------------------------------------------------===/
+
+#ifndef LLVM_CODEGEN_GLOBALISEL_GISELACCESSOR_H
+#define LLVM_CODEGEN_GLOBALISEL_GISELACCESSOR_H
+
+namespace llvm {
+class CallLowering;
+class RegisterBankInfo;
+
+/// The goal of this helper class is to gather the accessor to all
+/// the APIs related to GlobalISel.
+/// It should be derived to feature an actual accessor to the GISel APIs.
+/// The reason why this is not simply done into the subtarget is to avoid
+/// spreading ifdefs around.
+struct GISelAccessor {
+ virtual ~GISelAccessor() {}
+ virtual const CallLowering *getCallLowering() const { return nullptr;}
+ virtual const RegisterBankInfo *getRegBankInfo() const { return nullptr;}
+};
+} // End namespace llvm;
+#endif
diff --git a/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/include/llvm/CodeGen/GlobalISel/IRTranslator.h
new file mode 100644
index 000000000000..833e87493cad
--- /dev/null
+++ b/include/llvm/CodeGen/GlobalISel/IRTranslator.h
@@ -0,0 +1,158 @@
+//===-- llvm/CodeGen/GlobalISel/IRTranslator.h - IRTranslator ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file declares the IRTranslator pass.
+/// This pass is responsible for translating LLVM IR into MachineInstr.
+/// It uses target hooks to lower the ABI but aside from that, the pass
+/// generated code is generic. This is the default translator used for
+/// GlobalISel.
+///
+/// \todo Replace the comments with actual doxygen comments.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_GLOBALISEL_IRTRANSLATOR_H
+#define LLVM_CODEGEN_GLOBALISEL_IRTRANSLATOR_H
+
+#include "Types.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+
+namespace llvm {
+// Forward declarations.
+class BasicBlock;
+class CallLowering;
+class Constant;
+class Instruction;
+class MachineBasicBlock;
+class MachineFunction;
+class MachineInstr;
+class MachineRegisterInfo;
+
+// Technically the pass should run on an hypothetical MachineModule,
+// since it should translate Global into some sort of MachineGlobal.
+// The MachineGlobal should ultimately just be a transfer of ownership of
+// the interesting bits that are relevant to represent a global value.
+// That being said, we could investigate what would it cost to just duplicate
+// the information from the LLVM IR.
+// The idea is that ultimately we would be able to free up the memory used
+// by the LLVM IR as soon as the translation is over.
+class IRTranslator : public MachineFunctionPass {
+public:
+ static char ID;
+
+private:
+ /// Interface used to lower the everything related to calls.
+ const CallLowering *CLI;
+ /// Mapping of the values of the current LLVM IR function
+ /// to the related virtual registers.
+ ValueToVReg ValToVReg;
+ // Constants are special because when we encounter one,
+ // we do not know at first where to insert the definition since
+ // this depends on all its uses.
+ // Thus, we will insert the sequences to materialize them when
+ // we know all their users.
+ // In the meantime, just keep it in a set.
+ // Note: Constants that end up as immediate in the related instructions,
+ // do not appear in that map.
+ SmallSetVector<const Constant *, 8> Constants;
+
+ DenseMap<const BasicBlock *, MachineBasicBlock *> BBToMBB;
+
+ /// Methods for translating form LLVM IR to MachineInstr.
+ /// \see ::translate for general information on the translate methods.
+ /// @{
+
+ /// Translate \p Inst into its corresponding MachineInstr instruction(s).
+ /// Insert the newly translated instruction(s) right where the MIRBuilder
+ /// is set.
+ ///
+ /// The general algorithm is:
+ /// 1. Look for a virtual register for each operand or
+ /// create one.
+ /// 2 Update the ValToVReg accordingly.
+ /// 2.alt. For constant arguments, if they are compile time constants,
+ /// produce an immediate in the right operand and do not touch
+ /// ValToReg. Actually we will go with a virtual register for each
+ /// constants because it may be expensive to actually materialize the
+ /// constant. Moreover, if the constant spans on several instructions,
+ /// CSE may not catch them.
+ /// => Update ValToVReg and remember that we saw a constant in Constants.
+ /// We will materialize all the constants in finalize.
+ /// Note: we would need to do something so that we can recognize such operand
+ /// as constants.
+ /// 3. Create the generic instruction.
+ ///
+ /// \return true if the translation succeeded.
+ bool translate(const Instruction &Inst);
+
+ /// Translate \p Inst into a binary operation \p Opcode.
+ /// \pre \p Inst is a binary operation.
+ bool translateBinaryOp(unsigned Opcode, const Instruction &Inst);
+
+ /// Translate branch (br) instruction.
+ /// \pre \p Inst is a branch instruction.
+ bool translateBr(const Instruction &Inst);
+
+ /// Translate return (ret) instruction.
+ /// The target needs to implement CallLowering::lowerReturn for
+ /// this to succeed.
+ /// \pre \p Inst is a return instruction.
+ bool translateReturn(const Instruction &Inst);
+ /// @}
+
+ // Builder for machine instruction a la IRBuilder.
+ // I.e., compared to regular MIBuilder, this one also inserts the instruction
+ // in the current block, it can creates block, etc., basically a kind of
+ // IRBuilder, but for Machine IR.
+ MachineIRBuilder MIRBuilder;
+
+ /// MachineRegisterInfo used to create virtual registers.
+ MachineRegisterInfo *MRI;
+
+ // * Insert all the code needed to materialize the constants
+ // at the proper place. E.g., Entry block or dominator block
+ // of each constant depending on how fancy we want to be.
+ // * Clear the different maps.
+ void finalize();
+
+ /// Get the VReg that represents \p Val.
+ /// If such VReg does not exist, it is created.
+ unsigned getOrCreateVReg(const Value &Val);
+
+ /// Get the MachineBasicBlock that represents \p BB.
+ /// If such basic block does not exist, it is created.
+ MachineBasicBlock &getOrCreateBB(const BasicBlock &BB);
+
+public:
+ // Ctor, nothing fancy.
+ IRTranslator();
+
+ const char *getPassName() const override {
+ return "IRTranslator";
+ }
+
+ // Algo:
+ // CallLowering = MF.subtarget.getCallLowering()
+ // F = MF.getParent()
+ // MIRBuilder.reset(MF)
+ // MIRBuilder.getOrCreateBB(F.getEntryBB())
+ // CallLowering->translateArguments(MIRBuilder, F, ValToVReg)
+ // for each bb in F
+ // MIRBuilder.getOrCreateBB(bb)
+ // for each inst in bb
+ // if (!translate(MIRBuilder, inst, ValToVReg, ConstantToSequence))
+ // report_fatal_error(“Don’t know how to translate input");
+ // finalize()
+ bool runOnMachineFunction(MachineFunction &MF) override;
+};
+
+} // End namespace llvm.
+#endif
diff --git a/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
new file mode 100644
index 000000000000..efdc59a9cddf
--- /dev/null
+++ b/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
@@ -0,0 +1,146 @@
+//===-- llvm/CodeGen/GlobalISel/MachineIRBuilder.h - MIBuilder --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file declares the MachineIRBuilder class.
+/// This is a helper class to build MachineInstr.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_GLOBALISEL_MACHINEIRBUILDER_H
+#define LLVM_CODEGEN_GLOBALISEL_MACHINEIRBUILDER_H
+
+#include "llvm/CodeGen/GlobalISel/Types.h"
+
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/IR/DebugLoc.h"
+
+namespace llvm {
+
+// Forward declarations.
+class MachineFunction;
+class MachineInstr;
+class TargetInstrInfo;
+
+/// Helper class to build MachineInstr.
+/// It keeps internally the insertion point and debug location for all
+/// the new instructions we want to create.
+/// This information can be modify via the related setters.
+class MachineIRBuilder {
+ /// MachineFunction under construction.
+ MachineFunction *MF;
+ /// Information used to access the description of the opcodes.
+ const TargetInstrInfo *TII;
+ /// Debug location to be set to any instruction we create.
+ DebugLoc DL;
+
+ /// Fields describing the insertion point.
+ /// @{
+ MachineBasicBlock *MBB;
+ MachineInstr *MI;
+ bool Before;
+ /// @}
+
+ const TargetInstrInfo &getTII() {
+ assert(TII && "TargetInstrInfo is not set");
+ return *TII;
+ }
+
+public:
+ /// Getter for the function we currently build.
+ MachineFunction &getMF() {
+ assert(MF && "MachineFunction is not set");
+ return *MF;
+ }
+
+ /// Getter for the basic block we currently build.
+ MachineBasicBlock &getMBB() {
+ assert(MBB && "MachineBasicBlock is not set");
+ return *MBB;
+ }
+
+ /// Current insertion point for new instructions.
+ MachineBasicBlock::iterator getInsertPt();
+
+ /// Setters for the insertion point.
+ /// @{
+ /// Set the MachineFunction where to build instructions.
+ void setMF(MachineFunction &);
+
+ /// Set the insertion point to the beginning (\p Beginning = true) or end
+ /// (\p Beginning = false) of \p MBB.
+ /// \pre \p MBB must be contained by getMF().
+ void setMBB(MachineBasicBlock &MBB, bool Beginning = false);
+
+ /// Set the insertion point to before (\p Before = true) or after
+ /// (\p Before = false) \p MI.
+ /// \pre MI must be in getMF().
+ void setInstr(MachineInstr &MI, bool Before = false);
+ /// @}
+
+ /// Set the debug location to \p DL for all the next build instructions.
+ void setDebugLoc(const DebugLoc &DL) { this->DL = DL; }
+
+ /// Build and insert <empty> = \p Opcode [\p Ty] <empty>.
+ /// \p Ty is the type of the instruction if \p Opcode describes
+ /// a generic machine instruction. \p Ty must be nullptr if \p Opcode
+ /// does not describe a generic instruction.
+ /// The insertion point is the one set by the last call of either
+ /// setBasicBlock or setMI.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre Ty == nullptr or isPreISelGenericOpcode(Opcode)
+ ///
+ /// \return The newly created instruction.
+ MachineInstr *buildInstr(unsigned Opcode, Type *Ty);
+
+ /// Build and insert <empty> = \p Opcode [\p Ty] \p BB.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre Ty == nullptr or isPreISelGenericOpcode(Opcode)
+ ///
+ /// \return The newly created instruction.
+ MachineInstr *buildInstr(unsigned Opcode, Type *Ty, MachineBasicBlock &BB);
+
+ /// Build and insert \p Res<def> = \p Opcode [\p Ty] \p Op0, \p Op1.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre Ty == nullptr or isPreISelGenericOpcode(Opcode)
+ ///
+ /// \return The newly created instruction.
+ MachineInstr *buildInstr(unsigned Opcode, Type *Ty, unsigned Res,
+ unsigned Op0, unsigned Op1);
+
+ /// Build and insert \p Res<def> = \p Opcode \p Op0, \p Op1.
+ /// I.e., instruction with a non-generic opcode.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre not isPreISelGenericOpcode(\p Opcode)
+ ///
+ /// \return The newly created instruction.
+ MachineInstr *buildInstr(unsigned Opcode, unsigned Res, unsigned Op0,
+ unsigned Op1);
+
+ /// Build and insert \p Res<def> = \p Opcode \p Op0.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre not isPreISelGenericOpcode(\p Opcode)
+ ///
+ /// \return The newly created instruction.
+ MachineInstr *buildInstr(unsigned Opcode, unsigned Res, unsigned Op0);
+
+ /// Build and insert <empty> = \p Opcode <empty>.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre not isPreISelGenericOpcode(\p Opcode)
+ ///
+ /// \return The newly created instruction.
+ MachineInstr *buildInstr(unsigned Opcode);
+};
+
+} // End namespace llvm.
+#endif // LLVM_CODEGEN_GLOBALISEL_MACHINEIRBUILDER_H
diff --git a/include/llvm/CodeGen/GlobalISel/RegBankSelect.h b/include/llvm/CodeGen/GlobalISel/RegBankSelect.h
new file mode 100644
index 000000000000..b393744e67cb
--- /dev/null
+++ b/include/llvm/CodeGen/GlobalISel/RegBankSelect.h
@@ -0,0 +1,614 @@
+//== llvm/CodeGen/GlobalISel/RegBankSelect.h - Reg Bank Selector -*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file This file describes the interface of the MachineFunctionPass
+/// responsible for assigning the generic virtual registers to register bank.
+
+/// By default, the reg bank selector relies on local decisions to
+/// assign the register bank. In other words, it looks at one instruction
+/// at a time to decide where the operand of that instruction should live.
+///
+/// At higher optimization level, we could imagine that the reg bank selector
+/// would use more global analysis and do crazier thing like duplicating
+/// instructions and so on. This is future work.
+///
+/// For now, the pass uses a greedy algorithm to decide where the operand
+/// of an instruction should live. It asks the target which banks may be
+/// used for each operand of the instruction and what is the cost. Then,
+/// it chooses the solution which minimize the cost of the instruction plus
+/// the cost of any move that may be needed to to the values into the right
+/// register bank.
+/// In other words, the cost for an instruction on a register bank RegBank
+/// is: Cost of I on RegBank plus the sum of the cost for bringing the
+/// input operands from their current register bank to RegBank.
+/// Thus, the following formula:
+/// cost(I, RegBank) = cost(I.Opcode, RegBank) +
+/// sum(for each arg in I.arguments: costCrossCopy(arg.RegBank, RegBank))
+///
+/// E.g., Let say we are assigning the register bank for the instruction
+/// defining v2.
+/// v0(A_REGBANK) = ...
+/// v1(A_REGBANK) = ...
+/// v2 = G_ADD i32 v0, v1 <-- MI
+///
+/// The target may say it can generate G_ADD i32 on register bank A and B
+/// with a cost of respectively 5 and 1.
+/// Then, let say the cost of a cross register bank copies from A to B is 1.
+/// The reg bank selector would compare the following two costs:
+/// cost(MI, A_REGBANK) = cost(G_ADD, A_REGBANK) + cost(v0.RegBank, A_REGBANK) +
+/// cost(v1.RegBank, A_REGBANK)
+/// = 5 + cost(A_REGBANK, A_REGBANK) + cost(A_REGBANK,
+/// A_REGBANK)
+/// = 5 + 0 + 0 = 5
+/// cost(MI, B_REGBANK) = cost(G_ADD, B_REGBANK) + cost(v0.RegBank, B_REGBANK) +
+/// cost(v1.RegBank, B_REGBANK)
+/// = 1 + cost(A_REGBANK, B_REGBANK) + cost(A_REGBANK,
+/// B_REGBANK)
+/// = 1 + 1 + 1 = 3
+/// Therefore, in this specific example, the reg bank selector would choose
+/// bank B for MI.
+/// v0(A_REGBANK) = ...
+/// v1(A_REGBANK) = ...
+/// tmp0(B_REGBANK) = COPY v0
+/// tmp1(B_REGBANK) = COPY v1
+/// v2(B_REGBANK) = G_ADD i32 tmp0, tmp1
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_GLOBALISEL_REGBANKSELECT_H
+#define LLVM_CODEGEN_GLOBALISEL_REGBANKSELECT_H
+
+#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
+#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+
+namespace llvm {
+// Forward declarations.
+class BlockFrequency;
+class MachineBranchProbabilityInfo;
+class MachineBlockFrequencyInfo;
+class MachineRegisterInfo;
+class TargetRegisterInfo;
+
+/// This pass implements the reg bank selector pass used in the GlobalISel
+/// pipeline. At the end of this pass, all register operands have been assigned
+class RegBankSelect : public MachineFunctionPass {
+public:
+ static char ID;
+
+ /// List of the modes supported by the RegBankSelect pass.
+ enum Mode {
+ /// Assign the register banks as fast as possible (default).
+ Fast,
+ /// Greedily minimize the cost of assigning register banks.
+ /// This should produce code of greater quality, but will
+ /// require more compile time.
+ Greedy
+ };
+
+ /// Abstract class used to represent an insertion point in a CFG.
+ /// This class records an insertion point and materializes it on
+ /// demand.
+ /// It allows to reason about the frequency of this insertion point,
+ /// without having to logically materialize it (e.g., on an edge),
+ /// before we actually need to insert something.
+ class InsertPoint {
+ protected:
+ /// Tell if the insert point has already been materialized.
+ bool WasMaterialized = false;
+ /// Materialize the insertion point.
+ ///
+ /// If isSplit() is true, this involves actually splitting
+ /// the block or edge.
+ ///
+ /// \post getPointImpl() returns a valid iterator.
+ /// \post getInsertMBBImpl() returns a valid basic block.
+ /// \post isSplit() == false ; no more splitting should be required.
+ virtual void materialize() = 0;
+
+ /// Return the materialized insertion basic block.
+ /// Code will be inserted into that basic block.
+ ///
+ /// \pre ::materialize has been called.
+ virtual MachineBasicBlock &getInsertMBBImpl() = 0;
+
+ /// Return the materialized insertion point.
+ /// Code will be inserted before that point.
+ ///
+ /// \pre ::materialize has been called.
+ virtual MachineBasicBlock::iterator getPointImpl() = 0;
+
+ public:
+ virtual ~InsertPoint() {}
+
+ /// The first call to this method will cause the splitting to
+ /// happen if need be, then sub sequent calls just return
+ /// the iterator to that point. I.e., no more splitting will
+ /// occur.
+ ///
+ /// \return The iterator that should be used with
+ /// MachineBasicBlock::insert. I.e., additional code happens
+ /// before that point.
+ MachineBasicBlock::iterator getPoint() {
+ if (!WasMaterialized) {
+ WasMaterialized = true;
+ assert(canMaterialize() && "Impossible to materialize this point");
+ materialize();
+ }
+ // When we materialized the point we should have done the splitting.
+ assert(!isSplit() && "Wrong pre-condition");
+ return getPointImpl();
+ }
+
+ /// The first call to this method will cause the splitting to
+ /// happen if need be, then sub sequent calls just return
+ /// the basic block that contains the insertion point.
+ /// I.e., no more splitting will occur.
+ ///
+ /// \return The basic block should be used with
+ /// MachineBasicBlock::insert and ::getPoint. The new code should
+ /// happen before that point.
+ MachineBasicBlock &getInsertMBB() {
+ if (!WasMaterialized) {
+ WasMaterialized = true;
+ assert(canMaterialize() && "Impossible to materialize this point");
+ materialize();
+ }
+ // When we materialized the point we should have done the splitting.
+ assert(!isSplit() && "Wrong pre-condition");
+ return getInsertMBBImpl();
+ }
+
+ /// Insert \p MI in the just before ::getPoint()
+ MachineBasicBlock::iterator insert(MachineInstr &MI) {
+ return getInsertMBB().insert(getPoint(), &MI);
+ }
+
+ /// Does this point involve splitting an edge or block?
+ /// As soon as ::getPoint is called and thus, the point
+ /// materialized, the point will not require splitting anymore,
+ /// i.e., this will return false.
+ virtual bool isSplit() const { return false; }
+
+ /// Frequency of the insertion point.
+ /// \p P is used to access the various analysis that will help to
+ /// get that information, like MachineBlockFrequencyInfo. If \p P
+ /// does not contain enough enough to return the actual frequency,
+ /// this returns 1.
+ virtual uint64_t frequency(const Pass &P) const { return 1; }
+
+ /// Check whether this insertion point can be materialized.
+ /// As soon as ::getPoint is called and thus, the point materialized
+ /// calling this method does not make sense.
+ virtual bool canMaterialize() const { return false; }
+ };
+
+ /// Insertion point before or after an instruction.
+ class InstrInsertPoint : public InsertPoint {
+ private:
+ /// Insertion point.
+ MachineInstr &Instr;
+ /// Does the insertion point is before or after Instr.
+ bool Before;
+
+ void materialize() override;
+
+ MachineBasicBlock::iterator getPointImpl() override {
+ if (Before)
+ return Instr;
+ return Instr.getNextNode() ? *Instr.getNextNode()
+ : Instr.getParent()->end();
+ }
+
+ MachineBasicBlock &getInsertMBBImpl() override {
+ return *Instr.getParent();
+ }
+
+ public:
+ /// Create an insertion point before (\p Before=true) or after \p Instr.
+ InstrInsertPoint(MachineInstr &Instr, bool Before = true);
+ bool isSplit() const override;
+ uint64_t frequency(const Pass &P) const override;
+
+ // Worst case, we need to slice the basic block, but that is still doable.
+ bool canMaterialize() const override { return true; }
+ };
+
+ /// Insertion point at the beginning or end of a basic block.
+ class MBBInsertPoint : public InsertPoint {
+ private:
+ /// Insertion point.
+ MachineBasicBlock &MBB;
+ /// Does the insertion point is at the beginning or end of MBB.
+ bool Beginning;
+
+ void materialize() override { /*Nothing to do to materialize*/
+ }
+
+ MachineBasicBlock::iterator getPointImpl() override {
+ return Beginning ? MBB.begin() : MBB.end();
+ }
+
+ MachineBasicBlock &getInsertMBBImpl() override { return MBB; }
+
+ public:
+ MBBInsertPoint(MachineBasicBlock &MBB, bool Beginning = true)
+ : InsertPoint(), MBB(MBB), Beginning(Beginning) {
+ // If we try to insert before phis, we should use the insertion
+ // points on the incoming edges.
+ assert((!Beginning || MBB.getFirstNonPHI() == MBB.begin()) &&
+ "Invalid beginning point");
+ // If we try to insert after the terminators, we should use the
+ // points on the outcoming edges.
+ assert((Beginning || MBB.getFirstTerminator() == MBB.end()) &&
+ "Invalid end point");
+ }
+ bool isSplit() const override { return false; }
+ uint64_t frequency(const Pass &P) const override;
+ bool canMaterialize() const override { return true; };
+ };
+
+ /// Insertion point on an edge.
+ class EdgeInsertPoint : public InsertPoint {
+ private:
+ /// Source of the edge.
+ MachineBasicBlock &Src;
+ /// Destination of the edge.
+ /// After the materialization is done, this hold the basic block
+ /// that resulted from the splitting.
+ MachineBasicBlock *DstOrSplit;
+ /// P is used to update the analysis passes as applicable.
+ Pass &P;
+
+ void materialize() override;
+
+ MachineBasicBlock::iterator getPointImpl() override {
+ // DstOrSplit should be the Split block at this point.
+ // I.e., it should have one predecessor, Src, and one successor,
+ // the original Dst.
+ assert(DstOrSplit && DstOrSplit->isPredecessor(&Src) &&
+ DstOrSplit->pred_size() == 1 && DstOrSplit->succ_size() == 1 &&
+ "Did not split?!");
+ return DstOrSplit->begin();
+ }
+
+ MachineBasicBlock &getInsertMBBImpl() override { return *DstOrSplit; }
+
+ public:
+ EdgeInsertPoint(MachineBasicBlock &Src, MachineBasicBlock &Dst, Pass &P)
+ : InsertPoint(), Src(Src), DstOrSplit(&Dst), P(P) {}
+ bool isSplit() const override {
+ return Src.succ_size() > 1 && DstOrSplit->pred_size() > 1;
+ }
+ uint64_t frequency(const Pass &P) const override;
+ bool canMaterialize() const override;
+ };
+
+ /// Struct used to represent the placement of a repairing point for
+ /// a given operand.
+ class RepairingPlacement {
+ public:
+ /// Define the kind of action this repairing needs.
+ enum RepairingKind {
+ /// Nothing to repair, just drop this action.
+ None,
+ /// Reparing code needs to happen before InsertPoints.
+ Insert,
+ /// (Re)assign the register bank of the operand.
+ Reassign,
+ /// Mark this repairing placement as impossible.
+ Impossible
+ };
+
+ /// Convenient types for a list of insertion points.
+ /// @{
+ typedef SmallVector<std::unique_ptr<InsertPoint>, 2> InsertionPoints;
+ typedef InsertionPoints::iterator insertpt_iterator;
+ typedef InsertionPoints::const_iterator const_insertpt_iterator;
+ /// @}
+
+ private:
+ /// Kind of repairing.
+ RepairingKind Kind;
+ /// Index of the operand that will be repaired.
+ unsigned OpIdx;
+ /// Are all the insert points materializeable?
+ bool CanMaterialize;
+ /// Is there any of the insert points needing splitting?
+ bool HasSplit;
+ /// Insertion point for the repair code.
+ /// The repairing code needs to happen just before these points.
+ InsertionPoints InsertPoints;
+ /// Some insertion points may need to update the liveness and such.
+ Pass &P;
+
+ public:
+ /// Create a repairing placement for the \p OpIdx-th operand of
+ /// \p MI. \p TRI is used to make some checks on the register aliases
+ /// if the machine operand is a physical register. \p P is used to
+ /// to update liveness information and such when materializing the
+ /// points.
+ RepairingPlacement(MachineInstr &MI, unsigned OpIdx,
+ const TargetRegisterInfo &TRI, Pass &P,
+ RepairingKind Kind = RepairingKind::Insert);
+
+ /// Getters.
+ /// @{
+ RepairingKind getKind() const { return Kind; }
+ unsigned getOpIdx() const { return OpIdx; }
+ bool canMaterialize() const { return CanMaterialize; }
+ bool hasSplit() { return HasSplit; }
+ /// @}
+
+ /// Overloaded methods to add an insertion point.
+ /// @{
+ /// Add a MBBInsertionPoint to the list of InsertPoints.
+ void addInsertPoint(MachineBasicBlock &MBB, bool Beginning);
+ /// Add a InstrInsertionPoint to the list of InsertPoints.
+ void addInsertPoint(MachineInstr &MI, bool Before);
+ /// Add an EdgeInsertionPoint (\p Src, \p Dst) to the list of InsertPoints.
+ void addInsertPoint(MachineBasicBlock &Src, MachineBasicBlock &Dst);
+ /// Add an InsertPoint to the list of insert points.
+ /// This method takes the ownership of &\p Point.
+ void addInsertPoint(InsertPoint &Point);
+ /// @}
+
+ /// Accessors related to the insertion points.
+ /// @{
+ insertpt_iterator begin() { return InsertPoints.begin(); }
+ insertpt_iterator end() { return InsertPoints.end(); }
+
+ const_insertpt_iterator begin() const { return InsertPoints.begin(); }
+ const_insertpt_iterator end() const { return InsertPoints.end(); }
+
+ unsigned getNumInsertPoints() const { return InsertPoints.size(); }
+ /// @}
+
+ /// Change the type of this repairing placement to \p NewKind.
+ /// It is not possible to switch a repairing placement to the
+ /// RepairingKind::Insert. There is no fundamental problem with
+ /// that, but no uses as well, so do not support it for now.
+ ///
+ /// \pre NewKind != RepairingKind::Insert
+ /// \post getKind() == NewKind
+ void switchTo(RepairingKind NewKind) {
+ assert(NewKind != Kind && "Already of the right Kind");
+ Kind = NewKind;
+ InsertPoints.clear();
+ CanMaterialize = NewKind != RepairingKind::Impossible;
+ HasSplit = false;
+ assert(NewKind != RepairingKind::Insert &&
+ "We would need more MI to switch to Insert");
+ }
+ };
+
+private:
+ /// Helper class used to represent the cost for mapping an instruction.
+ /// When mapping an instruction, we may introduce some repairing code.
+ /// In most cases, the repairing code is local to the instruction,
+ /// thus, we can omit the basic block frequency from the cost.
+ /// However, some alternatives may produce non-local cost, e.g., when
+ /// repairing a phi, and thus we then need to scale the local cost
+ /// to the non-local cost. This class does this for us.
+ /// \note: We could simply always scale the cost. The problem is that
+ /// there are higher chances that we saturate the cost easier and end
+ /// up having the same cost for actually different alternatives.
+ /// Another option would be to use APInt everywhere.
+ class MappingCost {
+ private:
+ /// Cost of the local instructions.
+ /// This cost is free of basic block frequency.
+ uint64_t LocalCost;
+ /// Cost of the non-local instructions.
+ /// This cost should include the frequency of the related blocks.
+ uint64_t NonLocalCost;
+ /// Frequency of the block where the local instructions live.
+ uint64_t LocalFreq;
+
+ MappingCost(uint64_t LocalCost, uint64_t NonLocalCost, uint64_t LocalFreq)
+ : LocalCost(LocalCost), NonLocalCost(NonLocalCost),
+ LocalFreq(LocalFreq) {}
+
+ /// Check if this cost is saturated.
+ bool isSaturated() const;
+
+ public:
+ /// Create a MappingCost assuming that most of the instructions
+ /// will occur in a basic block with \p LocalFreq frequency.
+ MappingCost(const BlockFrequency &LocalFreq);
+
+ /// Add \p Cost to the local cost.
+ /// \return true if this cost is saturated, false otherwise.
+ bool addLocalCost(uint64_t Cost);
+
+ /// Add \p Cost to the non-local cost.
+ /// Non-local cost should reflect the frequency of their placement.
+ /// \return true if this cost is saturated, false otherwise.
+ bool addNonLocalCost(uint64_t Cost);
+
+ /// Saturate the cost to the maximal representable value.
+ void saturate();
+
+ /// Return an instance of MappingCost that represents an
+ /// impossible mapping.
+ static MappingCost ImpossibleCost();
+
+ /// Check if this is less than \p Cost.
+ bool operator<(const MappingCost &Cost) const;
+ /// Check if this is equal to \p Cost.
+ bool operator==(const MappingCost &Cost) const;
+ /// Check if this is not equal to \p Cost.
+ bool operator!=(const MappingCost &Cost) const { return !(*this == Cost); }
+ /// Check if this is greater than \p Cost.
+ bool operator>(const MappingCost &Cost) const {
+ return *this != Cost && Cost < *this;
+ }
+ };
+
+ /// Interface to the target lowering info related
+ /// to register banks.
+ const RegisterBankInfo *RBI;
+
+ /// MRI contains all the register class/bank information that this
+ /// pass uses and updates.
+ MachineRegisterInfo *MRI;
+
+ /// Information on the register classes for the current function.
+ const TargetRegisterInfo *TRI;
+
+ /// Get the frequency of blocks.
+ /// This is required for non-fast mode.
+ MachineBlockFrequencyInfo *MBFI;
+
+ /// Get the frequency of the edges.
+ /// This is required for non-fast mode.
+ MachineBranchProbabilityInfo *MBPI;
+
+ /// Helper class used for every code morphing.
+ MachineIRBuilder MIRBuilder;
+
+ /// Optimization mode of the pass.
+ Mode OptMode;
+
+ /// Assign the register bank of each operand of \p MI.
+ void assignInstr(MachineInstr &MI);
+
+ /// Initialize the field members using \p MF.
+ void init(MachineFunction &MF);
+
+ /// Check if \p Reg is already assigned what is described by \p ValMapping.
+ /// \p OnlyAssign == true means that \p Reg just needs to be assigned a
+ /// register bank. I.e., no repairing is necessary to have the
+ /// assignment match.
+ bool assignmentMatch(unsigned Reg,
+ const RegisterBankInfo::ValueMapping &ValMapping,
+ bool &OnlyAssign) const;
+
+ /// Insert repairing code for \p Reg as specified by \p ValMapping.
+ /// The repairing placement is specified by \p RepairPt.
+ /// \p NewVRegs contains all the registers required to remap \p Reg.
+ /// In other words, the number of registers in NewVRegs must be equal
+ /// to ValMapping.BreakDown.size().
+ ///
+ /// The transformation could be sketched as:
+ /// \code
+ /// ... = op Reg
+ /// \endcode
+ /// Becomes
+ /// \code
+ /// <NewRegs> = COPY or extract Reg
+ /// ... = op Reg
+ /// \endcode
+ ///
+ /// and
+ /// \code
+ /// Reg = op ...
+ /// \endcode
+ /// Becomes
+ /// \code
+ /// Reg = op ...
+ /// Reg = COPY or build_sequence <NewRegs>
+ /// \endcode
+ ///
+ /// \pre NewVRegs.size() == ValMapping.BreakDown.size()
+ ///
+ /// \note The caller is supposed to do the rewriting of op if need be.
+ /// I.e., Reg = op ... => <NewRegs> = NewOp ...
+ void repairReg(MachineOperand &MO,
+ const RegisterBankInfo::ValueMapping &ValMapping,
+ RegBankSelect::RepairingPlacement &RepairPt,
+ const iterator_range<SmallVectorImpl<unsigned>::const_iterator>
+ &NewVRegs);
+
+ /// Return the cost of the instruction needed to map \p MO to \p ValMapping.
+ /// The cost is free of basic block frequencies.
+ /// \pre MO.isReg()
+ /// \pre MO is assigned to a register bank.
+ /// \pre ValMapping is a valid mapping for MO.
+ uint64_t
+ getRepairCost(const MachineOperand &MO,
+ const RegisterBankInfo::ValueMapping &ValMapping) const;
+
+ /// Find the best mapping for \p MI from \p PossibleMappings.
+ /// \return a reference on the best mapping in \p PossibleMappings.
+ RegisterBankInfo::InstructionMapping &
+ findBestMapping(MachineInstr &MI,
+ RegisterBankInfo::InstructionMappings &PossibleMappings,
+ SmallVectorImpl<RepairingPlacement> &RepairPts);
+
+ /// Compute the cost of mapping \p MI with \p InstrMapping and
+ /// compute the repairing placement for such mapping in \p
+ /// RepairPts.
+ /// \p BestCost is used to specify when the cost becomes too high
+ /// and thus it is not worth computing the RepairPts. Moreover if
+ /// \p BestCost == nullptr, the mapping cost is actually not
+ /// computed.
+ MappingCost
+ computeMapping(MachineInstr &MI,
+ const RegisterBankInfo::InstructionMapping &InstrMapping,
+ SmallVectorImpl<RepairingPlacement> &RepairPts,
+ const MappingCost *BestCost = nullptr);
+
+ /// When \p RepairPt involves splitting to repair \p MO for the
+ /// given \p ValMapping, try to change the way we repair such that
+ /// the splitting is not required anymore.
+ ///
+ /// \pre \p RepairPt.hasSplit()
+ /// \pre \p MO == MO.getParent()->getOperand(\p RepairPt.getOpIdx())
+ /// \pre \p ValMapping is the mapping of \p MO for MO.getParent()
+ /// that implied \p RepairPt.
+ void tryAvoidingSplit(RegBankSelect::RepairingPlacement &RepairPt,
+ const MachineOperand &MO,
+ const RegisterBankInfo::ValueMapping &ValMapping) const;
+
+ /// Apply \p Mapping to \p MI. \p RepairPts represents the different
+ /// mapping action that need to happen for the mapping to be
+ /// applied.
+ void applyMapping(MachineInstr &MI,
+ const RegisterBankInfo::InstructionMapping &InstrMapping,
+ SmallVectorImpl<RepairingPlacement> &RepairPts);
+
+public:
+ /// Create a RegBankSelect pass with the specified \p RunningMode.
+ RegBankSelect(Mode RunningMode = Fast);
+
+ const char *getPassName() const override {
+ return "RegBankSelect";
+ }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override;
+
+ /// Walk through \p MF and assign a register bank to every virtual register
+ /// that are still mapped to nothing.
+ /// The target needs to provide a RegisterBankInfo and in particular
+ /// override RegisterBankInfo::getInstrMapping.
+ ///
+ /// Simplified algo:
+ /// \code
+ /// RBI = MF.subtarget.getRegBankInfo()
+ /// MIRBuilder.setMF(MF)
+ /// for each bb in MF
+ /// for each inst in bb
+ /// MIRBuilder.setInstr(inst)
+ /// MappingCosts = RBI.getMapping(inst);
+ /// Idx = findIdxOfMinCost(MappingCosts)
+ /// CurRegBank = MappingCosts[Idx].RegBank
+ /// MRI.setRegBank(inst.getOperand(0).getReg(), CurRegBank)
+ /// for each argument in inst
+ /// if (CurRegBank != argument.RegBank)
+ /// ArgReg = argument.getReg()
+ /// Tmp = MRI.createNewVirtual(MRI.getSize(ArgReg), CurRegBank)
+ /// MIRBuilder.buildInstr(COPY, Tmp, ArgReg)
+ /// inst.getOperand(argument.getOperandNo()).setReg(Tmp)
+ /// \endcode
+ bool runOnMachineFunction(MachineFunction &MF) override;
+};
+} // End namespace llvm.
+
+#endif
diff --git a/include/llvm/CodeGen/GlobalISel/RegisterBank.h b/include/llvm/CodeGen/GlobalISel/RegisterBank.h
new file mode 100644
index 000000000000..e886382fd8e8
--- /dev/null
+++ b/include/llvm/CodeGen/GlobalISel/RegisterBank.h
@@ -0,0 +1,101 @@
+//==-- llvm/CodeGen/GlobalISel/RegisterBank.h - Register Bank ----*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file This file declares the API of register banks.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_GLOBALISEL_REGBANK_H
+#define LLVM_CODEGEN_GLOBALISEL_REGBANK_H
+
+#include "llvm/ADT/BitVector.h"
+
+namespace llvm {
+// Forward declarations.
+class RegisterBankInfo;
+class raw_ostream;
+class TargetRegisterClass;
+class TargetRegisterInfo;
+
+/// This class implements the register bank concept.
+/// Two instances of RegisterBank must have different ID.
+/// This property is enforced by the RegisterBankInfo class.
+class RegisterBank {
+private:
+ unsigned ID;
+ const char *Name;
+ unsigned Size;
+ BitVector ContainedRegClasses;
+
+ /// Sentinel value used to recognize register bank not properly
+ /// initialized yet.
+ static const unsigned InvalidID;
+
+ /// Only the RegisterBankInfo can create RegisterBank.
+ /// The default constructor will leave the object in
+ /// an invalid state. I.e. isValid() == false.
+ /// The field must be updated to fix that.
+ RegisterBank();
+
+ friend RegisterBankInfo;
+
+public:
+ /// Get the identifier of this register bank.
+ unsigned getID() const { return ID; }
+
+ /// Get a user friendly name of this register bank.
+ /// Should be used only for debugging purposes.
+ const char *getName() const { return Name; }
+
+ /// Get the maximal size in bits that fits in this register bank.
+ unsigned getSize() const { return Size; }
+
+ /// Check whether this instance is ready to be used.
+ bool isValid() const;
+
+ /// Check if this register bank is valid. In other words,
+ /// if it has been properly constructed.
+ ///
+ /// \note This method does not check anything when assertions are disabled.
+ ///
+ /// \return True is the check was successful.
+ bool verify(const TargetRegisterInfo &TRI) const;
+
+ /// Check whether this register bank covers \p RC.
+ /// In other words, check if this register bank fully covers
+ /// the registers that \p RC contains.
+ /// \pre isValid()
+ bool covers(const TargetRegisterClass &RC) const;
+
+ /// Check whether \p OtherRB is the same as this.
+ bool operator==(const RegisterBank &OtherRB) const;
+ bool operator!=(const RegisterBank &OtherRB) const {
+ return !this->operator==(OtherRB);
+ }
+
+ /// Dump the register mask on dbgs() stream.
+ /// The dump is verbose.
+ void dump(const TargetRegisterInfo *TRI = nullptr) const;
+
+ /// Print the register mask on OS.
+ /// If IsForDebug is false, then only the name of the register bank
+ /// is printed. Otherwise, all the fields are printing.
+ /// TRI is then used to print the name of the register classes that
+ /// this register bank covers.
+ void print(raw_ostream &OS, bool IsForDebug = false,
+ const TargetRegisterInfo *TRI = nullptr) const;
+};
+
+inline raw_ostream &operator<<(raw_ostream &OS, const RegisterBank &RegBank) {
+ RegBank.print(OS);
+ return OS;
+}
+} // End namespace llvm.
+
+#endif
diff --git a/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h b/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h
new file mode 100644
index 000000000000..19d170365858
--- /dev/null
+++ b/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h
@@ -0,0 +1,602 @@
+//==-- llvm/CodeGen/GlobalISel/RegisterBankInfo.h ----------------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file This file declares the API for the register bank info.
+/// This API is responsible for handling the register banks.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_GLOBALISEL_REGBANKINFO_H
+#define LLVM_CODEGEN_GLOBALISEL_REGBANKINFO_H
+
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/GlobalISel/RegisterBank.h"
+#include "llvm/CodeGen/MachineValueType.h" // For SimpleValueType.
+#include "llvm/Support/ErrorHandling.h"
+
+#include <cassert>
+#include <memory> // For unique_ptr.
+
+namespace llvm {
+class MachineInstr;
+class MachineRegisterInfo;
+class TargetInstrInfo;
+class TargetRegisterInfo;
+class raw_ostream;
+
+/// Holds all the information related to register banks.
+class RegisterBankInfo {
+public:
+ /// Helper struct that represents how a value is partially mapped
+ /// into a register.
+ /// The StartIdx and Length represent what region of the orginal
+ /// value this partial mapping covers.
+ /// This can be represented as a Mask of contiguous bit starting
+ /// at StartIdx bit and spanning Length bits.
+ /// StartIdx is the number of bits from the less significant bits.
+ struct PartialMapping {
+ /// Number of bits at which this partial mapping starts in the
+ /// original value. The bits are counted from less significant
+ /// bits to most significant bits.
+ unsigned StartIdx;
+ /// Length of this mapping in bits. This is how many bits this
+ /// partial mapping covers in the original value:
+ /// from StartIdx to StartIdx + Length -1.
+ unsigned Length;
+ /// Register bank where the partial value lives.
+ const RegisterBank *RegBank;
+
+ PartialMapping() = default;
+
+ /// Provide a shortcut for quickly building PartialMapping.
+ PartialMapping(unsigned StartIdx, unsigned Length,
+ const RegisterBank &RegBank)
+ : StartIdx(StartIdx), Length(Length), RegBank(&RegBank) {}
+
+ /// \return the index of in the original value of the most
+ /// significant bit that this partial mapping covers.
+ unsigned getHighBitIdx() const { return StartIdx + Length - 1; }
+
+ /// Print this partial mapping on dbgs() stream.
+ void dump() const;
+
+ /// Print this partial mapping on \p OS;
+ void print(raw_ostream &OS) const;
+
+ /// Check that the Mask is compatible with the RegBank.
+ /// Indeed, if the RegBank cannot accomadate the "active bits" of the mask,
+ /// there is no way this mapping is valid.
+ ///
+ /// \note This method does not check anything when assertions are disabled.
+ ///
+ /// \return True is the check was successful.
+ bool verify() const;
+ };
+
+ /// Helper struct that represents how a value is mapped through
+ /// different register banks.
+ struct ValueMapping {
+ /// How the value is broken down between the different register banks.
+ SmallVector<PartialMapping, 2> BreakDown;
+
+ /// Verify that this mapping makes sense for a value of \p ExpectedBitWidth.
+ /// \note This method does not check anything when assertions are disabled.
+ ///
+ /// \return True is the check was successful.
+ bool verify(unsigned ExpectedBitWidth) const;
+
+ /// Print this on dbgs() stream.
+ void dump() const;
+
+ /// Print this on \p OS;
+ void print(raw_ostream &OS) const;
+ };
+
+ /// Helper class that represents how the value of an instruction may be
+ /// mapped and what is the related cost of such mapping.
+ class InstructionMapping {
+ /// Identifier of the mapping.
+ /// This is used to communicate between the target and the optimizers
+ /// which mapping should be realized.
+ unsigned ID;
+ /// Cost of this mapping.
+ unsigned Cost;
+ /// Mapping of all the operands.
+ std::unique_ptr<ValueMapping[]> OperandsMapping;
+ /// Number of operands.
+ unsigned NumOperands;
+
+ ValueMapping &getOperandMapping(unsigned i) {
+ assert(i < getNumOperands() && "Out of bound operand");
+ return OperandsMapping[i];
+ }
+
+ public:
+ /// Constructor for the mapping of an instruction.
+ /// \p NumOperands must be equal to number of all the operands of
+ /// the related instruction.
+ /// The rationale is that it is more efficient for the optimizers
+ /// to be able to assume that the mapping of the ith operand is
+ /// at the index i.
+ ///
+ /// \pre ID != InvalidMappingID
+ InstructionMapping(unsigned ID, unsigned Cost, unsigned NumOperands)
+ : ID(ID), Cost(Cost), NumOperands(NumOperands) {
+ assert(getID() != InvalidMappingID &&
+ "Use the default constructor for invalid mapping");
+ OperandsMapping.reset(new ValueMapping[getNumOperands()]);
+ }
+
+ /// Default constructor.
+ /// Use this constructor to express that the mapping is invalid.
+ InstructionMapping() : ID(InvalidMappingID), Cost(0), NumOperands(0) {}
+
+ /// Get the cost.
+ unsigned getCost() const { return Cost; }
+
+ /// Get the ID.
+ unsigned getID() const { return ID; }
+
+ /// Get the number of operands.
+ unsigned getNumOperands() const { return NumOperands; }
+
+ /// Get the value mapping of the ith operand.
+ const ValueMapping &getOperandMapping(unsigned i) const {
+ return const_cast<InstructionMapping *>(this)->getOperandMapping(i);
+ }
+
+ /// Get the value mapping of the ith operand.
+ void setOperandMapping(unsigned i, const ValueMapping &ValMapping) {
+ getOperandMapping(i) = ValMapping;
+ }
+
+ /// Check whether this object is valid.
+ /// This is a lightweight check for obvious wrong instance.
+ bool isValid() const { return getID() != InvalidMappingID; }
+
+ /// Set the operand mapping for the \p OpIdx-th operand.
+ /// The mapping will consist of only one element in the break down list.
+ /// This element will map to \p RegBank and fully define a mask, whose
+ /// bitwidth matches the size of \p MaskSize.
+ void setOperandMapping(unsigned OpIdx, unsigned MaskSize,
+ const RegisterBank &RegBank);
+
+ /// Verifiy that this mapping makes sense for \p MI.
+ /// \pre \p MI must be connected to a MachineFunction.
+ ///
+ /// \note This method does not check anything when assertions are disabled.
+ ///
+ /// \return True is the check was successful.
+ bool verify(const MachineInstr &MI) const;
+
+ /// Print this on dbgs() stream.
+ void dump() const;
+
+ /// Print this on \p OS;
+ void print(raw_ostream &OS) const;
+ };
+
+ /// Convenient type to represent the alternatives for mapping an
+ /// instruction.
+ /// \todo When we move to TableGen this should be an array ref.
+ typedef SmallVector<InstructionMapping, 4> InstructionMappings;
+
+ /// Helper class use to get/create the virtual registers that will be used
+ /// to replace the MachineOperand when applying a mapping.
+ class OperandsMapper {
+ /// The OpIdx-th cell contains the index in NewVRegs where the VRegs of the
+ /// OpIdx-th operand starts. -1 means we do not have such mapping yet.
+ std::unique_ptr<int[]> OpToNewVRegIdx;
+ /// Hold the registers that will be used to map MI with InstrMapping.
+ SmallVector<unsigned, 8> NewVRegs;
+ /// Current MachineRegisterInfo, used to create new virtual registers.
+ MachineRegisterInfo &MRI;
+ /// Instruction being remapped.
+ MachineInstr &MI;
+ /// New mapping of the instruction.
+ const InstructionMapping &InstrMapping;
+
+ /// Constant value identifying that the index in OpToNewVRegIdx
+ /// for an operand has not been set yet.
+ static const int DontKnowIdx;
+
+ /// Get the range in NewVRegs to store all the partial
+ /// values for the \p OpIdx-th operand.
+ ///
+ /// \return The iterator range for the space created.
+ //
+ /// \pre getMI().getOperand(OpIdx).isReg()
+ iterator_range<SmallVectorImpl<unsigned>::iterator>
+ getVRegsMem(unsigned OpIdx);
+
+ /// Get the end iterator for a range starting at \p StartIdx and
+ /// spannig \p NumVal in NewVRegs.
+ /// \pre StartIdx + NumVal <= NewVRegs.size()
+ SmallVectorImpl<unsigned>::const_iterator
+ getNewVRegsEnd(unsigned StartIdx, unsigned NumVal) const;
+ SmallVectorImpl<unsigned>::iterator getNewVRegsEnd(unsigned StartIdx,
+ unsigned NumVal);
+
+ public:
+ /// Create an OperandsMapper that will hold the information to apply \p
+ /// InstrMapping to \p MI.
+ /// \pre InstrMapping.verify(MI)
+ OperandsMapper(MachineInstr &MI, const InstructionMapping &InstrMapping,
+ MachineRegisterInfo &MRI);
+
+ /// Getters.
+ /// @{
+ /// The MachineInstr being remapped.
+ MachineInstr &getMI() const { return MI; }
+
+ /// The final mapping of the instruction.
+ const InstructionMapping &getInstrMapping() const { return InstrMapping; }
+ /// @}
+
+ /// Create as many new virtual registers as needed for the mapping of the \p
+ /// OpIdx-th operand.
+ /// The number of registers is determined by the number of breakdown for the
+ /// related operand in the instruction mapping.
+ ///
+ /// \pre getMI().getOperand(OpIdx).isReg()
+ ///
+ /// \post All the partial mapping of the \p OpIdx-th operand have been
+ /// assigned a new virtual register.
+ void createVRegs(unsigned OpIdx);
+
+ /// Set the virtual register of the \p PartialMapIdx-th partial mapping of
+ /// the OpIdx-th operand to \p NewVReg.
+ ///
+ /// \pre getMI().getOperand(OpIdx).isReg()
+ /// \pre getInstrMapping().getOperandMapping(OpIdx).BreakDown.size() >
+ /// PartialMapIdx
+ /// \pre NewReg != 0
+ ///
+ /// \post the \p PartialMapIdx-th register of the value mapping of the \p
+ /// OpIdx-th operand has been set.
+ void setVRegs(unsigned OpIdx, unsigned PartialMapIdx, unsigned NewVReg);
+
+ /// Get all the virtual registers required to map the \p OpIdx-th operand of
+ /// the instruction.
+ ///
+ /// This return an empty range when createVRegs or setVRegs has not been
+ /// called.
+ /// The iterator may be invalidated by a call to setVRegs or createVRegs.
+ ///
+ /// When \p ForDebug is true, we will not check that the list of new virtual
+ /// registers does not contain uninitialized values.
+ ///
+ /// \pre getMI().getOperand(OpIdx).isReg()
+ /// \pre ForDebug || All partial mappings have been set a register
+ iterator_range<SmallVectorImpl<unsigned>::const_iterator>
+ getVRegs(unsigned OpIdx, bool ForDebug = false) const;
+
+ /// Print this operands mapper on dbgs() stream.
+ void dump() const;
+
+ /// Print this operands mapper on \p OS stream.
+ void print(raw_ostream &OS, bool ForDebug = false) const;
+ };
+
+protected:
+ /// Hold the set of supported register banks.
+ std::unique_ptr<RegisterBank[]> RegBanks;
+ /// Total number of register banks.
+ unsigned NumRegBanks;
+
+ /// Mapping from MVT::SimpleValueType to register banks.
+ std::unique_ptr<const RegisterBank *[]> VTToRegBank;
+
+ /// Create a RegisterBankInfo that can accomodate up to \p NumRegBanks
+ /// RegisterBank instances.
+ ///
+ /// \note For the verify method to succeed all the \p NumRegBanks
+ /// must be initialized by createRegisterBank and updated with
+ /// addRegBankCoverage RegisterBank.
+ RegisterBankInfo(unsigned NumRegBanks);
+
+ /// This constructor is meaningless.
+ /// It just provides a default constructor that can be used at link time
+ /// when GlobalISel is not built.
+ /// That way, targets can still inherit from this class without doing
+ /// crazy gymnastic to avoid link time failures.
+ /// \note That works because the constructor is inlined.
+ RegisterBankInfo() {
+ llvm_unreachable("This constructor should not be executed");
+ }
+
+ /// Create a new register bank with the given parameter and add it
+ /// to RegBanks.
+ /// \pre \p ID must not already be used.
+ /// \pre \p ID < NumRegBanks.
+ void createRegisterBank(unsigned ID, const char *Name);
+
+ /// Add \p RCId to the set of register class that the register bank,
+ /// identified \p ID, covers.
+ /// This method transitively adds all the sub classes and the subreg-classes
+ /// of \p RCId to the set of covered register classes.
+ /// It also adjusts the size of the register bank to reflect the maximal
+ /// size of a value that can be hold into that register bank.
+ ///
+ /// If \p AddTypeMapping is true, this method also records what types can
+ /// be mapped to \p ID. Although this done by default, targets may want to
+ /// disable it, espicially if a given type may be mapped on different
+ /// register bank. Indeed, in such case, this method only records the
+ /// first register bank where the type matches.
+ /// This information is only used to provide default mapping
+ /// (see getInstrMappingImpl).
+ ///
+ /// \note This method does *not* add the super classes of \p RCId.
+ /// The rationale is if \p ID covers the registers of \p RCId, that
+ /// does not necessarily mean that \p ID covers the set of registers
+ /// of RCId's superclasses.
+ /// This method does *not* add the superreg classes as well for consistents.
+ /// The expected use is to add the coverage top-down with respect to the
+ /// register hierarchy.
+ ///
+ /// \todo TableGen should just generate the BitSet vector for us.
+ void addRegBankCoverage(unsigned ID, unsigned RCId,
+ const TargetRegisterInfo &TRI,
+ bool AddTypeMapping = true);
+
+ /// Get the register bank identified by \p ID.
+ RegisterBank &getRegBank(unsigned ID) {
+ assert(ID < getNumRegBanks() && "Accessing an unknown register bank");
+ return RegBanks[ID];
+ }
+
+ /// Get the register bank that has been recorded to cover \p SVT.
+ const RegisterBank *getRegBankForType(MVT::SimpleValueType SVT) const {
+ if (!VTToRegBank)
+ return nullptr;
+ assert(SVT < MVT::SimpleValueType::LAST_VALUETYPE && "Out-of-bound access");
+ return VTToRegBank.get()[SVT];
+ }
+
+ /// Record \p RegBank as the register bank that covers \p SVT.
+ /// If a record was already set for \p SVT, the mapping is not
+ /// updated, unless \p Force == true
+ ///
+ /// \post if getRegBankForType(SVT)\@pre == nullptr then
+ /// getRegBankForType(SVT) == &RegBank
+ /// \post if Force == true then getRegBankForType(SVT) == &RegBank
+ void recordRegBankForType(const RegisterBank &RegBank,
+ MVT::SimpleValueType SVT, bool Force = false) {
+ if (!VTToRegBank) {
+ VTToRegBank.reset(
+ new const RegisterBank *[MVT::SimpleValueType::LAST_VALUETYPE]);
+ std::fill(&VTToRegBank[0],
+ &VTToRegBank[MVT::SimpleValueType::LAST_VALUETYPE], nullptr);
+ }
+ assert(SVT < MVT::SimpleValueType::LAST_VALUETYPE && "Out-of-bound access");
+ // If we want to override the mapping or the mapping does not exits yet,
+ // set the register bank for SVT.
+ if (Force || !getRegBankForType(SVT))
+ VTToRegBank.get()[SVT] = &RegBank;
+ }
+
+ /// Try to get the mapping of \p MI.
+ /// See getInstrMapping for more details on what a mapping represents.
+ ///
+ /// Unlike getInstrMapping the returned InstructionMapping may be invalid
+ /// (isValid() == false).
+ /// This means that the target independent code is not smart enough
+ /// to get the mapping of \p MI and thus, the target has to provide the
+ /// information for \p MI.
+ ///
+ /// This implementation is able to get the mapping of:
+ /// - Target specific instructions by looking at the encoding constraints.
+ /// - Any instruction if all the register operands are already been assigned
+ /// a register, a register class, or a register bank.
+ /// - Copies and phis if at least one of the operand has been assigned a
+ /// register, a register class, or a register bank.
+ /// In other words, this method will likely fail to find a mapping for
+ /// any generic opcode that has not been lowered by target specific code.
+ InstructionMapping getInstrMappingImpl(const MachineInstr &MI) const;
+
+ /// Get the register bank for the \p OpIdx-th operand of \p MI form
+ /// the encoding constraints, if any.
+ ///
+ /// \return A register bank that covers the register class of the
+ /// related encoding constraints or nullptr if \p MI did not provide
+ /// enough information to deduce it.
+ const RegisterBank *
+ getRegBankFromConstraints(const MachineInstr &MI, unsigned OpIdx,
+ const TargetInstrInfo &TII,
+ const TargetRegisterInfo &TRI) const;
+
+ /// Helper method to apply something that is like the default mapping.
+ /// Basically, that means that \p OpdMapper.getMI() is left untouched
+ /// aside from the reassignment of the register operand that have been
+ /// remapped.
+ /// If the mapping of one of the operand spans several registers, this
+ /// method will abort as this is not like a default mapping anymore.
+ ///
+ /// \pre For OpIdx in {0..\p OpdMapper.getMI().getNumOperands())
+ /// the range OpdMapper.getVRegs(OpIdx) is empty or of size 1.
+ static void applyDefaultMapping(const OperandsMapper &OpdMapper);
+
+ /// See ::applyMapping.
+ virtual void applyMappingImpl(const OperandsMapper &OpdMapper) const {
+ llvm_unreachable("The target has to implement that part");
+ }
+
+public:
+ virtual ~RegisterBankInfo() {}
+
+ /// Get the register bank identified by \p ID.
+ const RegisterBank &getRegBank(unsigned ID) const {
+ return const_cast<RegisterBankInfo *>(this)->getRegBank(ID);
+ }
+
+ /// Get the register bank of \p Reg.
+ /// If Reg has not been assigned a register, a register class,
+ /// or a register bank, then this returns nullptr.
+ ///
+ /// \pre Reg != 0 (NoRegister)
+ const RegisterBank *getRegBank(unsigned Reg, const MachineRegisterInfo &MRI,
+ const TargetRegisterInfo &TRI) const;
+
+ /// Get the total number of register banks.
+ unsigned getNumRegBanks() const { return NumRegBanks; }
+
+ /// Get a register bank that covers \p RC.
+ ///
+ /// \pre \p RC is a user-defined register class (as opposed as one
+ /// generated by TableGen).
+ ///
+ /// \note The mapping RC -> RegBank could be built while adding the
+ /// coverage for the register banks. However, we do not do it, because,
+ /// at least for now, we only need this information for register classes
+ /// that are used in the description of instruction. In other words,
+ /// there are just a handful of them and we do not want to waste space.
+ ///
+ /// \todo This should be TableGen'ed.
+ virtual const RegisterBank &
+ getRegBankFromRegClass(const TargetRegisterClass &RC) const {
+ llvm_unreachable("The target must override this method");
+ }
+
+ /// Get the cost of a copy from \p B to \p A, or put differently,
+ /// get the cost of A = COPY B. Since register banks may cover
+ /// different size, \p Size specifies what will be the size in bits
+ /// that will be copied around.
+ ///
+ /// \note Since this is a copy, both registers have the same size.
+ virtual unsigned copyCost(const RegisterBank &A, const RegisterBank &B,
+ unsigned Size) const {
+ // Optimistically assume that copies are coalesced. I.e., when
+ // they are on the same bank, they are free.
+ // Otherwise assume a non-zero cost of 1. The targets are supposed
+ // to override that properly anyway if they care.
+ return &A != &B;
+ }
+
+ /// Identifier used when the related instruction mapping instance
+ /// is generated by target independent code.
+ /// Make sure not to use that identifier to avoid possible collision.
+ static const unsigned DefaultMappingID;
+
+ /// Identifier used when the related instruction mapping instance
+ /// is generated by the default constructor.
+ /// Make sure not to use that identifier.
+ static const unsigned InvalidMappingID;
+
+ /// Get the mapping of the different operands of \p MI
+ /// on the register bank.
+ /// This mapping should be the direct translation of \p MI.
+ /// In other words, when \p MI is mapped with the returned mapping,
+ /// only the register banks of the operands of \p MI need to be updated.
+ /// In particular, neither the opcode or the type of \p MI needs to be
+ /// updated for this direct mapping.
+ ///
+ /// The target independent implementation gives a mapping based on
+ /// the register classes for the target specific opcode.
+ /// It uses the ID RegisterBankInfo::DefaultMappingID for that mapping.
+ /// Make sure you do not use that ID for the alternative mapping
+ /// for MI. See getInstrAlternativeMappings for the alternative
+ /// mappings.
+ ///
+ /// For instance, if \p MI is a vector add, the mapping should
+ /// not be a scalarization of the add.
+ ///
+ /// \post returnedVal.verify(MI).
+ ///
+ /// \note If returnedVal does not verify MI, this would probably mean
+ /// that the target does not support that instruction.
+ virtual InstructionMapping getInstrMapping(const MachineInstr &MI) const;
+
+ /// Get the alternative mappings for \p MI.
+ /// Alternative in the sense different from getInstrMapping.
+ virtual InstructionMappings
+ getInstrAlternativeMappings(const MachineInstr &MI) const;
+
+ /// Get the possible mapping for \p MI.
+ /// A mapping defines where the different operands may live and at what cost.
+ /// For instance, let us consider:
+ /// v0(16) = G_ADD <2 x i8> v1, v2
+ /// The possible mapping could be:
+ ///
+ /// {/*ID*/VectorAdd, /*Cost*/1, /*v0*/{(0xFFFF, VPR)}, /*v1*/{(0xFFFF, VPR)},
+ /// /*v2*/{(0xFFFF, VPR)}}
+ /// {/*ID*/ScalarAddx2, /*Cost*/2, /*v0*/{(0x00FF, GPR),(0xFF00, GPR)},
+ /// /*v1*/{(0x00FF, GPR),(0xFF00, GPR)},
+ /// /*v2*/{(0x00FF, GPR),(0xFF00, GPR)}}
+ ///
+ /// \note The first alternative of the returned mapping should be the
+ /// direct translation of \p MI current form.
+ ///
+ /// \post !returnedVal.empty().
+ InstructionMappings getInstrPossibleMappings(const MachineInstr &MI) const;
+
+ /// Apply \p OpdMapper.getInstrMapping() to \p OpdMapper.getMI().
+ /// After this call \p OpdMapper.getMI() may not be valid anymore.
+ /// \p OpdMapper.getInstrMapping().getID() carries the information of
+ /// what has been chosen to map \p OpdMapper.getMI(). This ID is set
+ /// by the various getInstrXXXMapping method.
+ ///
+ /// Therefore, getting the mapping and applying it should be kept in
+ /// sync.
+ void applyMapping(const OperandsMapper &OpdMapper) const {
+ // The only mapping we know how to handle is the default mapping.
+ if (OpdMapper.getInstrMapping().getID() == DefaultMappingID)
+ return applyDefaultMapping(OpdMapper);
+ // For other mapping, the target needs to do the right thing.
+ // If that means calling applyDefaultMapping, fine, but this
+ // must be explicitly stated.
+ applyMappingImpl(OpdMapper);
+ }
+
+ /// Get the size in bits of \p Reg.
+ /// Utility method to get the size of any registers. Unlike
+ /// MachineRegisterInfo::getSize, the register does not need to be a
+ /// virtual register.
+ ///
+ /// \pre \p Reg != 0 (NoRegister).
+ static unsigned getSizeInBits(unsigned Reg, const MachineRegisterInfo &MRI,
+ const TargetRegisterInfo &TRI);
+
+ /// Check that information hold by this instance make sense for the
+ /// given \p TRI.
+ ///
+ /// \note This method does not check anything when assertions are disabled.
+ ///
+ /// \return True is the check was successful.
+ bool verify(const TargetRegisterInfo &TRI) const;
+};
+
+inline raw_ostream &
+operator<<(raw_ostream &OS,
+ const RegisterBankInfo::PartialMapping &PartMapping) {
+ PartMapping.print(OS);
+ return OS;
+}
+
+inline raw_ostream &
+operator<<(raw_ostream &OS, const RegisterBankInfo::ValueMapping &ValMapping) {
+ ValMapping.print(OS);
+ return OS;
+}
+
+inline raw_ostream &
+operator<<(raw_ostream &OS,
+ const RegisterBankInfo::InstructionMapping &InstrMapping) {
+ InstrMapping.print(OS);
+ return OS;
+}
+
+inline raw_ostream &
+operator<<(raw_ostream &OS, const RegisterBankInfo::OperandsMapper &OpdMapper) {
+ OpdMapper.print(OS, /*ForDebug*/ false);
+ return OS;
+}
+} // End namespace llvm.
+
+#endif
diff --git a/include/llvm/CodeGen/GlobalISel/Types.h b/include/llvm/CodeGen/GlobalISel/Types.h
new file mode 100644
index 000000000000..7d974878d3b9
--- /dev/null
+++ b/include/llvm/CodeGen/GlobalISel/Types.h
@@ -0,0 +1,32 @@
+//===-- llvm/CodeGen/GlobalISel/Types.h - Types used by GISel ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file describes high level types that are used by several passes or
+/// APIs involved in the GlobalISel pipeline.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_GLOBALISEL_TYPES_H
+#define LLVM_CODEGEN_GLOBALISEL_TYPES_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/IR/Value.h"
+
+namespace llvm {
+
+/// Map a value to a virtual register.
+/// For now, we chose to map aggregate types to on single virtual
+/// register. This might be revisited if it turns out to be inefficient.
+/// PR26161 tracks that.
+/// Note: We need to expose this type to the target hooks for thing like
+/// ABI lowering that would be used during IRTranslation.
+typedef DenseMap<const Value *, unsigned> ValueToVReg;
+
+} // End namespace llvm.
+#endif
diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h
index 158ff3cd36a8..89cb7a86f99f 100644
--- a/include/llvm/CodeGen/ISDOpcodes.h
+++ b/include/llvm/CodeGen/ISDOpcodes.h
@@ -257,6 +257,9 @@ namespace ISD {
/// value as an integer 0/1 value.
FGETSIGN,
+ /// Returns platform specific canonical encoding of a floating point number.
+ FCANONICALIZE,
+
/// BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a vector with the
/// specified, possibly variable, elements. The number of elements is
/// required to be a power of two. The types of the operands must all be
@@ -483,6 +486,12 @@ namespace ISD {
/// the same bit size (e.g. f32 <-> i32). This can also be used for
/// int-to-int or fp-to-fp conversions, but that is a noop, deleted by
/// getNode().
+ ///
+ /// This operator is subtly different from the bitcast instruction from
+ /// LLVM-IR since this node may change the bits in the register. For
+ /// example, this occurs on big-endian NEON and big-endian MSA where the
+ /// layout of the bits in the register depends on the vector type and this
+ /// operator acts as a shuffle operation for some vector type combinations.
BITCAST,
/// ADDRSPACECAST - This operator converts between pointers of different
@@ -869,56 +878,52 @@ namespace ISD {
SETCC_INVALID // Marker value.
};
- /// isSignedIntSetCC - Return true if this is a setcc instruction that
- /// performs a signed comparison when used with integer operands.
+ /// Return true if this is a setcc instruction that performs a signed
+ /// comparison when used with integer operands.
inline bool isSignedIntSetCC(CondCode Code) {
return Code == SETGT || Code == SETGE || Code == SETLT || Code == SETLE;
}
- /// isUnsignedIntSetCC - Return true if this is a setcc instruction that
- /// performs an unsigned comparison when used with integer operands.
+ /// Return true if this is a setcc instruction that performs an unsigned
+ /// comparison when used with integer operands.
inline bool isUnsignedIntSetCC(CondCode Code) {
return Code == SETUGT || Code == SETUGE || Code == SETULT || Code == SETULE;
}
- /// isTrueWhenEqual - 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.
+ /// 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.
inline bool isTrueWhenEqual(CondCode Cond) {
return ((int)Cond & 1) != 0;
}
- /// getUnorderedFlavor - This function returns 0 if the condition is always
- /// false if an operand is a NaN, 1 if the condition is always true if the
- /// operand is a NaN, and 2 if the condition is undefined if the operand is a
- /// NaN.
+ /// This function returns 0 if the condition is always false if an operand is
+ /// a NaN, 1 if the condition is always true if the operand is a NaN, and 2 if
+ /// the condition is undefined if the operand is a NaN.
inline unsigned getUnorderedFlavor(CondCode Cond) {
return ((int)Cond >> 3) & 3;
}
- /// getSetCCInverse - Return the operation corresponding to !(X op Y), where
- /// 'op' is a valid SetCC operation.
+ /// Return the operation corresponding to !(X op Y), where 'op' is a valid
+ /// SetCC operation.
CondCode getSetCCInverse(CondCode Operation, bool isInteger);
- /// getSetCCSwappedOperands - Return the operation corresponding to (Y op X)
- /// when given the operation for (X op Y).
+ /// Return the operation corresponding to (Y op X) when given the operation
+ /// for (X op Y).
CondCode getSetCCSwappedOperands(CondCode Operation);
- /// getSetCCOrOperation - Return the result of a logical OR between different
- /// comparisons of identical values: ((X op1 Y) | (X op2 Y)). This
- /// function returns SETCC_INVALID if it is not possible to represent the
- /// resultant comparison.
+ /// Return the result of a logical OR between different comparisons of
+ /// identical values: ((X op1 Y) | (X op2 Y)). This function returns
+ /// SETCC_INVALID if it is not possible to represent the resultant comparison.
CondCode getSetCCOrOperation(CondCode Op1, CondCode Op2, bool isInteger);
- /// getSetCCAndOperation - Return the result of a logical AND between
- /// different comparisons of identical values: ((X op1 Y) & (X op2 Y)). This
- /// function returns SETCC_INVALID if it is not possible to represent the
- /// resultant comparison.
+ /// Return the result of a logical AND between different comparisons of
+ /// identical values: ((X op1 Y) & (X op2 Y)). This function returns
+ /// SETCC_INVALID if it is not possible to represent the resultant comparison.
CondCode getSetCCAndOperation(CondCode Op1, CondCode Op2, bool isInteger);
//===--------------------------------------------------------------------===//
- /// CvtCode enum - This enum defines the various converts CONVERT_RNDSAT
- /// supports.
+ /// This enum defines the various converts CONVERT_RNDSAT supports.
enum CvtCode {
CVT_FF, /// Float from Float
CVT_FS, /// Float from Signed
diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h
index f1ea2c03f13c..04e840dea2ca 100644
--- a/include/llvm/CodeGen/LiveInterval.h
+++ b/include/llvm/CodeGen/LiveInterval.h
@@ -190,8 +190,8 @@ namespace llvm {
void dump() const;
};
- typedef SmallVector<Segment,4> Segments;
- typedef SmallVector<VNInfo*,4> VNInfoList;
+ typedef SmallVector<Segment, 2> Segments;
+ typedef SmallVector<VNInfo *, 2> VNInfoList;
Segments segments; // the liveness segments
VNInfoList valnos; // value#'s
@@ -613,6 +613,9 @@ namespace llvm {
BumpPtrAllocator &Allocator)
: LiveRange(Other, Allocator), Next(nullptr), LaneMask(LaneMask) {
}
+
+ void print(raw_ostream &OS) const;
+ void dump() const;
};
private:
@@ -712,10 +715,6 @@ namespace llvm {
/// are not considered valid and should only exist temporarily).
void removeEmptySubRanges();
- /// Construct main live range by merging the SubRanges of @p LI.
- void constructMainRangeFromSubranges(const SlotIndexes &Indexes,
- VNInfo::Allocator &VNIAllocator);
-
/// getSize - Returns the sum of sizes of all the LiveRange's.
///
unsigned getSize() const;
@@ -759,6 +758,12 @@ namespace llvm {
void freeSubRange(SubRange *S);
};
+ inline raw_ostream &operator<<(raw_ostream &OS,
+ const LiveInterval::SubRange &SR) {
+ SR.print(OS);
+ return OS;
+ }
+
inline raw_ostream &operator<<(raw_ostream &OS, const LiveInterval &LI) {
LI.print(OS);
return OS;
@@ -868,6 +873,5 @@ namespace llvm {
void Distribute(LiveInterval &LI, LiveInterval *LIV[],
MachineRegisterInfo &MRI);
};
-
}
#endif
diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h
index 87421e2f83b4..d4ee0582cc41 100644
--- a/include/llvm/CodeGen/LiveIntervalAnalysis.h
+++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h
@@ -31,7 +31,6 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include <cmath>
-#include <iterator>
namespace llvm {
@@ -105,7 +104,7 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
// Calculate the spill weight to assign to a single instruction.
static float getSpillWeight(bool isDef, bool isUse,
const MachineBlockFrequencyInfo *MBFI,
- const MachineInstr *Instr);
+ const MachineInstr &Instr);
LiveInterval &getInterval(unsigned Reg) {
if (hasInterval(Reg))
@@ -145,7 +144,7 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
/// Given a register and an instruction, adds a live segment from that
/// instruction to the end of its MBB.
LiveInterval::Segment addSegmentToEndOfBlock(unsigned reg,
- MachineInstr* startInst);
+ MachineInstr &startInst);
/// After removing some uses of a register, shrink its live range to just
/// the remaining uses. This method does not compute reaching defs for new
@@ -195,13 +194,13 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
/// isNotInMIMap - returns true if the specified machine instr has been
/// removed or was never entered in the map.
- bool isNotInMIMap(const MachineInstr* Instr) const {
+ bool isNotInMIMap(const MachineInstr &Instr) const {
return !Indexes->hasIndex(Instr);
}
/// Returns the base index of the given instruction.
- SlotIndex getInstructionIndex(const MachineInstr *instr) const {
- return Indexes->getInstructionIndex(instr);
+ SlotIndex getInstructionIndex(const MachineInstr &Instr) const {
+ return Indexes->getInstructionIndex(Instr);
}
/// Returns the instruction associated with the given index.
@@ -240,21 +239,21 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
RegMaskBlocks.push_back(std::make_pair(RegMaskSlots.size(), 0));
}
- SlotIndex InsertMachineInstrInMaps(MachineInstr *MI) {
+ SlotIndex InsertMachineInstrInMaps(MachineInstr &MI) {
return Indexes->insertMachineInstrInMaps(MI);
}
void InsertMachineInstrRangeInMaps(MachineBasicBlock::iterator B,
MachineBasicBlock::iterator E) {
for (MachineBasicBlock::iterator I = B; I != E; ++I)
- Indexes->insertMachineInstrInMaps(I);
+ Indexes->insertMachineInstrInMaps(*I);
}
- void RemoveMachineInstrFromMaps(MachineInstr *MI) {
+ void RemoveMachineInstrFromMaps(MachineInstr &MI) {
Indexes->removeMachineInstrFromMaps(MI);
}
- void ReplaceMachineInstrInMaps(MachineInstr *MI, MachineInstr *NewMI) {
+ void ReplaceMachineInstrInMaps(MachineInstr &MI, MachineInstr &NewMI) {
Indexes->replaceMachineInstrInMaps(MI, NewMI);
}
@@ -288,7 +287,7 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
/// are not supported.
///
/// \param UpdateFlags Update live intervals for nonallocatable physregs.
- void handleMove(MachineInstr* MI, bool UpdateFlags = false);
+ void handleMove(MachineInstr &MI, bool UpdateFlags = false);
/// moveIntoBundle - Update intervals for operands of MI so that they
/// begin/end on the SlotIndex for BundleStart.
@@ -298,7 +297,7 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
/// Requires MI and BundleStart to have SlotIndexes, and assumes
/// existing liveness is accurate. BundleStart should be the first
/// instruction in the Bundle.
- void handleMoveIntoBundle(MachineInstr* MI, MachineInstr* BundleStart,
+ void handleMoveIntoBundle(MachineInstr &MI, MachineInstr &BundleStart,
bool UpdateFlags = false);
/// repairIntervalsInRange - Update live intervals for instructions in a
@@ -406,6 +405,11 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
void splitSeparateComponents(LiveInterval &LI,
SmallVectorImpl<LiveInterval*> &SplitLIs);
+ /// For live interval \p LI with correct SubRanges construct matching
+ /// information for the main live range. Expects the main live range to not
+ /// have any segments or value numbers.
+ void constructMainRangeFromSubranges(LiveInterval &LI);
+
private:
/// Compute live intervals for all virtual registers.
void computeVirtRegs();
diff --git a/include/llvm/CodeGen/LivePhysRegs.h b/include/llvm/CodeGen/LivePhysRegs.h
index 3bdf5ae8d013..1cea9d5b90d6 100644
--- a/include/llvm/CodeGen/LivePhysRegs.h
+++ b/include/llvm/CodeGen/LivePhysRegs.h
@@ -84,12 +84,8 @@ public:
void removeReg(unsigned Reg) {
assert(TRI && "LivePhysRegs is not initialized.");
assert(Reg <= TRI->getNumRegs() && "Expected a physical register.");
- for (MCSubRegIterator SubRegs(Reg, TRI, /*IncludeSelf=*/true);
- SubRegs.isValid(); ++SubRegs)
- LiveRegs.erase(*SubRegs);
- for (MCSuperRegIterator SuperRegs(Reg, TRI, /*IncludeSelf=*/false);
- SuperRegs.isValid(); ++SuperRegs)
- LiveRegs.erase(*SuperRegs);
+ for (MCRegAliasIterator R(Reg, TRI, true); R.isValid(); ++R)
+ LiveRegs.erase(*R);
}
/// \brief Removes physical registers clobbered by the regmask operand @p MO.
@@ -97,10 +93,15 @@ public:
SmallVectorImpl<std::pair<unsigned, const MachineOperand*>> *Clobbers);
/// \brief Returns true if register @p Reg is contained in the set. This also
- /// works if only the super register of @p Reg has been defined, because we
- /// always add also all sub-registers to the set.
+ /// works if only the super register of @p Reg has been defined, because
+ /// addReg() always adds all sub-registers to the set as well.
+ /// Note: Returns false if just some sub registers are live, use available()
+ /// when searching a free register.
bool contains(unsigned Reg) const { return LiveRegs.count(Reg); }
+ /// Returns true if register \p Reg and no aliasing register is in the set.
+ bool available(const MachineRegisterInfo &MRI, unsigned Reg) const;
+
/// \brief Simulates liveness when stepping backwards over an
/// instruction(bundle): Remove Defs, add uses. This is the recommended way of
/// calculating liveness.
@@ -116,15 +117,20 @@ public:
void stepForward(const MachineInstr &MI,
SmallVectorImpl<std::pair<unsigned, const MachineOperand*>> &Clobbers);
- /// \brief Adds all live-in registers of basic block @p MBB; After prologue/
- /// epilogue insertion \p AddPristines should be set to true to insert the
+ /// Adds all live-in registers of basic block @p MBB.
+ /// Live in registers are the registers in the blocks live-in list and the
/// pristine registers.
- void addLiveIns(const MachineBasicBlock *MBB, bool AddPristines = false);
+ void addLiveIns(const MachineBasicBlock &MBB);
+
+ /// Adds all live-out registers of basic block @p MBB.
+ /// Live out registers are the union of the live-in registers of the successor
+ /// blocks and pristine registers. Live out registers of the end block are the
+ /// callee saved registers.
+ void addLiveOuts(const MachineBasicBlock &MBB);
- /// \brief Adds all live-out registers of basic block @p MBB; After prologue/
- /// epilogue insertion \p AddPristinesAndCSRs should be set to true.
- void addLiveOuts(const MachineBasicBlock *MBB,
- bool AddPristinesAndCSRs = false);
+ /// Like addLiveOuts() but does not add pristine registers/callee saved
+ /// registers.
+ void addLiveOutsNoPristines(const MachineBasicBlock &MBB);
typedef SparseSet<unsigned>::const_iterator const_iterator;
const_iterator begin() const { return LiveRegs.begin(); }
diff --git a/include/llvm/CodeGen/LiveRangeEdit.h b/include/llvm/CodeGen/LiveRangeEdit.h
index 2271e3352aa2..4250777682ba 100644
--- a/include/llvm/CodeGen/LiveRangeEdit.h
+++ b/include/llvm/CodeGen/LiveRangeEdit.h
@@ -72,6 +72,10 @@ private:
/// ScannedRemattable - true when remattable values have been identified.
bool ScannedRemattable;
+ /// DeadRemats - The saved instructions which have already been dead after
+ /// rematerialization but not deleted yet -- to be done in postOptimization.
+ SmallPtrSet<MachineInstr *, 32> *DeadRemats;
+
/// Remattable - Values defined by remattable instructions as identified by
/// tii.isTriviallyReMaterializable().
SmallPtrSet<const VNInfo*,4> Remattable;
@@ -96,7 +100,8 @@ private:
SmallVector<LiveInterval*, 8>,
SmallPtrSet<LiveInterval*, 8> > ToShrinkSet;
/// Helper for eliminateDeadDefs.
- void eliminateDeadDef(MachineInstr *MI, ToShrinkSet &ToShrink);
+ void eliminateDeadDef(MachineInstr *MI, ToShrinkSet &ToShrink,
+ AliasAnalysis *AA);
/// MachineRegisterInfo callback to notify when new virtual
/// registers are created.
@@ -116,13 +121,16 @@ public:
/// @param vrm Map of virtual registers to physical registers for this
/// function. If NULL, no virtual register map updates will
/// be done. This could be the case if called before Regalloc.
+ /// @param deadRemats The collection of all the instructions defining an
+ /// original reg and are dead after remat.
LiveRangeEdit(LiveInterval *parent, SmallVectorImpl<unsigned> &newRegs,
MachineFunction &MF, LiveIntervals &lis, VirtRegMap *vrm,
- Delegate *delegate = nullptr)
+ Delegate *delegate = nullptr,
+ SmallPtrSet<MachineInstr *, 32> *deadRemats = nullptr)
: Parent(parent), NewRegs(newRegs), MRI(MF.getRegInfo()), LIS(lis),
- VRM(vrm), TII(*MF.getSubtarget().getInstrInfo()),
- TheDelegate(delegate), FirstNew(newRegs.size()),
- ScannedRemattable(false) {
+ VRM(vrm), TII(*MF.getSubtarget().getInstrInfo()), TheDelegate(delegate),
+ FirstNew(newRegs.size()), ScannedRemattable(false),
+ DeadRemats(deadRemats) {
MRI.setDelegate(this);
}
@@ -142,6 +150,16 @@ public:
bool empty() const { return size() == 0; }
unsigned get(unsigned idx) const { return NewRegs[idx+FirstNew]; }
+ /// pop_back - It allows LiveRangeEdit users to drop new registers.
+ /// The context is when an original def instruction of a register is
+ /// dead after rematerialization, we still want to keep it for following
+ /// rematerializations. We save the def instruction in DeadRemats,
+ /// and replace the original dst register with a new dummy register so
+ /// the live range of original dst register can be shrinked normally.
+ /// We don't want to allocate phys register for the dummy register, so
+ /// we want to drop it from the NewRegs set.
+ void pop_back() { NewRegs.pop_back(); }
+
ArrayRef<unsigned> regs() const {
return makeArrayRef(NewRegs).slice(FirstNew);
}
@@ -175,15 +193,15 @@ public:
/// Remat - Information needed to rematerialize at a specific location.
struct Remat {
VNInfo *ParentVNI; // parent_'s value at the remat location.
- MachineInstr *OrigMI; // Instruction defining ParentVNI.
+ MachineInstr *OrigMI; // Instruction defining OrigVNI. It contains the
+ // real expr for remat.
explicit Remat(VNInfo *ParentVNI) : ParentVNI(ParentVNI), OrigMI(nullptr) {}
};
/// canRematerializeAt - Determine if ParentVNI can be rematerialized at
/// UseIdx. It is assumed that parent_.getVNINfoAt(UseIdx) == ParentVNI.
/// When cheapAsAMove is set, only cheap remats are allowed.
- bool canRematerializeAt(Remat &RM,
- SlotIndex UseIdx,
+ bool canRematerializeAt(Remat &RM, VNInfo *OrigVNI, SlotIndex UseIdx,
bool cheapAsAMove);
/// rematerializeAt - Rematerialize RM.ParentVNI into DestReg by inserting an
@@ -208,6 +226,12 @@ public:
return Rematted.count(ParentVNI);
}
+ void markDeadRemat(MachineInstr *inst) {
+ // DeadRemats is an optional field.
+ if (DeadRemats)
+ DeadRemats->insert(inst);
+ }
+
/// eraseVirtReg - Notify the delegate that Reg is no longer in use, and try
/// to erase it from LIS.
void eraseVirtReg(unsigned Reg);
@@ -218,8 +242,9 @@ public:
/// RegsBeingSpilled lists registers currently being spilled by the register
/// allocator. These registers should not be split into new intervals
/// as currently those new intervals are not guaranteed to spill.
- void eliminateDeadDefs(SmallVectorImpl<MachineInstr*> &Dead,
- ArrayRef<unsigned> RegsBeingSpilled = None);
+ void eliminateDeadDefs(SmallVectorImpl<MachineInstr *> &Dead,
+ ArrayRef<unsigned> RegsBeingSpilled = None,
+ AliasAnalysis *AA = nullptr);
/// calculateRegClassAndHint - Recompute register class and hint for each new
/// register.
diff --git a/include/llvm/CodeGen/LiveVariables.h b/include/llvm/CodeGen/LiveVariables.h
index 55b97dc3e71d..bc210dda08c0 100644
--- a/include/llvm/CodeGen/LiveVariables.h
+++ b/include/llvm/CodeGen/LiveVariables.h
@@ -91,9 +91,9 @@ public:
/// removeKill - Delete a kill corresponding to the specified
/// machine instruction. Returns true if there was a kill
/// corresponding to this instruction, false otherwise.
- bool removeKill(MachineInstr *MI) {
- std::vector<MachineInstr*>::iterator
- I = std::find(Kills.begin(), Kills.end(), MI);
+ bool removeKill(MachineInstr &MI) {
+ std::vector<MachineInstr *>::iterator I =
+ std::find(Kills.begin(), Kills.end(), &MI);
if (I == Kills.end())
return false;
Kills.erase(I);
@@ -155,10 +155,10 @@ private: // Intermediate data structures
/// HandleRegMask - Call HandlePhysRegKill for all registers clobbered by Mask.
void HandleRegMask(const MachineOperand&);
- void HandlePhysRegUse(unsigned Reg, MachineInstr *MI);
+ void HandlePhysRegUse(unsigned Reg, MachineInstr &MI);
void HandlePhysRegDef(unsigned Reg, MachineInstr *MI,
SmallVectorImpl<unsigned> &Defs);
- void UpdatePhysRegDefs(MachineInstr *MI, SmallVectorImpl<unsigned> &Defs);
+ void UpdatePhysRegDefs(MachineInstr &MI, SmallVectorImpl<unsigned> &Defs);
/// FindLastRefOrPartRef - Return the last reference or partial reference of
/// the specified register.
@@ -176,7 +176,7 @@ private: // Intermediate data structures
/// is coming from.
void analyzePHINodes(const MachineFunction& Fn);
- void runOnInstr(MachineInstr *MI, SmallVectorImpl<unsigned> &Defs);
+ void runOnInstr(MachineInstr &MI, SmallVectorImpl<unsigned> &Defs);
void runOnBlock(MachineBasicBlock *MBB, unsigned NumRegs);
public:
@@ -185,37 +185,37 @@ 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, unsigned 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,
- MachineInstr *NewMI);
+ void replaceKillInstruction(unsigned 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(unsigned IncomingReg, MachineInstr &MI,
bool AddIfNotFound = false) {
- if (MI->addRegisterKilled(IncomingReg, TRI, AddIfNotFound))
- getVarInfo(IncomingReg).Kills.push_back(MI);
+ if (MI.addRegisterKilled(IncomingReg, TRI, AddIfNotFound))
+ getVarInfo(IncomingReg).Kills.push_back(&MI);
}
/// removeVirtualRegisterKilled - Remove the specified kill of the virtual
/// 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) {
+ bool removeVirtualRegisterKilled(unsigned 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);
+ for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
+ MachineOperand &MO = MI.getOperand(i);
if (MO.isReg() && MO.isKill() && MO.getReg() == reg) {
MO.setIsKill(false);
Removed = true;
@@ -230,28 +230,28 @@ public:
/// removeVirtualRegistersKilled - Remove all killed info for the specified
/// instruction.
- void removeVirtualRegistersKilled(MachineInstr *MI);
+ void removeVirtualRegistersKilled(MachineInstr &MI);
/// 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(unsigned IncomingReg, MachineInstr &MI,
bool AddIfNotFound = false) {
- if (MI->addRegisterDead(IncomingReg, TRI, AddIfNotFound))
- getVarInfo(IncomingReg).Kills.push_back(MI);
+ if (MI.addRegisterDead(IncomingReg, TRI, AddIfNotFound))
+ getVarInfo(IncomingReg).Kills.push_back(&MI);
}
/// removeVirtualRegisterDead - Remove the specified kill of the virtual
/// 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) {
+ bool removeVirtualRegisterDead(unsigned 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);
+ for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
+ MachineOperand &MO = MI.getOperand(i);
if (MO.isReg() && MO.isDef() && MO.getReg() == reg) {
MO.setIsDead(false);
Removed = true;
@@ -278,9 +278,8 @@ public:
void MarkVirtRegAliveInBlock(VarInfo& VRInfo, MachineBasicBlock* DefBlock,
MachineBasicBlock *BB,
std::vector<MachineBasicBlock*> &WorkList);
- void HandleVirtRegDef(unsigned reg, MachineInstr *MI);
- void HandleVirtRegUse(unsigned reg, MachineBasicBlock *MBB,
- MachineInstr *MI);
+ void HandleVirtRegDef(unsigned reg, MachineInstr &MI);
+ void HandleVirtRegUse(unsigned reg, MachineBasicBlock *MBB, MachineInstr &MI);
bool isLiveIn(unsigned Reg, const MachineBasicBlock &MBB) {
return getVarInfo(Reg).isLiveIn(MBB, Reg, *MRI);
diff --git a/include/llvm/CodeGen/MIRParser/MIRParser.h b/include/llvm/CodeGen/MIRParser/MIRParser.h
index a569d5ec1f5e..dd0780397f42 100644
--- a/include/llvm/CodeGen/MIRParser/MIRParser.h
+++ b/include/llvm/CodeGen/MIRParser/MIRParser.h
@@ -18,7 +18,6 @@
#ifndef LLVM_CODEGEN_MIRPARSER_MIRPARSER_H
#define LLVM_CODEGEN_MIRPARSER_MIRPARSER_H
-#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/MachineFunctionInitializer.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -26,6 +25,7 @@
namespace llvm {
+class StringRef;
class MIRParserImpl;
class SMDiagnostic;
diff --git a/include/llvm/CodeGen/MIRYamlMapping.h b/include/llvm/CodeGen/MIRYamlMapping.h
index 14d3744741c5..7f9c44833336 100644
--- a/include/llvm/CodeGen/MIRYamlMapping.h
+++ b/include/llvm/CodeGen/MIRYamlMapping.h
@@ -7,9 +7,6 @@
//
//===----------------------------------------------------------------------===//
//
-// The MIR serialization library is currently a work in progress. It can't
-// serialize machine functions at this time.
-//
// This file implements the mapping between various MIR data structures and
// their corresponding YAML representation.
//
@@ -385,6 +382,8 @@ struct MachineFunction {
unsigned Alignment = 0;
bool ExposesReturnsTwice = false;
bool HasInlineAsm = false;
+ // MachineFunctionProperties
+ bool AllVRegsAllocated = false;
// Register information
bool IsSSA = false;
bool TracksRegLiveness = false;
@@ -408,6 +407,7 @@ template <> struct MappingTraits<MachineFunction> {
YamlIO.mapOptional("alignment", MF.Alignment);
YamlIO.mapOptional("exposesReturnsTwice", MF.ExposesReturnsTwice);
YamlIO.mapOptional("hasInlineAsm", MF.HasInlineAsm);
+ YamlIO.mapOptional("allVRegsAllocated", MF.AllVRegsAllocated);
YamlIO.mapOptional("isSSA", MF.IsSSA);
YamlIO.mapOptional("tracksRegLiveness", MF.TracksRegLiveness);
YamlIO.mapOptional("tracksSubRegLiveness", MF.TracksSubRegLiveness);
diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h
index 3d58c499823e..d5f918eb2bb9 100644
--- a/include/llvm/CodeGen/MachineBasicBlock.h
+++ b/include/llvm/CodeGen/MachineBasicBlock.h
@@ -15,6 +15,8 @@
#define LLVM_CODEGEN_MACHINEBASICBLOCK_H
#include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/CodeGen/MachineInstrBundleIterator.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Support/BranchProbability.h"
#include "llvm/MC/MCRegisterInfo.h"
@@ -157,80 +159,14 @@ public:
const MachineFunction *getParent() const { return xParent; }
MachineFunction *getParent() { return xParent; }
- /// MachineBasicBlock iterator that automatically skips over MIs that are
- /// inside bundles (i.e. walk top level MIs only).
- template<typename Ty, typename IterTy>
- class bundle_iterator
- : public std::iterator<std::bidirectional_iterator_tag, Ty, ptrdiff_t> {
- IterTy MII;
-
- public:
- bundle_iterator(IterTy MI) : MII(MI) {}
-
- bundle_iterator(Ty &MI) : MII(MI) {
- assert(!MI.isBundledWithPred() &&
- "It's not legal to initialize bundle_iterator with a bundled MI");
- }
- bundle_iterator(Ty *MI) : MII(MI) {
- assert((!MI || !MI->isBundledWithPred()) &&
- "It's not legal to initialize bundle_iterator with a bundled MI");
- }
- // Template allows conversion from const to nonconst.
- template<class OtherTy, class OtherIterTy>
- bundle_iterator(const bundle_iterator<OtherTy, OtherIterTy> &I)
- : MII(I.getInstrIterator()) {}
- bundle_iterator() : MII(nullptr) {}
-
- Ty &operator*() const { return *MII; }
- Ty *operator->() const { return &operator*(); }
-
- operator Ty *() const { return MII.getNodePtrUnchecked(); }
-
- bool operator==(const bundle_iterator &X) const {
- return MII == X.MII;
- }
- bool operator!=(const bundle_iterator &X) const {
- return !operator==(X);
- }
-
- // Increment and decrement operators...
- bundle_iterator &operator--() { // predecrement - Back up
- do --MII;
- while (MII->isBundledWithPred());
- return *this;
- }
- bundle_iterator &operator++() { // preincrement - Advance
- while (MII->isBundledWithSucc())
- ++MII;
- ++MII;
- return *this;
- }
- bundle_iterator operator--(int) { // postdecrement operators...
- bundle_iterator tmp = *this;
- --*this;
- return tmp;
- }
- bundle_iterator operator++(int) { // postincrement operators...
- bundle_iterator tmp = *this;
- ++*this;
- return tmp;
- }
-
- IterTy getInstrIterator() const {
- return MII;
- }
- };
-
typedef Instructions::iterator instr_iterator;
typedef Instructions::const_iterator const_instr_iterator;
typedef std::reverse_iterator<instr_iterator> reverse_instr_iterator;
typedef
std::reverse_iterator<const_instr_iterator> const_reverse_instr_iterator;
- typedef
- bundle_iterator<MachineInstr,instr_iterator> iterator;
- typedef
- bundle_iterator<const MachineInstr,const_instr_iterator> const_iterator;
+ typedef MachineInstrBundleIterator<MachineInstr> iterator;
+ typedef MachineInstrBundleIterator<const MachineInstr> const_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
@@ -257,6 +193,13 @@ public:
reverse_instr_iterator instr_rend () { return Insts.rend(); }
const_reverse_instr_iterator instr_rend () const { return Insts.rend(); }
+ typedef iterator_range<instr_iterator> instr_range;
+ typedef iterator_range<const_instr_iterator> const_instr_range;
+ instr_range instrs() { return instr_range(instr_begin(), instr_end()); }
+ const_instr_range instrs() const {
+ return const_instr_range(instr_begin(), instr_end());
+ }
+
iterator begin() { return instr_begin(); }
const_iterator begin() const { return instr_begin(); }
iterator end () { return instr_end(); }
@@ -399,10 +342,6 @@ public:
/// via an exception handler.
void setIsEHPad(bool V = true) { IsEHPad = V; }
- /// If this block has a successor that is a landing pad, return it. Otherwise
- /// return NULL.
- const MachineBasicBlock *getLandingPadSuccessor() const;
-
bool hasEHPadSuccessor() const;
/// Returns true if this is the entry block of an EH funclet.
@@ -563,7 +502,13 @@ public:
///
/// This function updates LiveVariables, MachineDominatorTree, and
/// MachineLoopInfo, as applicable.
- MachineBasicBlock *SplitCriticalEdge(MachineBasicBlock *Succ, Pass *P);
+ MachineBasicBlock *SplitCriticalEdge(MachineBasicBlock *Succ, Pass &P);
+
+ /// Check if the edge between this block and the given successor \p
+ /// Succ, can be split. If this returns true a subsequent call to
+ /// SplitCriticalEdge is guaranteed to return a valid basic block if
+ /// no changes occured in the meantime.
+ bool canSplitCriticalEdge(const MachineBasicBlock *Succ) const;
void pop_front() { Insts.pop_front(); }
void pop_back() { Insts.pop_back(); }
@@ -729,9 +674,9 @@ public:
// Debugging methods.
void dump() const;
- void print(raw_ostream &OS, SlotIndexes* = nullptr) const;
+ void print(raw_ostream &OS, const SlotIndexes* = nullptr) const;
void print(raw_ostream &OS, ModuleSlotTracker &MST,
- SlotIndexes * = nullptr) const;
+ const SlotIndexes* = nullptr) const;
// Printing method used by LoopInfo.
void printAsOperand(raw_ostream &OS, bool PrintType = true) const;
diff --git a/include/llvm/CodeGen/MachineBlockFrequencyInfo.h b/include/llvm/CodeGen/MachineBlockFrequencyInfo.h
index feb394e7a69e..7a236086ed09 100644
--- a/include/llvm/CodeGen/MachineBlockFrequencyInfo.h
+++ b/include/llvm/CodeGen/MachineBlockFrequencyInfo.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CODEGEN_MACHINEBLOCKFREQUENCYINFO_H
#define LLVM_CODEGEN_MACHINEBLOCKFREQUENCYINFO_H
+#include "llvm/ADT/Optional.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/Support/BlockFrequency.h"
#include <climits>
@@ -50,7 +51,10 @@ public:
///
BlockFrequency getBlockFreq(const MachineBasicBlock *MBB) const;
+ Optional<uint64_t> getBlockProfileCount(const MachineBasicBlock *MBB) const;
+
const MachineFunction *getFunction() const;
+ const MachineBranchProbabilityInfo *getMBPI() const;
void view() const;
// Print the block frequency Freq to OS using the current functions entry
diff --git a/include/llvm/CodeGen/MachineCombinerPattern.h b/include/llvm/CodeGen/MachineCombinerPattern.h
index f3891227746f..11238016d447 100644
--- a/include/llvm/CodeGen/MachineCombinerPattern.h
+++ b/include/llvm/CodeGen/MachineCombinerPattern.h
@@ -38,7 +38,40 @@ enum class MachineCombinerPattern {
MULSUBX_OP1,
MULSUBX_OP2,
MULADDXI_OP1,
- MULSUBXI_OP1
+ MULSUBXI_OP1,
+ // Floating Point
+ FMULADDS_OP1,
+ FMULADDS_OP2,
+ FMULSUBS_OP1,
+ FMULSUBS_OP2,
+ FMULADDD_OP1,
+ FMULADDD_OP2,
+ FMULSUBD_OP1,
+ FMULSUBD_OP2,
+ FMLAv1i32_indexed_OP1,
+ FMLAv1i32_indexed_OP2,
+ FMLAv1i64_indexed_OP1,
+ FMLAv1i64_indexed_OP2,
+ FMLAv2f32_OP2,
+ FMLAv2f32_OP1,
+ FMLAv2f64_OP1,
+ FMLAv2f64_OP2,
+ FMLAv2i32_indexed_OP1,
+ FMLAv2i32_indexed_OP2,
+ FMLAv2i64_indexed_OP1,
+ FMLAv2i64_indexed_OP2,
+ FMLAv4f32_OP1,
+ FMLAv4f32_OP2,
+ FMLAv4i32_indexed_OP1,
+ FMLAv4i32_indexed_OP2,
+ FMLSv1i32_indexed_OP2,
+ FMLSv1i64_indexed_OP2,
+ FMLSv2i32_indexed_OP2,
+ FMLSv2i64_indexed_OP2,
+ FMLSv2f32_OP2,
+ FMLSv2f64_OP2,
+ FMLSv4i32_indexed_OP2,
+ FMLSv4f32_OP2
};
} // end namespace llvm
diff --git a/include/llvm/CodeGen/MachineDominators.h b/include/llvm/CodeGen/MachineDominators.h
index a69936f6e267..ed7cc277e8b6 100644
--- a/include/llvm/CodeGen/MachineDominators.h
+++ b/include/llvm/CodeGen/MachineDominators.h
@@ -216,6 +216,8 @@ public:
void releaseMemory() override;
+ void verifyAnalysis() const override;
+
void print(raw_ostream &OS, const Module*) const override;
/// \brief Record that the critical edge (FromBB, ToBB) has been
@@ -239,6 +241,27 @@ public:
"A basic block inserted via edge splitting cannot appear twice");
CriticalEdgesToSplit.push_back({FromBB, ToBB, NewBB});
}
+
+ /// \brief Returns *false* if the other dominator tree matches this dominator
+ /// tree.
+ inline bool compare(const MachineDominatorTree &Other) const {
+ const MachineDomTreeNode *R = getRootNode();
+ const MachineDomTreeNode *OtherR = Other.getRootNode();
+
+ if (!R || !OtherR || R->getBlock() != OtherR->getBlock())
+ return true;
+
+ if (DT->compare(*Other.DT))
+ return true;
+
+ return false;
+ }
+
+ /// \brief Verify the correctness of the domtree by re-computing it.
+ ///
+ /// This should only be used for debugging as it aborts the program if the
+ /// verification fails.
+ void verifyDomTree() const;
};
//===-------------------------------------
diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h
index e50779aacc23..59755674c69e 100644
--- a/include/llvm/CodeGen/MachineFrameInfo.h
+++ b/include/llvm/CodeGen/MachineFrameInfo.h
@@ -122,21 +122,28 @@ class MachineFrameInfo {
// arguments have ABI-prescribed offsets).
bool isAliased;
+ /// If true, the object has been zero-extended.
+ bool isZExt;
+
+ /// If true, the object has been zero-extended.
+ bool isSExt;
+
StackObject(uint64_t Sz, unsigned Al, int64_t SP, bool IM,
bool isSS, const AllocaInst *Val, bool A)
: SPOffset(SP), Size(Sz), Alignment(Al), isImmutable(IM),
isSpillSlot(isSS), isStatepointSpillSlot(false), Alloca(Val),
- PreAllocated(false), isAliased(A) {}
+ PreAllocated(false), isAliased(A), isZExt(false), isSExt(false) {}
};
/// The alignment of the stack.
unsigned StackAlignment;
- /// Can the stack be realigned.
- /// Targets that set this to false don't have the ability to overalign
- /// their stack frame, and thus, overaligned allocas are all treated
- /// as dynamic allocations and the target must handle them as part
- /// of DYNAMIC_STACKALLOC lowering.
+ /// Can the stack be realigned. This can be false if the target does not
+ /// support stack realignment, or if the user asks us not to realign the
+ /// stack. In this situation, overaligned allocas are all treated as dynamic
+ /// allocations and the target must handle them as part of DYNAMIC_STACKALLOC
+ /// lowering. All non-alloca stack objects have their alignment clamped to the
+ /// base ABI stack alignment.
/// FIXME: There is room for improvement in this case, in terms of
/// grouping overaligned allocas into a "secondary stack frame" and
/// then only use a single alloca to allocate this frame and only a
@@ -145,39 +152,42 @@ class MachineFrameInfo {
/// realignment.
bool StackRealignable;
+ /// Whether the function has the \c alignstack attribute.
+ bool ForcedRealign;
+
/// The list of stack objects allocated.
std::vector<StackObject> Objects;
/// This contains the number of fixed objects contained on
/// the stack. Because fixed objects are stored at a negative index in the
/// Objects list, this is also the index to the 0th object in the list.
- unsigned NumFixedObjects;
+ unsigned NumFixedObjects = 0;
/// This boolean keeps track of whether any variable
/// sized objects have been allocated yet.
- bool HasVarSizedObjects;
+ bool HasVarSizedObjects = false;
/// This boolean keeps track of whether there is a call
/// to builtin \@llvm.frameaddress.
- bool FrameAddressTaken;
+ bool FrameAddressTaken = false;
/// This boolean keeps track of whether there is a call
/// to builtin \@llvm.returnaddress.
- bool ReturnAddressTaken;
+ bool ReturnAddressTaken = false;
/// This boolean keeps track of whether there is a call
/// to builtin \@llvm.experimental.stackmap.
- bool HasStackMap;
+ bool HasStackMap = false;
/// This boolean keeps track of whether there is a call
/// to builtin \@llvm.experimental.patchpoint.
- bool HasPatchPoint;
+ bool HasPatchPoint = false;
/// The prolog/epilog code inserter calculates the final stack
/// offsets for all of the fixed size objects, updating the Objects list
/// above. It then updates StackSize to contain the number of bytes that need
/// to be allocated on entry to the function.
- uint64_t StackSize;
+ uint64_t StackSize = 0;
/// The amount that a frame offset needs to be adjusted to
/// have the actual offset from the stack/frame pointer. The exact usage of
@@ -188,7 +198,7 @@ class MachineFrameInfo {
/// targets, this value is only used when generating debug info (via
/// TargetRegisterInfo::getFrameIndexReference); when generating code, the
/// corresponding adjustments are performed directly.
- int OffsetAdjustment;
+ int OffsetAdjustment = 0;
/// The prolog/epilog code inserter may process objects that require greater
/// alignment than the default alignment the target provides.
@@ -197,27 +207,27 @@ class MachineFrameInfo {
/// native alignment maintained by the compiler, dynamic alignment code will
/// be needed.
///
- unsigned MaxAlignment;
+ unsigned MaxAlignment = 0;
/// Set to true if this function adjusts the stack -- e.g.,
/// when calling another function. This is only valid during and after
/// prolog/epilog code insertion.
- bool AdjustsStack;
+ bool AdjustsStack = false;
/// Set to true if this function has any function calls.
- bool HasCalls;
+ bool HasCalls = false;
/// The frame index for the stack protector.
- int StackProtectorIdx;
+ int StackProtectorIdx = -1;
/// The frame index for the function context. Used for SjLj exceptions.
- int FunctionContextIdx;
+ int FunctionContextIdx = -1;
/// This contains the size of the largest call frame if the target uses frame
/// setup/destroy pseudo instructions (as defined in the TargetFrameInfo
/// class). This information is important for frame pointer elimination.
/// It is only valid during and after prolog/epilog code insertion.
- unsigned MaxCallFrameSize;
+ unsigned MaxCallFrameSize = 0;
/// The prolog/epilog code inserter fills in this vector with each
/// callee saved register saved in the frame. Beyond its use by the prolog/
@@ -226,79 +236,53 @@ class MachineFrameInfo {
std::vector<CalleeSavedInfo> CSInfo;
/// Has CSInfo been set yet?
- bool CSIValid;
+ bool CSIValid = false;
/// References to frame indices which are mapped
/// into the local frame allocation block. <FrameIdx, LocalOffset>
SmallVector<std::pair<int, int64_t>, 32> LocalFrameObjects;
/// Size of the pre-allocated local frame block.
- int64_t LocalFrameSize;
+ int64_t LocalFrameSize = 0;
/// Required alignment of the local object blob, which is the strictest
/// alignment of any object in it.
- unsigned LocalFrameMaxAlign;
+ unsigned LocalFrameMaxAlign = 0;
/// Whether the local object blob needs to be allocated together. If not,
/// PEI should ignore the isPreAllocated flags on the stack objects and
/// just allocate them normally.
- bool UseLocalStackAllocationBlock;
-
- /// Whether the "realign-stack" option is on.
- bool RealignOption;
+ bool UseLocalStackAllocationBlock = false;
/// True if the function dynamically adjusts the stack pointer through some
/// opaque mechanism like inline assembly or Win32 EH.
- bool HasOpaqueSPAdjustment;
+ bool HasOpaqueSPAdjustment = false;
/// True if the function contains operations which will lower down to
/// instructions which manipulate the stack pointer.
- bool HasCopyImplyingStackAdjustment;
+ bool HasCopyImplyingStackAdjustment = false;
/// True if the function contains a call to the llvm.vastart intrinsic.
- bool HasVAStart;
+ bool HasVAStart = false;
/// True if this is a varargs function that contains a musttail call.
- bool HasMustTailInVarArgFunc;
+ bool HasMustTailInVarArgFunc = false;
/// True if this function contains a tail call. If so immutable objects like
/// function arguments are no longer so. A tail call *can* override fixed
/// stack objects like arguments so we can't treat them as immutable.
- bool HasTailCall;
+ bool HasTailCall = false;
/// Not null, if shrink-wrapping found a better place for the prologue.
- MachineBasicBlock *Save;
+ MachineBasicBlock *Save = nullptr;
/// Not null, if shrink-wrapping found a better place for the epilogue.
- MachineBasicBlock *Restore;
+ MachineBasicBlock *Restore = nullptr;
public:
- explicit MachineFrameInfo(unsigned StackAlign, bool isStackRealign,
- bool RealignOpt)
- : StackAlignment(StackAlign), StackRealignable(isStackRealign),
- RealignOption(RealignOpt) {
- StackSize = NumFixedObjects = OffsetAdjustment = MaxAlignment = 0;
- HasVarSizedObjects = false;
- FrameAddressTaken = false;
- ReturnAddressTaken = false;
- HasStackMap = false;
- HasPatchPoint = false;
- AdjustsStack = false;
- HasCalls = false;
- StackProtectorIdx = -1;
- FunctionContextIdx = -1;
- MaxCallFrameSize = 0;
- CSIValid = false;
- LocalFrameSize = 0;
- LocalFrameMaxAlign = 0;
- UseLocalStackAllocationBlock = false;
- HasOpaqueSPAdjustment = false;
- HasCopyImplyingStackAdjustment = false;
- HasVAStart = false;
- HasMustTailInVarArgFunc = false;
- Save = nullptr;
- Restore = nullptr;
- HasTailCall = false;
- }
+ explicit MachineFrameInfo(unsigned StackAlignment, bool StackRealignable,
+ bool ForcedRealign)
+ : StackAlignment(StackAlignment), StackRealignable(StackRealignable),
+ ForcedRealign(ForcedRealign) {}
/// Return true if there are any stack objects in this function.
bool hasStackObjects() const { return !Objects.empty(); }
@@ -450,6 +434,30 @@ public:
return Objects[ObjectIdx+NumFixedObjects].SPOffset;
}
+ bool isObjectZExt(int ObjectIdx) const {
+ assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() &&
+ "Invalid Object Idx!");
+ return Objects[ObjectIdx+NumFixedObjects].isZExt;
+ }
+
+ void setObjectZExt(int ObjectIdx, bool IsZExt) {
+ assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() &&
+ "Invalid Object Idx!");
+ Objects[ObjectIdx+NumFixedObjects].isZExt = IsZExt;
+ }
+
+ bool isObjectSExt(int ObjectIdx) const {
+ assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() &&
+ "Invalid Object Idx!");
+ return Objects[ObjectIdx+NumFixedObjects].isSExt;
+ }
+
+ void setObjectSExt(int ObjectIdx, bool IsSExt) {
+ assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() &&
+ "Invalid Object Idx!");
+ Objects[ObjectIdx+NumFixedObjects].isSExt = IsSExt;
+ }
+
/// Set the stack frame offset of the specified object. The
/// offset is relative to the stack pointer on entry to the function.
void setObjectOffset(int ObjectIdx, int64_t SPOffset) {
diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h
index df7c951743c9..4aa9a92e6bee 100644
--- a/include/llvm/CodeGen/MachineFunction.h
+++ b/include/llvm/CodeGen/MachineFunction.h
@@ -18,12 +18,15 @@
#ifndef LLVM_CODEGEN_MACHINEFUNCTION_H
#define LLVM_CODEGEN_MACHINEFUNCTION_H
+#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/ilist.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/Metadata.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/ArrayRecycler.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/Recycler.h"
namespace llvm {
@@ -50,6 +53,8 @@ struct ilist_traits<MachineBasicBlock>
: public ilist_default_traits<MachineBasicBlock> {
mutable ilist_half_node<MachineBasicBlock> Sentinel;
public:
+ // FIXME: This downcast is UB. See llvm.org/PR26753.
+ LLVM_NO_SANITIZE("object-size")
MachineBasicBlock *createSentinel() const {
return static_cast<MachineBasicBlock*>(&Sentinel);
}
@@ -85,6 +90,74 @@ struct MachineFunctionInfo {
}
};
+/// Properties which a MachineFunction may have at a given point in time.
+/// Each of these has checking code in the MachineVerifier, and passes can
+/// require that a property be set.
+class MachineFunctionProperties {
+ // TODO: Add MachineVerifier checks for AllVRegsAllocated
+ // TODO: Add a way to print the properties and make more useful error messages
+ // Possible TODO: Allow targets to extend this (perhaps by allowing the
+ // constructor to specify the size of the bit vector)
+ // Possible TODO: Allow requiring the negative (e.g. VRegsAllocated could be
+ // stated as the negative of "has vregs"
+
+public:
+ // The properties are stated in "positive" form; i.e. a pass could require
+ // that the property hold, but not that it does not hold.
+
+ // Property descriptions:
+ // IsSSA: True when the machine function is in SSA form and virtual registers
+ // have a single def.
+ // TracksLiveness: True when tracking register liveness accurately.
+ // While this property is set, register liveness information in basic block
+ // live-in lists and machine instruction operands (e.g. kill flags, implicit
+ // defs) is accurate. This means it can be used to change the code in ways
+ // that affect the values in registers, for example by the register
+ // scavenger.
+ // When this property is clear, liveness is no longer reliable.
+ // AllVRegsAllocated: All virtual registers have been allocated; i.e. all
+ // register operands are physical registers.
+ enum class Property : unsigned {
+ IsSSA,
+ TracksLiveness,
+ AllVRegsAllocated,
+ LastProperty,
+ };
+
+ bool hasProperty(Property P) const {
+ return Properties[static_cast<unsigned>(P)];
+ }
+ MachineFunctionProperties &set(Property P) {
+ Properties.set(static_cast<unsigned>(P));
+ return *this;
+ }
+ MachineFunctionProperties &clear(Property P) {
+ Properties.reset(static_cast<unsigned>(P));
+ return *this;
+ }
+ MachineFunctionProperties &set(const MachineFunctionProperties &MFP) {
+ Properties |= MFP.Properties;
+ return *this;
+ }
+ MachineFunctionProperties &clear(const MachineFunctionProperties &MFP) {
+ Properties.reset(MFP.Properties);
+ return *this;
+ }
+ // Returns true if all properties set in V (i.e. required by a pass) are set
+ // in this.
+ bool verifyRequiredProperties(const MachineFunctionProperties &V) const {
+ return !V.Properties.test(Properties);
+ }
+
+ // Print the MachineFunctionProperties in human-readable form. If OnlySet is
+ // true, only print the properties that are set.
+ void print(raw_ostream &ROS, bool OnlySet=false) const;
+
+private:
+ BitVector Properties =
+ BitVector(static_cast<unsigned>(Property::LastProperty));
+};
+
class MachineFunction {
const Function *Fn;
const TargetMachine &Target;
@@ -146,10 +219,14 @@ class MachineFunction {
/// the attribute itself.
/// This is used to limit optimizations which cannot reason
/// about the control flow of such functions.
- bool ExposesReturnsTwice;
+ bool ExposesReturnsTwice = false;
/// True if the function includes any inline assembly.
- bool HasInlineAsm;
+ bool HasInlineAsm = false;
+
+ /// Current high-level properties of the IR of the function (e.g. is in SSA
+ /// form or whether registers have been allocated)
+ MachineFunctionProperties Properties;
// Allocation management for pseudo source values.
std::unique_ptr<PseudoSourceValueManager> PSVManager;
@@ -268,6 +345,10 @@ public:
HasInlineAsm = B;
}
+ /// Get the function properties
+ const MachineFunctionProperties &getProperties() const { return Properties; }
+ MachineFunctionProperties &getProperties() { return Properties; }
+
/// getInfo - Keep track of various per-function pieces of information for
/// backends that would like to do so.
///
@@ -311,7 +392,7 @@ public:
/// print - Print out the MachineFunction in a format suitable for debugging
/// to the specified stream.
///
- void print(raw_ostream &OS, SlotIndexes* = nullptr) const;
+ void print(raw_ostream &OS, const SlotIndexes* = nullptr) const;
/// viewCFG - This function is meant for use from the debugger. You can just
/// say 'call F->viewCFG()' and a ghostview window should pop up from the
@@ -332,9 +413,11 @@ public:
///
void dump() const;
- /// verify - Run the current MachineFunction through the machine code
- /// verifier, useful for debugger use.
- void verify(Pass *p = nullptr, const char *Banner = nullptr) const;
+ /// Run the current MachineFunction through the machine code verifier, useful
+ /// for debugger use.
+ /// \returns true if no problems were found.
+ bool verify(Pass *p = nullptr, const char *Banner = nullptr,
+ bool AbortOnError = true) const;
// Provide accessors for the MachineBasicBlock list...
typedef BasicBlockListType::iterator iterator;
@@ -420,8 +503,7 @@ public:
/// CreateMachineInstr - Allocate a new MachineInstr. Use this instead
/// of `new MachineInstr'.
///
- MachineInstr *CreateMachineInstr(const MCInstrDesc &MCID,
- DebugLoc DL,
+ MachineInstr *CreateMachineInstr(const MCInstrDesc &MCID, const DebugLoc &DL,
bool NoImp = false);
/// CloneMachineInstr - Create a new MachineInstr which is a copy of the
@@ -449,8 +531,8 @@ public:
/// MachineMemOperands are owned by the MachineFunction and need not be
/// explicitly deallocated.
MachineMemOperand *getMachineMemOperand(MachinePointerInfo PtrInfo,
- unsigned f, uint64_t s,
- unsigned base_alignment,
+ MachineMemOperand::Flags f,
+ uint64_t s, unsigned base_alignment,
const AAMDNodes &AAInfo = AAMDNodes(),
const MDNode *Ranges = nullptr);
diff --git a/include/llvm/CodeGen/MachineFunctionPass.h b/include/llvm/CodeGen/MachineFunctionPass.h
index 50a1f6e96217..653d1175d04b 100644
--- a/include/llvm/CodeGen/MachineFunctionPass.h
+++ b/include/llvm/CodeGen/MachineFunctionPass.h
@@ -20,16 +20,24 @@
#define LLVM_CODEGEN_MACHINEFUNCTIONPASS_H
#include "llvm/Pass.h"
+#include "llvm/CodeGen/MachineFunction.h"
namespace llvm {
-class MachineFunction;
-
/// MachineFunctionPass - This class adapts the FunctionPass interface to
/// allow convenient creation of passes that operate on the MachineFunction
/// representation. Instead of overriding runOnFunction, subclasses
/// override runOnMachineFunction.
class MachineFunctionPass : public FunctionPass {
+public:
+ bool doInitialization(Module&) override {
+ // Cache the properties info at module-init time so we don't have to
+ // construct them for every function.
+ RequiredProperties = getRequiredProperties();
+ SetProperties = getSetProperties();
+ ClearedProperties = getClearedProperties();
+ return false;
+ }
protected:
explicit MachineFunctionPass(char &ID) : FunctionPass(ID) {}
@@ -46,7 +54,21 @@ protected:
///
void getAnalysisUsage(AnalysisUsage &AU) const override;
+ virtual MachineFunctionProperties getRequiredProperties() const {
+ return MachineFunctionProperties();
+ }
+ virtual MachineFunctionProperties getSetProperties() const {
+ return MachineFunctionProperties();
+ }
+ virtual MachineFunctionProperties getClearedProperties() const {
+ return MachineFunctionProperties();
+ }
+
private:
+ MachineFunctionProperties RequiredProperties;
+ MachineFunctionProperties SetProperties;
+ MachineFunctionProperties ClearedProperties;
+
/// createPrinterPass - Get a machine function printer pass.
Pass *createPrinterPass(raw_ostream &O,
const std::string &Banner) const override;
diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h
index 05c9a9e0b079..8f1cb9b6f659 100644
--- a/include/llvm/CodeGen/MachineInstr.h
+++ b/include/llvm/CodeGen/MachineInstr.h
@@ -16,16 +16,13 @@
#ifndef LLVM_CODEGEN_MACHINEINSTR_H
#define LLVM_CODEGEN_MACHINEINSTR_H
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/ilist_node.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/CodeGen/MachineOperand.h"
-#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/MC/MCInstrDesc.h"
@@ -34,10 +31,17 @@
namespace llvm {
+class StringRef;
+template <typename T> class ArrayRef;
template <typename T> class SmallVectorImpl;
+class DILocalVariable;
+class DIExpression;
class TargetInstrInfo;
class TargetRegisterClass;
class TargetRegisterInfo;
+#ifdef LLVM_BUILD_GLOBAL_ISEL
+class Type;
+#endif
class MachineFunction;
class MachineMemOperand;
@@ -102,6 +106,13 @@ private:
DebugLoc debugLoc; // Source line information.
+#ifdef LLVM_BUILD_GLOBAL_ISEL
+ /// Type of the instruction in case of a generic opcode.
+ /// \invariant This must be nullptr is getOpcode() is not
+ /// in the range of generic opcodes.
+ Type *Ty;
+#endif
+
MachineInstr(const MachineInstr&) = delete;
void operator=(const MachineInstr&) = delete;
// Use MachineFunction::DeleteMachineInstr() instead.
@@ -176,6 +187,11 @@ public:
Flags &= ~((uint8_t)Flag);
}
+ /// Set the type of the instruction.
+ /// \pre getOpcode() is in the range of the generic opcodes.
+ void setType(Type *Ty);
+ Type *getType() const;
+
/// Return true if MI is in a bundle (but not the first MI in a bundle).
///
/// A bundle looks like this before it's finalized:
@@ -248,17 +264,11 @@ public:
/// Return the debug variable referenced by
/// this DBG_VALUE instruction.
- const DILocalVariable *getDebugVariable() const {
- assert(isDebugValue() && "not a DBG_VALUE");
- return cast<DILocalVariable>(getOperand(2).getMetadata());
- }
+ const DILocalVariable *getDebugVariable() const;
/// Return the complex address expression referenced by
/// this DBG_VALUE instruction.
- const DIExpression *getDebugExpression() const {
- assert(isDebugValue() && "not a DBG_VALUE");
- return cast<DIExpression>(getOperand(3).getMetadata());
- }
+ const DIExpression *getDebugExpression() const;
/// Emit an error referring to the source location of this instruction.
/// This should only be used for inline assembly that is somehow
@@ -343,6 +353,14 @@ public:
return make_range(operands_begin() + getDesc().getNumDefs(),
operands_end());
}
+ iterator_range<mop_iterator> explicit_uses() {
+ return make_range(operands_begin() + getDesc().getNumDefs(),
+ operands_begin() + getNumExplicitOperands() );
+ }
+ iterator_range<const_mop_iterator> explicit_uses() const {
+ return make_range(operands_begin() + getDesc().getNumDefs(),
+ operands_begin() + getNumExplicitOperands() );
+ }
/// Returns the number of the operand iterator \p I points to.
unsigned getOperandNo(const_mop_iterator I) const {
@@ -508,6 +526,11 @@ public:
/// Convergent instructions can not be made control-dependent on any
/// additional values.
bool isConvergent(QueryType Type = AnyInBundle) const {
+ if (isInlineAsm()) {
+ unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm();
+ if (ExtraInfo & InlineAsm::Extra_IsConvergent)
+ return true;
+ }
return hasProperty(MCID::Convergent, Type);
}
@@ -713,7 +736,7 @@ public:
/// Return true if this instruction is identical to (same
/// opcode and same operands as) the specified instruction.
- bool isIdenticalTo(const MachineInstr *Other,
+ bool isIdenticalTo(const MachineInstr &Other,
MICheckType Check = CheckDefs) const;
/// Unlink 'this' from the containing basic block, and return it without
@@ -899,6 +922,10 @@ public:
return findRegisterDefOperandIdx(Reg, true, false, TRI) != -1;
}
+ /// Returns true if the MachineInstr has an implicit-use operand of exactly
+ /// the given register (not considering sub/super-registers).
+ bool hasRegisterImplicitUseOperand(unsigned Reg) const;
+
/// Returns the operand index that is a use of the specific register or -1
/// if it is not found. It further tightens the search criteria to a use
/// that kills the register if isKill is true.
@@ -1054,8 +1081,8 @@ public:
const TargetRegisterInfo *RegInfo,
bool AddIfNotFound = false);
- /// Clear all kill flags affecting Reg. If RegInfo is
- /// provided, this includes super-register kills.
+ /// Clear all kill flags affecting Reg. If RegInfo is provided, this includes
+ /// all aliasing registers.
void clearRegisterKills(unsigned Reg, const TargetRegisterInfo *RegInfo);
/// We have determined MI defined a register without a use.
@@ -1125,7 +1152,7 @@ public:
/// Copy implicit register operands from specified
/// instruction to this instruction.
- void copyImplicitOps(MachineFunction &MF, const MachineInstr *MI);
+ void copyImplicitOps(MachineFunction &MF, const MachineInstr &MI);
//
// Debugging support
@@ -1168,7 +1195,7 @@ public:
assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor");
}
- /// Erase an operand from an instruction, leaving it with one
+ /// Erase an operand from an instruction, leaving it with one
/// fewer operand than it started with.
void RemoveOperand(unsigned i);
@@ -1268,7 +1295,7 @@ struct MachineInstrExpressionTrait : DenseMapInfo<MachineInstr*> {
if (RHS == getEmptyKey() || RHS == getTombstoneKey() ||
LHS == getEmptyKey() || LHS == getTombstoneKey())
return LHS == RHS;
- return LHS->isIdenticalTo(RHS, MachineInstr::IgnoreVRegDefs);
+ return LHS->isIdenticalTo(*RHS, MachineInstr::IgnoreVRegDefs);
}
};
diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h
index 8fe9b280d5d2..37b67aa0cf5c 100644
--- a/include/llvm/CodeGen/MachineInstrBuilder.h
+++ b/include/llvm/CodeGen/MachineInstrBuilder.h
@@ -10,7 +10,9 @@
// This file exposes a function named BuildMI, which is useful for dramatically
// simplifying how MachineInstr's are created. It allows use of code like this:
//
-// M = BuildMI(X86::ADDrr8, 2).addReg(argVal1).addReg(argVal2);
+// M = BuildMI(MBB, MI, DL, TII.get(X86::ADD8rr), Dst)
+// .addReg(argVal1)
+// .addReg(argVal2);
//
//===----------------------------------------------------------------------===//
@@ -51,6 +53,8 @@ public:
/// Create a MachineInstrBuilder for manipulating an existing instruction.
/// F must be the machine function that was used to allocate I.
MachineInstrBuilder(MachineFunction &F, MachineInstr *I) : MF(&F), MI(I) {}
+ MachineInstrBuilder(MachineFunction &F, MachineBasicBlock::iterator I)
+ : MF(&F), MI(&*I) {}
/// Allow automatic conversion to the machine instruction we are working on.
operator MachineInstr*() const { return MI; }
@@ -228,25 +232,22 @@ public:
/// Copy all the implicit operands from OtherMI onto this one.
const MachineInstrBuilder &
- copyImplicitOps(const MachineInstr *OtherMI) const {
+ copyImplicitOps(const MachineInstr &OtherMI) const {
MI->copyImplicitOps(*MF, OtherMI);
return *this;
}
};
/// Builder interface. Specify how to create the initial instruction itself.
-inline MachineInstrBuilder BuildMI(MachineFunction &MF,
- DebugLoc DL,
+inline MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL,
const MCInstrDesc &MCID) {
return MachineInstrBuilder(MF, MF.CreateMachineInstr(MCID, DL));
}
/// This version of the builder sets up the first operand as a
/// destination virtual register.
-inline MachineInstrBuilder BuildMI(MachineFunction &MF,
- DebugLoc DL,
- const MCInstrDesc &MCID,
- unsigned DestReg) {
+inline MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL,
+ const MCInstrDesc &MCID, unsigned DestReg) {
return MachineInstrBuilder(MF, MF.CreateMachineInstr(MCID, DL))
.addReg(DestReg, RegState::Define);
}
@@ -256,8 +257,7 @@ inline MachineInstrBuilder BuildMI(MachineFunction &MF,
/// operand as a destination virtual register.
inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
MachineBasicBlock::iterator I,
- DebugLoc DL,
- const MCInstrDesc &MCID,
+ const DebugLoc &DL, const MCInstrDesc &MCID,
unsigned DestReg) {
MachineFunction &MF = *BB.getParent();
MachineInstr *MI = MF.CreateMachineInstr(MCID, DL);
@@ -265,10 +265,15 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
return MachineInstrBuilder(MF, MI).addReg(DestReg, RegState::Define);
}
+/// This version of the builder inserts the newly-built instruction before
+/// the given position in the given MachineBasicBlock, and sets up the first
+/// operand as a destination virtual register.
+///
+/// If \c I is inside a bundle, then the newly inserted \a MachineInstr is
+/// added to the same bundle.
inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
MachineBasicBlock::instr_iterator I,
- DebugLoc DL,
- const MCInstrDesc &MCID,
+ const DebugLoc &DL, const MCInstrDesc &MCID,
unsigned DestReg) {
MachineFunction &MF = *BB.getParent();
MachineInstr *MI = MF.CreateMachineInstr(MCID, DL);
@@ -276,18 +281,20 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
return MachineInstrBuilder(MF, MI).addReg(DestReg, RegState::Define);
}
-inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
- MachineInstr *I,
- DebugLoc DL,
- const MCInstrDesc &MCID,
+inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, MachineInstr &I,
+ const DebugLoc &DL, const MCInstrDesc &MCID,
unsigned DestReg) {
- if (I->isInsideBundle()) {
- MachineBasicBlock::instr_iterator MII(I);
- return BuildMI(BB, MII, DL, MCID, DestReg);
- }
+ // Calling the overload for instr_iterator is always correct. However, the
+ // definition is not available in headers, so inline the check.
+ if (I.isInsideBundle())
+ return BuildMI(BB, MachineBasicBlock::instr_iterator(I), DL, MCID, DestReg);
+ return BuildMI(BB, MachineBasicBlock::iterator(I), DL, MCID, DestReg);
+}
- MachineBasicBlock::iterator MII = I;
- return BuildMI(BB, MII, DL, MCID, DestReg);
+inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, MachineInstr *I,
+ const DebugLoc &DL, const MCInstrDesc &MCID,
+ unsigned DestReg) {
+ return BuildMI(BB, *I, DL, MCID, DestReg);
}
/// This version of the builder inserts the newly-built instruction before the
@@ -295,7 +302,7 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
/// destination register.
inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
MachineBasicBlock::iterator I,
- DebugLoc DL,
+ const DebugLoc &DL,
const MCInstrDesc &MCID) {
MachineFunction &MF = *BB.getParent();
MachineInstr *MI = MF.CreateMachineInstr(MCID, DL);
@@ -305,7 +312,7 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
MachineBasicBlock::instr_iterator I,
- DebugLoc DL,
+ const DebugLoc &DL,
const MCInstrDesc &MCID) {
MachineFunction &MF = *BB.getParent();
MachineInstr *MI = MF.CreateMachineInstr(MCID, DL);
@@ -313,23 +320,25 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
return MachineInstrBuilder(MF, MI);
}
-inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
- MachineInstr *I,
- DebugLoc DL,
+inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, MachineInstr &I,
+ const DebugLoc &DL,
const MCInstrDesc &MCID) {
- if (I->isInsideBundle()) {
- MachineBasicBlock::instr_iterator MII(I);
- return BuildMI(BB, MII, DL, MCID);
- }
+ // Calling the overload for instr_iterator is always correct. However, the
+ // definition is not available in headers, so inline the check.
+ if (I.isInsideBundle())
+ return BuildMI(BB, MachineBasicBlock::instr_iterator(I), DL, MCID);
+ return BuildMI(BB, MachineBasicBlock::iterator(I), DL, MCID);
+}
- MachineBasicBlock::iterator MII = I;
- return BuildMI(BB, MII, DL, MCID);
+inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, MachineInstr *I,
+ const DebugLoc &DL,
+ const MCInstrDesc &MCID) {
+ return BuildMI(BB, *I, DL, MCID);
}
/// This version of the builder inserts the newly-built instruction at the end
/// of the given MachineBasicBlock, and does NOT take a destination register.
-inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB,
- DebugLoc DL,
+inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, const DebugLoc &DL,
const MCInstrDesc &MCID) {
return BuildMI(*BB, BB->end(), DL, MCID);
}
@@ -337,10 +346,8 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB,
/// This version of the builder inserts the newly-built instruction at the
/// end of the given MachineBasicBlock, and sets up the first operand as a
/// destination virtual register.
-inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB,
- DebugLoc DL,
- const MCInstrDesc &MCID,
- unsigned DestReg) {
+inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, const DebugLoc &DL,
+ const MCInstrDesc &MCID, unsigned DestReg) {
return BuildMI(*BB, BB->end(), DL, MCID, DestReg);
}
@@ -348,47 +355,19 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB,
/// for either a value in a register or a register-indirect+offset
/// address. The convention is that a DBG_VALUE is indirect iff the
/// second operand is an immediate.
-inline MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL,
- const MCInstrDesc &MCID, bool IsIndirect,
- unsigned Reg, unsigned Offset,
- const MDNode *Variable, const MDNode *Expr) {
- assert(isa<DILocalVariable>(Variable) && "not a variable");
- assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
- assert(cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(DL) &&
- "Expected inlined-at fields to agree");
- if (IsIndirect)
- return BuildMI(MF, DL, MCID)
- .addReg(Reg, RegState::Debug)
- .addImm(Offset)
- .addMetadata(Variable)
- .addMetadata(Expr);
- else {
- assert(Offset == 0 && "A direct address cannot have an offset.");
- return BuildMI(MF, DL, MCID)
- .addReg(Reg, RegState::Debug)
- .addReg(0U, RegState::Debug)
- .addMetadata(Variable)
- .addMetadata(Expr);
- }
-}
+MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL,
+ const MCInstrDesc &MCID, bool IsIndirect,
+ unsigned Reg, unsigned Offset,
+ const MDNode *Variable, const MDNode *Expr);
/// This version of the builder builds a DBG_VALUE intrinsic
/// for either a value in a register or a register-indirect+offset
/// address and inserts it at position I.
-inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
- MachineBasicBlock::iterator I, DebugLoc DL,
- const MCInstrDesc &MCID, bool IsIndirect,
- unsigned Reg, unsigned Offset,
- const MDNode *Variable, const MDNode *Expr) {
- assert(isa<DILocalVariable>(Variable) && "not a variable");
- assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
- MachineFunction &MF = *BB.getParent();
- MachineInstr *MI =
- BuildMI(MF, DL, MCID, IsIndirect, Reg, Offset, Variable, Expr);
- BB.insert(I, MI);
- return MachineInstrBuilder(MF, MI);
-}
-
+MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
+ MachineBasicBlock::iterator I, const DebugLoc &DL,
+ const MCInstrDesc &MCID, bool IsIndirect,
+ unsigned Reg, unsigned Offset,
+ const MDNode *Variable, const MDNode *Expr);
inline unsigned getDefRegState(bool B) {
return B ? RegState::Define : 0;
@@ -412,6 +391,17 @@ inline unsigned getDebugRegState(bool B) {
return B ? RegState::Debug : 0;
}
+/// Get all register state flags from machine operand \p RegOp.
+inline unsigned getRegState(const MachineOperand &RegOp) {
+ assert(RegOp.isReg() && "Not a register operand");
+ return getDefRegState(RegOp.isDef()) |
+ getImplRegState(RegOp.isImplicit()) |
+ getKillRegState(RegOp.isKill()) |
+ getDeadRegState(RegOp.isDead()) |
+ getUndefRegState(RegOp.isUndef()) |
+ getInternalReadRegState(RegOp.isInternalRead()) |
+ getDebugRegState(RegOp.isDebug());
+}
/// Helper class for constructing bundles of MachineInstrs.
///
@@ -426,28 +416,26 @@ class MIBundleBuilder {
public:
/// Create an MIBundleBuilder that inserts instructions into a new bundle in
/// BB above the bundle or instruction at Pos.
- MIBundleBuilder(MachineBasicBlock &BB,
- MachineBasicBlock::iterator Pos)
- : MBB(BB), Begin(Pos.getInstrIterator()), End(Begin) {}
+ MIBundleBuilder(MachineBasicBlock &BB, MachineBasicBlock::iterator Pos)
+ : MBB(BB), Begin(Pos.getInstrIterator()), End(Begin) {}
/// Create a bundle from the sequence of instructions between B and E.
- MIBundleBuilder(MachineBasicBlock &BB,
- MachineBasicBlock::iterator B,
+ MIBundleBuilder(MachineBasicBlock &BB, MachineBasicBlock::iterator B,
MachineBasicBlock::iterator E)
- : MBB(BB), Begin(B.getInstrIterator()), End(E.getInstrIterator()) {
+ : MBB(BB), Begin(B.getInstrIterator()), End(E.getInstrIterator()) {
assert(B != E && "No instructions to bundle");
++B;
while (B != E) {
- MachineInstr *MI = B;
+ MachineInstr &MI = *B;
++B;
- MI->bundleWithPred();
+ MI.bundleWithPred();
}
}
/// Create an MIBundleBuilder representing an existing instruction or bundle
/// that has MI as its head.
explicit MIBundleBuilder(MachineInstr *MI)
- : MBB(*MI->getParent()), Begin(MI), End(getBundleEnd(MI)) {}
+ : MBB(*MI->getParent()), Begin(MI), End(getBundleEnd(*MI)) {}
/// Return a reference to the basic block containing this bundle.
MachineBasicBlock &getMBB() const { return MBB; }
diff --git a/include/llvm/CodeGen/MachineInstrBundle.h b/include/llvm/CodeGen/MachineInstrBundle.h
index 4e88606c05a7..c0033a5148cf 100644
--- a/include/llvm/CodeGen/MachineInstrBundle.h
+++ b/include/llvm/CodeGen/MachineInstrBundle.h
@@ -43,23 +43,22 @@ bool finalizeBundles(MachineFunction &MF);
/// getBundleStart - Returns the first instruction in the bundle containing MI.
///
-inline MachineInstr *getBundleStart(MachineInstr *MI) {
+inline MachineInstr &getBundleStart(MachineInstr &MI) {
MachineBasicBlock::instr_iterator I(MI);
while (I->isBundledWithPred())
--I;
- return &*I;
+ return *I;
}
-inline const MachineInstr *getBundleStart(const MachineInstr *MI) {
+inline const MachineInstr &getBundleStart(const MachineInstr &MI) {
MachineBasicBlock::const_instr_iterator I(MI);
while (I->isBundledWithPred())
--I;
- return &*I;
+ return *I;
}
/// Return an iterator pointing beyond the bundle containing MI.
-inline MachineBasicBlock::instr_iterator
-getBundleEnd(MachineInstr *MI) {
+inline MachineBasicBlock::instr_iterator getBundleEnd(MachineInstr &MI) {
MachineBasicBlock::instr_iterator I(MI);
while (I->isBundledWithSucc())
++I;
@@ -68,7 +67,7 @@ getBundleEnd(MachineInstr *MI) {
/// Return an iterator pointing beyond the bundle containing MI.
inline MachineBasicBlock::const_instr_iterator
-getBundleEnd(const MachineInstr *MI) {
+getBundleEnd(const MachineInstr &MI) {
MachineBasicBlock::const_instr_iterator I(MI);
while (I->isBundledWithSucc())
++I;
@@ -114,12 +113,12 @@ protected:
/// @param MI The instruction to examine.
/// @param WholeBundle When true, visit all operands on the entire bundle.
///
- explicit MachineOperandIteratorBase(MachineInstr *MI, bool WholeBundle) {
+ explicit MachineOperandIteratorBase(MachineInstr &MI, bool WholeBundle) {
if (WholeBundle) {
- InstrI = getBundleStart(MI)->getIterator();
- InstrE = MI->getParent()->instr_end();
+ InstrI = getBundleStart(MI).getIterator();
+ InstrE = MI.getParent()->instr_end();
} else {
- InstrI = InstrE = MI->getIterator();
+ InstrI = InstrE = MI.getIterator();
++InstrE;
}
OpI = InstrI->operands_begin();
@@ -184,10 +183,16 @@ public:
/// Reg or a super-register is read. The full register is read.
bool FullyRead;
- /// Reg is FullyDefined and all defs of reg or an overlapping register are
- /// dead.
+ /// Either:
+ /// - Reg is FullyDefined and all defs of reg or an overlapping
+ /// register are dead, or
+ /// - Reg is completely dead because "defined" by a clobber.
bool DeadDef;
+ /// Reg is Defined and all defs of reg or an overlapping register are
+ /// dead.
+ bool PartialDeadDef;
+
/// There is a use operand of reg or a super-register with kill flag set.
bool Killed;
};
@@ -216,7 +221,7 @@ public:
///
class MIOperands : public MachineOperandIteratorBase {
public:
- MIOperands(MachineInstr *MI) : MachineOperandIteratorBase(MI, false) {}
+ MIOperands(MachineInstr &MI) : MachineOperandIteratorBase(MI, false) {}
MachineOperand &operator* () const { return deref(); }
MachineOperand *operator->() const { return &deref(); }
};
@@ -225,8 +230,8 @@ public:
///
class ConstMIOperands : public MachineOperandIteratorBase {
public:
- ConstMIOperands(const MachineInstr *MI)
- : MachineOperandIteratorBase(const_cast<MachineInstr*>(MI), false) {}
+ ConstMIOperands(const MachineInstr &MI)
+ : MachineOperandIteratorBase(const_cast<MachineInstr &>(MI), false) {}
const MachineOperand &operator* () const { return deref(); }
const MachineOperand *operator->() const { return &deref(); }
};
@@ -236,7 +241,7 @@ public:
///
class MIBundleOperands : public MachineOperandIteratorBase {
public:
- MIBundleOperands(MachineInstr *MI) : MachineOperandIteratorBase(MI, true) {}
+ MIBundleOperands(MachineInstr &MI) : MachineOperandIteratorBase(MI, true) {}
MachineOperand &operator* () const { return deref(); }
MachineOperand *operator->() const { return &deref(); }
};
@@ -246,8 +251,8 @@ public:
///
class ConstMIBundleOperands : public MachineOperandIteratorBase {
public:
- ConstMIBundleOperands(const MachineInstr *MI)
- : MachineOperandIteratorBase(const_cast<MachineInstr*>(MI), true) {}
+ ConstMIBundleOperands(const MachineInstr &MI)
+ : MachineOperandIteratorBase(const_cast<MachineInstr &>(MI), true) {}
const MachineOperand &operator* () const { return deref(); }
const MachineOperand *operator->() const { return &deref(); }
};
diff --git a/include/llvm/CodeGen/MachineInstrBundleIterator.h b/include/llvm/CodeGen/MachineInstrBundleIterator.h
new file mode 100644
index 000000000000..45a9a188f90e
--- /dev/null
+++ b/include/llvm/CodeGen/MachineInstrBundleIterator.h
@@ -0,0 +1,92 @@
+//===- llvm/CodeGen/MachineInstrBundleIterator.h ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines an iterator class that bundles MachineInstr.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_MACHINEINSTRBUNDLEITERATOR_H
+#define LLVM_CODEGEN_MACHINEINSTRBUNDLEITERATOR_H
+
+#include "llvm/ADT/ilist.h"
+#include <iterator>
+
+namespace llvm {
+
+/// MachineBasicBlock iterator that automatically skips over MIs that are
+/// inside bundles (i.e. walk top level MIs only).
+template <typename Ty>
+class MachineInstrBundleIterator
+ : public std::iterator<std::bidirectional_iterator_tag, Ty, ptrdiff_t> {
+ typedef ilist_iterator<Ty> instr_iterator;
+ instr_iterator MII;
+
+public:
+ MachineInstrBundleIterator(instr_iterator MI) : MII(MI) {}
+
+ MachineInstrBundleIterator(Ty &MI) : MII(MI) {
+ assert(!MI.isBundledWithPred() && "It's not legal to initialize "
+ "MachineInstrBundleIterator with a "
+ "bundled MI");
+ }
+ MachineInstrBundleIterator(Ty *MI) : MII(MI) {
+ // FIXME: This conversion should be explicit.
+ assert((!MI || !MI->isBundledWithPred()) && "It's not legal to initialize "
+ "MachineInstrBundleIterator "
+ "with a bundled MI");
+ }
+ // Template allows conversion from const to nonconst.
+ template <class OtherTy>
+ MachineInstrBundleIterator(const MachineInstrBundleIterator<OtherTy> &I)
+ : MII(I.getInstrIterator()) {}
+ MachineInstrBundleIterator() : MII(nullptr) {}
+
+ Ty &operator*() const { return *MII; }
+ Ty *operator->() const { return &operator*(); }
+
+ // FIXME: This conversion should be explicit.
+ operator Ty *() const { return MII.getNodePtrUnchecked(); }
+
+ bool operator==(const MachineInstrBundleIterator &X) const {
+ return MII == X.MII;
+ }
+ bool operator!=(const MachineInstrBundleIterator &X) const {
+ return !operator==(X);
+ }
+
+ // Increment and decrement operators...
+ MachineInstrBundleIterator &operator--() {
+ do
+ --MII;
+ while (MII->isBundledWithPred());
+ return *this;
+ }
+ MachineInstrBundleIterator &operator++() {
+ while (MII->isBundledWithSucc())
+ ++MII;
+ ++MII;
+ return *this;
+ }
+ MachineInstrBundleIterator operator--(int) {
+ MachineInstrBundleIterator Temp = *this;
+ --*this;
+ return Temp;
+ }
+ MachineInstrBundleIterator operator++(int) {
+ MachineInstrBundleIterator Temp = *this;
+ ++*this;
+ return Temp;
+ }
+
+ instr_iterator getInstrIterator() const { return MII; }
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/include/llvm/CodeGen/MachineLoopInfo.h b/include/llvm/CodeGen/MachineLoopInfo.h
index 4868b7363f82..224a2a1aa59f 100644
--- a/include/llvm/CodeGen/MachineLoopInfo.h
+++ b/include/llvm/CodeGen/MachineLoopInfo.h
@@ -44,14 +44,14 @@ class MachineLoop : public LoopBase<MachineBasicBlock, MachineLoop> {
public:
MachineLoop();
- /// getTopBlock - Return the "top" block in the loop, which is the first
- /// block in the linear layout, ignoring any parts of the loop not
- /// contiguous with the part the contains the header.
+ /// Return the "top" block in the loop, which is the first block in the linear
+ /// layout, ignoring any parts of the loop not contiguous with the part that
+ /// contains the header.
MachineBasicBlock *getTopBlock();
- /// getBottomBlock - Return the "bottom" block in the loop, which is the last
- /// block in the linear layout, ignoring any parts of the loop not
- /// contiguous with the part the contains the header.
+ /// Return the "bottom" block in the loop, which is the last block in the
+ /// linear layout, ignoring any parts of the loop not contiguous with the part
+ /// that contains the header.
MachineBasicBlock *getBottomBlock();
void dump() const;
@@ -81,72 +81,64 @@ public:
LoopInfoBase<MachineBasicBlock, MachineLoop>& getBase() { return LI; }
- /// iterator/begin/end - The interface to the top-level loops in the current
- /// function.
- ///
+ /// The iterator interface to the top-level loops in the current function.
typedef LoopInfoBase<MachineBasicBlock, MachineLoop>::iterator iterator;
inline iterator begin() const { return LI.begin(); }
inline iterator end() const { return LI.end(); }
bool empty() const { return LI.empty(); }
- /// getLoopFor - Return the inner most loop that BB lives in. If a basic
- /// block is in no loop (for example the entry node), null is returned.
- ///
+ /// Return the innermost loop that BB lives in. If a basic block is in no loop
+ /// (for example the entry node), null is returned.
inline MachineLoop *getLoopFor(const MachineBasicBlock *BB) const {
return LI.getLoopFor(BB);
}
- /// operator[] - same as getLoopFor...
- ///
+ /// Same as getLoopFor.
inline const MachineLoop *operator[](const MachineBasicBlock *BB) const {
return LI.getLoopFor(BB);
}
- /// getLoopDepth - Return the loop nesting level of the specified block...
- ///
+ /// Return the loop nesting level of the specified block.
inline unsigned getLoopDepth(const MachineBasicBlock *BB) const {
return LI.getLoopDepth(BB);
}
- // isLoopHeader - True if the block is a loop header node
+ /// True if the block is a loop header node.
inline bool isLoopHeader(const MachineBasicBlock *BB) const {
return LI.isLoopHeader(BB);
}
- /// runOnFunction - Calculate the natural loop information.
- ///
+ /// Calculate the natural loop information.
bool runOnMachineFunction(MachineFunction &F) override;
void releaseMemory() override { LI.releaseMemory(); }
void getAnalysisUsage(AnalysisUsage &AU) const override;
- /// removeLoop - This removes the specified top-level loop from this loop info
- /// object. The loop is not deleted, as it will presumably be inserted into
- /// another loop.
+ /// This removes the specified top-level loop from this loop info object. The
+ /// loop is not deleted, as it will presumably be inserted into another loop.
inline MachineLoop *removeLoop(iterator I) { return LI.removeLoop(I); }
- /// changeLoopFor - Change the top-level loop that contains BB to the
- /// specified loop. This should be used by transformations that restructure
- /// the loop hierarchy tree.
+ /// Change the top-level loop that contains BB to the specified loop. This
+ /// should be used by transformations that restructure the loop hierarchy
+ /// tree.
inline void changeLoopFor(MachineBasicBlock *BB, MachineLoop *L) {
LI.changeLoopFor(BB, L);
}
- /// changeTopLevelLoop - Replace the specified loop in the top-level loops
- /// list with the indicated loop.
+ /// Replace the specified loop in the top-level loops list with the indicated
+ /// loop.
inline void changeTopLevelLoop(MachineLoop *OldLoop, MachineLoop *NewLoop) {
LI.changeTopLevelLoop(OldLoop, NewLoop);
}
- /// addTopLevelLoop - This adds the specified loop to the collection of
- /// top-level loops.
+ /// This adds the specified loop to the collection of top-level loops.
inline void addTopLevelLoop(MachineLoop *New) {
LI.addTopLevelLoop(New);
}
- /// removeBlock - This method completely removes BB from all data structures,
- /// including all of the Loop objects it is nested in and our mapping from
+ /// This method completely removes BB from all data structures, including all
+ /// of the Loop objects it is nested in and our mapping from
/// MachineBasicBlocks to loops.
void removeBlock(MachineBasicBlock *BB) {
LI.removeBlock(BB);
diff --git a/include/llvm/CodeGen/MachineMemOperand.h b/include/llvm/CodeGen/MachineMemOperand.h
index 1ca0d90465a4..5fa7058733b3 100644
--- a/include/llvm/CodeGen/MachineMemOperand.h
+++ b/include/llvm/CodeGen/MachineMemOperand.h
@@ -16,6 +16,7 @@
#ifndef LLVM_CODEGEN_MACHINEMEMOPERAND_H
#define LLVM_CODEGEN_MACHINEMEMOPERAND_H
+#include "llvm/ADT/BitmaskEnum.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/IR/Metadata.h"
@@ -30,12 +31,11 @@ class raw_ostream;
class MachineFunction;
class ModuleSlotTracker;
-/// MachinePointerInfo - This class contains a discriminated union of
-/// information about pointers in memory operands, relating them back to LLVM IR
-/// or to virtual locations (such as frame indices) that are exposed during
-/// codegen.
+/// This class contains a discriminated union of information about pointers in
+/// memory operands, relating them back to LLVM IR or to virtual locations (such
+/// as frame indices) that are exposed during codegen.
struct MachinePointerInfo {
- /// V - This is the IR pointer value for the access, or it is null if unknown.
+ /// This is the IR pointer value for the access, or it is null if unknown.
/// If this is null, then the access is to a pointer in the default address
/// space.
PointerUnion<const Value *, const PseudoSourceValue *> V;
@@ -57,34 +57,30 @@ struct MachinePointerInfo {
return MachinePointerInfo(V.get<const PseudoSourceValue*>(), Offset+O);
}
- /// getAddrSpace - Return the LLVM IR address space number that this pointer
- /// points into.
+ /// Return the LLVM IR address space number that this pointer points into.
unsigned getAddrSpace() const;
- /// getConstantPool - Return a MachinePointerInfo record that refers to the
- /// constant pool.
+ /// Return a MachinePointerInfo record that refers to the constant pool.
static MachinePointerInfo getConstantPool(MachineFunction &MF);
- /// getFixedStack - Return a MachinePointerInfo record that refers to the
- /// the specified FrameIndex.
+ /// Return a MachinePointerInfo record that refers to the specified
+ /// FrameIndex.
static MachinePointerInfo getFixedStack(MachineFunction &MF, int FI,
int64_t Offset = 0);
- /// getJumpTable - Return a MachinePointerInfo record that refers to a
- /// jump table entry.
+ /// Return a MachinePointerInfo record that refers to a jump table entry.
static MachinePointerInfo getJumpTable(MachineFunction &MF);
- /// getGOT - Return a MachinePointerInfo record that refers to a
- /// GOT entry.
+ /// Return a MachinePointerInfo record that refers to a GOT entry.
static MachinePointerInfo getGOT(MachineFunction &MF);
- /// getStack - stack pointer relative access.
+ /// Stack pointer relative access.
static MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset);
};
//===----------------------------------------------------------------------===//
-/// MachineMemOperand - A description of a memory reference used in the backend.
+/// A description of a memory reference used in the backend.
/// Instead of holding a StoreInst or LoadInst, this class holds the address
/// Value of the reference along with a byte size and offset. This allows it
/// to describe lowered loads and stores. Also, the special PseudoSourceValue
@@ -92,43 +88,50 @@ struct MachinePointerInfo {
/// that aren't explicit in the regular LLVM IR.
///
class MachineMemOperand {
- MachinePointerInfo PtrInfo;
- uint64_t Size;
- unsigned Flags;
- AAMDNodes AAInfo;
- const MDNode *Ranges;
-
public:
/// Flags values. These may be or'd together.
- enum MemOperandFlags {
+ enum Flags : uint16_t {
+ // No flags set.
+ MONone = 0,
/// The memory access reads data.
- MOLoad = 1,
+ MOLoad = 1u << 0,
/// The memory access writes data.
- MOStore = 2,
+ MOStore = 1u << 1,
/// The memory access is volatile.
- MOVolatile = 4,
+ MOVolatile = 1u << 2,
/// The memory access is non-temporal.
- MONonTemporal = 8,
+ MONonTemporal = 1u << 3,
/// The memory access is invariant.
- MOInvariant = 16,
- // Target hints allow target passes to annotate memory operations.
- MOTargetStartBit = 5,
- MOTargetNumBits = 3,
- // This is the number of bits we need to represent flags.
- MOMaxBits = 8
+ MOInvariant = 1u << 4,
+
+ // Reserved for use by target-specific passes.
+ MOTargetFlag1 = 1u << 5,
+ MOTargetFlag2 = 1u << 6,
+ MOTargetFlag3 = 1u << 7,
+
+ LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ MOTargetFlag3)
};
- /// MachineMemOperand - Construct an MachineMemOperand object with the
- /// specified PtrInfo, flags, size, and base alignment.
- MachineMemOperand(MachinePointerInfo PtrInfo, unsigned flags, uint64_t s,
+private:
+ MachinePointerInfo PtrInfo;
+ uint64_t Size;
+ Flags FlagVals;
+ uint16_t BaseAlignLog2; // log_2(base_alignment) + 1
+ AAMDNodes AAInfo;
+ const MDNode *Ranges;
+
+public:
+ /// Construct a MachineMemOperand object with the specified PtrInfo, flags,
+ /// size, and base alignment.
+ MachineMemOperand(MachinePointerInfo PtrInfo, Flags flags, uint64_t s,
unsigned base_alignment,
const AAMDNodes &AAInfo = AAMDNodes(),
const MDNode *Ranges = nullptr);
const MachinePointerInfo &getPointerInfo() const { return PtrInfo; }
- /// getValue - Return the base address of the memory access. This may either
- /// be a normal LLVM IR Value, or one of the special values used in CodeGen.
+ /// Return the base address of the memory access. This may either be a normal
+ /// LLVM IR Value, or one of the special values used in CodeGen.
/// Special values are those obtained via
/// PseudoSourceValue::getFixedStack(int), PseudoSourceValue::getStack, and
/// other PseudoSourceValue member functions which return objects which stand
@@ -142,59 +145,58 @@ public:
const void *getOpaqueValue() const { return PtrInfo.V.getOpaqueValue(); }
- /// getFlags - Return the raw flags of the source value, \see MemOperandFlags.
- unsigned int getFlags() const { return Flags & ((1 << MOMaxBits) - 1); }
+ /// Return the raw flags of the source value, \see Flags.
+ Flags getFlags() const { return FlagVals; }
/// Bitwise OR the current flags with the given flags.
- void setFlags(unsigned f) { Flags |= (f & ((1 << MOMaxBits) - 1)); }
+ void setFlags(Flags f) { FlagVals |= f; }
- /// getOffset - For normal values, this is a byte offset added to the base
- /// address. For PseudoSourceValue::FPRel values, this is the FrameIndex
- /// number.
+ /// For normal values, this is a byte offset added to the base address.
+ /// For PseudoSourceValue::FPRel values, this is the FrameIndex number.
int64_t getOffset() const { return PtrInfo.Offset; }
unsigned getAddrSpace() const { return PtrInfo.getAddrSpace(); }
- /// getSize - Return the size in bytes of the memory reference.
+ /// Return the size in bytes of the memory reference.
uint64_t getSize() const { return Size; }
- /// getAlignment - Return the minimum known alignment in bytes of the
- /// actual memory reference.
+ /// Return the minimum known alignment in bytes of the actual memory
+ /// reference.
uint64_t getAlignment() const;
- /// getBaseAlignment - Return the minimum known alignment in bytes of the
- /// base address, without the offset.
- uint64_t getBaseAlignment() const { return (1u << (Flags >> MOMaxBits)) >> 1; }
+ /// Return the minimum known alignment in bytes of the base address, without
+ /// the offset.
+ uint64_t getBaseAlignment() const { return (1u << BaseAlignLog2) >> 1; }
- /// getAAInfo - Return the AA tags for the memory reference.
+ /// Return the AA tags for the memory reference.
AAMDNodes getAAInfo() const { return AAInfo; }
- /// getRanges - Return the range tag for the memory reference.
+ /// Return the range tag for the memory reference.
const MDNode *getRanges() const { return Ranges; }
- bool isLoad() const { return Flags & MOLoad; }
- bool isStore() const { return Flags & MOStore; }
- bool isVolatile() const { return Flags & MOVolatile; }
- bool isNonTemporal() const { return Flags & MONonTemporal; }
- bool isInvariant() const { return Flags & MOInvariant; }
+ bool isLoad() const { return FlagVals & MOLoad; }
+ bool isStore() const { return FlagVals & MOStore; }
+ bool isVolatile() const { return FlagVals & MOVolatile; }
+ bool isNonTemporal() const { return FlagVals & MONonTemporal; }
+ bool isInvariant() const { return FlagVals & MOInvariant; }
- /// isUnordered - Returns true if this memory operation doesn't have any
- /// ordering constraints other than normal aliasing. Volatile and atomic
- /// memory operations can't be reordered.
+ /// Returns true if this memory operation doesn't have any ordering
+ /// constraints other than normal aliasing. Volatile and atomic memory
+ /// operations can't be reordered.
///
/// Currently, we don't model the difference between volatile and atomic
/// operations. They should retain their ordering relative to all memory
/// operations.
bool isUnordered() const { return !isVolatile(); }
- /// refineAlignment - Update this MachineMemOperand to reflect the alignment
- /// of MMO, if it has a greater alignment. This must only be used when the
- /// new alignment applies to all users of this MachineMemOperand.
+ /// Update this MachineMemOperand to reflect the alignment of MMO, if it has a
+ /// greater alignment. This must only be used when the new alignment applies
+ /// to all users of this MachineMemOperand.
void refineAlignment(const MachineMemOperand *MMO);
- /// setValue - Change the SourceValue for this MachineMemOperand. This
- /// should only be used when an object is being relocated and all references
- /// to it are being updated.
+ /// Change the SourceValue for this MachineMemOperand. This should only be
+ /// used when an object is being relocated and all references to it are being
+ /// updated.
void setValue(const Value *NewSV) { PtrInfo.V = NewSV; }
void setValue(const PseudoSourceValue *NewSV) { PtrInfo.V = NewSV; }
void setOffset(int64_t NewOffset) { PtrInfo.Offset = NewOffset; }
diff --git a/include/llvm/CodeGen/MachineModuleInfoImpls.h b/include/llvm/CodeGen/MachineModuleInfoImpls.h
index e7472145e71f..f9fa6999073f 100644
--- a/include/llvm/CodeGen/MachineModuleInfoImpls.h
+++ b/include/llvm/CodeGen/MachineModuleInfoImpls.h
@@ -23,44 +23,35 @@ class MCSymbol;
/// MachineModuleInfoMachO - This is a MachineModuleInfoImpl implementation
/// for MachO targets.
class MachineModuleInfoMachO : public MachineModuleInfoImpl {
- /// FnStubs - Darwin '$stub' stubs. The key is something like "Lfoo$stub",
- /// the value is something like "_foo".
- DenseMap<MCSymbol *, StubValueTy> FnStubs;
-
/// GVStubs - Darwin '$non_lazy_ptr' stubs. The key is something like
/// "Lfoo$non_lazy_ptr", the value is something like "_foo". The extra bit
/// is true if this GV is external.
DenseMap<MCSymbol *, StubValueTy> GVStubs;
- /// HiddenGVStubs - Darwin '$non_lazy_ptr' stubs. The key is something like
- /// "Lfoo$non_lazy_ptr", the value is something like "_foo". Unlike GVStubs
- /// these are for things with hidden visibility. The extra bit is true if
- /// this GV is external.
- DenseMap<MCSymbol *, StubValueTy> HiddenGVStubs;
+ /// ThreadLocalGVStubs - Darwin '$non_lazy_ptr' stubs. The key is something
+ /// like "Lfoo$non_lazy_ptr", the value is something like "_foo". The extra
+ /// bit is true if this GV is external.
+ DenseMap<MCSymbol *, StubValueTy> ThreadLocalGVStubs;
virtual void anchor(); // Out of line virtual method.
public:
MachineModuleInfoMachO(const MachineModuleInfo &) {}
- StubValueTy &getFnStubEntry(MCSymbol *Sym) {
- assert(Sym && "Key cannot be null");
- return FnStubs[Sym];
- }
-
StubValueTy &getGVStubEntry(MCSymbol *Sym) {
assert(Sym && "Key cannot be null");
return GVStubs[Sym];
}
- StubValueTy &getHiddenGVStubEntry(MCSymbol *Sym) {
+ StubValueTy &getThreadLocalGVStubEntry(MCSymbol *Sym) {
assert(Sym && "Key cannot be null");
- return HiddenGVStubs[Sym];
+ return ThreadLocalGVStubs[Sym];
}
/// Accessor methods to return the set of stubs in sorted order.
- SymbolListTy GetFnStubList() { return getSortedStubs(FnStubs); }
SymbolListTy GetGVStubList() { return getSortedStubs(GVStubs); }
- SymbolListTy GetHiddenGVStubList() { return getSortedStubs(HiddenGVStubs); }
+ SymbolListTy GetThreadLocalGVStubList() {
+ return getSortedStubs(ThreadLocalGVStubs);
+ }
};
/// MachineModuleInfoELF - This is a MachineModuleInfoImpl implementation
diff --git a/include/llvm/CodeGen/MachineOperand.h b/include/llvm/CodeGen/MachineOperand.h
index c43e47c36d06..ee0a9cf11e6a 100644
--- a/include/llvm/CodeGen/MachineOperand.h
+++ b/include/llvm/CodeGen/MachineOperand.h
@@ -534,6 +534,15 @@ public:
Contents.MBB = MBB;
}
+ /// Sets value of register mask operand referencing Mask. The
+ /// operand does not take ownership of the memory referenced by Mask, it must
+ /// remain valid for the lifetime of the operand. See CreateRegMask().
+ /// Any physreg with a 0 bit in the mask is clobbered by the instruction.
+ void setRegMask(const uint32_t *RegMaskPtr) {
+ assert(isRegMask() && "Wrong MachineOperand mutator");
+ Contents.RegMask = RegMaskPtr;
+ }
+
//===--------------------------------------------------------------------===//
// Other methods.
//===--------------------------------------------------------------------===//
diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h
index 04191bc1b74f..07d2d016f274 100644
--- a/include/llvm/CodeGen/MachineRegisterInfo.h
+++ b/include/llvm/CodeGen/MachineRegisterInfo.h
@@ -16,7 +16,10 @@
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/IndexedMap.h"
+#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/iterator_range.h"
+// PointerUnion needs to have access to the full RegisterBank type.
+#include "llvm/CodeGen/GlobalISel/RegisterBank.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBundle.h"
#include "llvm/Target/TargetRegisterInfo.h"
@@ -26,6 +29,10 @@
namespace llvm {
class PSetIterator;
+/// Convenient type to represent either a register class or a register bank.
+typedef PointerUnion<const TargetRegisterClass *, const RegisterBank *>
+ RegClassOrRegBank;
+
/// MachineRegisterInfo - Keep track of information for virtual and physical
/// registers, including vreg register classes, use/def chains for registers,
/// etc.
@@ -40,18 +47,9 @@ public:
};
private:
- const MachineFunction *MF;
+ MachineFunction *MF;
Delegate *TheDelegate;
- /// IsSSA - True when the machine function is in SSA form and virtual
- /// registers have a single def.
- bool IsSSA;
-
- /// TracksLiveness - True while register liveness is being tracked accurately.
- /// Basic block live-in lists, kill flags, and implicit defs may not be
- /// accurate when after this flag is cleared.
- bool TracksLiveness;
-
/// True if subregister liveness is tracked.
bool TracksSubRegLiveness;
@@ -59,8 +57,9 @@ private:
///
/// Each element in this list contains the register class of the vreg and the
/// start of the use/def list for the register.
- IndexedMap<std::pair<const TargetRegisterClass*, MachineOperand*>,
- VirtReg2IndexFunctor> VRegInfo;
+ IndexedMap<std::pair<RegClassOrRegBank, MachineOperand *>,
+ VirtReg2IndexFunctor>
+ VRegInfo;
/// RegAllocHints - This vector records register allocation hints for virtual
/// registers. For each virtual register, it keeps a register and hint type
@@ -105,6 +104,18 @@ private:
/// started.
BitVector ReservedRegs;
+ typedef DenseMap<unsigned, unsigned> VRegToSizeMap;
+ /// Map generic virtual registers to their actual size.
+ mutable std::unique_ptr<VRegToSizeMap> VRegToSize;
+
+ /// Accessor for VRegToSize. This accessor should only be used
+ /// by global-isel related work.
+ VRegToSizeMap &getVRegToSize() const {
+ if (!VRegToSize)
+ VRegToSize.reset(new VRegToSizeMap);
+ return *VRegToSize.get();
+ }
+
/// Keep track of the physical registers that are live in to the function.
/// Live in values are typically arguments in registers. LiveIn values are
/// allowed to have virtual registers associated with them, stored in the
@@ -114,7 +125,7 @@ private:
MachineRegisterInfo(const MachineRegisterInfo&) = delete;
void operator=(const MachineRegisterInfo&) = delete;
public:
- explicit MachineRegisterInfo(const MachineFunction *MF);
+ explicit MachineRegisterInfo(MachineFunction *MF);
const TargetRegisterInfo *getTargetRegisterInfo() const {
return MF->getSubtarget().getRegisterInfo();
@@ -148,27 +159,32 @@ public:
// The TwoAddressInstructionPass and PHIElimination passes take the machine
// function out of SSA form when they introduce multiple defs per virtual
// register.
- bool isSSA() const { return IsSSA; }
+ bool isSSA() const {
+ return MF->getProperties().hasProperty(
+ MachineFunctionProperties::Property::IsSSA);
+ }
// leaveSSA - Indicates that the machine function is no longer in SSA form.
- void leaveSSA() { IsSSA = false; }
+ void leaveSSA() {
+ MF->getProperties().clear(MachineFunctionProperties::Property::IsSSA);
+ }
/// tracksLiveness - Returns true when tracking register liveness accurately.
- ///
- /// While this flag is true, register liveness information in basic block
- /// live-in lists and machine instruction operands is accurate. This means it
- /// can be used to change the code in ways that affect the values in
- /// registers, for example by the register scavenger.
- ///
- /// When this flag is false, liveness is no longer reliable.
- bool tracksLiveness() const { return TracksLiveness; }
+ /// (see MachineFUnctionProperties::Property description for details)
+ bool tracksLiveness() const {
+ return MF->getProperties().hasProperty(
+ MachineFunctionProperties::Property::TracksLiveness);
+ }
/// invalidateLiveness - Indicates that register liveness is no longer being
/// tracked accurately.
///
/// This should be called by late passes that invalidate the liveness
/// information.
- void invalidateLiveness() { TracksLiveness = false; }
+ void invalidateLiveness() {
+ MF->getProperties().clear(
+ MachineFunctionProperties::Property::TracksLiveness);
+ }
/// Returns true if liveness for register class @p RC should be tracked at
/// the subregister level.
@@ -375,8 +391,8 @@ public:
/// specified register (it may be live-in).
bool def_empty(unsigned RegNo) const { return def_begin(RegNo) == def_end(); }
- /// hasOneDef - Return true if there is exactly one instruction defining the
- /// specified register.
+ /// Return true if there is exactly one operand defining the specified
+ /// register.
bool hasOneDef(unsigned RegNo) const {
def_iterator DI = def_begin(RegNo);
if (DI == def_end())
@@ -551,9 +567,47 @@ public:
// Virtual Register Info
//===--------------------------------------------------------------------===//
- /// getRegClass - Return the register class of the specified virtual register.
+ /// Return the register class of the specified virtual register.
+ /// This shouldn't be used directly unless \p Reg has a register class.
+ /// \see getRegClassOrNull when this might happen.
///
const TargetRegisterClass *getRegClass(unsigned Reg) const {
+ assert(VRegInfo[Reg].first.is<const TargetRegisterClass *>() &&
+ "Register class not set, wrong accessor");
+ return VRegInfo[Reg].first.get<const TargetRegisterClass *>();
+ }
+
+ /// Return the register class of \p Reg, or null if Reg has not been assigned
+ /// a register class yet.
+ ///
+ /// \note A null register class can only happen when these two
+ /// conditions are met:
+ /// 1. Generic virtual registers are created.
+ /// 2. The machine function has not completely been through the
+ /// instruction selection process.
+ /// None of this condition is possible without GlobalISel for now.
+ /// In other words, if GlobalISel is not used or if the query happens after
+ /// the select pass, using getRegClass is safe.
+ const TargetRegisterClass *getRegClassOrNull(unsigned Reg) const {
+ const RegClassOrRegBank &Val = VRegInfo[Reg].first;
+ return Val.dyn_cast<const TargetRegisterClass *>();
+ }
+
+ /// Return the register bank of \p Reg, or null if Reg has not been assigned
+ /// a register bank or has been assigned a register class.
+ /// \note It is possible to get the register bank from the register class via
+ /// RegisterBankInfo::getRegBankFromRegClass.
+ ///
+ const RegisterBank *getRegBankOrNull(unsigned Reg) const {
+ const RegClassOrRegBank &Val = VRegInfo[Reg].first;
+ return Val.dyn_cast<const RegisterBank *>();
+ }
+
+ /// Return the register bank or register class of \p Reg.
+ /// \note Before the register bank gets assigned (i.e., before the
+ /// RegBankSelect pass) \p Reg may not have either.
+ ///
+ const RegClassOrRegBank &getRegClassOrRegBank(unsigned Reg) const {
return VRegInfo[Reg].first;
}
@@ -561,6 +615,10 @@ public:
///
void setRegClass(unsigned Reg, const TargetRegisterClass *RC);
+ /// Set the register bank to \p RegBank for \p Reg.
+ ///
+ void setRegBank(unsigned Reg, const RegisterBank &RegBank);
+
/// constrainRegClass - Constrain the register class of the specified virtual
/// register to be a common subclass of RC and the current register class,
/// but only if the new class has at least MinNumRegs registers. Return the
@@ -587,6 +645,19 @@ public:
///
unsigned createVirtualRegister(const TargetRegisterClass *RegClass);
+ /// Get the size in bits of \p VReg or 0 if VReg is not a generic
+ /// (target independent) virtual register.
+ unsigned getSize(unsigned VReg) const;
+
+ /// Set the size in bits of \p VReg to \p Size.
+ /// Although the size should be set at build time, mir infrastructure
+ /// is not yet able to do it.
+ void setSize(unsigned VReg, unsigned Size);
+
+ /// Create and return a new generic virtual register with a size of \p Size.
+ /// \pre Size > 0.
+ unsigned createGenericVirtualRegister(unsigned Size);
+
/// getNumVirtRegs - Return the number of virtual registers created.
///
unsigned getNumVirtRegs() const { return VRegInfo.size(); }
@@ -632,9 +703,10 @@ public:
/// Return true if the specified register is modified in this function.
/// This checks that no defining machine operands exist for the register or
/// any of its aliases. Definitions found on functions marked noreturn are
- /// ignored. The register is also considered modified when it is set in the
- /// UsedPhysRegMask.
- bool isPhysRegModified(unsigned PhysReg) const;
+ /// ignored, to consider them pass 'true' for optional parameter
+ /// SkipNoReturnDef. The register is also considered modified when it is set
+ /// in the UsedPhysRegMask.
+ bool isPhysRegModified(unsigned PhysReg, bool SkipNoReturnDef = false) const;
/// Return true if the specified register is modified or read in this
/// function. This checks that no machine operands exist for the register or
@@ -820,10 +892,10 @@ public:
advance();
} while (Op && Op->getParent() == P);
} else if (ByBundle) {
- MachineInstr *P = getBundleStart(Op->getParent());
+ MachineInstr &P = getBundleStart(*Op->getParent());
do {
advance();
- } while (Op && getBundleStart(Op->getParent()) == P);
+ } while (Op && &getBundleStart(*Op->getParent()) == &P);
}
return *this;
@@ -922,10 +994,10 @@ public:
advance();
} while (Op && Op->getParent() == P);
} else if (ByBundle) {
- MachineInstr *P = getBundleStart(Op->getParent());
+ MachineInstr &P = getBundleStart(*Op->getParent());
do {
advance();
- } while (Op && getBundleStart(Op->getParent()) == P);
+ } while (Op && &getBundleStart(*Op->getParent()) == &P);
}
return *this;
@@ -937,15 +1009,12 @@ public:
// Retrieve a reference to the current operand.
MachineInstr &operator*() const {
assert(Op && "Cannot dereference end iterator!");
- if (ByBundle) return *(getBundleStart(Op->getParent()));
+ if (ByBundle)
+ return getBundleStart(*Op->getParent());
return *Op->getParent();
}
- MachineInstr *operator->() const {
- assert(Op && "Cannot dereference end iterator!");
- if (ByBundle) return getBundleStart(Op->getParent());
- return Op->getParent();
- }
+ MachineInstr *operator->() const { return &operator*(); }
};
};
diff --git a/include/llvm/CodeGen/MachineSSAUpdater.h b/include/llvm/CodeGen/MachineSSAUpdater.h
index 5f988ad86320..50a7d90bf25b 100644
--- a/include/llvm/CodeGen/MachineSSAUpdater.h
+++ b/include/llvm/CodeGen/MachineSSAUpdater.h
@@ -14,7 +14,6 @@
#ifndef LLVM_CODEGEN_MACHINESSAUPDATER_H
#define LLVM_CODEGEN_MACHINESSAUPDATER_H
-#include "llvm/Support/Allocator.h"
#include "llvm/Support/Compiler.h"
namespace llvm {
diff --git a/include/llvm/CodeGen/MachineScheduler.h b/include/llvm/CodeGen/MachineScheduler.h
index 358fd5a3732a..06e992179031 100644
--- a/include/llvm/CodeGen/MachineScheduler.h
+++ b/include/llvm/CodeGen/MachineScheduler.h
@@ -66,8 +66,6 @@
//
// void <SubTarget>Subtarget::
// overrideSchedPolicy(MachineSchedPolicy &Policy,
-// MachineInstr *begin,
-// MachineInstr *end,
// unsigned NumRegionInstrs) const {
// Policy.<Flag> = true;
// }
@@ -81,6 +79,7 @@
#include "llvm/CodeGen/MachinePassRegistry.h"
#include "llvm/CodeGen/RegisterPressure.h"
#include "llvm/CodeGen/ScheduleDAGInstrs.h"
+#include "llvm/CodeGen/ScheduleDAGMutation.h"
#include <memory>
namespace llvm {
@@ -150,6 +149,9 @@ class ScheduleDAGMI;
struct MachineSchedPolicy {
// Allow the scheduler to disable register pressure tracking.
bool ShouldTrackPressure;
+ /// Track LaneMasks to allow reordering of independent subregister writes
+ /// of the same vreg. \sa MachineSchedStrategy::shouldTrackLaneMasks()
+ bool ShouldTrackLaneMasks;
// Allow the scheduler to force top-down or bottom-up scheduling. If neither
// is true, the scheduler runs in both directions and converges.
@@ -160,8 +162,8 @@ struct MachineSchedPolicy {
// first.
bool DisableLatencyHeuristic;
- MachineSchedPolicy(): ShouldTrackPressure(false), OnlyTopDown(false),
- OnlyBottomUp(false), DisableLatencyHeuristic(false) {}
+ MachineSchedPolicy(): ShouldTrackPressure(false), ShouldTrackLaneMasks(false),
+ OnlyTopDown(false), OnlyBottomUp(false), DisableLatencyHeuristic(false) {}
};
/// MachineSchedStrategy - Interface to the scheduling algorithm used by
@@ -185,6 +187,11 @@ public:
/// initializing this strategy. Called after initPolicy.
virtual bool shouldTrackPressure() const { return true; }
+ /// Returns true if lanemasks should be tracked. LaneMask tracking is
+ /// necessary to reorder independent subregister defs for the same vreg.
+ /// This has to be enabled in combination with shouldTrackPressure().
+ virtual bool shouldTrackLaneMasks() const { return false; }
+
/// Initialize the strategy after building the DAG for a new region.
virtual void initialize(ScheduleDAGMI *DAG) = 0;
@@ -212,15 +219,6 @@ public:
virtual void releaseBottomNode(SUnit *SU) = 0;
};
-/// Mutate the DAG as a postpass after normal DAG building.
-class ScheduleDAGMutation {
- virtual void anchor();
-public:
- virtual ~ScheduleDAGMutation() {}
-
- virtual void apply(ScheduleDAGMI *DAG) = 0;
-};
-
/// ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply
/// schedules machine instructions according to the given MachineSchedStrategy
/// without much extra book-keeping. This is the common functionality between
@@ -371,6 +369,7 @@ protected:
/// Register pressure in this region computed by initRegPressure.
bool ShouldTrackPressure;
+ bool ShouldTrackLaneMasks;
IntervalPressure RegPressure;
RegPressureTracker RPTracker;
@@ -387,13 +386,18 @@ protected:
IntervalPressure BotPressure;
RegPressureTracker BotRPTracker;
+ /// True if disconnected subregister components are already renamed.
+ /// The renaming is only done on demand if lane masks are tracked.
+ bool DisconnectedComponentsRenamed;
+
public:
ScheduleDAGMILive(MachineSchedContext *C,
std::unique_ptr<MachineSchedStrategy> S)
: ScheduleDAGMI(C, std::move(S), /*RemoveKillFlags=*/false),
RegClassInfo(C->RegClassInfo), DFSResult(nullptr),
- ShouldTrackPressure(false), RPTracker(RegPressure),
- TopRPTracker(TopPressure), BotRPTracker(BotPressure) {}
+ ShouldTrackPressure(false), ShouldTrackLaneMasks(false),
+ RPTracker(RegPressure), TopRPTracker(TopPressure),
+ BotRPTracker(BotPressure), DisconnectedComponentsRenamed(false) {}
~ScheduleDAGMILive() override;
@@ -455,6 +459,10 @@ protected:
/// bottom of the DAG region without covereing any unscheduled instruction.
void buildDAGWithRegPressure();
+ /// Release ExitSU predecessors and setup scheduler queues. Re-position
+ /// the Top RP tracker in case the region beginning has changed.
+ void initQueues(ArrayRef<SUnit*> TopRoots, ArrayRef<SUnit*> BotRoots);
+
/// Move an instruction and update register pressure.
void scheduleMI(SUnit *SU, bool IsTopNode);
@@ -462,7 +470,7 @@ protected:
void initRegPressure();
- void updatePressureDiffs(ArrayRef<unsigned> LiveUses);
+ void updatePressureDiffs(ArrayRef<RegisterMaskPair> LiveUses);
void updateScheduledPressure(const SUnit *SU,
const std::vector<unsigned> &NewMaxPressure);
@@ -753,9 +761,9 @@ class GenericSchedulerBase : public MachineSchedStrategy {
public:
/// Represent the type of SchedCandidate found within a single queue.
/// pickNodeBidirectional depends on these listed by decreasing priority.
- enum CandReason {
- NoCand, PhysRegCopy, RegExcess, RegCritical, Stall, Cluster, Weak, RegMax,
- ResourceReduce, ResourceDemand, BotHeightReduce, BotPathReduce,
+ enum CandReason : uint8_t {
+ NoCand, Only1, PhysRegCopy, RegExcess, RegCritical, Stall, Cluster, Weak,
+ RegMax, ResourceReduce, ResourceDemand, BotHeightReduce, BotPathReduce,
TopDepthReduce, TopPathReduce, NextDefUse, NodeOrder};
#ifndef NDEBUG
@@ -769,6 +777,15 @@ public:
unsigned DemandResIdx;
CandPolicy(): ReduceLatency(false), ReduceResIdx(0), DemandResIdx(0) {}
+
+ bool operator==(const CandPolicy &RHS) const {
+ return ReduceLatency == RHS.ReduceLatency &&
+ ReduceResIdx == RHS.ReduceResIdx &&
+ DemandResIdx == RHS.DemandResIdx;
+ }
+ bool operator!=(const CandPolicy &RHS) const {
+ return !(*this == RHS);
+ }
};
/// Status of an instruction's critical resource consumption.
@@ -801,8 +818,8 @@ public:
// The reason for this candidate.
CandReason Reason;
- // Set of reasons that apply to multiple candidates.
- uint32_t RepeatReasonSet;
+ // Whether this candidate should be scheduled at top/bottom.
+ bool AtTop;
// Register pressure values for the best candidate.
RegPressureDelta RPDelta;
@@ -810,8 +827,17 @@ public:
// Critical resource consumption of the best candidate.
SchedResourceDelta ResDelta;
- SchedCandidate(const CandPolicy &policy)
- : Policy(policy), SU(nullptr), Reason(NoCand), RepeatReasonSet(0) {}
+ SchedCandidate() { reset(CandPolicy()); }
+ SchedCandidate(const CandPolicy &Policy) { reset(Policy); }
+
+ void reset(const CandPolicy &NewPolicy) {
+ Policy = NewPolicy;
+ SU = nullptr;
+ Reason = NoCand;
+ AtTop = false;
+ RPDelta = RegPressureDelta();
+ ResDelta = SchedResourceDelta();
+ }
bool isValid() const { return SU; }
@@ -820,13 +846,11 @@ public:
assert(Best.Reason != NoCand && "uninitialized Sched candidate");
SU = Best.SU;
Reason = Best.Reason;
+ AtTop = Best.AtTop;
RPDelta = Best.RPDelta;
ResDelta = Best.ResDelta;
}
- bool isRepeat(CandReason R) { return RepeatReasonSet & (1 << R); }
- void setRepeat(CandReason R) { RepeatReasonSet |= (1 << R); }
-
void initResourceDelta(const ScheduleDAGMI *DAG,
const TargetSchedModel *SchedModel);
};
@@ -858,6 +882,11 @@ class GenericScheduler : public GenericSchedulerBase {
SchedBoundary Top;
SchedBoundary Bot;
+ /// Candidate last picked from Top boundary.
+ SchedCandidate TopCand;
+ /// Candidate last picked from Bot boundary.
+ SchedCandidate BotCand;
+
MachineSchedPolicy RegionPolicy;
public:
GenericScheduler(const MachineSchedContext *C):
@@ -874,6 +903,10 @@ public:
return RegionPolicy.ShouldTrackPressure;
}
+ bool shouldTrackLaneMasks() const override {
+ return RegionPolicy.ShouldTrackLaneMasks;
+ }
+
void initialize(ScheduleDAGMI *dag) override;
SUnit *pickNode(bool &IsTopNode) override;
@@ -882,10 +915,12 @@ public:
void releaseTopNode(SUnit *SU) override {
Top.releaseTopNode(SU);
+ TopCand.SU = nullptr;
}
void releaseBottomNode(SUnit *SU) override {
Bot.releaseBottomNode(SU);
+ BotCand.SU = nullptr;
}
void registerRoots() override;
@@ -893,15 +928,18 @@ public:
protected:
void checkAcyclicLatency();
+ void initCandidate(SchedCandidate &Cand, SUnit *SU, bool AtTop,
+ const RegPressureTracker &RPTracker,
+ RegPressureTracker &TempTracker);
+
void tryCandidate(SchedCandidate &Cand,
SchedCandidate &TryCand,
- SchedBoundary &Zone,
- const RegPressureTracker &RPTracker,
- RegPressureTracker &TempTracker);
+ SchedBoundary *Zone);
SUnit *pickNodeBidirectional(bool &IsTopNode);
void pickNodeFromQueue(SchedBoundary &Zone,
+ const CandPolicy &ZonePolicy,
const RegPressureTracker &RPTracker,
SchedCandidate &Candidate);
diff --git a/include/llvm/CodeGen/MachineTraceMetrics.h b/include/llvm/CodeGen/MachineTraceMetrics.h
index bfe6e945b6da..06db17abaed9 100644
--- a/include/llvm/CodeGen/MachineTraceMetrics.h
+++ b/include/llvm/CodeGen/MachineTraceMetrics.h
@@ -50,6 +50,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/TargetSchedule.h"
namespace llvm {
@@ -275,24 +276,24 @@ public:
/// Return the depth and height of MI. The depth is only valid for
/// instructions in or above the trace center block. The height is only
/// valid for instructions in or below the trace center block.
- InstrCycles getInstrCycles(const MachineInstr *MI) const {
- return TE.Cycles.lookup(MI);
+ InstrCycles getInstrCycles(const MachineInstr &MI) const {
+ return TE.Cycles.lookup(&MI);
}
/// Return the slack of MI. This is the number of cycles MI can be delayed
/// before the critical path becomes longer.
/// MI must be an instruction in the trace center block.
- unsigned getInstrSlack(const MachineInstr *MI) const;
+ unsigned getInstrSlack(const MachineInstr &MI) const;
/// Return the Depth of a PHI instruction in a trace center block successor.
/// The PHI does not have to be part of the trace.
- unsigned getPHIDepth(const MachineInstr *PHI) const;
+ unsigned getPHIDepth(const MachineInstr &PHI) const;
/// A dependence is useful if the basic block of the defining instruction
/// is part of the trace of the user instruction. It is assumed that DefMI
/// dominates UseMI (see also isUsefulDominator).
- bool isDepInTrace(const MachineInstr *DefMI,
- const MachineInstr *UseMI) const;
+ bool isDepInTrace(const MachineInstr &DefMI,
+ const MachineInstr &UseMI) const;
};
/// A trace ensemble is a collection of traces selected using the same
diff --git a/include/llvm/CodeGen/MachineValueType.h b/include/llvm/CodeGen/MachineValueType.h
index 04d6ee3be531..0bb53d1a5374 100644
--- a/include/llvm/CodeGen/MachineValueType.h
+++ b/include/llvm/CodeGen/MachineValueType.h
@@ -28,7 +28,7 @@ namespace llvm {
/// type can be represented by an MVT.
class MVT {
public:
- enum SimpleValueType {
+ enum SimpleValueType : int8_t {
// INVALID_SIMPLE_VALUE_TYPE - Simple value types less than zero are
// considered extended value types.
INVALID_SIMPLE_VALUE_TYPE = -1,
@@ -142,38 +142,38 @@ class MVT {
MAX_ALLOWED_VALUETYPE = 96,
// Token - A value of type llvm::TokenTy
- token = 249,
+ token = 120,
// Metadata - This is MDNode or MDString.
- Metadata = 250,
+ Metadata = 121,
// iPTRAny - An int value the size of the pointer of the current
// target to any address space. This must only be used internal to
// tblgen. Other than for overloading, we treat iPTRAny the same as iPTR.
- iPTRAny = 251,
+ iPTRAny = 122,
// vAny - A vector with any length and element size. This is used
// for intrinsics that have overloadings based on vector types.
// This is only for tblgen's consumption!
- vAny = 252,
+ vAny = 123,
// fAny - Any floating-point or vector floating-point value. This is used
// for intrinsics that have overloadings based on floating-point types.
// This is only for tblgen's consumption!
- fAny = 253,
+ fAny = 124,
// iAny - An integer or vector integer value of any bit width. This is
// used for intrinsics that have overloadings based on integer bit widths.
// This is only for tblgen's consumption!
- iAny = 254,
+ iAny = 125,
// iPTR - An int value the size of the pointer of the current
// target. This should only be used internal to tblgen!
- iPTR = 255,
+ iPTR = 126,
// Any - Any type. This is used for intrinsics that have overloadings.
// This is only for tblgen's consumption!
- Any = 256
+ Any = 127
};
SimpleValueType SimpleTy;
@@ -210,6 +210,13 @@ class MVT {
SimpleTy <= MVT::LAST_INTEGER_VECTOR_VALUETYPE));
}
+ /// isScalarInteger - Return true if this is an integer, not including
+ /// vectors.
+ bool isScalarInteger() const {
+ return (SimpleTy >= MVT::FIRST_INTEGER_VALUETYPE &&
+ SimpleTy <= MVT::LAST_INTEGER_VALUETYPE);
+ }
+
/// isVector - Return true if this is a vector value type.
bool isVector() const {
return (SimpleTy >= MVT::FIRST_VECTOR_VALUETYPE &&
diff --git a/include/llvm/CodeGen/PBQP/Graph.h b/include/llvm/CodeGen/PBQP/Graph.h
index f73383ed1000..8301ca4d8536 100644
--- a/include/llvm/CodeGen/PBQP/Graph.h
+++ b/include/llvm/CodeGen/PBQP/Graph.h
@@ -15,12 +15,11 @@
#ifndef LLVM_CODEGEN_PBQP_GRAPH_H
#define LLVM_CODEGEN_PBQP_GRAPH_H
-#include "llvm/ADT/ilist.h"
-#include "llvm/ADT/ilist_node.h"
#include "llvm/Support/Debug.h"
-#include <list>
-#include <map>
-#include <set>
+#include <algorithm>
+#include <cassert>
+#include <limits>
+#include <utility>
#include <vector>
namespace llvm {
@@ -72,7 +71,7 @@ namespace PBQP {
return std::numeric_limits<AdjEdgeIdx>::max();
}
- NodeEntry(VectorPtr Costs) : Costs(Costs) {}
+ NodeEntry(VectorPtr Costs) : Costs(std::move(Costs)) {}
AdjEdgeIdx addAdjEdgeId(EdgeId EId) {
AdjEdgeIdx Idx = AdjEdgeIds.size();
@@ -103,7 +102,7 @@ namespace PBQP {
class EdgeEntry {
public:
EdgeEntry(NodeId N1Id, NodeId N2Id, MatrixPtr Costs)
- : Costs(Costs) {
+ : Costs(std::move(Costs)) {
NIds[0] = N1Id;
NIds[1] = N2Id;
ThisEdgeAdjIdxs[0] = NodeEntry::getInvalidAdjEdgeIdx();
@@ -348,7 +347,8 @@ namespace PBQP {
Graph() : Solver(nullptr) {}
/// @brief Construct an empty PBQP graph with the given graph metadata.
- Graph(GraphMetadata Metadata) : Metadata(Metadata), Solver(nullptr) {}
+ Graph(GraphMetadata Metadata)
+ : Metadata(std::move(Metadata)), Solver(nullptr) {}
/// @brief Get a reference to the graph metadata.
GraphMetadata& getMetadata() { return Metadata; }
diff --git a/include/llvm/CodeGen/ParallelCG.h b/include/llvm/CodeGen/ParallelCG.h
index fa7002fa21fb..14ef0ec408ba 100644
--- a/include/llvm/CodeGen/ParallelCG.h
+++ b/include/llvm/CodeGen/ParallelCG.h
@@ -14,29 +14,34 @@
#ifndef LLVM_CODEGEN_PARALLELCG_H
#define LLVM_CODEGEN_PARALLELCG_H
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Target/TargetMachine.h"
+#include <functional>
+
namespace llvm {
+template <typename T> class ArrayRef;
class Module;
class TargetOptions;
class raw_pwrite_stream;
-/// Split M into OSs.size() partitions, and generate code for each. Writes
-/// OSs.size() output files to the output streams in OSs. The resulting output
-/// files if linked together are intended to be equivalent to the single output
-/// file that would have been code generated from M.
+/// Split M into OSs.size() partitions, and generate code for each. Takes a
+/// factory function for the TargetMachine TMFactory. Writes OSs.size() output
+/// files to the output streams in OSs. The resulting output files if linked
+/// together are intended to be equivalent to the single output file that would
+/// have been code generated from M.
+///
+/// Writes bitcode for individual partitions into output streams in BCOSs, if
+/// BCOSs is not empty.
///
/// \returns M if OSs.size() == 1, otherwise returns std::unique_ptr<Module>().
std::unique_ptr<Module>
splitCodeGen(std::unique_ptr<Module> M, ArrayRef<raw_pwrite_stream *> OSs,
- StringRef CPU, StringRef Features, const TargetOptions &Options,
- Reloc::Model RM = Reloc::Default,
- CodeModel::Model CM = CodeModel::Default,
- CodeGenOpt::Level OL = CodeGenOpt::Default,
- TargetMachine::CodeGenFileType FT = TargetMachine::CGFT_ObjectFile);
+ ArrayRef<llvm::raw_pwrite_stream *> BCOSs,
+ const std::function<std::unique_ptr<TargetMachine>()> &TMFactory,
+ TargetMachine::CodeGenFileType FT = TargetMachine::CGFT_ObjectFile,
+ bool PreserveLocals = false);
} // namespace llvm
diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h
index f45f0ed57d6b..ae9e5dfe2d65 100644
--- a/include/llvm/CodeGen/Passes.h
+++ b/include/llvm/CodeGen/Passes.h
@@ -15,352 +15,21 @@
#ifndef LLVM_CODEGEN_PASSES_H
#define LLVM_CODEGEN_PASSES_H
-#include "llvm/Pass.h"
-#include "llvm/Target/TargetMachine.h"
#include <functional>
#include <string>
namespace llvm {
+class Function;
+class FunctionPass;
class MachineFunctionPass;
-class PassConfigImpl;
-class PassInfo;
-class ScheduleDAGInstrs;
-class TargetLowering;
-class TargetLoweringBase;
+class ModulePass;
+class Pass;
+class TargetMachine;
class TargetRegisterClass;
class raw_ostream;
-struct MachineSchedContext;
-
-// The old pass manager infrastructure is hidden in a legacy namespace now.
-namespace legacy {
-class PassManagerBase;
-}
-using legacy::PassManagerBase;
-
-/// Discriminated union of Pass ID types.
-///
-/// The PassConfig API prefers dealing with IDs because they are safer and more
-/// efficient. IDs decouple configuration from instantiation. This way, when a
-/// pass is overriden, it isn't unnecessarily instantiated. It is also unsafe to
-/// refer to a Pass pointer after adding it to a pass manager, which deletes
-/// redundant pass instances.
-///
-/// However, it is convient to directly instantiate target passes with
-/// non-default ctors. These often don't have a registered PassInfo. Rather than
-/// force all target passes to implement the pass registry boilerplate, allow
-/// the PassConfig API to handle either type.
-///
-/// AnalysisID is sadly char*, so PointerIntPair won't work.
-class IdentifyingPassPtr {
- union {
- AnalysisID ID;
- Pass *P;
- };
- bool IsInstance;
-public:
- IdentifyingPassPtr() : P(nullptr), IsInstance(false) {}
- IdentifyingPassPtr(AnalysisID IDPtr) : ID(IDPtr), IsInstance(false) {}
- IdentifyingPassPtr(Pass *InstancePtr) : P(InstancePtr), IsInstance(true) {}
-
- bool isValid() const { return P; }
- bool isInstance() const { return IsInstance; }
-
- AnalysisID getID() const {
- assert(!IsInstance && "Not a Pass ID");
- return ID;
- }
- Pass *getInstance() const {
- assert(IsInstance && "Not a Pass Instance");
- return P;
- }
-};
-
-template <> struct isPodLike<IdentifyingPassPtr> {
- static const bool value = true;
-};
-
-/// Target-Independent Code Generator Pass Configuration Options.
-///
-/// This is an ImmutablePass solely for the purpose of exposing CodeGen options
-/// to the internals of other CodeGen passes.
-class TargetPassConfig : public ImmutablePass {
-public:
- /// Pseudo Pass IDs. These are defined within TargetPassConfig because they
- /// are unregistered pass IDs. They are only useful for use with
- /// TargetPassConfig APIs to identify multiple occurrences of the same pass.
- ///
-
- /// EarlyTailDuplicate - A clone of the TailDuplicate pass that runs early
- /// during codegen, on SSA form.
- static char EarlyTailDuplicateID;
-
- /// PostRAMachineLICM - A clone of the LICM pass that runs during late machine
- /// optimization after regalloc.
- static char PostRAMachineLICMID;
-
-private:
- PassManagerBase *PM;
- AnalysisID StartBefore, StartAfter;
- AnalysisID StopAfter;
- bool Started;
- bool Stopped;
- bool AddingMachinePasses;
-
-protected:
- TargetMachine *TM;
- PassConfigImpl *Impl; // Internal data structures
- bool Initialized; // Flagged after all passes are configured.
-
- // Target Pass Options
- // Targets provide a default setting, user flags override.
- //
- bool DisableVerify;
-
- /// Default setting for -enable-tail-merge on this target.
- bool EnableTailMerge;
-
-public:
- TargetPassConfig(TargetMachine *tm, PassManagerBase &pm);
- // Dummy constructor.
- TargetPassConfig();
-
- ~TargetPassConfig() override;
-
- static char ID;
-
- /// Get the right type of TargetMachine for this target.
- template<typename TMC> TMC &getTM() const {
- return *static_cast<TMC*>(TM);
- }
-
- //
- void setInitialized() { Initialized = true; }
-
- CodeGenOpt::Level getOptLevel() const { return TM->getOptLevel(); }
-
- /// Set the StartAfter, StartBefore and StopAfter passes to allow running only
- /// a portion of the normal code-gen pass sequence.
- ///
- /// If the StartAfter and StartBefore pass ID is zero, then compilation will
- /// begin at the normal point; otherwise, clear the Started flag to indicate
- /// that passes should not be added until the starting pass is seen. If the
- /// Stop pass ID is zero, then compilation will continue to the end.
- ///
- /// This function expects that at least one of the StartAfter or the
- /// StartBefore pass IDs is null.
- void setStartStopPasses(AnalysisID StartBefore, AnalysisID StartAfter,
- AnalysisID StopAfter) {
- if (StartAfter)
- assert(!StartBefore && "Start after and start before passes are given");
- this->StartBefore = StartBefore;
- this->StartAfter = StartAfter;
- this->StopAfter = StopAfter;
- Started = (StartAfter == nullptr) && (StartBefore == nullptr);
- }
-
- void setDisableVerify(bool Disable) { setOpt(DisableVerify, Disable); }
- bool getEnableTailMerge() const { return EnableTailMerge; }
- void setEnableTailMerge(bool Enable) { setOpt(EnableTailMerge, Enable); }
-
- /// Allow the target to override a specific pass without overriding the pass
- /// pipeline. When passes are added to the standard pipeline at the
- /// point where StandardID is expected, add TargetID in its place.
- void substitutePass(AnalysisID StandardID, IdentifyingPassPtr TargetID);
-
- /// Insert InsertedPassID pass after TargetPassID pass.
- void insertPass(AnalysisID TargetPassID, IdentifyingPassPtr InsertedPassID,
- bool VerifyAfter = true, bool PrintAfter = true);
-
- /// Allow the target to enable a specific standard pass by default.
- void enablePass(AnalysisID PassID) { substitutePass(PassID, PassID); }
-
- /// Allow the target to disable a specific standard pass by default.
- void disablePass(AnalysisID PassID) {
- substitutePass(PassID, IdentifyingPassPtr());
- }
-
- /// Return the pass substituted for StandardID by the target.
- /// If no substitution exists, return StandardID.
- IdentifyingPassPtr getPassSubstitution(AnalysisID StandardID) const;
-
- /// Return true if the optimized regalloc pipeline is enabled.
- bool getOptimizeRegAlloc() const;
-
- /// Return true if shrink wrapping is enabled.
- bool getEnableShrinkWrap() const;
-
- /// Return true if the default global register allocator is in use and
- /// has not be overriden on the command line with '-regalloc=...'
- bool usingDefaultRegAlloc() const;
-
- /// Add common target configurable passes that perform LLVM IR to IR
- /// transforms following machine independent optimization.
- virtual void addIRPasses();
-
- /// Add passes to lower exception handling for the code generator.
- void addPassesToHandleExceptions();
-
- /// Add pass to prepare the LLVM IR for code generation. This should be done
- /// before exception handling preparation passes.
- virtual void addCodeGenPrepare();
-
- /// Add common passes that perform LLVM IR to IR transforms in preparation for
- /// instruction selection.
- virtual void addISelPrepare();
-
- /// addInstSelector - This method should install an instruction selector pass,
- /// which converts from LLVM code to machine instructions.
- virtual bool addInstSelector() {
- return true;
- }
-
- /// Add the complete, standard set of LLVM CodeGen passes.
- /// Fully developed targets will not generally override this.
- virtual void addMachinePasses();
-
- /// Create an instance of ScheduleDAGInstrs to be run within the standard
- /// MachineScheduler pass for this function and target at the current
- /// optimization level.
- ///
- /// This can also be used to plug a new MachineSchedStrategy into an instance
- /// of the standard ScheduleDAGMI:
- /// return new ScheduleDAGMI(C, make_unique<MyStrategy>(C), /*RemoveKillFlags=*/false)
- ///
- /// Return NULL to select the default (generic) machine scheduler.
- virtual ScheduleDAGInstrs *
- createMachineScheduler(MachineSchedContext *C) const {
- return nullptr;
- }
-
- /// Similar to createMachineScheduler but used when postRA machine scheduling
- /// is enabled.
- virtual ScheduleDAGInstrs *
- createPostMachineScheduler(MachineSchedContext *C) const {
- return nullptr;
- }
-
-protected:
- // Helper to verify the analysis is really immutable.
- void setOpt(bool &Opt, bool Val);
-
- /// 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.
- ///
-
- /// addPreISelPasses - This method should add any "last minute" LLVM->LLVM
- /// passes (which are run just before instruction selector).
- virtual bool addPreISel() {
- return true;
- }
-
- /// addMachineSSAOptimization - Add standard passes that optimize machine
- /// instructions in SSA form.
- virtual void addMachineSSAOptimization();
-
- /// 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.
- virtual bool addILPOpts() {
- return false;
- }
-
- /// This method may be implemented by targets that want to run passes
- /// immediately before register allocation.
- virtual void addPreRegAlloc() { }
-
- /// createTargetRegisterAllocator - Create the register allocator pass for
- /// this target at the current optimization level.
- virtual FunctionPass *createTargetRegisterAllocator(bool Optimized);
-
- /// addFastRegAlloc - Add the minimum set of target-independent passes that
- /// are required for fast register allocation.
- virtual void addFastRegAlloc(FunctionPass *RegAllocPass);
-
- /// addOptimizedRegAlloc - Add passes related to register allocation.
- /// LLVMTargetMachine provides standard regalloc passes for most targets.
- virtual void addOptimizedRegAlloc(FunctionPass *RegAllocPass);
-
- /// 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.
- virtual bool addPreRewrite() {
- return false;
- }
-
- /// This method may be implemented by targets that want to run passes after
- /// register allocation pass pipeline but before prolog-epilog insertion.
- virtual void addPostRegAlloc() { }
-
- /// Add passes that optimize machine instructions after register allocation.
- virtual void addMachineLateOptimization();
-
- /// This method may be implemented by targets that want to run passes after
- /// prolog-epilog insertion and before the second instruction scheduling pass.
- virtual void addPreSched2() { }
-
- /// addGCPasses - Add late codegen passes that analyze code for garbage
- /// collection. This should return true if GC info should be printed after
- /// these passes.
- virtual bool addGCPasses();
-
- /// Add standard basic block placement passes.
- virtual void addBlockPlacement();
-
- /// This pass may be implemented by targets that want to run passes
- /// immediately before machine code is emitted.
- virtual void addPreEmitPass() { }
-
- /// Utilities for targets to add passes to the pass manager.
- ///
-
- /// 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);
-
- /// 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);
-
- /// addMachinePasses helper to create the target-selected or overriden
- /// regalloc pass.
- FunctionPass *createRegAllocPass(bool Optimized);
-
- /// printAndVerify - Add a pass to dump then verify the machine function, if
- /// those steps are enabled.
- ///
- void printAndVerify(const std::string &Banner);
-
- /// Add a pass to print the machine function if printing is enabled.
- void addPrintPass(const std::string &Banner);
-
- /// Add a pass to perform basic verification of the machine function if
- /// verification is enabled.
- void addVerifyPass(const std::string &Banner);
-};
-} // namespace llvm
+} // End llvm namespace
/// List of target independent CodeGen pass IDs.
namespace llvm {
@@ -457,6 +126,9 @@ namespace llvm {
/// DeadMachineInstructionElim - This pass removes dead machine instructions.
extern char &DeadMachineInstructionElimID;
+ /// This pass adds dead/undef flags after analyzing subregister lanes.
+ extern char &DetectDeadLanesID;
+
/// FastRegisterAllocation Pass - This pass register allocates as fast as
/// possible. It is best suited for debug code where live ranges are short.
///
@@ -480,11 +152,16 @@ namespace llvm {
/// PrologEpilogCodeInserter - This pass inserts prolog and epilog code,
/// and eliminates abstract frame references.
extern char &PrologEpilogCodeInserterID;
+ MachineFunctionPass *createPrologEpilogInserterPass(const TargetMachine *TM);
/// ExpandPostRAPseudos - This pass expands pseudo instructions after
/// register allocation.
extern char &ExpandPostRAPseudosID;
+ /// createPostRAHazardRecognizer - This pass runs the post-ra hazard
+ /// recognizer.
+ extern char &PostRAHazardRecognizerID;
+
/// createPostRAScheduler - This pass performs post register allocation
/// scheduling.
extern char &PostRASchedulerID;
@@ -586,6 +263,13 @@ namespace llvm {
/// \brief This pass lays out funclets contiguously.
extern char &FuncletLayoutID;
+ /// This pass inserts the XRay instrumentation sleds if they are supported by
+ /// the target platform.
+ extern char &XRayInstrumentationID;
+
+ /// \brief This pass implements the "patchable-function" attribute.
+ extern char &PatchableFunctionID;
+
/// createStackProtectorPass - This pass adds stack protectors to functions.
///
FunctionPass *createStackProtectorPass(const TargetMachine *TM);
@@ -654,6 +338,42 @@ namespace llvm {
/// memory accesses to target specific intrinsics.
///
FunctionPass *createInterleavedAccessPass(const TargetMachine *TM);
+
+ /// LowerEmuTLS - This pass generates __emutls_[vt].xyz variables for all
+ /// TLS variables for the emulated TLS model.
+ ///
+ ModulePass *createLowerEmuTLSPass(const TargetMachine *TM);
+
+ /// This pass lowers the @llvm.load.relative intrinsic to instructions.
+ /// This is unsafe to do earlier because a pass may combine the constant
+ /// initializer into the load, which may result in an overflowing evaluation.
+ ModulePass *createPreISelIntrinsicLoweringPass();
+
+ /// GlobalMerge - This pass merges internal (by default) globals into structs
+ /// to enable reuse of a base pointer by indexed addressing modes.
+ /// It can also be configured to focus on size optimizations only.
+ ///
+ Pass *createGlobalMergePass(const TargetMachine *TM, unsigned MaximalOffset,
+ bool OnlyOptimizeForSize = false,
+ bool MergeExternalByDefault = false);
+
+ /// This pass splits the stack into a safe stack and an unsafe stack to
+ /// protect against stack-based overflow vulnerabilities.
+ FunctionPass *createSafeStackPass(const TargetMachine *TM = nullptr);
+
+ /// This pass detects subregister lanes in a virtual register that are used
+ /// independently of other lanes and splits them into separate virtual
+ /// registers.
+ extern char &RenameIndependentSubregsID;
+
+ /// This pass is executed POST-RA to collect which physical registers are
+ /// preserved by given machine function.
+ FunctionPass *createRegUsageInfoCollector();
+
+ /// Return a MachineFunction pass that identifies call sites
+ /// and propagates register usage information of callee to caller
+ /// if available with PysicalRegisterUsageInfo pass.
+ FunctionPass *createRegUsageInfoPropPass();
} // End llvm namespace
/// Target machine pass initializer for passes with dependencies. Use with
@@ -662,15 +382,18 @@ namespace llvm {
/// Target machine pass initializer for passes with dependencies. Use with
/// INITIALIZE_TM_PASS_BEGIN.
-#define INITIALIZE_TM_PASS_END(passName, arg, name, cfg, analysis) \
- PassInfo *PI = new PassInfo(name, arg, & passName ::ID, \
- PassInfo::NormalCtor_t(callDefaultCtor< passName >), cfg, analysis, \
- PassInfo::TargetMachineCtor_t(callTargetMachineCtor< passName >)); \
- Registry.registerPass(*PI, true); \
- return PI; \
- } \
- void llvm::initialize##passName##Pass(PassRegistry &Registry) { \
- CALL_ONCE_INITIALIZATION(initialize##passName##PassOnce) \
+#define INITIALIZE_TM_PASS_END(passName, arg, name, cfg, analysis) \
+ PassInfo *PI = new PassInfo( \
+ name, arg, &passName::ID, \
+ PassInfo::NormalCtor_t(callDefaultCtor<passName>), cfg, analysis, \
+ PassInfo::TargetMachineCtor_t(callTargetMachineCtor<passName>)); \
+ Registry.registerPass(*PI, true); \
+ return PI; \
+ } \
+ LLVM_DEFINE_ONCE_FLAG(Initialize##passName##PassFlag); \
+ void llvm::initialize##passName##Pass(PassRegistry &Registry) { \
+ llvm::call_once(Initialize##passName##PassFlag, \
+ initialize##passName##PassOnce, std::ref(Registry)); \
}
/// This initializer registers TargetMachine constructor, so the pass being
@@ -678,8 +401,8 @@ namespace llvm {
/// macro to be together with INITIALIZE_PASS, which is a complete target
/// independent initializer, and we don't want to make libScalarOpts depend
/// on libCodeGen.
-#define INITIALIZE_TM_PASS(passName, arg, name, cfg, analysis) \
- INITIALIZE_TM_PASS_BEGIN(passName, arg, name, cfg, analysis) \
- INITIALIZE_TM_PASS_END(passName, arg, name, cfg, analysis)
+#define INITIALIZE_TM_PASS(passName, arg, name, cfg, analysis) \
+ INITIALIZE_TM_PASS_BEGIN(passName, arg, name, cfg, analysis) \
+ INITIALIZE_TM_PASS_END(passName, arg, name, cfg, analysis)
#endif
diff --git a/include/llvm/CodeGen/PreISelIntrinsicLowering.h b/include/llvm/CodeGen/PreISelIntrinsicLowering.h
new file mode 100644
index 000000000000..765ca085244a
--- /dev/null
+++ b/include/llvm/CodeGen/PreISelIntrinsicLowering.h
@@ -0,0 +1,26 @@
+//===--- PreISelIntrinsicLowering.h - Pre-ISel intrinsic lowering pass ----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass implements IR lowering for the llvm.load.relative intrinsic.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CODEGEN_PREISELINTRINSICLOWERING_H
+#define LLVM_CODEGEN_PREISELINTRINSICLOWERING_H
+
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+struct PreISelIntrinsicLoweringPass
+ : PassInfoMixin<PreISelIntrinsicLoweringPass> {
+ PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
+};
+}
+
+#endif // LLVM_CODEGEN_PREISELINTRINSICLOWERING_H
diff --git a/include/llvm/CodeGen/PseudoSourceValue.h b/include/llvm/CodeGen/PseudoSourceValue.h
index f67552030db4..c3f6fde9fb3f 100644
--- a/include/llvm/CodeGen/PseudoSourceValue.h
+++ b/include/llvm/CodeGen/PseudoSourceValue.h
@@ -27,6 +27,8 @@ class MachineMemOperand;
class raw_ostream;
raw_ostream &operator<<(raw_ostream &OS, const MachineMemOperand &MMO);
+class PseudoSourceValue;
+raw_ostream &operator<<(raw_ostream &OS, const PseudoSourceValue* PSV);
/// Special value supplied for machine level alias analysis. It indicates that
/// a memory access references the functions stack frame (e.g., a spill slot),
@@ -45,6 +47,8 @@ public:
private:
PSVKind Kind;
+ friend raw_ostream &llvm::operator<<(raw_ostream &OS,
+ const PseudoSourceValue* PSV);
friend class MachineMemOperand; // For printCustom().
diff --git a/include/llvm/CodeGen/RegAllocPBQP.h b/include/llvm/CodeGen/RegAllocPBQP.h
index 4122811a9e5c..21952272ffdb 100644
--- a/include/llvm/CodeGen/RegAllocPBQP.h
+++ b/include/llvm/CodeGen/RegAllocPBQP.h
@@ -21,6 +21,7 @@
#include "llvm/CodeGen/PBQP/ReductionRules.h"
#include "llvm/CodeGen/PBQPRAConstraint.h"
#include "llvm/Support/ErrorHandling.h"
+#include <set>
namespace llvm {
diff --git a/include/llvm/CodeGen/RegisterPressure.h b/include/llvm/CodeGen/RegisterPressure.h
index 9bbdf3e071bd..aaddac40ca76 100644
--- a/include/llvm/CodeGen/RegisterPressure.h
+++ b/include/llvm/CodeGen/RegisterPressure.h
@@ -26,14 +26,22 @@ class LiveRange;
class RegisterClassInfo;
class MachineInstr;
+struct RegisterMaskPair {
+ unsigned RegUnit; ///< Virtual register or register unit.
+ LaneBitmask LaneMask;
+
+ RegisterMaskPair(unsigned RegUnit, LaneBitmask LaneMask)
+ : RegUnit(RegUnit), LaneMask(LaneMask) {}
+};
+
/// Base class for register pressure results.
struct RegisterPressure {
/// Map of max reg pressure indexed by pressure set ID, not class ID.
std::vector<unsigned> MaxSetPressure;
/// List of live in virtual registers or physical register units.
- SmallVector<unsigned,8> LiveInRegs;
- SmallVector<unsigned,8> LiveOutRegs;
+ SmallVector<RegisterMaskPair,8> LiveInRegs;
+ SmallVector<RegisterMaskPair,8> LiveOutRegs;
void dump(const TargetRegisterInfo *TRI) const;
};
@@ -144,23 +152,32 @@ public:
/// List of registers defined and used by a machine instruction.
class RegisterOperands {
public:
- /// List of virtual regiserts and register units read by the instruction.
- SmallVector<unsigned, 8> Uses;
+ /// List of virtual registers and register units read by the instruction.
+ SmallVector<RegisterMaskPair, 8> Uses;
/// \brief List of virtual registers and register units defined by the
/// instruction which are not dead.
- SmallVector<unsigned, 8> Defs;
+ SmallVector<RegisterMaskPair, 8> Defs;
/// \brief List of virtual registers and register units defined by the
/// instruction but dead.
- SmallVector<unsigned, 8> DeadDefs;
+ SmallVector<RegisterMaskPair, 8> DeadDefs;
/// Analyze the given instruction \p MI and fill in the Uses, Defs and
/// DeadDefs list based on the MachineOperand flags.
void collect(const MachineInstr &MI, const TargetRegisterInfo &TRI,
- const MachineRegisterInfo &MRI, bool IgnoreDead = false);
+ const MachineRegisterInfo &MRI, bool TrackLaneMasks,
+ bool IgnoreDead);
/// Use liveness information to find dead defs not marked with a dead flag
/// and move them to the DeadDefs vector.
void detectDeadDefs(const MachineInstr &MI, const LiveIntervals &LIS);
+
+ /// Use liveness information to find out which uses/defs are partially
+ /// undefined/dead and adjust the RegisterMaskPairs accordingly.
+ /// If \p AddFlagsMI is given then missing read-undef and dead flags will be
+ /// added to the instruction.
+ void adjustLaneLiveness(const LiveIntervals &LIS,
+ const MachineRegisterInfo &MRI, SlotIndex Pos,
+ MachineInstr *AddFlagsMI = nullptr);
};
/// Array of PressureDiffs.
@@ -225,7 +242,20 @@ struct RegPressureDelta {
/// and virtual register indexes to an index usable by the sparse set.
class LiveRegSet {
private:
- SparseSet<unsigned> Regs;
+ struct IndexMaskPair {
+ unsigned Index;
+ LaneBitmask LaneMask;
+
+ IndexMaskPair(unsigned Index, LaneBitmask LaneMask)
+ : Index(Index), LaneMask(LaneMask) {}
+
+ unsigned getSparseSetIndex() const {
+ return Index;
+ }
+ };
+
+ typedef SparseSet<IndexMaskPair> RegSet;
+ RegSet Regs;
unsigned NumRegUnits;
unsigned getSparseIndexFromReg(unsigned Reg) const {
@@ -244,19 +274,37 @@ public:
void clear();
void init(const MachineRegisterInfo &MRI);
- bool contains(unsigned Reg) const {
+ LaneBitmask contains(unsigned Reg) const {
unsigned SparseIndex = getSparseIndexFromReg(Reg);
- return Regs.count(SparseIndex);
+ RegSet::const_iterator I = Regs.find(SparseIndex);
+ if (I == Regs.end())
+ return 0;
+ return I->LaneMask;
}
- bool insert(unsigned Reg) {
- unsigned SparseIndex = getSparseIndexFromReg(Reg);
- return Regs.insert(SparseIndex).second;
+ /// Mark the \p Pair.LaneMask lanes of \p Pair.Reg as live.
+ /// Returns the previously live lanes of \p Pair.Reg.
+ LaneBitmask insert(RegisterMaskPair Pair) {
+ unsigned SparseIndex = getSparseIndexFromReg(Pair.RegUnit);
+ auto InsertRes = Regs.insert(IndexMaskPair(SparseIndex, Pair.LaneMask));
+ if (!InsertRes.second) {
+ unsigned PrevMask = InsertRes.first->LaneMask;
+ InsertRes.first->LaneMask |= Pair.LaneMask;
+ return PrevMask;
+ }
+ return 0;
}
- bool erase(unsigned Reg) {
- unsigned SparseIndex = getSparseIndexFromReg(Reg);
- return Regs.erase(SparseIndex);
+ /// Clears the \p Pair.LaneMask lanes of \p Pair.Reg (mark them as dead).
+ /// Returns the previously live lanes of \p Pair.Reg.
+ LaneBitmask erase(RegisterMaskPair Pair) {
+ unsigned SparseIndex = getSparseIndexFromReg(Pair.RegUnit);
+ RegSet::iterator I = Regs.find(SparseIndex);
+ if (I == Regs.end())
+ return 0;
+ unsigned PrevMask = I->LaneMask;
+ I->LaneMask &= ~Pair.LaneMask;
+ return PrevMask;
}
size_t size() const {
@@ -265,9 +313,10 @@ public:
template<typename ContainerT>
void appendTo(ContainerT &To) const {
- for (unsigned I : Regs) {
- unsigned Reg = getRegFromSparseIndex(I);
- To.push_back(Reg);
+ for (const IndexMaskPair &P : Regs) {
+ unsigned Reg = getRegFromSparseIndex(P.Index);
+ if (P.LaneMask != 0)
+ To.push_back(RegisterMaskPair(Reg, P.LaneMask));
}
}
};
@@ -308,6 +357,9 @@ class RegPressureTracker {
/// True if UntiedDefs will be populated.
bool TrackUntiedDefs;
+ /// True if lanemasks should be tracked.
+ bool TrackLaneMasks;
+
/// Register pressure corresponds to liveness before this instruction
/// iterator. It may point to the end of the block or a DebugValue rather than
/// an instruction.
@@ -327,23 +379,23 @@ class RegPressureTracker {
public:
RegPressureTracker(IntervalPressure &rp) :
MF(nullptr), TRI(nullptr), RCI(nullptr), LIS(nullptr), MBB(nullptr), P(rp),
- RequireIntervals(true), TrackUntiedDefs(false) {}
+ RequireIntervals(true), TrackUntiedDefs(false), TrackLaneMasks(false) {}
RegPressureTracker(RegionPressure &rp) :
MF(nullptr), TRI(nullptr), RCI(nullptr), LIS(nullptr), MBB(nullptr), P(rp),
- RequireIntervals(false), TrackUntiedDefs(false) {}
+ RequireIntervals(false), TrackUntiedDefs(false), TrackLaneMasks(false) {}
void reset();
void init(const MachineFunction *mf, const RegisterClassInfo *rci,
const LiveIntervals *lis, const MachineBasicBlock *mbb,
MachineBasicBlock::const_iterator pos,
- bool ShouldTrackUntiedDefs = false);
+ bool TrackLaneMasks, bool TrackUntiedDefs);
/// Force liveness of virtual registers or physical register
/// units. Particularly useful to initialize the livein/out state of the
/// tracker before the first call to advance/recede.
- void addLiveRegs(ArrayRef<unsigned> Regs);
+ void addLiveRegs(ArrayRef<RegisterMaskPair> Regs);
/// Get the MI position corresponding to this register pressure.
MachineBasicBlock::const_iterator getPos() const { return CurrPos; }
@@ -355,14 +407,14 @@ public:
void setPos(MachineBasicBlock::const_iterator Pos) { CurrPos = Pos; }
/// Recede across the previous instruction.
- void recede(SmallVectorImpl<unsigned> *LiveUses = nullptr);
+ void recede(SmallVectorImpl<RegisterMaskPair> *LiveUses = nullptr);
/// Recede across the previous instruction.
/// This "low-level" variant assumes that recedeSkipDebugValues() was
/// called previously and takes precomputed RegisterOperands for the
/// instruction.
void recede(const RegisterOperands &RegOpers,
- SmallVectorImpl<unsigned> *LiveUses = nullptr);
+ SmallVectorImpl<RegisterMaskPair> *LiveUses = nullptr);
/// Recede until we find an instruction which is not a DebugValue.
void recedeSkipDebugValues();
@@ -370,6 +422,11 @@ public:
/// Advance across the current instruction.
void advance();
+ /// Advance across the current instruction.
+ /// This is a "low-level" variant of advance() which takes precomputed
+ /// RegisterOperands of the instruction.
+ void advance(const RegisterOperands &RegOpers);
+
/// Finalize the region boundaries and recored live ins and live outs.
void closeRegion();
@@ -469,18 +526,31 @@ public:
void dump() const;
protected:
- void discoverLiveOut(unsigned Reg);
- void discoverLiveIn(unsigned Reg);
+ /// Add Reg to the live out set and increase max pressure.
+ void discoverLiveOut(RegisterMaskPair Pair);
+ /// Add Reg to the live in set and increase max pressure.
+ void discoverLiveIn(RegisterMaskPair Pair);
/// \brief Get the SlotIndex for the first nondebug instruction including or
/// after the current position.
SlotIndex getCurrSlot() const;
- void increaseRegPressure(ArrayRef<unsigned> Regs);
- void decreaseRegPressure(ArrayRef<unsigned> Regs);
+ void increaseRegPressure(unsigned RegUnit, LaneBitmask PreviousMask,
+ LaneBitmask NewMask);
+ void decreaseRegPressure(unsigned RegUnit, LaneBitmask PreviousMask,
+ LaneBitmask NewMask);
+
+ void bumpDeadDefs(ArrayRef<RegisterMaskPair> DeadDefs);
void bumpUpwardPressure(const MachineInstr *MI);
void bumpDownwardPressure(const MachineInstr *MI);
+
+ void discoverLiveInOrOut(RegisterMaskPair Pair,
+ SmallVectorImpl<RegisterMaskPair> &LiveInOrOut);
+
+ LaneBitmask getLastUsedLanes(unsigned RegUnit, SlotIndex Pos) const;
+ LaneBitmask getLiveLanesAt(unsigned RegUnit, SlotIndex Pos) const;
+ LaneBitmask getLiveThroughAt(unsigned RegUnit, SlotIndex Pos) const;
};
void dumpRegSetPressure(ArrayRef<unsigned> SetPressure,
diff --git a/include/llvm/CodeGen/RegisterScavenging.h b/include/llvm/CodeGen/RegisterScavenging.h
index 122c78534253..efe1a3c6d0f7 100644
--- a/include/llvm/CodeGen/RegisterScavenging.h
+++ b/include/llvm/CodeGen/RegisterScavenging.h
@@ -7,10 +7,11 @@
//
//===----------------------------------------------------------------------===//
//
-// This file declares the machine register scavenger class. It can provide
-// information such as unused register at any point in a machine basic block.
-// It also provides a mechanism to make registers available by evicting them
-// to spill slots.
+/// \file
+/// This file declares the machine register scavenger class. It can provide
+/// information such as unused register at any point in a machine basic block.
+/// It also provides a mechanism to make registers available by evicting them
+/// to spill slots.
//
//===----------------------------------------------------------------------===//
@@ -71,8 +72,8 @@ public:
RegScavenger()
: MBB(nullptr), NumRegUnits(0), Tracking(false) {}
- /// Start tracking liveness from the begin of the specific basic block.
- void enterBasicBlock(MachineBasicBlock *mbb);
+ /// Start tracking liveness from the begin of basic block \p MBB.
+ void enterBasicBlock(MachineBasicBlock &MBB);
/// Move the internal MBB iterator and update register states.
void forward();
diff --git a/include/llvm/CodeGen/RegisterUsageInfo.h b/include/llvm/CodeGen/RegisterUsageInfo.h
new file mode 100644
index 000000000000..3f88032cb638
--- /dev/null
+++ b/include/llvm/CodeGen/RegisterUsageInfo.h
@@ -0,0 +1,75 @@
+//==- RegisterUsageInfo.h - Register Usage Informartion Storage -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This pass is required to take advantage of the interprocedural register
+/// allocation infrastructure.
+///
+/// This pass is simple immutable pass which keeps RegMasks (calculated based on
+/// actual register allocation) for functions in a module and provides simple
+/// API to query this information.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_PHYSICALREGISTERUSAGEINFO_H
+#define LLVM_CODEGEN_PHYSICALREGISTERUSAGEINFO_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+
+class PhysicalRegisterUsageInfo : public ImmutablePass {
+ virtual void anchor();
+
+public:
+ static char ID;
+
+ PhysicalRegisterUsageInfo() : ImmutablePass(ID) {
+ PassRegistry &Registry = *PassRegistry::getPassRegistry();
+ initializePhysicalRegisterUsageInfoPass(Registry);
+ }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.setPreservesAll();
+ }
+
+ /// To set TargetMachine *, which is used to print
+ /// analysis when command line option -print-regusage is used.
+ void setTargetMachine(const TargetMachine *TM_) { TM = TM_; }
+
+ bool doInitialization(Module &M) override;
+
+ bool doFinalization(Module &M) override;
+
+ /// To store RegMask for given Function *.
+ void storeUpdateRegUsageInfo(const Function *FP,
+ std::vector<uint32_t> RegMask);
+
+ /// To query stored RegMask for given Function *, it will return nullptr if
+ /// function is not known.
+ const std::vector<uint32_t> *getRegUsageInfo(const Function *FP);
+
+ void print(raw_ostream &OS, const Module *M = nullptr) const override;
+
+private:
+ /// A Dense map from Function * to RegMask.
+ /// In RegMask 0 means register used (clobbered) by function.
+ /// and 1 means content of register will be preserved around function call.
+ DenseMap<const Function *, std::vector<uint32_t>> RegMasks;
+
+ const TargetMachine *TM;
+};
+}
+
+#endif
diff --git a/include/llvm/CodeGen/ResourcePriorityQueue.h b/include/llvm/CodeGen/ResourcePriorityQueue.h
index 0097e0472e5c..9c8f5f487d38 100644
--- a/include/llvm/CodeGen/ResourcePriorityQueue.h
+++ b/include/llvm/CodeGen/ResourcePriorityQueue.h
@@ -72,7 +72,7 @@ namespace llvm {
/// Heuristics for estimating register pressure.
unsigned ParallelLiveRanges;
- signed HorizontalVerticalBalance;
+ int HorizontalVerticalBalance;
public:
ResourcePriorityQueue(SelectionDAGISel *IS);
@@ -103,14 +103,14 @@ namespace llvm {
/// Single cost function reflecting benefit of scheduling SU
/// in the current cycle.
- signed SUSchedulingCost (SUnit *SU);
+ int SUSchedulingCost (SUnit *SU);
/// InitNumRegDefsLeft - Determine the # of regs defined by this node.
///
void initNumRegDefsLeft(SUnit *SU);
void updateNumRegDefsLeft(SUnit *SU);
- signed regPressureDelta(SUnit *SU, bool RawPressure = false);
- signed rawRegPressureDelta (SUnit *SU, unsigned RCId);
+ int regPressureDelta(SUnit *SU, bool RawPressure = false);
+ int rawRegPressureDelta (SUnit *SU, unsigned RCId);
bool empty() const override { return Queue.empty(); }
diff --git a/include/llvm/CodeGen/RuntimeLibcalls.h b/include/llvm/CodeGen/RuntimeLibcalls.h
index 7db03459f9bf..16d305c7297f 100644
--- a/include/llvm/CodeGen/RuntimeLibcalls.h
+++ b/include/llvm/CodeGen/RuntimeLibcalls.h
@@ -215,6 +215,8 @@ namespace RTLIB {
FMAX_PPCF128,
// CONVERSION
+ FPEXT_F32_PPCF128,
+ FPEXT_F64_PPCF128,
FPEXT_F64_F128,
FPEXT_F32_F128,
FPEXT_F32_F64,
@@ -296,27 +298,35 @@ namespace RTLIB {
OEQ_F32,
OEQ_F64,
OEQ_F128,
+ OEQ_PPCF128,
UNE_F32,
UNE_F64,
UNE_F128,
+ UNE_PPCF128,
OGE_F32,
OGE_F64,
OGE_F128,
+ OGE_PPCF128,
OLT_F32,
OLT_F64,
OLT_F128,
+ OLT_PPCF128,
OLE_F32,
OLE_F64,
OLE_F128,
+ OLE_PPCF128,
OGT_F32,
OGT_F64,
OGT_F128,
+ OGT_PPCF128,
UO_F32,
UO_F64,
UO_F128,
+ UO_PPCF128,
O_F32,
O_F64,
O_F128,
+ O_PPCF128,
// MEMORY
MEMCPY,
@@ -326,7 +336,11 @@ namespace RTLIB {
// EXCEPTION HANDLING
UNWIND_RESUME,
- // Family ATOMICs
+ // Note: there's two sets of atomics libcalls; see
+ // <http://llvm.org/docs/Atomics.html> for more info on the
+ // difference between them.
+
+ // Atomic '__sync_*' libcalls.
SYNC_VAL_COMPARE_AND_SWAP_1,
SYNC_VAL_COMPARE_AND_SWAP_2,
SYNC_VAL_COMPARE_AND_SWAP_4,
@@ -388,9 +402,77 @@ namespace RTLIB {
SYNC_FETCH_AND_UMIN_8,
SYNC_FETCH_AND_UMIN_16,
+ // Atomic '__atomic_*' libcalls.
+ ATOMIC_LOAD,
+ ATOMIC_LOAD_1,
+ ATOMIC_LOAD_2,
+ ATOMIC_LOAD_4,
+ ATOMIC_LOAD_8,
+ ATOMIC_LOAD_16,
+
+ ATOMIC_STORE,
+ ATOMIC_STORE_1,
+ ATOMIC_STORE_2,
+ ATOMIC_STORE_4,
+ ATOMIC_STORE_8,
+ ATOMIC_STORE_16,
+
+ ATOMIC_EXCHANGE,
+ ATOMIC_EXCHANGE_1,
+ ATOMIC_EXCHANGE_2,
+ ATOMIC_EXCHANGE_4,
+ ATOMIC_EXCHANGE_8,
+ ATOMIC_EXCHANGE_16,
+
+ ATOMIC_COMPARE_EXCHANGE,
+ ATOMIC_COMPARE_EXCHANGE_1,
+ ATOMIC_COMPARE_EXCHANGE_2,
+ ATOMIC_COMPARE_EXCHANGE_4,
+ ATOMIC_COMPARE_EXCHANGE_8,
+ ATOMIC_COMPARE_EXCHANGE_16,
+
+ ATOMIC_FETCH_ADD_1,
+ ATOMIC_FETCH_ADD_2,
+ ATOMIC_FETCH_ADD_4,
+ ATOMIC_FETCH_ADD_8,
+ ATOMIC_FETCH_ADD_16,
+
+ ATOMIC_FETCH_SUB_1,
+ ATOMIC_FETCH_SUB_2,
+ ATOMIC_FETCH_SUB_4,
+ ATOMIC_FETCH_SUB_8,
+ ATOMIC_FETCH_SUB_16,
+
+ ATOMIC_FETCH_AND_1,
+ ATOMIC_FETCH_AND_2,
+ ATOMIC_FETCH_AND_4,
+ ATOMIC_FETCH_AND_8,
+ ATOMIC_FETCH_AND_16,
+
+ ATOMIC_FETCH_OR_1,
+ ATOMIC_FETCH_OR_2,
+ ATOMIC_FETCH_OR_4,
+ ATOMIC_FETCH_OR_8,
+ ATOMIC_FETCH_OR_16,
+
+ ATOMIC_FETCH_XOR_1,
+ ATOMIC_FETCH_XOR_2,
+ ATOMIC_FETCH_XOR_4,
+ ATOMIC_FETCH_XOR_8,
+ ATOMIC_FETCH_XOR_16,
+
+ ATOMIC_FETCH_NAND_1,
+ ATOMIC_FETCH_NAND_2,
+ ATOMIC_FETCH_NAND_4,
+ ATOMIC_FETCH_NAND_8,
+ ATOMIC_FETCH_NAND_16,
+
// Stack Protector Fail.
STACKPROTECTOR_CHECK_FAIL,
+ // Deoptimization.
+ DEOPTIMIZE,
+
UNKNOWN_LIBCALL
};
@@ -420,7 +502,7 @@ namespace RTLIB {
/// Return the SYNC_FETCH_AND_* value for the given opcode and type, or
/// UNKNOWN_LIBCALL if there is none.
- Libcall getATOMIC(unsigned Opc, MVT VT);
+ Libcall getSYNC(unsigned Opc, MVT VT);
}
}
diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h
index bda9dbd51fff..6469cabd3de1 100644
--- a/include/llvm/CodeGen/ScheduleDAG.h
+++ b/include/llvm/CodeGen/ScheduleDAG.h
@@ -396,6 +396,17 @@ namespace llvm {
/// specified node.
bool addPred(const SDep &D, bool Required = true);
+ /// addPredBarrier - This adds a barrier edge to SU by calling
+ /// addPred(), with latency 0 generally or latency 1 for a store
+ /// followed by a load.
+ bool addPredBarrier(SUnit *SU) {
+ SDep Dep(SU, SDep::Barrier);
+ unsigned TrueMemOrderLatency =
+ ((SU->getInstr()->mayStore() && this->getInstr()->mayLoad()) ? 1 : 0);
+ Dep.setLatency(TrueMemOrderLatency);
+ return addPred(Dep);
+ }
+
/// removePred - This removes the specified edge as a pred of the current
/// node if it exists. It also removes the current node as a successor of
/// the specified node.
diff --git a/include/llvm/CodeGen/ScheduleDAGInstrs.h b/include/llvm/CodeGen/ScheduleDAGInstrs.h
index c574df094911..12124ecc4b3e 100644
--- a/include/llvm/CodeGen/ScheduleDAGInstrs.h
+++ b/include/llvm/CodeGen/ScheduleDAGInstrs.h
@@ -15,12 +15,14 @@
#ifndef LLVM_CODEGEN_SCHEDULEDAGINSTRS_H
#define LLVM_CODEGEN_SCHEDULEDAGINSTRS_H
+#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SparseMultiSet.h"
#include "llvm/ADT/SparseSet.h"
#include "llvm/CodeGen/ScheduleDAG.h"
#include "llvm/CodeGen/TargetSchedule.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Target/TargetRegisterInfo.h"
+#include <list>
namespace llvm {
class MachineFrameInfo;
@@ -84,6 +86,15 @@ namespace llvm {
typedef SparseMultiSet<VReg2SUnitOperIdx, VirtReg2IndexFunctor>
VReg2SUnitOperIdxMultiMap;
+ typedef PointerUnion<const Value *, const PseudoSourceValue *> ValueType;
+ struct UnderlyingObject : PointerIntPair<ValueType, 1, bool> {
+ UnderlyingObject(ValueType V, bool MayAlias)
+ : PointerIntPair<ValueType, 1, bool>(V, MayAlias) {}
+ ValueType getValue() const { return getPointer(); }
+ bool mayAlias() const { return getInt(); }
+ };
+ typedef SmallVector<UnderlyingObject, 4> UnderlyingObjectsVector;
+
/// ScheduleDAGInstrs - A ScheduleDAG subclass for scheduling lists of
/// MachineInstrs.
class ScheduleDAGInstrs : public ScheduleDAG {
@@ -149,10 +160,66 @@ namespace llvm {
/// Tracks the last instructions in this region using each virtual register.
VReg2SUnitOperIdxMultiMap CurrentVRegUses;
- /// PendingLoads - Remember where unknown loads are after the most recent
- /// unknown store, as we iterate. As with Defs and Uses, this is here
- /// to minimize construction/destruction.
- std::vector<SUnit *> PendingLoads;
+ AliasAnalysis *AAForDep;
+
+ /// Remember a generic side-effecting instruction as we proceed.
+ /// No other SU ever gets scheduled around it (except in the special
+ /// case of a huge region that gets reduced).
+ SUnit *BarrierChain;
+
+ public:
+
+ /// A list of SUnits, used in Value2SUsMap, during DAG construction.
+ /// Note: to gain speed it might be worth investigating an optimized
+ /// implementation of this data structure, such as a singly linked list
+ /// with a memory pool (SmallVector was tried but slow and SparseSet is not
+ /// applicable).
+ typedef std::list<SUnit *> SUList;
+ protected:
+ /// A map from ValueType to SUList, used during DAG construction,
+ /// as a means of remembering which SUs depend on which memory
+ /// locations.
+ class Value2SUsMap;
+
+ /// Remove in FIFO order some SUs from huge maps.
+ void reduceHugeMemNodeMaps(Value2SUsMap &stores,
+ Value2SUsMap &loads, unsigned N);
+
+ /// Add a chain edge between SUa and SUb, but only if both AliasAnalysis
+ /// and Target fail to deny the dependency.
+ void addChainDependency(SUnit *SUa, SUnit *SUb,
+ unsigned Latency = 0);
+
+ /// Add dependencies as needed from all SUs in list to SU.
+ void addChainDependencies(SUnit *SU, SUList &sus, unsigned Latency) {
+ for (auto *su : sus)
+ addChainDependency(SU, su, Latency);
+ }
+
+ /// Add dependencies as needed from all SUs in map, to SU.
+ void addChainDependencies(SUnit *SU, Value2SUsMap &Val2SUsMap);
+
+ /// Add dependencies as needed to SU, from all SUs mapped to V.
+ void addChainDependencies(SUnit *SU, Value2SUsMap &Val2SUsMap,
+ ValueType V);
+
+ /// Add barrier chain edges from all SUs in map, and then clear
+ /// the map. This is equivalent to insertBarrierChain(), but
+ /// optimized for the common case where the new BarrierChain (a
+ /// global memory object) has a higher NodeNum than all SUs in
+ /// map. It is assumed BarrierChain has been set before calling
+ /// this.
+ void addBarrierChain(Value2SUsMap &map);
+
+ /// Insert a barrier chain in a huge region, far below current
+ /// SU. Add barrier chain edges from all SUs in map with higher
+ /// NodeNums than this new BarrierChain, and remove them from
+ /// map. It is assumed BarrierChain has been set before calling
+ /// this.
+ void insertBarrierChain(Value2SUsMap &map);
+
+ /// For an unanalyzable memory access, this Value is used in maps.
+ UndefValue *UnknownValue;
/// DbgValues - Remember instruction that precedes DBG_VALUE.
/// These are generated by buildSchedGraph but persist so they can be
@@ -214,6 +281,7 @@ namespace llvm {
void buildSchedGraph(AliasAnalysis *AA,
RegPressureTracker *RPTracker = nullptr,
PressureDiffs *PDiffs = nullptr,
+ LiveIntervals *LIS = nullptr,
bool TrackLaneMasks = false);
/// addSchedBarrierDeps - Add dependencies from instructions in the current
diff --git a/include/llvm/CodeGen/ScheduleDAGMutation.h b/include/llvm/CodeGen/ScheduleDAGMutation.h
new file mode 100644
index 000000000000..02fe2294815c
--- /dev/null
+++ b/include/llvm/CodeGen/ScheduleDAGMutation.h
@@ -0,0 +1,31 @@
+//==- ScheduleDAGMutation.h - MachineInstr Scheduling ------------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the ScheduleDAGMutation class, which represents
+// a target-specific mutation of the dependency graph for scheduling.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_SCHEDULEDAGMUTATION_H
+#define LLVM_CODEGEN_SCHEDULEDAGMUTATION_H
+
+namespace llvm {
+ class ScheduleDAGInstrs;
+
+ /// Mutate the DAG as a postpass after normal DAG building.
+ class ScheduleDAGMutation {
+ virtual void anchor();
+ public:
+ virtual ~ScheduleDAGMutation() {}
+
+ virtual void apply(ScheduleDAGInstrs *DAG) = 0;
+ };
+}
+
+#endif
diff --git a/include/llvm/CodeGen/ScheduleHazardRecognizer.h b/include/llvm/CodeGen/ScheduleHazardRecognizer.h
index 8a40e7212ff6..214be2794ba3 100644
--- a/include/llvm/CodeGen/ScheduleHazardRecognizer.h
+++ b/include/llvm/CodeGen/ScheduleHazardRecognizer.h
@@ -17,6 +17,7 @@
namespace llvm {
+class MachineInstr;
class SUnit;
/// HazardRecognizer - This determines whether or not an instruction can be
@@ -70,6 +71,10 @@ public:
/// emitted, to advance the hazard state.
virtual void EmitInstruction(SUnit *) {}
+ /// This overload will be used when the hazard recognizer is being used
+ /// by a non-scheduling pass, which does not use SUnits.
+ virtual void EmitInstruction(MachineInstr *) {}
+
/// PreEmitNoops - This callback is invoked prior to emitting an instruction.
/// It should return the number of noops to emit prior to the provided
/// instruction.
@@ -79,6 +84,12 @@ public:
return 0;
}
+ /// This overload will be used when the hazard recognizer is being used
+ /// by a non-scheduling pass, which does not use SUnits.
+ virtual unsigned PreEmitNoops(MachineInstr *) {
+ return 0;
+ }
+
/// ShouldPreferAnother - This callback may be invoked if getHazardType
/// returns NoHazard. If, even though there is no hazard, it would be better to
/// schedule another available instruction, this callback should return true.
diff --git a/include/llvm/CodeGen/ScoreboardHazardRecognizer.h b/include/llvm/CodeGen/ScoreboardHazardRecognizer.h
index ab14c2de32b0..e0c30fe4d82a 100644
--- a/include/llvm/CodeGen/ScoreboardHazardRecognizer.h
+++ b/include/llvm/CodeGen/ScoreboardHazardRecognizer.h
@@ -83,11 +83,9 @@ class ScoreboardHazardRecognizer : public ScheduleHazardRecognizer {
void dump() const;
};
-#ifndef NDEBUG
// Support for tracing ScoreboardHazardRecognizer as a component within
- // another module. Follows the current thread-unsafe model of tracing.
- static const char *DebugType;
-#endif
+ // another module.
+ const char *DebugType;
// Itinerary data for the target.
const InstrItineraryData *ItinData;
diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h
index a21e9ae881a7..29cce873c2f3 100644
--- a/include/llvm/CodeGen/SelectionDAG.h
+++ b/include/llvm/CodeGen/SelectionDAG.h
@@ -23,6 +23,7 @@
#include "llvm/CodeGen/DAGCombine.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
+#include "llvm/Support/ArrayRecycler.h"
#include "llvm/Support/RecyclingAllocator.h"
#include "llvm/Target/TargetMachine.h"
#include <cassert>
@@ -37,7 +38,7 @@ class MachineFunction;
class MDNode;
class SDDbgValue;
class TargetLowering;
-class TargetSelectionDAGInfo;
+class SelectionDAGTargetInfo;
class SDVTListNode : public FoldingSetNode {
friend struct FoldingSetTrait<SDVTListNode>;
@@ -178,7 +179,7 @@ void checkForCycles(const SelectionDAG *DAG, bool force = false);
///
class SelectionDAG {
const TargetMachine &TM;
- const TargetSelectionDAGInfo *TSI;
+ const SelectionDAGTargetInfo *TSI;
const TargetLowering *TLI;
MachineFunction *MF;
LLVMContext *Context;
@@ -208,6 +209,7 @@ class SelectionDAG {
/// Pool allocation for machine-opcode SDNode operands.
BumpPtrAllocator OperandAllocator;
+ ArrayRecycler<SDUse> OperandRecycler;
/// Pool allocation for misc. objects that are created once per SelectionDAG.
BumpPtrAllocator Allocator;
@@ -247,6 +249,14 @@ public:
virtual void NodeUpdated(SDNode *N);
};
+ struct DAGNodeDeletedListener : public DAGUpdateListener {
+ std::function<void(SDNode *, SDNode *)> Callback;
+ DAGNodeDeletedListener(SelectionDAG &DAG,
+ std::function<void(SDNode *, SDNode *)> Callback)
+ : DAGUpdateListener(DAG), Callback(Callback) {}
+ void NodeDeleted(SDNode *N, SDNode *E) override { Callback(N, E); }
+ };
+
/// 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
@@ -268,6 +278,36 @@ private:
DenseSet<SDNode *> &visited,
int level, bool &printed);
+ template <typename SDNodeT, typename... ArgTypes>
+ SDNodeT *newSDNode(ArgTypes &&... Args) {
+ return new (NodeAllocator.template Allocate<SDNodeT>())
+ SDNodeT(std::forward<ArgTypes>(Args)...);
+ }
+
+ void createOperands(SDNode *Node, ArrayRef<SDValue> Vals) {
+ assert(!Node->OperandList && "Node already has operands");
+ SDUse *Ops = OperandRecycler.allocate(
+ ArrayRecycler<SDUse>::Capacity::get(Vals.size()), OperandAllocator);
+
+ for (unsigned I = 0; I != Vals.size(); ++I) {
+ Ops[I].setUser(Node);
+ Ops[I].setInitial(Vals[I]);
+ }
+ Node->NumOperands = Vals.size();
+ Node->OperandList = Ops;
+ checkForCycles(Node);
+ }
+
+ void removeOperands(SDNode *Node) {
+ if (!Node->OperandList)
+ return;
+ OperandRecycler.deallocate(
+ ArrayRecycler<SDUse>::Capacity::get(Node->NumOperands),
+ Node->OperandList);
+ Node->NumOperands = 0;
+ Node->OperandList = nullptr;
+ }
+
void operator=(const SelectionDAG&) = delete;
SelectionDAG(const SelectionDAG&) = delete;
@@ -287,7 +327,7 @@ public:
const TargetMachine &getTarget() const { return TM; }
const TargetSubtargetInfo &getSubtarget() const { return MF->getSubtarget(); }
const TargetLowering &getTargetLoweringInfo() const { return *TLI; }
- const TargetSelectionDAGInfo &getSelectionDAGInfo() const { return *TSI; }
+ const SelectionDAGTargetInfo &getSelectionDAGInfo() const { return *TSI; }
LLVMContext *getContext() const {return Context; }
/// Pop up a GraphViz/gv window with the DAG rendered using 'dot'.
@@ -427,45 +467,64 @@ public:
//===--------------------------------------------------------------------===//
// Node creation methods.
//
- SDValue getConstant(uint64_t Val, SDLoc DL, EVT VT, bool isTarget = false,
- bool isOpaque = false);
- SDValue getConstant(const APInt &Val, SDLoc DL, EVT VT, bool isTarget = false,
- bool isOpaque = false);
- SDValue getConstant(const ConstantInt &Val, SDLoc DL, EVT VT,
+
+ /// \brief Create a ConstantSDNode wrapping a constant value.
+ /// If VT is a vector type, the constant is splatted into a BUILD_VECTOR.
+ ///
+ /// If only legal types can be produced, this does the necessary
+ /// transformations (e.g., if the vector element type is illegal).
+ /// @{
+ SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT,
+ bool isTarget = false, bool isOpaque = false);
+ SDValue getConstant(const APInt &Val, const SDLoc &DL, EVT VT,
bool isTarget = false, bool isOpaque = false);
- SDValue getIntPtrConstant(uint64_t Val, SDLoc DL, bool isTarget = false);
- SDValue getTargetConstant(uint64_t Val, SDLoc DL, EVT VT,
+ SDValue getConstant(const ConstantInt &Val, const SDLoc &DL, EVT VT,
+ bool isTarget = false, bool isOpaque = false);
+ SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL,
+ bool isTarget = false);
+ SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT,
bool isOpaque = false) {
return getConstant(Val, DL, VT, true, isOpaque);
}
- SDValue getTargetConstant(const APInt &Val, SDLoc DL, EVT VT,
+ SDValue getTargetConstant(const APInt &Val, const SDLoc &DL, EVT VT,
bool isOpaque = false) {
return getConstant(Val, DL, VT, true, isOpaque);
}
- SDValue getTargetConstant(const ConstantInt &Val, SDLoc DL, EVT VT,
+ SDValue getTargetConstant(const ConstantInt &Val, const SDLoc &DL, EVT VT,
bool isOpaque = false) {
return getConstant(Val, DL, VT, true, isOpaque);
}
- // The forms below that take a double should only be used for simple
- // constants that can be exactly represented in VT. No checks are made.
- SDValue getConstantFP(double Val, SDLoc DL, EVT VT, bool isTarget = false);
- SDValue getConstantFP(const APFloat& Val, SDLoc DL, EVT VT,
+ /// @}
+
+ /// \brief Create a ConstantFPSDNode wrapping a constant value.
+ /// If VT is a vector type, the constant is splatted into a BUILD_VECTOR.
+ ///
+ /// If only legal types can be produced, this does the necessary
+ /// transformations (e.g., if the vector element type is illegal).
+ /// The forms that take a double should only be used for simple constants
+ /// that can be exactly represented in VT. No checks are made.
+ /// @{
+ SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT,
bool isTarget = false);
- SDValue getConstantFP(const ConstantFP &CF, SDLoc DL, EVT VT,
+ SDValue getConstantFP(const APFloat &Val, const SDLoc &DL, EVT VT,
bool isTarget = false);
- SDValue getTargetConstantFP(double Val, SDLoc DL, EVT VT) {
+ SDValue getConstantFP(const ConstantFP &CF, const SDLoc &DL, EVT VT,
+ bool isTarget = false);
+ SDValue getTargetConstantFP(double Val, const SDLoc &DL, EVT VT) {
return getConstantFP(Val, DL, VT, true);
}
- SDValue getTargetConstantFP(const APFloat& Val, SDLoc DL, EVT VT) {
+ SDValue getTargetConstantFP(const APFloat &Val, const SDLoc &DL, EVT VT) {
return getConstantFP(Val, DL, VT, true);
}
- SDValue getTargetConstantFP(const ConstantFP &Val, SDLoc DL, EVT VT) {
+ SDValue getTargetConstantFP(const ConstantFP &Val, const SDLoc &DL, EVT VT) {
return getConstantFP(Val, DL, VT, true);
}
- SDValue getGlobalAddress(const GlobalValue *GV, SDLoc DL, EVT VT,
+ /// @}
+
+ SDValue getGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT,
int64_t offset = 0, bool isTargetGA = false,
unsigned char TargetFlags = 0);
- SDValue getTargetGlobalAddress(const GlobalValue *GV, SDLoc DL, EVT VT,
+ SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT,
int64_t offset = 0,
unsigned char TargetFlags = 0) {
return getGlobalAddress(GV, DL, VT, offset, true, TargetFlags);
@@ -502,7 +561,7 @@ public:
SDValue getBasicBlock(MachineBasicBlock *MBB);
SDValue getBasicBlock(MachineBasicBlock *MBB, SDLoc dl);
SDValue getExternalSymbol(const char *Sym, EVT VT);
- SDValue getExternalSymbol(const char *Sym, SDLoc dl, EVT VT);
+ SDValue getExternalSymbol(const char *Sym, const SDLoc &dl, EVT VT);
SDValue getTargetExternalSymbol(const char *Sym, EVT VT,
unsigned char TargetFlags = 0);
SDValue getMCSymbol(MCSymbol *Sym, EVT VT);
@@ -510,7 +569,7 @@ public:
SDValue getValueType(EVT);
SDValue getRegister(unsigned Reg, EVT VT);
SDValue getRegisterMask(const uint32_t *RegMask);
- SDValue getEHLabel(SDLoc dl, SDValue Root, MCSymbol *Label);
+ SDValue getEHLabel(const SDLoc &dl, SDValue Root, MCSymbol *Label);
SDValue getBlockAddress(const BlockAddress *BA, EVT VT,
int64_t Offset = 0, bool isTarget = false,
unsigned char TargetFlags = 0);
@@ -520,7 +579,8 @@ public:
return getBlockAddress(BA, VT, Offset, true, TargetFlags);
}
- SDValue getCopyToReg(SDValue Chain, SDLoc dl, unsigned Reg, SDValue N) {
+ SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, unsigned Reg,
+ SDValue N) {
return getNode(ISD::CopyToReg, dl, MVT::Other, Chain,
getRegister(Reg, N.getValueType()), N);
}
@@ -528,7 +588,7 @@ public:
// This version of the getCopyToReg method takes an extra operand, which
// indicates that there is potentially an incoming glue value (if Glue is not
// null) and that there should be a glue result.
- SDValue getCopyToReg(SDValue Chain, SDLoc dl, unsigned Reg, SDValue N,
+ SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, unsigned Reg, SDValue N,
SDValue Glue) {
SDVTList VTs = getVTList(MVT::Other, MVT::Glue);
SDValue Ops[] = { Chain, getRegister(Reg, N.getValueType()), N, Glue };
@@ -537,15 +597,15 @@ public:
}
// Similar to last getCopyToReg() except parameter Reg is a SDValue
- SDValue getCopyToReg(SDValue Chain, SDLoc dl, SDValue Reg, SDValue N,
- SDValue Glue) {
+ SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, SDValue Reg, SDValue N,
+ SDValue Glue) {
SDVTList VTs = getVTList(MVT::Other, MVT::Glue);
SDValue Ops[] = { Chain, Reg, N, Glue };
return getNode(ISD::CopyToReg, dl, VTs,
makeArrayRef(Ops, Glue.getNode() ? 4 : 3));
}
- SDValue getCopyFromReg(SDValue Chain, SDLoc dl, unsigned Reg, EVT VT) {
+ SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, unsigned Reg, EVT VT) {
SDVTList VTs = getVTList(VT, MVT::Other);
SDValue Ops[] = { Chain, getRegister(Reg, VT) };
return getNode(ISD::CopyFromReg, dl, VTs, Ops);
@@ -554,8 +614,8 @@ public:
// This version of the getCopyFromReg method takes an extra operand, which
// indicates that there is potentially an incoming glue value (if Glue is not
// null) and that there should be a glue result.
- SDValue getCopyFromReg(SDValue Chain, SDLoc dl, unsigned Reg, EVT VT,
- SDValue Glue) {
+ SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, unsigned Reg, EVT VT,
+ SDValue Glue) {
SDVTList VTs = getVTList(VT, MVT::Other, MVT::Glue);
SDValue Ops[] = { Chain, getRegister(Reg, VT), Glue };
return getNode(ISD::CopyFromReg, dl, VTs,
@@ -566,20 +626,46 @@ public:
/// Returns the ConvertRndSat Note: Avoid using this node because it may
/// disappear in the future and most targets don't support it.
- SDValue getConvertRndSat(EVT VT, SDLoc dl, SDValue Val, SDValue DTy,
- SDValue STy,
- SDValue Rnd, SDValue Sat, ISD::CvtCode Code);
+ SDValue getConvertRndSat(EVT VT, const SDLoc &dl, SDValue Val, SDValue DTy,
+ SDValue STy, SDValue Rnd, SDValue Sat,
+ ISD::CvtCode Code);
/// Return an ISD::VECTOR_SHUFFLE node. The number of elements in VT,
/// which must be a vector type, must match the number of mask elements
/// NumElts. An integer mask element equal to -1 is treated as undefined.
- SDValue getVectorShuffle(EVT VT, SDLoc dl, SDValue N1, SDValue N2,
- const int *MaskElts);
- SDValue getVectorShuffle(EVT VT, SDLoc dl, SDValue N1, SDValue N2,
- ArrayRef<int> MaskElts) {
- assert(VT.getVectorNumElements() == MaskElts.size() &&
- "Must have the same number of vector elements as mask elements!");
- return getVectorShuffle(VT, dl, N1, N2, MaskElts.data());
+ SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2,
+ ArrayRef<int> Mask);
+
+ /// Return an ISD::BUILD_VECTOR node. The number of elements in VT,
+ /// which must be a vector type, must match the number of operands in Ops.
+ /// The operands must have the same type as (or, for integers, a type wider
+ /// than) VT's element type.
+ SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef<SDValue> Ops) {
+ // VerifySDNode (via InsertNode) checks BUILD_VECTOR later.
+ return getNode(ISD::BUILD_VECTOR, DL, VT, Ops);
+ }
+
+ /// Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all
+ /// elements. VT must be a vector type. Op's type must be the same as (or,
+ /// for integers, a type wider than) VT's element type.
+ SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op) {
+ // VerifySDNode (via InsertNode) checks BUILD_VECTOR later.
+ if (Op.getOpcode() == ISD::UNDEF) {
+ assert((VT.getVectorElementType() == Op.getValueType() ||
+ (VT.isInteger() &&
+ VT.getVectorElementType().bitsLE(Op.getValueType()))) &&
+ "A splatted value must have a width equal or (for integers) "
+ "greater than the vector element type!");
+ return getNode(ISD::UNDEF, SDLoc(), VT);
+ }
+
+ SmallVector<SDValue, 16> Ops(VT.getVectorNumElements(), Op);
+ return getNode(ISD::BUILD_VECTOR, DL, VT, Ops);
+ }
+
+ /// Return a splat ISD::BUILD_VECTOR node, but with Op's SDLoc.
+ SDValue getSplatBuildVector(EVT VT, SDValue Op) {
+ return getSplatBuildVector(VT, SDLoc(Op), Op);
}
/// \brief Returns an ISD::VECTOR_SHUFFLE node semantically equivalent to
@@ -590,52 +676,52 @@ public:
/// Convert Op, which must be of integer type, to the
/// integer type VT, by either any-extending or truncating it.
- SDValue getAnyExtOrTrunc(SDValue Op, SDLoc DL, EVT VT);
+ SDValue getAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT);
/// Convert Op, which must be of integer type, to the
/// integer type VT, by either sign-extending or truncating it.
- SDValue getSExtOrTrunc(SDValue Op, SDLoc DL, EVT VT);
+ SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT);
/// Convert Op, which must be of integer type, to the
/// integer type VT, by either zero-extending or truncating it.
- SDValue getZExtOrTrunc(SDValue Op, SDLoc DL, EVT VT);
+ SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT);
/// Return the expression required to zero extend the Op
/// value assuming it was the smaller SrcTy value.
- SDValue getZeroExtendInReg(SDValue Op, SDLoc DL, EVT SrcTy);
+ SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT SrcTy);
/// Return an operation which will any-extend the low lanes of the operand
/// into the specified vector type. For example,
/// this can convert a v16i8 into a v4i32 by any-extending the low four
/// lanes of the operand from i8 to i32.
- SDValue getAnyExtendVectorInReg(SDValue Op, SDLoc DL, EVT VT);
+ SDValue getAnyExtendVectorInReg(SDValue Op, const SDLoc &DL, EVT VT);
/// Return an operation which will sign extend the low lanes of the operand
/// into the specified vector type. For example,
/// this can convert a v16i8 into a v4i32 by sign extending the low four
/// lanes of the operand from i8 to i32.
- SDValue getSignExtendVectorInReg(SDValue Op, SDLoc DL, EVT VT);
+ SDValue getSignExtendVectorInReg(SDValue Op, const SDLoc &DL, EVT VT);
/// Return an operation which will zero extend the low lanes of the operand
/// into the specified vector type. For example,
/// this can convert a v16i8 into a v4i32 by zero extending the low four
/// lanes of the operand from i8 to i32.
- SDValue getZeroExtendVectorInReg(SDValue Op, SDLoc DL, EVT VT);
+ SDValue getZeroExtendVectorInReg(SDValue Op, const SDLoc &DL, EVT VT);
/// Convert Op, which must be of integer type, to the integer type VT,
/// by using an extension appropriate for the target's
/// BooleanContent for type OpVT or truncating it.
- SDValue getBoolExtOrTrunc(SDValue Op, SDLoc SL, EVT VT, EVT OpVT);
+ SDValue getBoolExtOrTrunc(SDValue Op, const SDLoc &SL, EVT VT, EVT OpVT);
/// Create a bitwise NOT operation as (XOR Val, -1).
- SDValue getNOT(SDLoc DL, SDValue Val, EVT VT);
+ SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT);
/// \brief Create a logical NOT operation as (XOR Val, BooleanOne).
- SDValue getLogicalNOT(SDLoc DL, SDValue Val, EVT VT);
+ SDValue getLogicalNOT(const SDLoc &DL, SDValue Val, EVT VT);
/// Return a new CALLSEQ_START node, which always must have a glue result
/// (to ensure it's not CSE'd). CALLSEQ_START does not have a useful SDLoc.
- SDValue getCALLSEQ_START(SDValue Chain, SDValue Op, SDLoc DL) {
+ SDValue getCALLSEQ_START(SDValue Chain, SDValue Op, const SDLoc &DL) {
SDVTList VTs = getVTList(MVT::Other, MVT::Glue);
SDValue Ops[] = { Chain, Op };
return getNode(ISD::CALLSEQ_START, DL, VTs, Ops);
@@ -645,7 +731,7 @@ public:
/// glue result (to ensure it's not CSE'd).
/// CALLSEQ_END does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2,
- SDValue InGlue, SDLoc DL) {
+ SDValue InGlue, const SDLoc &DL) {
SDVTList NodeTys = getVTList(MVT::Other, MVT::Glue);
SmallVector<SDValue, 4> Ops;
Ops.push_back(Chain);
@@ -668,38 +754,38 @@ public:
/// Gets or creates the specified node.
///
- SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT,
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
ArrayRef<SDUse> Ops);
- SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT,
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
ArrayRef<SDValue> Ops, const SDNodeFlags *Flags = nullptr);
- SDValue getNode(unsigned Opcode, SDLoc DL, ArrayRef<EVT> ResultTys,
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, ArrayRef<EVT> ResultTys,
ArrayRef<SDValue> Ops);
- SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs,
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTs,
ArrayRef<SDValue> Ops);
// Specialize based on number of operands.
- SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT);
- SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N);
- SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2,
- const SDNodeFlags *Flags = nullptr);
- SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2,
- SDValue N3);
- SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2,
- SDValue N3, SDValue N4);
- SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2,
- SDValue N3, SDValue N4, SDValue N5);
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT);
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N);
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N1,
+ SDValue N2, const SDNodeFlags *Flags = nullptr);
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N1,
+ SDValue N2, SDValue N3);
+ 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,
+ SDValue N2, SDValue N3, SDValue N4, SDValue N5);
// Specialize again based on number of operands for nodes with a VTList
// rather than a single VT.
- SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs);
- SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N);
- SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N1,
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTs);
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTs, SDValue N);
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTs, SDValue N1,
SDValue N2);
- SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N1,
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTs, SDValue N1,
SDValue N2, SDValue N3);
- SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N1,
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTs, SDValue N1,
SDValue N2, SDValue N3, SDValue N4);
- SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N1,
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTs, SDValue N1,
SDValue N2, SDValue N3, SDValue N4, SDValue N5);
/// Compute a TokenFactor to force all the incoming stack arguments to be
@@ -707,24 +793,24 @@ public:
/// stack arguments from being clobbered.
SDValue getStackArgumentTokenFactor(SDValue Chain);
- SDValue getMemcpy(SDValue Chain, SDLoc dl, SDValue Dst, SDValue Src,
+ SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src,
SDValue Size, unsigned Align, bool isVol, bool AlwaysInline,
bool isTailCall, MachinePointerInfo DstPtrInfo,
MachinePointerInfo SrcPtrInfo);
- SDValue getMemmove(SDValue Chain, SDLoc dl, SDValue Dst, SDValue Src,
+ SDValue getMemmove(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src,
SDValue Size, unsigned Align, bool isVol, bool isTailCall,
MachinePointerInfo DstPtrInfo,
MachinePointerInfo SrcPtrInfo);
- SDValue getMemset(SDValue Chain, SDLoc dl, SDValue Dst, SDValue Src,
+ SDValue getMemset(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src,
SDValue Size, unsigned Align, bool isVol, bool isTailCall,
MachinePointerInfo DstPtrInfo);
/// Helper function to make it easier to build SetCC's if you just
/// have an ISD::CondCode instead of an SDValue.
///
- SDValue getSetCC(SDLoc DL, EVT VT, SDValue LHS, SDValue RHS,
+ SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS,
ISD::CondCode Cond) {
assert(LHS.getValueType().isVector() == RHS.getValueType().isVector() &&
"Cannot compare scalars to vectors");
@@ -737,8 +823,8 @@ public:
/// Helper function to make it easier to build Select's if you just
/// have operands and don't want to check for vector.
- SDValue getSelect(SDLoc DL, EVT VT, SDValue Cond,
- SDValue LHS, SDValue RHS) {
+ SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS,
+ SDValue RHS) {
assert(LHS.getValueType() == RHS.getValueType() &&
"Cannot use select on differing types");
assert(VT.isVector() == LHS.getValueType().isVector() &&
@@ -750,139 +836,145 @@ public:
/// Helper function to make it easier to build SelectCC's if you
/// just have an ISD::CondCode instead of an SDValue.
///
- SDValue getSelectCC(SDLoc DL, SDValue LHS, SDValue RHS,
- SDValue True, SDValue False, ISD::CondCode Cond) {
+ SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True,
+ SDValue False, ISD::CondCode Cond) {
return getNode(ISD::SELECT_CC, DL, True.getValueType(),
LHS, RHS, True, False, getCondCode(Cond));
}
/// VAArg produces a result and token chain, and takes a pointer
/// and a source value as input.
- SDValue getVAArg(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr,
+ SDValue getVAArg(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr,
SDValue SV, unsigned Align);
/// Gets a node for an atomic cmpxchg op. There are two
/// valid Opcodes. ISD::ATOMIC_CMO_SWAP produces the value loaded and a
/// chain result. ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS produces the value loaded,
/// a success flag (initially i1), and a chain.
- SDValue getAtomicCmpSwap(unsigned Opcode, SDLoc dl, EVT MemVT, SDVTList VTs,
- SDValue Chain, SDValue Ptr, SDValue Cmp, SDValue Swp,
- MachinePointerInfo PtrInfo, unsigned Alignment,
- AtomicOrdering SuccessOrdering,
+ SDValue getAtomicCmpSwap(unsigned Opcode, const SDLoc &dl, EVT MemVT,
+ SDVTList VTs, SDValue Chain, SDValue Ptr,
+ SDValue Cmp, SDValue Swp, MachinePointerInfo PtrInfo,
+ unsigned Alignment, AtomicOrdering SuccessOrdering,
AtomicOrdering FailureOrdering,
SynchronizationScope SynchScope);
- SDValue getAtomicCmpSwap(unsigned Opcode, SDLoc dl, EVT MemVT, SDVTList VTs,
- SDValue Chain, SDValue Ptr, SDValue Cmp, SDValue Swp,
- MachineMemOperand *MMO,
+ SDValue getAtomicCmpSwap(unsigned Opcode, const SDLoc &dl, EVT MemVT,
+ SDVTList VTs, SDValue Chain, SDValue Ptr,
+ SDValue Cmp, SDValue Swp, MachineMemOperand *MMO,
AtomicOrdering SuccessOrdering,
AtomicOrdering FailureOrdering,
SynchronizationScope SynchScope);
/// Gets a node for an atomic op, produces result (if relevant)
/// and chain and takes 2 operands.
- SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDValue Chain,
+ SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT, SDValue Chain,
SDValue Ptr, SDValue Val, const Value *PtrVal,
unsigned Alignment, AtomicOrdering Ordering,
SynchronizationScope SynchScope);
- SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDValue Chain,
+ SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT, SDValue Chain,
SDValue Ptr, SDValue Val, MachineMemOperand *MMO,
- AtomicOrdering Ordering,
- SynchronizationScope SynchScope);
+ AtomicOrdering Ordering, SynchronizationScope SynchScope);
/// Gets a node for an atomic op, produces result and chain and
/// takes 1 operand.
- SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, EVT VT,
+ SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT, EVT VT,
SDValue Chain, SDValue Ptr, MachineMemOperand *MMO,
- AtomicOrdering Ordering,
- SynchronizationScope SynchScope);
+ AtomicOrdering Ordering, SynchronizationScope SynchScope);
/// Gets a node for an atomic op, produces result and chain and takes N
/// operands.
- SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDVTList VTList,
- ArrayRef<SDValue> Ops, MachineMemOperand *MMO,
- AtomicOrdering SuccessOrdering,
+ SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT,
+ SDVTList VTList, ArrayRef<SDValue> Ops,
+ MachineMemOperand *MMO, AtomicOrdering SuccessOrdering,
AtomicOrdering FailureOrdering,
SynchronizationScope SynchScope);
- SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDVTList VTList,
- ArrayRef<SDValue> Ops, MachineMemOperand *MMO,
- AtomicOrdering Ordering, SynchronizationScope SynchScope);
+ SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT,
+ SDVTList VTList, ArrayRef<SDValue> Ops,
+ MachineMemOperand *MMO, AtomicOrdering Ordering,
+ SynchronizationScope SynchScope);
/// Creates a MemIntrinsicNode that may produce a
/// result and takes a list of operands. Opcode may be INTRINSIC_VOID,
/// INTRINSIC_W_CHAIN, or a target-specific opcode with a value not
/// less than FIRST_TARGET_MEMORY_OPCODE.
- SDValue getMemIntrinsicNode(unsigned Opcode, SDLoc dl, SDVTList VTList,
- ArrayRef<SDValue> Ops,
- EVT MemVT, MachinePointerInfo PtrInfo,
- unsigned Align = 0, bool Vol = false,
- bool ReadMem = true, bool WriteMem = true,
- unsigned Size = 0);
+ SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList,
+ ArrayRef<SDValue> Ops, EVT MemVT,
+ MachinePointerInfo PtrInfo, unsigned Align = 0,
+ bool Vol = false, bool ReadMem = true,
+ bool WriteMem = true, unsigned Size = 0);
- SDValue getMemIntrinsicNode(unsigned Opcode, SDLoc dl, SDVTList VTList,
- ArrayRef<SDValue> Ops,
- EVT MemVT, MachineMemOperand *MMO);
+ SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList,
+ ArrayRef<SDValue> Ops, EVT MemVT,
+ MachineMemOperand *MMO);
/// Create a MERGE_VALUES node from the given operands.
- SDValue getMergeValues(ArrayRef<SDValue> Ops, SDLoc dl);
+ SDValue getMergeValues(ArrayRef<SDValue> Ops, const SDLoc &dl);
/// Loads are not normal binary operators: their result type is not
/// determined by their operands, and they produce a value AND a token chain.
///
- SDValue getLoad(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr,
- MachinePointerInfo PtrInfo, bool isVolatile,
- bool isNonTemporal, bool isInvariant, unsigned Alignment,
+ /// 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, unsigned Alignment = 0,
+ MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone,
const AAMDNodes &AAInfo = AAMDNodes(),
const MDNode *Ranges = nullptr);
- SDValue getLoad(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr,
+ SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr,
MachineMemOperand *MMO);
- SDValue getExtLoad(ISD::LoadExtType ExtType, SDLoc dl, EVT VT,
- SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo,
- EVT MemVT, bool isVolatile,
- bool isNonTemporal, bool isInvariant, unsigned Alignment,
- const AAMDNodes &AAInfo = AAMDNodes());
- SDValue getExtLoad(ISD::LoadExtType ExtType, SDLoc dl, EVT VT,
+ SDValue
+ getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain,
+ SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT,
+ unsigned Alignment = 0,
+ MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone,
+ const AAMDNodes &AAInfo = AAMDNodes());
+ SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT,
SDValue Chain, SDValue Ptr, EVT MemVT,
MachineMemOperand *MMO);
- SDValue getIndexedLoad(SDValue OrigLoad, SDLoc dl, SDValue Base,
+ SDValue getIndexedLoad(SDValue OrigLoad, const SDLoc &dl, SDValue Base,
SDValue Offset, ISD::MemIndexedMode AM);
- SDValue getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType,
- EVT VT, SDLoc dl,
- SDValue Chain, SDValue Ptr, SDValue Offset,
- MachinePointerInfo PtrInfo, EVT MemVT,
- bool isVolatile, bool isNonTemporal, bool isInvariant,
- unsigned Alignment, const AAMDNodes &AAInfo = AAMDNodes(),
+ 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,
+ MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone,
+ const AAMDNodes &AAInfo = AAMDNodes(),
const MDNode *Ranges = nullptr);
- SDValue getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType,
- EVT VT, SDLoc dl,
- SDValue Chain, SDValue Ptr, SDValue Offset,
+ SDValue getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT,
+ const SDLoc &dl, SDValue Chain, SDValue Ptr, SDValue Offset,
EVT MemVT, MachineMemOperand *MMO);
/// Helper function to build ISD::STORE nodes.
- SDValue getStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr,
- MachinePointerInfo PtrInfo, bool isVolatile,
- bool isNonTemporal, unsigned Alignment,
- const AAMDNodes &AAInfo = AAMDNodes());
- SDValue getStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr,
+ ///
+ /// This function will set the MOStore flag on MMOFlags, but you can set it if
+ /// you want. The MOLoad and MOInvariant flags must not be set.
+ SDValue
+ getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr,
+ MachinePointerInfo PtrInfo, unsigned Alignment = 0,
+ MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone,
+ const AAMDNodes &AAInfo = AAMDNodes());
+ SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr,
MachineMemOperand *MMO);
- SDValue getTruncStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr,
- MachinePointerInfo PtrInfo, EVT TVT,
- bool isNonTemporal, bool isVolatile,
- unsigned Alignment,
- const AAMDNodes &AAInfo = AAMDNodes());
- SDValue getTruncStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr,
- EVT TVT, MachineMemOperand *MMO);
- SDValue getIndexedStore(SDValue OrigStoe, SDLoc dl, SDValue Base,
- SDValue Offset, ISD::MemIndexedMode AM);
-
- SDValue getMaskedLoad(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr,
+ SDValue
+ getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr,
+ MachinePointerInfo PtrInfo, EVT TVT, unsigned Alignment = 0,
+ MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone,
+ const AAMDNodes &AAInfo = AAMDNodes());
+ SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val,
+ SDValue Ptr, EVT TVT, MachineMemOperand *MMO);
+ SDValue getIndexedStore(SDValue OrigStoe, const SDLoc &dl, SDValue Base,
+ SDValue Offset, ISD::MemIndexedMode AM);
+
+ /// Returns sum of the base pointer and offset.
+ SDValue getMemBasePlusOffset(SDValue Base, unsigned Offset, const SDLoc &DL);
+
+ SDValue getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr,
SDValue Mask, SDValue Src0, EVT MemVT,
MachineMemOperand *MMO, ISD::LoadExtType);
- SDValue getMaskedStore(SDValue Chain, SDLoc dl, SDValue Val,
+ SDValue getMaskedStore(SDValue Chain, const SDLoc &dl, SDValue Val,
SDValue Ptr, SDValue Mask, EVT MemVT,
MachineMemOperand *MMO, bool IsTrunc);
- SDValue getMaskedGather(SDVTList VTs, EVT VT, SDLoc dl,
+ SDValue getMaskedGather(SDVTList VTs, EVT VT, const SDLoc &dl,
ArrayRef<SDValue> Ops, MachineMemOperand *MMO);
- SDValue getMaskedScatter(SDVTList VTs, EVT VT, SDLoc dl,
+ SDValue getMaskedScatter(SDVTList VTs, EVT VT, const SDLoc &dl,
ArrayRef<SDValue> Ops, MachineMemOperand *MMO);
/// Construct a node to track a Value* through the backend.
SDValue getSrcValue(const Value *v);
@@ -895,8 +987,8 @@ public:
SDValue getBitcast(EVT VT, SDValue V);
/// Return an AddrSpaceCastSDNode.
- SDValue getAddrSpaceCast(SDLoc dl, EVT VT, SDValue Ptr,
- unsigned SrcAS, unsigned DestAS);
+ SDValue getAddrSpaceCast(const SDLoc &dl, EVT VT, SDValue Ptr, unsigned SrcAS,
+ unsigned DestAS);
/// Return the specified value casted to
/// the target's desired shift amount type.
@@ -965,45 +1057,46 @@ public:
/// Note that getMachineNode returns the resultant node. If there is already
/// a node of the specified opcode and operands, it returns that node instead
/// of the current one.
- MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT);
- MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT,
- SDValue Op1);
- MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT,
- SDValue Op1, SDValue Op2);
- MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT,
- SDValue Op1, SDValue Op2, SDValue Op3);
- MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT,
- ArrayRef<SDValue> Ops);
- MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2);
- MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2,
+ MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT);
+ MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT,
SDValue Op1);
- MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2,
+ MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT,
SDValue Op1, SDValue Op2);
- MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2,
+ MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT,
SDValue Op1, SDValue Op2, SDValue Op3);
- MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2,
+ MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT,
ArrayRef<SDValue> Ops);
- MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2,
- EVT VT3, SDValue Op1, SDValue Op2);
- MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2,
- EVT VT3, SDValue Op1, SDValue Op2,
+ MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT1,
+ EVT VT2);
+ MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT1,
+ EVT VT2, SDValue Op1);
+ MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT1,
+ EVT VT2, SDValue Op1, SDValue Op2);
+ MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT1,
+ EVT VT2, SDValue Op1, SDValue Op2, SDValue Op3);
+ MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT1,
+ EVT VT2, ArrayRef<SDValue> Ops);
+ MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT1,
+ EVT VT2, EVT VT3, SDValue Op1, SDValue Op2);
+ MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT1,
+ EVT VT2, EVT VT3, SDValue Op1, SDValue Op2,
SDValue Op3);
- MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2,
- EVT VT3, ArrayRef<SDValue> Ops);
- MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2,
- EVT VT3, EVT VT4, ArrayRef<SDValue> Ops);
- MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl,
- ArrayRef<EVT> ResultTys,
+ MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT1,
+ EVT VT2, EVT VT3, ArrayRef<SDValue> Ops);
+ MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT1,
+ EVT VT2, EVT VT3, EVT VT4,
ArrayRef<SDValue> Ops);
- MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, SDVTList VTs,
+ MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl,
+ ArrayRef<EVT> ResultTys, ArrayRef<SDValue> Ops);
+ MachineSDNode *getMachineNode(unsigned Opcode, const SDLoc &dl, SDVTList VTs,
ArrayRef<SDValue> Ops);
/// A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
- SDValue getTargetExtractSubreg(int SRIdx, SDLoc DL, EVT VT,
+ SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT,
SDValue Operand);
/// A convenience function for creating TargetInstrInfo::INSERT_SUBREG nodes.
- SDValue getTargetInsertSubreg(int SRIdx, SDLoc DL, EVT VT,
+ SDValue getTargetInsertSubreg(int SRIdx, const SDLoc &DL, EVT VT,
SDValue Operand, SDValue Subreg);
/// Get the specified node if it's already available, or else return NULL.
@@ -1012,16 +1105,17 @@ public:
/// Creates a SDDbgValue node.
SDDbgValue *getDbgValue(MDNode *Var, MDNode *Expr, SDNode *N, unsigned R,
- bool IsIndirect, uint64_t Off, DebugLoc DL,
+ bool IsIndirect, uint64_t Off, const DebugLoc &DL,
unsigned O);
/// Constant
SDDbgValue *getConstantDbgValue(MDNode *Var, MDNode *Expr, const Value *C,
- uint64_t Off, DebugLoc DL, unsigned O);
+ uint64_t Off, const DebugLoc &DL, unsigned O);
/// FrameIndex
SDDbgValue *getFrameIndexDbgValue(MDNode *Var, MDNode *Expr, unsigned FI,
- uint64_t Off, DebugLoc DL, unsigned O);
+ uint64_t Off, const DebugLoc &DL,
+ unsigned O);
/// Remove the specified node from the system. If any of its
/// operands then becomes dead, remove them as well. Inform UpdateListener
@@ -1129,9 +1223,11 @@ public:
return DbgInfo->getSDDbgValues(SD);
}
- /// Transfer SDDbgValues.
+private:
+ /// Transfer SDDbgValues. Called via ReplaceAllUses{OfValue}?With
void TransferDbgValues(SDValue From, SDValue To);
+public:
/// Return true if there are any SDDbgValue nodes associated
/// with this SelectionDAG.
bool hasDebugValues() const { return !DbgInfo->empty(); }
@@ -1147,29 +1243,32 @@ public:
void dump() const;
- /// Create a stack temporary, suitable for holding the
- /// specified value type. If minAlign is specified, the slot size will have
- /// at least that alignment.
+ /// Create a stack temporary, suitable for holding the specified value type.
+ /// If minAlign is specified, the slot size will have at least that alignment.
SDValue CreateStackTemporary(EVT VT, unsigned minAlign = 1);
- /// Create a stack temporary suitable for holding
- /// either of the specified value types.
+ /// Create a stack temporary suitable for holding either of the specified
+ /// value types.
SDValue CreateStackTemporary(EVT VT1, EVT VT2);
- SDValue FoldConstantArithmetic(unsigned Opcode, SDLoc DL, EVT VT,
+ SDValue FoldSymbolOffset(unsigned Opcode, EVT VT,
+ const GlobalAddressSDNode *GA,
+ const SDNode *N2);
+
+ SDValue FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT,
SDNode *Cst1, SDNode *Cst2);
- SDValue FoldConstantArithmetic(unsigned Opcode, SDLoc DL, EVT VT,
+ SDValue FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT,
const ConstantSDNode *Cst1,
const ConstantSDNode *Cst2);
- SDValue FoldConstantVectorArithmetic(unsigned Opcode, SDLoc DL,
- EVT VT, ArrayRef<SDValue> Ops,
+ SDValue FoldConstantVectorArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT,
+ ArrayRef<SDValue> Ops,
const SDNodeFlags *Flags = nullptr);
/// Constant fold a setcc to true or false.
- SDValue FoldSetCC(EVT VT, SDValue N1,
- SDValue N2, ISD::CondCode Cond, SDLoc dl);
+ SDValue FoldSetCC(EVT VT, SDValue N1, SDValue N2, ISD::CondCode Cond,
+ const SDLoc &dl);
/// Return true if the sign bit of Op is known to be zero.
/// We use this predicate to simplify operations downstream.
@@ -1188,27 +1287,32 @@ public:
void computeKnownBits(SDValue Op, APInt &KnownZero, APInt &KnownOne,
unsigned Depth = 0) const;
- /// Return the number of times the sign bit of the
- /// register is replicated into the other bits. We know that at least 1 bit
- /// is always equal to the sign bit (itself), but other cases can give us
- /// information. For example, immediately after an "SRA X, 2", we know that
- /// the top 3 bits are all equal to each other, so we return 3. Targets can
- /// implement the ComputeNumSignBitsForTarget method in the TargetLowering
- /// class to allow target nodes to be understood.
+ /// 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(SDValue Val) const;
+
+ /// Return the number of times the sign bit of the register is replicated into
+ /// the other bits. We know that at least 1 bit is always equal to the sign
+ /// bit (itself), but other cases can give us information. For example,
+ /// immediately after an "SRA X, 2", we know that the top 3 bits are all equal
+ /// to each other, so we return 3. Targets can implement the
+ /// ComputeNumSignBitsForTarget method in the TargetLowering class to allow
+ /// target nodes to be understood.
unsigned ComputeNumSignBits(SDValue Op, unsigned Depth = 0) const;
- /// Return true if the specified operand is an
- /// ISD::ADD with a ConstantSDNode on the right-hand side, or if it is an
- /// ISD::OR with a ConstantSDNode that is guaranteed to have the same
- /// semantics as an ADD. This handles the equivalence:
+ /// Return true if the specified operand is an ISD::ADD with a ConstantSDNode
+ /// on the right-hand side, or if it is an ISD::OR with a ConstantSDNode that
+ /// is guaranteed to have the same semantics as an ADD. This handles the
+ /// equivalence:
/// X|Cst == X+Cst iff X&Cst = 0.
bool isBaseWithConstantOffset(SDValue Op) const;
/// Test whether the given SDValue is known to never be NaN.
bool isKnownNeverNaN(SDValue Op) const;
- /// Test whether the given SDValue is known to never be
- /// positive or negative Zero.
+ /// Test whether the given SDValue is known to never be positive or negative
+ /// zero.
bool isKnownNeverZero(SDValue Op) const;
/// Test whether two SDValues are known to compare equal. This
@@ -1228,10 +1332,12 @@ public:
/// vector op and fill the end of the resulting vector with UNDEFS.
SDValue UnrollVectorOp(SDNode *N, unsigned ResNE = 0);
- /// Return true if LD is loading 'Bytes' bytes from a location that is 'Dist'
- /// units away from the location that the 'Base' load is loading from.
- bool isConsecutiveLoad(LoadSDNode *LD, LoadSDNode *Base,
- unsigned Bytes, int Dist) const;
+ /// Return true if loads are next to each other and can be
+ /// merged. Check that both are nonvolatile and if LD is loading
+ /// 'Bytes' bytes from a location that is 'Dist' units away from the
+ /// location that the 'Base' load is loading from.
+ bool areNonVolatileConsecutiveLoads(LoadSDNode *LD, LoadSDNode *Base,
+ unsigned Bytes, int Dist) const;
/// Infer alignment of a load / store address. Return 0 if
/// it cannot be inferred.
@@ -1265,8 +1371,12 @@ public:
void ExtractVectorElements(SDValue Op, SmallVectorImpl<SDValue> &Args,
unsigned Start = 0, unsigned Count = 0);
+ /// Compute the default alignment value for the given type.
unsigned getEVTAlignment(EVT MemoryVT) const;
+ /// Test whether the given value is a constant int or similar node.
+ SDNode *isConstantIntBuildVectorOrConstantInt(SDValue N);
+
private:
void InsertNode(SDNode *N);
bool RemoveNodeFromCSEMaps(SDNode *N);
@@ -1276,16 +1386,16 @@ private:
void *&InsertPos);
SDNode *FindModifiedNodeSlot(SDNode *N, ArrayRef<SDValue> Ops,
void *&InsertPos);
- SDNode *UpdadeSDLocOnMergedSDNode(SDNode *N, SDLoc loc);
+ SDNode *UpdadeSDLocOnMergedSDNode(SDNode *N, const SDLoc &loc);
void DeleteNodeNotInCSEMaps(SDNode *N);
void DeallocateNode(SDNode *N);
void allnodes_clear();
- BinarySDNode *GetBinarySDNode(unsigned Opcode, SDLoc DL, SDVTList VTs,
- SDValue N1, SDValue N2,
- const SDNodeFlags *Flags = nullptr);
+ SDNode *GetBinarySDNode(unsigned Opcode, const SDLoc &DL, SDVTList VTs,
+ SDValue N1, SDValue N2,
+ const SDNodeFlags *Flags = nullptr);
/// Look up the node specified by ID in CSEMap. If it exists, return it. If
/// not, return the insertion token that will make insertion faster. This
@@ -1296,7 +1406,7 @@ private:
/// Look up the node specified by ID in CSEMap. If it exists, return it. If
/// not, return the insertion token that will make insertion faster. Performs
/// additional processing for constant nodes.
- SDNode *FindNodeOrInsertPos(const FoldingSetNodeID &ID, DebugLoc DL,
+ SDNode *FindNodeOrInsertPos(const FoldingSetNodeID &ID, const SDLoc &DL,
void *&InsertPos);
/// List of non-single value types.
diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h
index a011e4c338c4..7f4549d3058f 100644
--- a/include/llvm/CodeGen/SelectionDAGISel.h
+++ b/include/llvm/CodeGen/SelectionDAGISel.h
@@ -76,8 +76,8 @@ public:
/// right after selection.
virtual void PostprocessISelDAG() {}
- /// Select - Main hook targets implement to select a node.
- virtual SDNode *Select(SDNode *N) = 0;
+ /// Main hook for targets to transform nodes into machine nodes.
+ virtual void Select(SDNode *N) = 0;
/// SelectInlineAsmMemoryOperand - Select the specified address as a target
/// addressing mode, according to the specified constraint. If this does
@@ -111,6 +111,8 @@ public:
OPC_RecordMemRef,
OPC_CaptureGlueInput,
OPC_MoveChild,
+ OPC_MoveChild0, OPC_MoveChild1, OPC_MoveChild2, OPC_MoveChild3,
+ OPC_MoveChild4, OPC_MoveChild5, OPC_MoveChild6, OPC_MoveChild7,
OPC_MoveParent,
OPC_CheckSame,
OPC_CheckChild0Same, OPC_CheckChild1Same,
@@ -140,11 +142,15 @@ public:
OPC_EmitMergeInputChains,
OPC_EmitMergeInputChains1_0,
OPC_EmitMergeInputChains1_1,
+ OPC_EmitMergeInputChains1_2,
OPC_EmitCopyToReg,
OPC_EmitNodeXForm,
OPC_EmitNode,
+ // Space-optimized forms that implicitly encode number of result VTs.
+ OPC_EmitNode0, OPC_EmitNode1, OPC_EmitNode2,
OPC_MorphNodeTo,
- OPC_MarkGlueResults,
+ // Space-optimized forms that implicitly encode number of result VTs.
+ OPC_MorphNodeTo0, OPC_MorphNodeTo1, OPC_MorphNodeTo2,
OPC_CompleteMatch
};
@@ -196,11 +202,16 @@ protected:
CurDAG->ReplaceAllUsesWith(F, T);
}
+ /// Replace all uses of \c F with \c T, then remove \c F from the DAG.
+ void ReplaceNode(SDNode *F, SDNode *T) {
+ CurDAG->ReplaceAllUsesWith(F, T);
+ CurDAG->RemoveDeadNode(F);
+ }
/// SelectInlineAsmMemoryOperands - Calls to this are automatically generated
/// by tblgen. Others should not call it.
- void SelectInlineAsmMemoryOperands(std::vector<SDValue> &Ops, SDLoc DL);
-
+ void SelectInlineAsmMemoryOperands(std::vector<SDValue> &Ops,
+ const SDLoc &DL);
public:
// Calls to these predicates are generated by tblgen.
@@ -236,9 +247,8 @@ public:
llvm_unreachable("Tblgen should generate this!");
}
- SDNode *SelectCodeCommon(SDNode *NodeToMatch,
- const unsigned char *MatcherTable,
- unsigned TableSize);
+ void SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable,
+ unsigned TableSize);
/// \brief Return true if complex patterns for this target can mutate the
/// DAG.
@@ -249,10 +259,10 @@ public:
private:
// Calls to these functions are generated by tblgen.
- SDNode *Select_INLINEASM(SDNode *N);
- SDNode *Select_READ_REGISTER(SDNode *N);
- SDNode *Select_WRITE_REGISTER(SDNode *N);
- SDNode *Select_UNDEF(SDNode *N);
+ void Select_INLINEASM(SDNode *N);
+ void Select_READ_REGISTER(SDNode *N);
+ void Select_WRITE_REGISTER(SDNode *N);
+ void Select_UNDEF(SDNode *N);
void CannotYetSelect(SDNode *N);
private:
@@ -294,11 +304,9 @@ private:
/// state machines that start with a OPC_SwitchOpcode node.
std::vector<unsigned> OpcodeOffset;
- void UpdateChainsAndGlue(SDNode *NodeToMatch, SDValue InputChain,
- const SmallVectorImpl<SDNode*> &ChainNodesMatched,
- SDValue InputGlue, const SmallVectorImpl<SDNode*> &F,
- bool isMorphNodeTo);
-
+ void UpdateChains(SDNode *NodeToMatch, SDValue InputChain,
+ const SmallVectorImpl<SDNode *> &ChainNodesMatched,
+ bool isMorphNodeTo);
};
}
diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h
index 536fc656e8e2..cfcc4117f93b 100644
--- a/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -44,7 +44,7 @@ class GlobalValue;
class MachineBasicBlock;
class MachineConstantPoolValue;
class SDNode;
-class BinaryWithFlagsSDNode;
+class HandleSDNode;
class Value;
class MCSymbol;
template <typename T> struct DenseMapInfo;
@@ -66,24 +66,28 @@ struct SDVTList {
namespace ISD {
/// Node predicates
- /// Return true if the specified node is a
- /// BUILD_VECTOR where all of the elements are ~0 or undef.
+ /// 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.
+ /// Return true if the specified node is a BUILD_VECTOR where all of the
+ /// elements are 0 or undef.
bool isBuildVectorAllZeros(const SDNode *N);
- /// \brief Return true if the specified node is a BUILD_VECTOR node of
- /// all ConstantSDNode or undef.
+ /// Return true if the specified node is a BUILD_VECTOR node of all
+ /// ConstantSDNode or undef.
bool isBuildVectorOfConstantSDNodes(const SDNode *N);
- /// \brief Return true if the specified node is a BUILD_VECTOR node of
- /// all ConstantFPSDNode or undef.
+ /// 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.
+ /// 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 llvm:ISD namespace
@@ -280,6 +284,8 @@ public:
private:
friend class SelectionDAG;
friend class SDNode;
+ // TODO: unfriend HandleSDNode once we fix its operand handling.
+ friend class HandleSDNode;
void setUser(SDNode *p) { User = p; }
@@ -328,6 +334,7 @@ private:
bool NoInfs : 1;
bool NoSignedZeros : 1;
bool AllowReciprocal : 1;
+ bool VectorReduction : 1;
public:
/// Default constructor turns off all optimization flags.
@@ -340,6 +347,7 @@ public:
NoInfs = false;
NoSignedZeros = false;
AllowReciprocal = false;
+ VectorReduction = false;
}
// These are mutators for each flag.
@@ -351,6 +359,7 @@ public:
void setNoInfs(bool b) { NoInfs = b; }
void setNoSignedZeros(bool b) { NoSignedZeros = b; }
void setAllowReciprocal(bool b) { AllowReciprocal = b; }
+ void setVectorReduction(bool b) { VectorReduction = b; }
// These are accessors for each flag.
bool hasNoUnsignedWrap() const { return NoUnsignedWrap; }
@@ -361,6 +370,7 @@ public:
bool hasNoInfs() const { return NoInfs; }
bool hasNoSignedZeros() const { return NoSignedZeros; }
bool hasAllowReciprocal() const { return AllowReciprocal; }
+ bool hasVectorReduction() const { return VectorReduction; }
/// Return a raw encoding of the flags.
/// This function should only be used to add data to the NodeID value.
@@ -390,10 +400,6 @@ private:
/// The operation that this node performs.
int16_t NodeType;
- /// This is true if OperandList was new[]'d. If true,
- /// then they will be delete[]'d when the node is destroyed.
- uint16_t OperandsNeedDelete : 1;
-
/// This tracks whether this node has one or more dbg_value
/// nodes corresponding to it.
uint16_t HasDebugValue : 1;
@@ -402,7 +408,7 @@ protected:
/// This member is defined by this class, but is not used for
/// anything. Subclasses can use it to hold whatever state they find useful.
/// This field is initialized to zero by the ctor.
- uint16_t SubclassData : 14;
+ uint16_t SubclassData : 15;
private:
/// Unique id per SDNode in the DAG.
@@ -436,6 +442,8 @@ private:
friend class SelectionDAG;
friend struct ilist_traits<SDNode>;
+ // TODO: unfriend HandleSDNode once we fix its operand handling.
+ friend class HandleSDNode;
public:
/// Unique and persistent id per SDNode in the DAG.
@@ -621,18 +629,32 @@ public:
/// NOTE: This is an expensive method. Use it carefully.
bool hasPredecessor(const SDNode *N) const;
- /// Return true if N is a predecessor of this node.
- /// N is either an operand of this node, or can be reached by recursively
- /// traversing up the operands.
- /// In this helper the Visited and worklist sets are held externally to
- /// cache predecessors over multiple invocations. If you want to test for
- /// multiple predecessors this method is preferable to multiple calls to
- /// hasPredecessor. Be sure to clear Visited and Worklist if the DAG
- /// changes.
- /// NOTE: This is still very expensive. Use carefully.
- bool hasPredecessorHelper(const SDNode *N,
- SmallPtrSetImpl<const SDNode *> &Visited,
- SmallVectorImpl<const SDNode *> &Worklist) const;
+ /// Returns true if N is a predecessor of any node in Worklist. This
+ /// helper keeps Visited and Worklist sets externally to allow unions
+ /// searches to be performed in parallel, caching of results across
+ /// queries and incremental addition to Worklist. Stops early if N is
+ /// found but will resume. Remember to clear Visited and Worklists
+ /// if DAG changes.
+ static bool hasPredecessorHelper(const SDNode *N,
+ SmallPtrSetImpl<const SDNode *> &Visited,
+ SmallVectorImpl<const SDNode *> &Worklist) {
+ if (Visited.count(N))
+ return true;
+ while (!Worklist.empty()) {
+ const SDNode *M = Worklist.pop_back_val();
+ bool Found = false;
+ for (const SDValue &OpV : M->op_values()) {
+ SDNode *Op = OpV.getNode();
+ if (Visited.insert(Op).second)
+ Worklist.push_back(Op);
+ if (Op == N)
+ Found = true;
+ }
+ if (Found)
+ return true;
+ }
+ return false;
+ }
/// Return the number of values used by this operation.
unsigned getNumOperands() const { return NumOperands; }
@@ -788,101 +810,20 @@ protected:
return Ret;
}
- SDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs,
- ArrayRef<SDValue> Ops)
- : NodeType(Opc), OperandsNeedDelete(true), HasDebugValue(false),
- SubclassData(0), NodeId(-1),
- OperandList(Ops.size() ? new SDUse[Ops.size()] : nullptr),
- ValueList(VTs.VTs), UseList(nullptr), NumOperands(Ops.size()),
- NumValues(VTs.NumVTs), IROrder(Order), debugLoc(std::move(dl)) {
- assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor");
- assert(NumOperands == Ops.size() &&
- "NumOperands wasn't wide enough for its operands!");
- assert(NumValues == VTs.NumVTs &&
- "NumValues wasn't wide enough for its operands!");
- for (unsigned i = 0; i != Ops.size(); ++i) {
- assert(OperandList && "no operands available");
- OperandList[i].setUser(this);
- OperandList[i].setInitial(Ops[i]);
- }
- checkForCycles(this);
- }
-
- /// This constructor adds no operands itself; operands can be
- /// set later with InitOperands.
+ /// Create an SDNode.
+ ///
+ /// SDNodes are created without any operands, and never own the operand
+ /// storage. To add operands, see SelectionDAG::createOperands.
SDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs)
- : NodeType(Opc), OperandsNeedDelete(false), HasDebugValue(false),
- SubclassData(0), NodeId(-1), OperandList(nullptr), ValueList(VTs.VTs),
- UseList(nullptr), NumOperands(0), NumValues(VTs.NumVTs),
- IROrder(Order), debugLoc(std::move(dl)) {
+ : NodeType(Opc), HasDebugValue(false), SubclassData(0), NodeId(-1),
+ OperandList(nullptr), ValueList(VTs.VTs), UseList(nullptr),
+ NumOperands(0), NumValues(VTs.NumVTs), IROrder(Order),
+ debugLoc(std::move(dl)) {
assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor");
assert(NumValues == VTs.NumVTs &&
"NumValues wasn't wide enough for its operands!");
}
- /// Initialize the operands list of this with 1 operand.
- void InitOperands(SDUse *Ops, const SDValue &Op0) {
- Ops[0].setUser(this);
- Ops[0].setInitial(Op0);
- NumOperands = 1;
- OperandList = Ops;
- checkForCycles(this);
- }
-
- /// Initialize the operands list of this with 2 operands.
- void InitOperands(SDUse *Ops, const SDValue &Op0, const SDValue &Op1) {
- Ops[0].setUser(this);
- Ops[0].setInitial(Op0);
- Ops[1].setUser(this);
- Ops[1].setInitial(Op1);
- NumOperands = 2;
- OperandList = Ops;
- checkForCycles(this);
- }
-
- /// Initialize the operands list of this with 3 operands.
- void InitOperands(SDUse *Ops, const SDValue &Op0, const SDValue &Op1,
- const SDValue &Op2) {
- Ops[0].setUser(this);
- Ops[0].setInitial(Op0);
- Ops[1].setUser(this);
- Ops[1].setInitial(Op1);
- Ops[2].setUser(this);
- Ops[2].setInitial(Op2);
- NumOperands = 3;
- OperandList = Ops;
- checkForCycles(this);
- }
-
- /// Initialize the operands list of this with 4 operands.
- void InitOperands(SDUse *Ops, const SDValue &Op0, const SDValue &Op1,
- const SDValue &Op2, const SDValue &Op3) {
- Ops[0].setUser(this);
- Ops[0].setInitial(Op0);
- Ops[1].setUser(this);
- Ops[1].setInitial(Op1);
- Ops[2].setUser(this);
- Ops[2].setInitial(Op2);
- Ops[3].setUser(this);
- Ops[3].setInitial(Op3);
- NumOperands = 4;
- OperandList = Ops;
- checkForCycles(this);
- }
-
- /// Initialize the operands list of this with N operands.
- void InitOperands(SDUse *Ops, const SDValue *Vals, unsigned N) {
- for (unsigned i = 0; i != N; ++i) {
- Ops[i].setUser(this);
- Ops[i].setInitial(Vals[i]);
- }
- NumOperands = N;
- assert(NumOperands == N &&
- "NumOperands wasn't wide enough for its operands!");
- OperandList = Ops;
- checkForCycles(this);
- }
-
/// Release the operands and set this node to have zero operands.
void DropOperands();
};
@@ -898,40 +839,20 @@ protected:
/// be used by the DAGBuilder, the other to be used by others.
class SDLoc {
private:
- // Ptr could be used for either Instruction* or SDNode*. It is used for
- // Instruction* if IROrder is not -1.
- const void *Ptr;
- int IROrder;
+ DebugLoc DL;
+ int IROrder = 0;
public:
- SDLoc() : Ptr(nullptr), IROrder(0) {}
- SDLoc(const SDNode *N) : Ptr(N), IROrder(-1) {
- assert(N && "null SDNode");
- }
- SDLoc(const SDValue V) : Ptr(V.getNode()), IROrder(-1) {
- assert(Ptr && "null SDNode");
- }
- SDLoc(const Instruction *I, int Order) : Ptr(I), IROrder(Order) {
+ SDLoc() = default;
+ SDLoc(const SDNode *N) : DL(N->getDebugLoc()), IROrder(N->getIROrder()) {}
+ SDLoc(const SDValue V) : SDLoc(V.getNode()) {}
+ SDLoc(const Instruction *I, int Order) : IROrder(Order) {
assert(Order >= 0 && "bad IROrder");
+ if (I)
+ DL = I->getDebugLoc();
}
- unsigned getIROrder() {
- if (IROrder >= 0 || Ptr == nullptr) {
- return (unsigned)IROrder;
- }
- const SDNode *N = (const SDNode*)(Ptr);
- return N->getIROrder();
- }
- DebugLoc getDebugLoc() {
- if (!Ptr) {
- return DebugLoc();
- }
- if (IROrder >= 0) {
- const Instruction *I = (const Instruction*)(Ptr);
- return I->getDebugLoc();
- }
- const SDNode *N = (const SDNode*)(Ptr);
- return N->getDebugLoc();
- }
+ unsigned getIROrder() const { return IROrder; }
+ const DebugLoc &getDebugLoc() const { return DL; }
};
@@ -1008,30 +929,6 @@ inline void SDUse::setNode(SDNode *N) {
if (N) N->addUse(*this);
}
-/// This class is used for single-operand SDNodes. This is solely
-/// to allow co-allocation of node operands with the node itself.
-class UnarySDNode : public SDNode {
- SDUse Op;
-public:
- UnarySDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs,
- SDValue X)
- : SDNode(Opc, Order, dl, VTs) {
- InitOperands(&Op, X);
- }
-};
-
-/// This class is used for two-operand SDNodes. This is solely
-/// to allow co-allocation of node operands with the node itself.
-class BinarySDNode : public SDNode {
- SDUse Ops[2];
-public:
- BinarySDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs,
- SDValue X, SDValue Y)
- : SDNode(Opc, Order, dl, VTs) {
- InitOperands(Ops, X, Y);
- }
-};
-
/// Returns true if the opcode is a binary operation with flags.
static bool isBinOpWithFlags(unsigned Opcode) {
switch (Opcode) {
@@ -1056,30 +953,17 @@ static bool isBinOpWithFlags(unsigned Opcode) {
/// This class is an extension of BinarySDNode
/// used from those opcodes that have associated extra flags.
-class BinaryWithFlagsSDNode : public BinarySDNode {
+class BinaryWithFlagsSDNode : public SDNode {
public:
SDNodeFlags Flags;
- BinaryWithFlagsSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs,
- SDValue X, SDValue Y, const SDNodeFlags &NodeFlags)
- : BinarySDNode(Opc, Order, dl, VTs, X, Y), Flags(NodeFlags) {}
+ BinaryWithFlagsSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl,
+ SDVTList VTs, const SDNodeFlags &NodeFlags)
+ : SDNode(Opc, Order, dl, VTs), Flags(NodeFlags) {}
static bool classof(const SDNode *N) {
return isBinOpWithFlags(N->getOpcode());
}
};
-/// This class is used for three-operand SDNodes. This is solely
-/// to allow co-allocation of node operands with the node itself.
-class TernarySDNode : public SDNode {
- SDUse Ops[3];
-public:
- TernarySDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs,
- SDValue X, SDValue Y, SDValue Z)
- : SDNode(Opc, Order, dl, VTs) {
- InitOperands(Ops, X, Y, Z);
- }
-};
-
-
/// This class is used to form a handle around another node that
/// is persistent and is updated across invocations of replaceAllUsesWith on its
/// operand. This node should be directly created by end-users and not added to
@@ -1092,19 +976,27 @@ public:
// HandleSDNodes are never inserted into the DAG, so they won't be
// auto-numbered. Use ID 65535 as a sentinel.
PersistentId = 0xffff;
- InitOperands(&Op, X);
+
+ // Manually set up the operand list. This node type is special in that it's
+ // always stack allocated and SelectionDAG does not manage its operands.
+ // TODO: This should either (a) not be in the SDNode hierarchy, or (b) not
+ // be so special.
+ Op.setUser(this);
+ Op.setInitial(X);
+ NumOperands = 1;
+ OperandList = &Op;
}
~HandleSDNode();
const SDValue &getValue() const { return Op; }
};
-class AddrSpaceCastSDNode : public UnarySDNode {
+class AddrSpaceCastSDNode : public SDNode {
private:
unsigned SrcAddrSpace;
unsigned DestAddrSpace;
public:
- AddrSpaceCastSDNode(unsigned Order, DebugLoc dl, EVT VT, SDValue X,
+ AddrSpaceCastSDNode(unsigned Order, const DebugLoc &dl, EVT VT,
unsigned SrcAS, unsigned DestAS);
unsigned getSrcAddressSpace() const { return SrcAddrSpace; }
@@ -1126,12 +1018,9 @@ protected:
MachineMemOperand *MMO;
public:
- MemSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs,
+ MemSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl, SDVTList VTs,
EVT MemoryVT, MachineMemOperand *MMO);
- MemSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs,
- ArrayRef<SDValue> Ops, EVT MemoryVT, MachineMemOperand *MMO);
-
bool readMem() const { return MMO->isLoad(); }
bool writeMem() const { return MMO->isStore(); }
@@ -1234,8 +1123,6 @@ public:
/// This is an SDNode representing atomic operations.
class AtomicSDNode : public MemSDNode {
- SDUse Ops[4];
-
/// For cmpxchg instructions, the ordering requirements when a store does not
/// occur.
AtomicOrdering FailureOrdering;
@@ -1244,13 +1131,15 @@ class AtomicSDNode : public MemSDNode {
AtomicOrdering FailureOrdering,
SynchronizationScope SynchScope) {
// This must match encodeMemSDNodeFlags() in SelectionDAG.cpp.
- assert((SuccessOrdering & 15) == SuccessOrdering &&
+ assert((AtomicOrdering)((unsigned)SuccessOrdering & 15) ==
+ SuccessOrdering &&
"Ordering may not require more than 4 bits!");
- assert((FailureOrdering & 15) == FailureOrdering &&
+ assert((AtomicOrdering)((unsigned)FailureOrdering & 15) ==
+ FailureOrdering &&
"Ordering may not require more than 4 bits!");
assert((SynchScope & 1) == SynchScope &&
"SynchScope may not require more than 1 bit!");
- SubclassData |= SuccessOrdering << 8;
+ SubclassData |= (unsigned)SuccessOrdering << 8;
SubclassData |= SynchScope << 12;
this->FailureOrdering = FailureOrdering;
assert(getSuccessOrdering() == SuccessOrdering &&
@@ -1261,50 +1150,12 @@ class AtomicSDNode : public MemSDNode {
}
public:
- // Opc: opcode for atomic
- // VTL: value type list
- // Chain: memory chain for operaand
- // Ptr: address to update as a SDValue
- // Cmp: compare value
- // Swp: swap value
- // SrcVal: address to update as a Value (used for MemOperand)
- // Align: alignment of memory
- AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL,
- EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Cmp, SDValue Swp,
- MachineMemOperand *MMO, AtomicOrdering Ordering,
- SynchronizationScope SynchScope)
- : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) {
- InitAtomic(Ordering, Ordering, SynchScope);
- InitOperands(Ops, Chain, Ptr, Cmp, Swp);
- }
- AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL,
- EVT MemVT,
- SDValue Chain, SDValue Ptr,
- SDValue Val, MachineMemOperand *MMO,
- AtomicOrdering Ordering, SynchronizationScope SynchScope)
- : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) {
- InitAtomic(Ordering, Ordering, SynchScope);
- InitOperands(Ops, Chain, Ptr, Val);
- }
- AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL,
- EVT MemVT,
- SDValue Chain, SDValue Ptr,
- MachineMemOperand *MMO,
- AtomicOrdering Ordering, SynchronizationScope SynchScope)
- : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) {
- InitAtomic(Ordering, Ordering, SynchScope);
- InitOperands(Ops, Chain, Ptr);
- }
- AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL, EVT MemVT,
- const SDValue* AllOps, SDUse *DynOps, unsigned NumOps,
- MachineMemOperand *MMO,
+ AtomicSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl, SDVTList VTL,
+ EVT MemVT, MachineMemOperand *MMO,
AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering,
SynchronizationScope SynchScope)
- : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) {
+ : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) {
InitAtomic(SuccessOrdering, FailureOrdering, SynchScope);
- assert((DynOps || NumOps <= array_lengthof(Ops)) &&
- "Too many ops for internal storage!");
- InitOperands(DynOps ? DynOps : Ops, AllOps, NumOps);
}
const SDValue &getBasePtr() const { return getOperand(1); }
@@ -1351,10 +1202,9 @@ public:
/// with a value not less than FIRST_TARGET_MEMORY_OPCODE.
class MemIntrinsicSDNode : public MemSDNode {
public:
- MemIntrinsicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs,
- ArrayRef<SDValue> Ops, EVT MemoryVT,
- MachineMemOperand *MMO)
- : MemSDNode(Opc, Order, dl, VTs, Ops, MemoryVT, MMO) {
+ MemIntrinsicSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl,
+ SDVTList VTs, EVT MemoryVT, MachineMemOperand *MMO)
+ : MemSDNode(Opc, Order, dl, VTs, MemoryVT, MMO) {
SubclassData |= 1u << 13;
}
@@ -1377,20 +1227,15 @@ public:
/// An index of -1 is treated as undef, such that the code generator may put
/// any value in the corresponding element of the result.
class ShuffleVectorSDNode : public SDNode {
- SDUse Ops[2];
-
// The memory for Mask is owned by the SelectionDAG's OperandAllocator, and
// is freed when the SelectionDAG object is destroyed.
const int *Mask;
protected:
friend class SelectionDAG;
- ShuffleVectorSDNode(EVT VT, unsigned Order, DebugLoc dl, SDValue N1,
- SDValue N2, const int *M)
- : SDNode(ISD::VECTOR_SHUFFLE, Order, dl, getSDVTList(VT)), Mask(M) {
- InitOperands(Ops, N1, N2);
- }
-public:
+ ShuffleVectorSDNode(EVT VT, unsigned Order, const DebugLoc &dl, const int *M)
+ : SDNode(ISD::VECTOR_SHUFFLE, Order, dl, getSDVTList(VT)), Mask(M) {}
+public:
ArrayRef<int> getMask() const {
EVT VT = getValueType(0);
return makeArrayRef(Mask, VT.getVectorNumElements());
@@ -1414,7 +1259,7 @@ public:
/// Change values in a shuffle permute mask assuming
/// the two vector operands have swapped position.
- static void commuteMask(SmallVectorImpl<int> &Mask) {
+ static void commuteMask(MutableArrayRef<int> Mask) {
unsigned NumElems = Mask.size();
for (unsigned i = 0; i != NumElems; ++i) {
int idx = Mask[i];
@@ -1436,9 +1281,10 @@ class ConstantSDNode : public SDNode {
const ConstantInt *Value;
friend class SelectionDAG;
ConstantSDNode(bool isTarget, bool isOpaque, const ConstantInt *val,
- DebugLoc DL, EVT VT)
- : SDNode(isTarget ? ISD::TargetConstant : ISD::Constant,
- 0, DL, getSDVTList(VT)), Value(val) {
+ const DebugLoc &DL, EVT VT)
+ : SDNode(isTarget ? ISD::TargetConstant : ISD::Constant, 0, DL,
+ getSDVTList(VT)),
+ Value(val) {
SubclassData |= (uint16_t)isOpaque;
}
public:
@@ -1463,10 +1309,12 @@ public:
class ConstantFPSDNode : public SDNode {
const ConstantFP *Value;
friend class SelectionDAG;
- ConstantFPSDNode(bool isTarget, const ConstantFP *val, DebugLoc DL, EVT VT)
- : SDNode(isTarget ? ISD::TargetConstantFP : ISD::ConstantFP,
- 0, DL, getSDVTList(VT)), Value(val) {
- }
+ ConstantFPSDNode(bool isTarget, const ConstantFP *val, const DebugLoc &DL,
+ EVT VT)
+ : SDNode(isTarget ? ISD::TargetConstantFP : ISD::ConstantFP, 0, DL,
+ getSDVTList(VT)),
+ Value(val) {}
+
public:
const APFloat& getValueAPF() const { return Value->getValueAPF(); }
@@ -1517,15 +1365,19 @@ bool isNullFPConstant(SDValue V);
bool isAllOnesConstant(SDValue V);
/// Returns true if \p V is a constant integer one.
bool isOneConstant(SDValue V);
+/// Returns true if \p V is a bitwise not operation. Assumes that an all ones
+/// constant is canonicalized to be operand 1.
+bool isBitwiseNot(SDValue V);
class GlobalAddressSDNode : public SDNode {
const GlobalValue *TheGlobal;
int64_t Offset;
unsigned char TargetFlags;
friend class SelectionDAG;
- GlobalAddressSDNode(unsigned Opc, unsigned Order, DebugLoc DL,
+ GlobalAddressSDNode(unsigned Opc, unsigned Order, const DebugLoc &DL,
const GlobalValue *GA, EVT VT, int64_t o,
unsigned char TargetFlags);
+
public:
const GlobalValue *getGlobal() const { return TheGlobal; }
@@ -1821,13 +1673,11 @@ public:
};
class EHLabelSDNode : public SDNode {
- SDUse Chain;
MCSymbol *Label;
friend class SelectionDAG;
- EHLabelSDNode(unsigned Order, DebugLoc dl, SDValue ch, MCSymbol *L)
- : SDNode(ISD::EH_LABEL, Order, dl, getSDVTList(MVT::Other)), Label(L) {
- InitOperands(&Chain, ch);
- }
+ EHLabelSDNode(unsigned Order, const DebugLoc &dl, MCSymbol *L)
+ : SDNode(ISD::EH_LABEL, Order, dl, getSDVTList(MVT::Other)), Label(L) {}
+
public:
MCSymbol *getLabel() const { return Label; }
@@ -1892,12 +1742,11 @@ public:
class CvtRndSatSDNode : public SDNode {
ISD::CvtCode CvtCode;
friend class SelectionDAG;
- explicit CvtRndSatSDNode(EVT VT, unsigned Order, DebugLoc dl,
- ArrayRef<SDValue> Ops, ISD::CvtCode Code)
- : SDNode(ISD::CONVERT_RNDSAT, Order, dl, getSDVTList(VT), Ops),
- CvtCode(Code) {
- assert(Ops.size() == 5 && "wrong number of operations");
+ explicit CvtRndSatSDNode(EVT VT, unsigned Order, const DebugLoc &dl,
+ ISD::CvtCode Code)
+ : SDNode(ISD::CONVERT_RNDSAT, Order, dl, getSDVTList(VT)), CvtCode(Code) {
}
+
public:
ISD::CvtCode getCvtCode() const { return CvtCode; }
@@ -1926,24 +1775,13 @@ public:
/// Base class for LoadSDNode and StoreSDNode
class LSBaseSDNode : public MemSDNode {
- //! Operand array for load and store
- /*!
- \note Moving this array to the base class captures more
- common functionality shared between LoadSDNode and
- StoreSDNode
- */
- SDUse Ops[4];
public:
- LSBaseSDNode(ISD::NodeType NodeTy, unsigned Order, DebugLoc dl,
- SDValue *Operands, unsigned numOperands,
+ LSBaseSDNode(ISD::NodeType NodeTy, unsigned Order, const DebugLoc &dl,
SDVTList VTs, ISD::MemIndexedMode AM, EVT MemVT,
MachineMemOperand *MMO)
- : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) {
+ : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) {
SubclassData |= AM << 2;
assert(getAddressingMode() == AM && "MemIndexedMode encoding error!");
- InitOperands(Ops, Operands, numOperands);
- assert((getOffset().getOpcode() == ISD::UNDEF || isIndexed()) &&
- "Only indexed loads and stores have a non-undef offset operand");
}
const SDValue &getOffset() const {
@@ -1971,10 +1809,10 @@ public:
/// This class is used to represent ISD::LOAD nodes.
class LoadSDNode : public LSBaseSDNode {
friend class SelectionDAG;
- LoadSDNode(SDValue *ChainPtrOff, unsigned Order, DebugLoc dl, SDVTList VTs,
+ LoadSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs,
ISD::MemIndexedMode AM, ISD::LoadExtType ETy, EVT MemVT,
MachineMemOperand *MMO)
- : LSBaseSDNode(ISD::LOAD, Order, dl, ChainPtrOff, 3, VTs, AM, MemVT, MMO) {
+ : LSBaseSDNode(ISD::LOAD, Order, dl, VTs, AM, MemVT, MMO) {
SubclassData |= (unsigned short)ETy;
assert(getExtensionType() == ETy && "LoadExtType encoding error!");
assert(readMem() && "Load MachineMemOperand is not a load!");
@@ -1999,11 +1837,10 @@ public:
/// This class is used to represent ISD::STORE nodes.
class StoreSDNode : public LSBaseSDNode {
friend class SelectionDAG;
- StoreSDNode(SDValue *ChainValuePtrOff, unsigned Order, DebugLoc dl,
- SDVTList VTs, ISD::MemIndexedMode AM, bool isTrunc, EVT MemVT,
+ StoreSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs,
+ ISD::MemIndexedMode AM, bool isTrunc, EVT MemVT,
MachineMemOperand *MMO)
- : LSBaseSDNode(ISD::STORE, Order, dl, ChainValuePtrOff, 4,
- VTs, AM, MemVT, MMO) {
+ : LSBaseSDNode(ISD::STORE, Order, dl, VTs, AM, MemVT, MMO) {
SubclassData |= (unsigned short)isTrunc;
assert(isTruncatingStore() == isTrunc && "isTrunc encoding error!");
assert(!readMem() && "Store MachineMemOperand is a load!");
@@ -2027,16 +1864,12 @@ public:
/// This base class is used to represent MLOAD and MSTORE nodes
class MaskedLoadStoreSDNode : public MemSDNode {
- // Operands
- SDUse Ops[4];
public:
friend class SelectionDAG;
- MaskedLoadStoreSDNode(ISD::NodeType NodeTy, unsigned Order, DebugLoc dl,
- SDValue *Operands, unsigned numOperands, SDVTList VTs,
- EVT MemVT, MachineMemOperand *MMO)
- : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) {
- InitOperands(Ops, Operands, numOperands);
- }
+ MaskedLoadStoreSDNode(ISD::NodeType NodeTy, unsigned Order,
+ const DebugLoc &dl, SDVTList VTs, EVT MemVT,
+ MachineMemOperand *MMO)
+ : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) {}
// In the both nodes address is Op1, mask is Op2:
// MaskedLoadSDNode (Chain, ptr, mask, src0), src0 is a passthru value
@@ -2055,11 +1888,9 @@ public:
class MaskedLoadSDNode : public MaskedLoadStoreSDNode {
public:
friend class SelectionDAG;
- MaskedLoadSDNode(unsigned Order, DebugLoc dl, SDValue *Operands,
- unsigned numOperands, SDVTList VTs, ISD::LoadExtType ETy,
- EVT MemVT, MachineMemOperand *MMO)
- : MaskedLoadStoreSDNode(ISD::MLOAD, Order, dl, Operands, numOperands,
- VTs, MemVT, MMO) {
+ MaskedLoadSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs,
+ ISD::LoadExtType ETy, EVT MemVT, MachineMemOperand *MMO)
+ : MaskedLoadStoreSDNode(ISD::MLOAD, Order, dl, VTs, MemVT, MMO) {
SubclassData |= (unsigned short)ETy;
}
@@ -2077,12 +1908,10 @@ class MaskedStoreSDNode : public MaskedLoadStoreSDNode {
public:
friend class SelectionDAG;
- MaskedStoreSDNode(unsigned Order, DebugLoc dl, SDValue *Operands,
- unsigned numOperands, SDVTList VTs, bool isTrunc, EVT MemVT,
- MachineMemOperand *MMO)
- : MaskedLoadStoreSDNode(ISD::MSTORE, Order, dl, Operands, numOperands,
- VTs, MemVT, MMO) {
- SubclassData |= (unsigned short)isTrunc;
+ MaskedStoreSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs,
+ bool isTrunc, EVT MemVT, MachineMemOperand *MMO)
+ : MaskedLoadStoreSDNode(ISD::MSTORE, Order, dl, VTs, MemVT, MMO) {
+ SubclassData |= (unsigned short)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.
@@ -2100,17 +1929,12 @@ public:
/// MGATHER and MSCATTER nodes
///
class MaskedGatherScatterSDNode : public MemSDNode {
- // Operands
- SDUse Ops[5];
public:
friend class SelectionDAG;
- MaskedGatherScatterSDNode(ISD::NodeType NodeTy, unsigned Order, DebugLoc dl,
- ArrayRef<SDValue> Operands, SDVTList VTs, EVT MemVT,
+ MaskedGatherScatterSDNode(ISD::NodeType NodeTy, unsigned Order,
+ const DebugLoc &dl, SDVTList VTs, EVT MemVT,
MachineMemOperand *MMO)
- : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) {
- assert(Operands.size() == 5 && "Incompatible number of operands");
- InitOperands(Ops, Operands.data(), Operands.size());
- }
+ : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) {}
// In the both nodes address is Op1, mask is Op2:
// MaskedGatherSDNode (Chain, src0, mask, base, index), src0 is a passthru value
@@ -2132,19 +1956,9 @@ public:
class MaskedGatherSDNode : public MaskedGatherScatterSDNode {
public:
friend class SelectionDAG;
- MaskedGatherSDNode(unsigned Order, DebugLoc dl, ArrayRef<SDValue> Operands,
- SDVTList VTs, EVT MemVT, MachineMemOperand *MMO)
- : MaskedGatherScatterSDNode(ISD::MGATHER, Order, dl, Operands, VTs, MemVT,
- MMO) {
- assert(getValue().getValueType() == getValueType(0) &&
- "Incompatible type of the PassThru value in MaskedGatherSDNode");
- assert(getMask().getValueType().getVectorNumElements() ==
- getValueType(0).getVectorNumElements() &&
- "Vector width mismatch between mask and data");
- assert(getIndex().getValueType().getVectorNumElements() ==
- getValueType(0).getVectorNumElements() &&
- "Vector width mismatch between index and data");
- }
+ MaskedGatherSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs,
+ EVT MemVT, MachineMemOperand *MMO)
+ : MaskedGatherScatterSDNode(ISD::MGATHER, Order, dl, VTs, MemVT, MMO) {}
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::MGATHER;
@@ -2157,17 +1971,9 @@ class MaskedScatterSDNode : public MaskedGatherScatterSDNode {
public:
friend class SelectionDAG;
- MaskedScatterSDNode(unsigned Order, DebugLoc dl,ArrayRef<SDValue> Operands,
- SDVTList VTs, EVT MemVT, MachineMemOperand *MMO)
- : MaskedGatherScatterSDNode(ISD::MSCATTER, Order, dl, Operands, VTs, MemVT,
- MMO) {
- assert(getMask().getValueType().getVectorNumElements() ==
- getValue().getValueType().getVectorNumElements() &&
- "Vector width mismatch between mask and data");
- assert(getIndex().getValueType().getVectorNumElements() ==
- getValue().getValueType().getVectorNumElements() &&
- "Vector width mismatch between index and data");
- }
+ MaskedScatterSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs,
+ EVT MemVT, MachineMemOperand *MMO)
+ : MaskedGatherScatterSDNode(ISD::MSCATTER, Order, dl, VTs, MemVT, MMO) {}
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::MSCATTER;
@@ -2183,12 +1989,8 @@ public:
private:
friend class SelectionDAG;
- MachineSDNode(unsigned Opc, unsigned Order, const DebugLoc DL, SDVTList VTs)
- : SDNode(Opc, Order, DL, VTs), MemRefs(nullptr), MemRefsEnd(nullptr) {}
-
- /// Operands for this instruction, if they fit here. If
- /// they don't, this field is unused.
- SDUse LocalOperands[4];
+ MachineSDNode(unsigned Opc, unsigned Order, const DebugLoc &DL, SDVTList VTs)
+ : SDNode(Opc, Order, DL, VTs), MemRefs(nullptr), MemRefsEnd(nullptr) {}
/// Memory reference descriptions for this instruction.
mmo_iterator MemRefs;
@@ -2264,8 +2066,13 @@ template <> struct GraphTraits<SDNode*> {
}
};
-/// The largest SDNode class.
-typedef MaskedGatherScatterSDNode LargestSDNode;
+/// A representation of the largest SDNode, for use in sizeof().
+///
+/// This needs to be a union because the largest node differs on 32 bit systems
+/// with 4 and 8 byte pointer alignment, respectively.
+typedef AlignedCharArrayUnion<AtomicSDNode, TargetIndexSDNode,
+ BlockAddressSDNode, GlobalAddressSDNode>
+ LargestSDNode;
/// The SDNode class with the greatest alignment requirement.
typedef GlobalAddressSDNode MostAlignedSDNode;
diff --git a/include/llvm/Target/TargetSelectionDAGInfo.h b/include/llvm/CodeGen/SelectionDAGTargetInfo.h
index a7143ac3fa66..ac5092af8def 100644
--- a/include/llvm/Target/TargetSelectionDAGInfo.h
+++ b/include/llvm/CodeGen/SelectionDAGTargetInfo.h
@@ -1,4 +1,4 @@
-//==-- llvm/Target/TargetSelectionDAGInfo.h - SelectionDAG Info --*- C++ -*-==//
+//==-- llvm/CodeGen/SelectionDAGTargetInfo.h - SelectionDAG Info -*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
@@ -7,16 +7,17 @@
//
//===----------------------------------------------------------------------===//
//
-// This file declares the TargetSelectionDAGInfo class, which targets can
+// This file declares the SelectionDAGTargetInfo class, which targets can
// subclass to parameterize the SelectionDAG lowering and instruction
// selection process.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_TARGET_TARGETSELECTIONDAGINFO_H
-#define LLVM_TARGET_TARGETSELECTIONDAGINFO_H
+#ifndef LLVM_CODEGEN_SELECTIONDAGTARGETINFO_H
+#define LLVM_CODEGEN_SELECTIONDAGTARGETINFO_H
#include "llvm/CodeGen/SelectionDAGNodes.h"
+#include "llvm/Support/CodeGen.h"
namespace llvm {
@@ -24,13 +25,13 @@ namespace llvm {
/// Targets can subclass this to parameterize the
/// SelectionDAG lowering and instruction selection process.
///
-class TargetSelectionDAGInfo {
- TargetSelectionDAGInfo(const TargetSelectionDAGInfo &) = delete;
- void operator=(const TargetSelectionDAGInfo &) = delete;
+class SelectionDAGTargetInfo {
+ SelectionDAGTargetInfo(const SelectionDAGTargetInfo &) = delete;
+ void operator=(const SelectionDAGTargetInfo &) = delete;
public:
- explicit TargetSelectionDAGInfo() = default;
- virtual ~TargetSelectionDAGInfo();
+ explicit SelectionDAGTargetInfo() = default;
+ virtual ~SelectionDAGTargetInfo();
/// Emit target-specific code that performs a memcpy.
/// This can be used by targets to provide code sequences for cases
@@ -45,14 +46,13 @@ public:
/// expanded in a place where calls are not feasible (e.g. within the prologue
/// for another call). If the target chooses to decline an AlwaysInline
/// request here, legalize will resort to using simple loads and stores.
- virtual SDValue
- EmitTargetCodeForMemcpy(SelectionDAG &DAG, SDLoc dl,
- SDValue Chain,
- SDValue Op1, SDValue Op2,
- SDValue Op3, unsigned Align, bool isVolatile,
- bool AlwaysInline,
- MachinePointerInfo DstPtrInfo,
- MachinePointerInfo SrcPtrInfo) const {
+ virtual SDValue EmitTargetCodeForMemcpy(SelectionDAG &DAG, const SDLoc &dl,
+ SDValue Chain, SDValue Op1,
+ SDValue Op2, SDValue Op3,
+ unsigned Align, bool isVolatile,
+ bool AlwaysInline,
+ MachinePointerInfo DstPtrInfo,
+ MachinePointerInfo SrcPtrInfo) const {
return SDValue();
}
@@ -62,13 +62,10 @@ public:
/// more efficient than using a library call. This function can return a null
/// SDValue if the target declines to use custom code and a different
/// lowering strategy should be used.
- virtual SDValue
- EmitTargetCodeForMemmove(SelectionDAG &DAG, SDLoc dl,
- SDValue Chain,
- SDValue Op1, SDValue Op2,
- SDValue Op3, unsigned Align, bool isVolatile,
- MachinePointerInfo DstPtrInfo,
- MachinePointerInfo SrcPtrInfo) const {
+ virtual SDValue EmitTargetCodeForMemmove(
+ SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Op1,
+ SDValue Op2, SDValue Op3, unsigned Align, bool isVolatile,
+ MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo) const {
return SDValue();
}
@@ -78,12 +75,11 @@ public:
/// efficient than using a library call. This function can return a null
/// SDValue if the target declines to use custom code and a different
/// lowering strategy should be used.
- virtual SDValue
- EmitTargetCodeForMemset(SelectionDAG &DAG, SDLoc dl,
- SDValue Chain,
- SDValue Op1, SDValue Op2,
- SDValue Op3, unsigned Align, bool isVolatile,
- MachinePointerInfo DstPtrInfo) const {
+ virtual SDValue EmitTargetCodeForMemset(SelectionDAG &DAG, const SDLoc &dl,
+ SDValue Chain, SDValue Op1,
+ SDValue Op2, SDValue Op3,
+ unsigned Align, bool isVolatile,
+ MachinePointerInfo DstPtrInfo) const {
return SDValue();
}
@@ -92,10 +88,9 @@ public:
/// memcmp and the second is the chain. Both SDValues can be null if a normal
/// libcall should be used.
virtual std::pair<SDValue, SDValue>
- EmitTargetCodeForMemcmp(SelectionDAG &DAG, SDLoc dl,
- SDValue Chain,
- SDValue Op1, SDValue Op2,
- SDValue Op3, MachinePointerInfo Op1PtrInfo,
+ EmitTargetCodeForMemcmp(SelectionDAG &DAG, const SDLoc &dl, SDValue Chain,
+ SDValue Op1, SDValue Op2, SDValue Op3,
+ MachinePointerInfo Op1PtrInfo,
MachinePointerInfo Op2PtrInfo) const {
return std::make_pair(SDValue(), SDValue());
}
@@ -105,7 +100,7 @@ public:
/// memchr and the second is the chain. Both SDValues can be null if a normal
/// libcall should be used.
virtual std::pair<SDValue, SDValue>
- EmitTargetCodeForMemchr(SelectionDAG &DAG, SDLoc dl, SDValue Chain,
+ EmitTargetCodeForMemchr(SelectionDAG &DAG, const SDLoc &dl, SDValue Chain,
SDValue Src, SDValue Char, SDValue Length,
MachinePointerInfo SrcPtrInfo) const {
return std::make_pair(SDValue(), SDValue());
@@ -118,11 +113,10 @@ public:
/// for stpcpy) and the second is the chain. Both SDValues can be null
/// if a normal libcall should be used.
virtual std::pair<SDValue, SDValue>
- EmitTargetCodeForStrcpy(SelectionDAG &DAG, SDLoc DL, SDValue Chain,
+ EmitTargetCodeForStrcpy(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain,
SDValue Dest, SDValue Src,
MachinePointerInfo DestPtrInfo,
- MachinePointerInfo SrcPtrInfo,
- bool isStpcpy) const {
+ MachinePointerInfo SrcPtrInfo, bool isStpcpy) const {
return std::make_pair(SDValue(), SDValue());
}
@@ -131,8 +125,7 @@ public:
/// The first returned SDValue is the result of the strcmp and the second is
/// the chain. Both SDValues can be null if a normal libcall should be used.
virtual std::pair<SDValue, SDValue>
- EmitTargetCodeForStrcmp(SelectionDAG &DAG, SDLoc dl,
- SDValue Chain,
+ EmitTargetCodeForStrcmp(SelectionDAG &DAG, const SDLoc &dl, SDValue Chain,
SDValue Op1, SDValue Op2,
MachinePointerInfo Op1PtrInfo,
MachinePointerInfo Op2PtrInfo) const {
@@ -140,17 +133,22 @@ public:
}
virtual std::pair<SDValue, SDValue>
- EmitTargetCodeForStrlen(SelectionDAG &DAG, SDLoc DL, SDValue Chain,
+ EmitTargetCodeForStrlen(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain,
SDValue Src, MachinePointerInfo SrcPtrInfo) const {
return std::make_pair(SDValue(), SDValue());
}
virtual std::pair<SDValue, SDValue>
- EmitTargetCodeForStrnlen(SelectionDAG &DAG, SDLoc DL, SDValue Chain,
+ EmitTargetCodeForStrnlen(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain,
SDValue Src, SDValue MaxLength,
MachinePointerInfo SrcPtrInfo) const {
return std::make_pair(SDValue(), SDValue());
}
+ // Return true when the decision to generate FMA's (or FMS, FMLA etc) rather
+ // than FMUL and ADD is delegated to the machine combiner.
+ virtual bool generateFMAsInMachineCombiner(CodeGenOpt::Level OptLevel) const {
+ return false;
+ }
};
} // end llvm namespace
diff --git a/include/llvm/CodeGen/SlotIndexes.h b/include/llvm/CodeGen/SlotIndexes.h
index 7b621bee259f..afb0288b024f 100644
--- a/include/llvm/CodeGen/SlotIndexes.h
+++ b/include/llvm/CodeGen/SlotIndexes.h
@@ -66,7 +66,6 @@ namespace llvm {
bool isPoisoned() const { return (reinterpret_cast<intptr_t>(mi) & 0x1) == 0x1; }
#endif // EXPENSIVE_CHECKS
-
};
template <>
@@ -99,7 +98,7 @@ namespace llvm {
Slot_Block,
/// Early-clobber register use/def slot. A live range defined at
- /// Slot_EarlyCLobber interferes with normal live ranges killed at
+ /// Slot_EarlyClobber interferes with normal live ranges killed at
/// Slot_Register. Also used as the kill slot for live ranges tied to an
/// early-clobber def.
Slot_EarlyClobber,
@@ -213,6 +212,12 @@ namespace llvm {
return A.listEntry()->getIndex() < B.listEntry()->getIndex();
}
+ /// Return true if A refers to the same instruction as B or an earlier one.
+ /// This is equivalent to !isEarlierInstr(B, A).
+ static bool isEarlierEqualInstr(SlotIndex A, SlotIndex B) {
+ return !isEarlierInstr(B, A);
+ }
+
/// Return the distance from this index to the given one.
int distance(SlotIndex other) const {
return other.getIndex() - getIndex();
@@ -302,7 +307,6 @@ namespace llvm {
SlotIndex getPrevIndex() const {
return SlotIndex(&*--listEntry()->getIterator(), getSlot());
}
-
};
template <> struct isPodLike<SlotIndex> { static const bool value = true; };
@@ -376,7 +380,7 @@ namespace llvm {
initializeSlotIndexesPass(*PassRegistry::getPassRegistry());
}
- ~SlotIndexes() {
+ ~SlotIndexes() override {
// The indexList's nodes are all allocated in the BumpPtrAllocator.
indexList.clearAndLeakNodesUnsafely();
}
@@ -410,14 +414,14 @@ namespace llvm {
/// Returns true if the given machine instr is mapped to an index,
/// otherwise returns false.
- bool hasIndex(const MachineInstr *instr) const {
- return mi2iMap.count(instr);
+ bool hasIndex(const MachineInstr &instr) const {
+ return mi2iMap.count(&instr);
}
/// Returns the base index for the given instruction.
- SlotIndex getInstructionIndex(const MachineInstr *MI) const {
+ SlotIndex getInstructionIndex(const MachineInstr &MI) const {
// Instructions inside a bundle have the same number as the bundle itself.
- Mi2IndexMap::const_iterator itr = mi2iMap.find(getBundleStart(MI));
+ Mi2IndexMap::const_iterator itr = mi2iMap.find(&getBundleStart(MI));
assert(itr != mi2iMap.end() && "Instruction not found in maps.");
return itr->second;
}
@@ -443,15 +447,15 @@ namespace llvm {
/// getIndexBefore - Returns the index of the last indexed instruction
/// before MI, or the start index of its basic block.
/// MI is not required to have an index.
- SlotIndex getIndexBefore(const MachineInstr *MI) const {
- const MachineBasicBlock *MBB = MI->getParent();
+ SlotIndex getIndexBefore(const MachineInstr &MI) const {
+ const MachineBasicBlock *MBB = MI.getParent();
assert(MBB && "MI must be inserted inna basic block");
MachineBasicBlock::const_iterator I = MI, B = MBB->begin();
for (;;) {
if (I == B)
return getMBBStartIdx(MBB);
--I;
- Mi2IndexMap::const_iterator MapItr = mi2iMap.find(I);
+ Mi2IndexMap::const_iterator MapItr = mi2iMap.find(&*I);
if (MapItr != mi2iMap.end())
return MapItr->second;
}
@@ -460,15 +464,15 @@ namespace llvm {
/// getIndexAfter - Returns the index of the first indexed instruction
/// after MI, or the end index of its basic block.
/// MI is not required to have an index.
- SlotIndex getIndexAfter(const MachineInstr *MI) const {
- const MachineBasicBlock *MBB = MI->getParent();
+ SlotIndex getIndexAfter(const MachineInstr &MI) const {
+ const MachineBasicBlock *MBB = MI.getParent();
assert(MBB && "MI must be inserted inna basic block");
MachineBasicBlock::const_iterator I = MI, E = MBB->end();
for (;;) {
++I;
if (I == E)
return getMBBEndIdx(MBB);
- Mi2IndexMap::const_iterator MapItr = mi2iMap.find(I);
+ Mi2IndexMap::const_iterator MapItr = mi2iMap.find(&*I);
if (MapItr != mi2iMap.end())
return MapItr->second;
}
@@ -573,25 +577,25 @@ namespace llvm {
/// If Late is set and there are null indexes between mi's neighboring
/// instructions, create the new index after the null indexes instead of
/// before them.
- SlotIndex insertMachineInstrInMaps(MachineInstr *mi, bool Late = false) {
- assert(!mi->isInsideBundle() &&
+ SlotIndex insertMachineInstrInMaps(MachineInstr &MI, bool Late = false) {
+ assert(!MI.isInsideBundle() &&
"Instructions inside bundles should use bundle start's slot.");
- assert(mi2iMap.find(mi) == mi2iMap.end() && "Instr already indexed.");
+ assert(mi2iMap.find(&MI) == mi2iMap.end() && "Instr already indexed.");
// Numbering DBG_VALUE instructions could cause code generation to be
// affected by debug information.
- assert(!mi->isDebugValue() && "Cannot number DBG_VALUE instructions.");
+ assert(!MI.isDebugValue() && "Cannot number DBG_VALUE instructions.");
- assert(mi->getParent() != nullptr && "Instr must be added to function.");
+ assert(MI.getParent() != nullptr && "Instr must be added to function.");
- // Get the entries where mi should be inserted.
+ // Get the entries where MI should be inserted.
IndexList::iterator prevItr, nextItr;
if (Late) {
- // Insert mi's index immediately before the following instruction.
- nextItr = getIndexAfter(mi).listEntry()->getIterator();
+ // Insert MI's index immediately before the following instruction.
+ nextItr = getIndexAfter(MI).listEntry()->getIterator();
prevItr = std::prev(nextItr);
} else {
- // Insert mi's index immediately after the preceding instruction.
- prevItr = getIndexBefore(mi).listEntry()->getIterator();
+ // Insert MI's index immediately after the preceding instruction.
+ prevItr = getIndexBefore(MI).listEntry()->getIterator();
nextItr = std::next(prevItr);
}
@@ -600,27 +604,27 @@ namespace llvm {
unsigned dist = ((nextItr->getIndex() - prevItr->getIndex())/2) & ~3u;
unsigned newNumber = prevItr->getIndex() + dist;
- // Insert a new list entry for mi.
+ // Insert a new list entry for MI.
IndexList::iterator newItr =
- indexList.insert(nextItr, createEntry(mi, newNumber));
+ indexList.insert(nextItr, createEntry(&MI, newNumber));
// Renumber locally if we need to.
if (dist == 0)
renumberIndexes(newItr);
SlotIndex newIndex(&*newItr, SlotIndex::Slot_Block);
- mi2iMap.insert(std::make_pair(mi, newIndex));
+ mi2iMap.insert(std::make_pair(&MI, newIndex));
return newIndex;
}
/// Remove the given machine instruction from the mapping.
- void removeMachineInstrFromMaps(MachineInstr *mi) {
+ void removeMachineInstrFromMaps(MachineInstr &MI) {
// remove index -> MachineInstr and
// MachineInstr -> index mappings
- Mi2IndexMap::iterator mi2iItr = mi2iMap.find(mi);
+ Mi2IndexMap::iterator mi2iItr = mi2iMap.find(&MI);
if (mi2iItr != mi2iMap.end()) {
IndexListEntry *miEntry(mi2iItr->second.listEntry());
- assert(miEntry->getInstr() == mi && "Instruction indexes broken.");
+ assert(miEntry->getInstr() == &MI && "Instruction indexes broken.");
// FIXME: Eventually we want to actually delete these indexes.
miEntry->setInstr(nullptr);
mi2iMap.erase(mi2iItr);
@@ -629,17 +633,17 @@ namespace llvm {
/// ReplaceMachineInstrInMaps - Replacing a machine instr with a new one in
/// maps used by register allocator.
- void replaceMachineInstrInMaps(MachineInstr *mi, MachineInstr *newMI) {
- Mi2IndexMap::iterator mi2iItr = mi2iMap.find(mi);
+ void replaceMachineInstrInMaps(MachineInstr &MI, MachineInstr &NewMI) {
+ Mi2IndexMap::iterator mi2iItr = mi2iMap.find(&MI);
if (mi2iItr == mi2iMap.end())
return;
SlotIndex replaceBaseIndex = mi2iItr->second;
IndexListEntry *miEntry(replaceBaseIndex.listEntry());
- assert(miEntry->getInstr() == mi &&
+ assert(miEntry->getInstr() == &MI &&
"Mismatched instruction in index tables.");
- miEntry->setInstr(newMI);
+ miEntry->setInstr(&NewMI);
mi2iMap.erase(mi2iItr);
- mi2iMap.insert(std::make_pair(newMI, replaceBaseIndex));
+ mi2iMap.insert(std::make_pair(&NewMI, replaceBaseIndex));
}
/// Add the given MachineBasicBlock into the maps.
@@ -703,15 +707,13 @@ namespace llvm {
indexList.erase(entry);
#endif
}
-
};
-
// Specialize IntervalMapInfo for half-open slot index intervals.
template <>
struct IntervalMapInfo<SlotIndex> : IntervalMapHalfOpenInfo<SlotIndex> {
};
-}
+} // end namespace llvm
#endif // LLVM_CODEGEN_SLOTINDEXES_H
diff --git a/include/llvm/CodeGen/StackMaps.h b/include/llvm/CodeGen/StackMaps.h
index 972a616ad779..918848f6b2a1 100644
--- a/include/llvm/CodeGen/StackMaps.h
+++ b/include/llvm/CodeGen/StackMaps.h
@@ -14,8 +14,6 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/MC/MCSymbol.h"
-#include "llvm/Support/Debug.h"
-#include <map>
#include <vector>
namespace llvm {
diff --git a/include/llvm/CodeGen/StackProtector.h b/include/llvm/CodeGen/StackProtector.h
index 8cef85cb4485..1b3c0eb4a4d0 100644
--- a/include/llvm/CodeGen/StackProtector.h
+++ b/include/llvm/CodeGen/StackProtector.h
@@ -75,6 +75,12 @@ private:
/// times.
SmallPtrSet<const PHINode *, 16> VisitedPHIs;
+ // A prologue is generated.
+ bool HasPrologue = false;
+
+ // IR checking code is generated.
+ bool HasIRCheck = false;
+
/// InsertStackProtectors - Insert code into the prologue and epilogue of
/// the function.
///
@@ -120,6 +126,10 @@ public:
}
SSPLayoutKind getSSPLayout(const AllocaInst *AI) const;
+
+ // Return true if StackProtector is supposed to be handled by SelectionDAG.
+ bool shouldEmitSDCheck(const BasicBlock &BB) const;
+
void adjustForColoring(const AllocaInst *From, const AllocaInst *To);
bool runOnFunction(Function &Fn) override;
diff --git a/include/llvm/CodeGen/TailDuplicator.h b/include/llvm/CodeGen/TailDuplicator.h
new file mode 100644
index 000000000000..8e65199418a6
--- /dev/null
+++ b/include/llvm/CodeGen/TailDuplicator.h
@@ -0,0 +1,92 @@
+//===-- llvm/CodeGen/TailDuplicator.h ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the TailDuplicator class. Used by the
+// TailDuplication pass, and MachineBlockPlacement.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_TAILDUPLICATOR_H
+#define LLVM_CODEGEN_TAILDUPLICATOR_H
+
+#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/MachineSSAUpdater.h"
+#include "llvm/CodeGen/RegisterScavenging.h"
+#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
+
+namespace llvm {
+
+/// Utility class to perform tail duplication.
+class TailDuplicator {
+ const TargetInstrInfo *TII;
+ const TargetRegisterInfo *TRI;
+ const MachineBranchProbabilityInfo *MBPI;
+ const MachineModuleInfo *MMI;
+ MachineRegisterInfo *MRI;
+ bool PreRegAlloc;
+
+ // A list of virtual registers for which to update SSA form.
+ SmallVector<unsigned, 16> SSAUpdateVRs;
+
+ // For each virtual register in SSAUpdateVals keep a list of source virtual
+ // registers.
+ typedef std::vector<std::pair<MachineBasicBlock *, unsigned>> AvailableValsTy;
+
+ DenseMap<unsigned, AvailableValsTy> SSAUpdateVals;
+
+public:
+ void initMF(MachineFunction &MF, const MachineModuleInfo *MMI,
+ const MachineBranchProbabilityInfo *MBPI);
+ bool tailDuplicateBlocks(MachineFunction &MF);
+ static bool isSimpleBB(MachineBasicBlock *TailBB);
+ bool shouldTailDuplicate(const MachineFunction &MF, bool IsSimple,
+ MachineBasicBlock &TailBB);
+ bool tailDuplicateAndUpdate(MachineFunction &MF, bool IsSimple,
+ MachineBasicBlock *MBB);
+
+private:
+ typedef TargetInstrInfo::RegSubRegPair RegSubRegPair;
+
+ void addSSAUpdateEntry(unsigned OrigReg, unsigned NewReg,
+ MachineBasicBlock *BB);
+ void processPHI(MachineInstr *MI, MachineBasicBlock *TailBB,
+ MachineBasicBlock *PredBB,
+ DenseMap<unsigned, RegSubRegPair> &LocalVRMap,
+ SmallVectorImpl<std::pair<unsigned, RegSubRegPair>> &Copies,
+ const DenseSet<unsigned> &UsedByPhi, bool Remove);
+ void duplicateInstruction(MachineInstr *MI, MachineBasicBlock *TailBB,
+ MachineBasicBlock *PredBB, MachineFunction &MF,
+ DenseMap<unsigned, RegSubRegPair> &LocalVRMap,
+ const DenseSet<unsigned> &UsedByPhi);
+ void updateSuccessorsPHIs(MachineBasicBlock *FromBB, bool isDead,
+ SmallVectorImpl<MachineBasicBlock *> &TDBBs,
+ SmallSetVector<MachineBasicBlock *, 8> &Succs);
+ bool canCompletelyDuplicateBB(MachineBasicBlock &BB);
+ bool duplicateSimpleBB(MachineBasicBlock *TailBB,
+ SmallVectorImpl<MachineBasicBlock *> &TDBBs,
+ const DenseSet<unsigned> &RegsUsedByPhi,
+ SmallVectorImpl<MachineInstr *> &Copies);
+ bool tailDuplicate(MachineFunction &MF, bool IsSimple,
+ MachineBasicBlock *TailBB,
+ SmallVectorImpl<MachineBasicBlock *> &TDBBs,
+ SmallVectorImpl<MachineInstr *> &Copies);
+ void appendCopies(MachineBasicBlock *MBB,
+ SmallVectorImpl<std::pair<unsigned,RegSubRegPair>> &CopyInfos,
+ SmallVectorImpl<MachineInstr *> &Copies);
+
+ void removeDeadBlock(MachineBasicBlock *MBB);
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
index 2f1379131cbd..c856435f5ddc 100644
--- a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
+++ b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
@@ -15,7 +15,7 @@
#ifndef LLVM_CODEGEN_TARGETLOWERINGOBJECTFILEIMPL_H
#define LLVM_CODEGEN_TARGETLOWERINGOBJECTFILEIMPL_H
-#include "llvm/ADT/StringRef.h"
+#include "llvm/MC/MCExpr.h"
#include "llvm/MC/SectionKind.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
@@ -23,7 +23,6 @@ namespace llvm {
class MachineModuleInfo;
class Mangler;
class MCAsmInfo;
- class MCExpr;
class MCSection;
class MCSectionMachO;
class MCSymbol;
@@ -36,6 +35,10 @@ class TargetLoweringObjectFileELF : public TargetLoweringObjectFile {
bool UseInitArray;
mutable unsigned NextUniqueID = 0;
+protected:
+ MCSymbolRefExpr::VariantKind PLTRelativeVariantKind =
+ MCSymbolRefExpr::VK_None;
+
public:
TargetLoweringObjectFileELF() : UseInitArray(false) {}
@@ -47,7 +50,8 @@ public:
/// Given a constant with the SectionKind, return a section that it should be
/// placed in.
MCSection *getSectionForConstant(const DataLayout &DL, SectionKind Kind,
- const Constant *C) const override;
+ const Constant *C,
+ unsigned &Align) const override;
MCSection *getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind,
Mangler &Mang,
@@ -81,6 +85,10 @@ public:
const MCSymbol *KeySym) const override;
MCSection *getStaticDtorSection(unsigned Priority,
const MCSymbol *KeySym) const override;
+
+ const MCExpr *lowerRelativeReference(const GlobalValue *LHS,
+ const GlobalValue *RHS, Mangler &Mang,
+ const TargetMachine &TM) const override;
};
@@ -104,7 +112,8 @@ public:
const TargetMachine &TM) const override;
MCSection *getSectionForConstant(const DataLayout &DL, SectionKind Kind,
- const Constant *C) const override;
+ const Constant *C,
+ unsigned &Align) const override;
/// The mach-o version of this method defaults to returning a stub reference.
const MCExpr *
@@ -131,6 +140,8 @@ public:
class TargetLoweringObjectFileCOFF : public TargetLoweringObjectFile {
+ mutable unsigned NextUniqueID = 0;
+
public:
~TargetLoweringObjectFileCOFF() override {}
diff --git a/include/llvm/CodeGen/TargetPassConfig.h b/include/llvm/CodeGen/TargetPassConfig.h
new file mode 100644
index 000000000000..9309655a972e
--- /dev/null
+++ b/include/llvm/CodeGen/TargetPassConfig.h
@@ -0,0 +1,376 @@
+//===-- TargetPassConfig.h - Code Generation pass options -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// Target-Independent Code Generator Pass Configuration Options pass.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_TARGETPASSCONFIG_H
+#define LLVM_CODEGEN_TARGETPASSCONFIG_H
+
+#include "llvm/Pass.h"
+#include "llvm/Support/CodeGen.h"
+#include <string>
+
+namespace llvm {
+
+class PassConfigImpl;
+class ScheduleDAGInstrs;
+class TargetMachine;
+struct MachineSchedContext;
+
+// The old pass manager infrastructure is hidden in a legacy namespace now.
+namespace legacy {
+class PassManagerBase;
+}
+using legacy::PassManagerBase;
+
+/// Discriminated union of Pass ID types.
+///
+/// The PassConfig API prefers dealing with IDs because they are safer and more
+/// efficient. IDs decouple configuration from instantiation. This way, when a
+/// pass is overriden, it isn't unnecessarily instantiated. It is also unsafe to
+/// refer to a Pass pointer after adding it to a pass manager, which deletes
+/// redundant pass instances.
+///
+/// However, it is convient to directly instantiate target passes with
+/// non-default ctors. These often don't have a registered PassInfo. Rather than
+/// force all target passes to implement the pass registry boilerplate, allow
+/// the PassConfig API to handle either type.
+///
+/// AnalysisID is sadly char*, so PointerIntPair won't work.
+class IdentifyingPassPtr {
+ union {
+ AnalysisID ID;
+ Pass *P;
+ };
+ bool IsInstance;
+public:
+ IdentifyingPassPtr() : P(nullptr), IsInstance(false) {}
+ IdentifyingPassPtr(AnalysisID IDPtr) : ID(IDPtr), IsInstance(false) {}
+ IdentifyingPassPtr(Pass *InstancePtr) : P(InstancePtr), IsInstance(true) {}
+
+ bool isValid() const { return P; }
+ bool isInstance() const { return IsInstance; }
+
+ AnalysisID getID() const {
+ assert(!IsInstance && "Not a Pass ID");
+ return ID;
+ }
+ Pass *getInstance() const {
+ assert(IsInstance && "Not a Pass Instance");
+ return P;
+ }
+};
+
+template <> struct isPodLike<IdentifyingPassPtr> {
+ static const bool value = true;
+};
+
+/// Target-Independent Code Generator Pass Configuration Options.
+///
+/// This is an ImmutablePass solely for the purpose of exposing CodeGen options
+/// to the internals of other CodeGen passes.
+class TargetPassConfig : public ImmutablePass {
+public:
+ /// Pseudo Pass IDs. These are defined within TargetPassConfig because they
+ /// are unregistered pass IDs. They are only useful for use with
+ /// TargetPassConfig APIs to identify multiple occurrences of the same pass.
+ ///
+
+ /// EarlyTailDuplicate - A clone of the TailDuplicate pass that runs early
+ /// during codegen, on SSA form.
+ static char EarlyTailDuplicateID;
+
+ /// PostRAMachineLICM - A clone of the LICM pass that runs during late machine
+ /// optimization after regalloc.
+ static char PostRAMachineLICMID;
+
+private:
+ PassManagerBase *PM;
+ AnalysisID StartBefore, StartAfter;
+ AnalysisID StopAfter;
+ bool Started;
+ bool Stopped;
+ bool AddingMachinePasses;
+
+protected:
+ TargetMachine *TM;
+ PassConfigImpl *Impl; // Internal data structures
+ bool Initialized; // Flagged after all passes are configured.
+
+ // Target Pass Options
+ // Targets provide a default setting, user flags override.
+ //
+ bool DisableVerify;
+
+ /// Default setting for -enable-tail-merge on this target.
+ bool EnableTailMerge;
+
+public:
+ TargetPassConfig(TargetMachine *tm, PassManagerBase &pm);
+ // Dummy constructor.
+ TargetPassConfig();
+
+ ~TargetPassConfig() override;
+
+ static char ID;
+
+ /// Get the right type of TargetMachine for this target.
+ template<typename TMC> TMC &getTM() const {
+ return *static_cast<TMC*>(TM);
+ }
+
+ //
+ void setInitialized() { Initialized = true; }
+
+ CodeGenOpt::Level getOptLevel() const;
+
+ /// Set the StartAfter, StartBefore and StopAfter passes to allow running only
+ /// a portion of the normal code-gen pass sequence.
+ ///
+ /// If the StartAfter and StartBefore pass ID is zero, then compilation will
+ /// begin at the normal point; otherwise, clear the Started flag to indicate
+ /// that passes should not be added until the starting pass is seen. If the
+ /// Stop pass ID is zero, then compilation will continue to the end.
+ ///
+ /// This function expects that at least one of the StartAfter or the
+ /// StartBefore pass IDs is null.
+ void setStartStopPasses(AnalysisID StartBefore, AnalysisID StartAfter,
+ AnalysisID StopAfter) {
+ if (StartAfter)
+ assert(!StartBefore && "Start after and start before passes are given");
+ this->StartBefore = StartBefore;
+ this->StartAfter = StartAfter;
+ this->StopAfter = StopAfter;
+ Started = (StartAfter == nullptr) && (StartBefore == nullptr);
+ }
+
+ void setDisableVerify(bool Disable) { setOpt(DisableVerify, Disable); }
+
+ bool getEnableTailMerge() const { return EnableTailMerge; }
+ void setEnableTailMerge(bool Enable) { setOpt(EnableTailMerge, Enable); }
+
+ /// Allow the target to override a specific pass without overriding the pass
+ /// pipeline. When passes are added to the standard pipeline at the
+ /// point where StandardID is expected, add TargetID in its place.
+ void substitutePass(AnalysisID StandardID, IdentifyingPassPtr TargetID);
+
+ /// Insert InsertedPassID pass after TargetPassID pass.
+ void insertPass(AnalysisID TargetPassID, IdentifyingPassPtr InsertedPassID,
+ bool VerifyAfter = true, bool PrintAfter = true);
+
+ /// Allow the target to enable a specific standard pass by default.
+ void enablePass(AnalysisID PassID) { substitutePass(PassID, PassID); }
+
+ /// Allow the target to disable a specific standard pass by default.
+ void disablePass(AnalysisID PassID) {
+ substitutePass(PassID, IdentifyingPassPtr());
+ }
+
+ /// Return the pass substituted for StandardID by the target.
+ /// If no substitution exists, return StandardID.
+ IdentifyingPassPtr getPassSubstitution(AnalysisID StandardID) const;
+
+ /// Return true if the pass has been substituted by the target or
+ /// overridden on the command line.
+ bool isPassSubstitutedOrOverridden(AnalysisID ID) const;
+
+ /// Return true if the optimized regalloc pipeline is enabled.
+ bool getOptimizeRegAlloc() const;
+
+ /// Return true if shrink wrapping is enabled.
+ bool getEnableShrinkWrap() const;
+
+ /// Return true if the default global register allocator is in use and
+ /// has not be overriden on the command line with '-regalloc=...'
+ bool usingDefaultRegAlloc() const;
+
+ /// Add common target configurable passes that perform LLVM IR to IR
+ /// transforms following machine independent optimization.
+ virtual void addIRPasses();
+
+ /// Add passes to lower exception handling for the code generator.
+ void addPassesToHandleExceptions();
+
+ /// Add pass to prepare the LLVM IR for code generation. This should be done
+ /// before exception handling preparation passes.
+ virtual void addCodeGenPrepare();
+
+ /// Add common passes that perform LLVM IR to IR transforms in preparation for
+ /// instruction selection.
+ virtual void addISelPrepare();
+
+ /// addInstSelector - This method should install an instruction selector pass,
+ /// which converts from LLVM code to machine instructions.
+ virtual bool addInstSelector() {
+ return true;
+ }
+
+ /// This method should install an IR translator pass, which converts from
+ /// LLVM code to machine instructions with possibly generic opcodes.
+ virtual bool addIRTranslator() { return true; }
+
+ /// This method may be implemented by targets that want to run passes
+ /// immediately before the register bank selection.
+ virtual void addPreRegBankSelect() {}
+
+ /// This method should install a register bank selector pass, which
+ /// assigns register banks to virtual registers without a register
+ /// class or register banks.
+ virtual bool addRegBankSelect() { return true; }
+
+ /// Add the complete, standard set of LLVM CodeGen passes.
+ /// Fully developed targets will not generally override this.
+ virtual void addMachinePasses();
+
+ /// Create an instance of ScheduleDAGInstrs to be run within the standard
+ /// MachineScheduler pass for this function and target at the current
+ /// optimization level.
+ ///
+ /// This can also be used to plug a new MachineSchedStrategy into an instance
+ /// of the standard ScheduleDAGMI:
+ /// return new ScheduleDAGMI(C, make_unique<MyStrategy>(C), /*RemoveKillFlags=*/false)
+ ///
+ /// Return NULL to select the default (generic) machine scheduler.
+ virtual ScheduleDAGInstrs *
+ createMachineScheduler(MachineSchedContext *C) const {
+ return nullptr;
+ }
+
+ /// Similar to createMachineScheduler but used when postRA machine scheduling
+ /// is enabled.
+ virtual ScheduleDAGInstrs *
+ createPostMachineScheduler(MachineSchedContext *C) const {
+ return nullptr;
+ }
+
+ /// printAndVerify - Add a pass to dump then verify the machine function, if
+ /// those steps are enabled.
+ ///
+ void printAndVerify(const std::string &Banner);
+
+ /// Add a pass to print the machine function if printing is enabled.
+ void addPrintPass(const std::string &Banner);
+
+ /// Add a pass to perform basic verification of the machine function if
+ /// verification is enabled.
+ void addVerifyPass(const std::string &Banner);
+
+protected:
+ // Helper to verify the analysis is really immutable.
+ void setOpt(bool &Opt, bool Val);
+
+ /// 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.
+ ///
+
+ /// addPreISelPasses - This method should add any "last minute" LLVM->LLVM
+ /// passes (which are run just before instruction selector).
+ virtual bool addPreISel() {
+ return true;
+ }
+
+ /// addMachineSSAOptimization - Add standard passes that optimize machine
+ /// instructions in SSA form.
+ virtual void addMachineSSAOptimization();
+
+ /// 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.
+ virtual bool addILPOpts() {
+ return false;
+ }
+
+ /// This method may be implemented by targets that want to run passes
+ /// immediately before register allocation.
+ virtual void addPreRegAlloc() { }
+
+ /// createTargetRegisterAllocator - Create the register allocator pass for
+ /// this target at the current optimization level.
+ virtual FunctionPass *createTargetRegisterAllocator(bool Optimized);
+
+ /// addFastRegAlloc - Add the minimum set of target-independent passes that
+ /// are required for fast register allocation.
+ virtual void addFastRegAlloc(FunctionPass *RegAllocPass);
+
+ /// addOptimizedRegAlloc - Add passes related to register allocation.
+ /// LLVMTargetMachine provides standard regalloc passes for most targets.
+ virtual void addOptimizedRegAlloc(FunctionPass *RegAllocPass);
+
+ /// 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.
+ virtual bool addPreRewrite() {
+ return false;
+ }
+
+ /// This method may be implemented by targets that want to run passes after
+ /// register allocation pass pipeline but before prolog-epilog insertion.
+ virtual void addPostRegAlloc() { }
+
+ /// Add passes that optimize machine instructions after register allocation.
+ virtual void addMachineLateOptimization();
+
+ /// This method may be implemented by targets that want to run passes after
+ /// prolog-epilog insertion and before the second instruction scheduling pass.
+ virtual void addPreSched2() { }
+
+ /// addGCPasses - Add late codegen passes that analyze code for garbage
+ /// collection. This should return true if GC info should be printed after
+ /// these passes.
+ virtual bool addGCPasses();
+
+ /// Add standard basic block placement passes.
+ virtual void addBlockPlacement();
+
+ /// This pass may be implemented by targets that want to run passes
+ /// immediately before machine code is emitted.
+ virtual void addPreEmitPass() { }
+
+ /// Utilities for targets to add passes to the pass manager.
+ ///
+
+ /// 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);
+
+ /// 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);
+
+ /// addMachinePasses helper to create the target-selected or overriden
+ /// regalloc pass.
+ FunctionPass *createRegAllocPass(bool Optimized);
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/include/llvm/CodeGen/UnreachableBlockElim.h b/include/llvm/CodeGen/UnreachableBlockElim.h
new file mode 100644
index 000000000000..3e7afd4cd433
--- /dev/null
+++ b/include/llvm/CodeGen/UnreachableBlockElim.h
@@ -0,0 +1,37 @@
+//===-- UnreachableBlockElim.h - Remove unreachable blocks for codegen --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass is an extremely simple version of the SimplifyCFG pass. Its sole
+// job is to delete LLVM basic blocks that are not reachable from the entry
+// node. To do this, it performs a simple depth first traversal of the CFG,
+// then deletes any unvisited nodes.
+//
+// Note that this pass is really a hack. In particular, the instruction
+// selectors for various targets should just not generate code for unreachable
+// blocks. Until LLVM has a more systematic way of defining instruction
+// selectors, however, we cannot really expect them to handle additional
+// complexity.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_CODEGEN_UNREACHABLEBLOCKELIM_H
+#define LLVM_LIB_CODEGEN_UNREACHABLEBLOCKELIM_H
+
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+class UnreachableBlockElimPass
+ : public PassInfoMixin<UnreachableBlockElimPass> {
+public:
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+};
+} // end namespace llvm
+
+#endif // LLVM_LIB_CODEGEN_UNREACHABLEBLOCKELIM_H
diff --git a/include/llvm/CodeGen/ValueTypes.h b/include/llvm/CodeGen/ValueTypes.h
index 929eb88a0393..524a90803df8 100644
--- a/include/llvm/CodeGen/ValueTypes.h
+++ b/include/llvm/CodeGen/ValueTypes.h
@@ -124,6 +124,11 @@ namespace llvm {
return isSimple() ? V.isInteger() : isExtendedInteger();
}
+ /// isScalarInteger - Return true if this is an integer, but not a vector.
+ bool isScalarInteger() const {
+ return isSimple() ? V.isScalarInteger() : isExtendedScalarInteger();
+ }
+
/// isVector - Return true if this is a vector value type.
bool isVector() const {
return isSimple() ? V.isVector() : isExtendedVector();
@@ -367,6 +372,7 @@ namespace llvm {
unsigned NumElements);
bool isExtendedFloatingPoint() const LLVM_READONLY;
bool isExtendedInteger() const LLVM_READONLY;
+ bool isExtendedScalarInteger() const LLVM_READONLY;
bool isExtendedVector() const LLVM_READONLY;
bool isExtended16BitVector() const LLVM_READONLY;
bool isExtended32BitVector() const LLVM_READONLY;
@@ -378,7 +384,7 @@ namespace llvm {
bool isExtended2048BitVector() const LLVM_READONLY;
EVT getExtendedVectorElementType() const;
unsigned getExtendedVectorNumElements() const LLVM_READONLY;
- unsigned getExtendedSizeInBits() const;
+ unsigned getExtendedSizeInBits() const LLVM_READONLY;
};
} // End llvm namespace
diff --git a/include/llvm/CodeGen/ValueTypes.td b/include/llvm/CodeGen/ValueTypes.td
index f29ec42714e8..f7b1661d7451 100644
--- a/include/llvm/CodeGen/ValueTypes.td
+++ b/include/llvm/CodeGen/ValueTypes.td
@@ -39,8 +39,8 @@ def v8i1 : ValueType<8 , 15>; // 8 x i1 vector value
def v16i1 : ValueType<16, 16>; // 16 x i1 vector value
def v32i1 : ValueType<32 , 17>; // 32 x i1 vector value
def v64i1 : ValueType<64 , 18>; // 64 x i1 vector value
-def v512i1 : ValueType<512, 19>; // 512 x i8 vector value
-def v1024i1: ValueType<1024,20>; //1024 x i8 vector value
+def v512i1 : ValueType<512, 19>; // 512 x i1 vector value
+def v1024i1: ValueType<1024,20>; //1024 x i1 vector value
def v1i8 : ValueType<16, 21>; // 1 x i8 vector value
def v2i8 : ValueType<16 , 22>; // 2 x i8 vector value
@@ -96,24 +96,24 @@ def x86mmx : ValueType<64 , 64>; // X86 MMX value
def FlagVT : ValueType<0 , 65>; // Pre-RA sched glue
def isVoid : ValueType<0 , 66>; // Produces no value
def untyped: ValueType<8 , 67>; // Produces an untyped value
-def token : ValueType<0 , 249>; // TokenTy
-def MetadataVT: ValueType<0, 250>; // Metadata
+def token : ValueType<0 , 120>; // TokenTy
+def MetadataVT: ValueType<0, 121>; // Metadata
// Pseudo valuetype mapped to the current pointer size to any address space.
// Should only be used in TableGen.
-def iPTRAny : ValueType<0, 251>;
+def iPTRAny : ValueType<0, 122>;
// Pseudo valuetype to represent "vector of any size"
-def vAny : ValueType<0 , 252>;
+def vAny : ValueType<0 , 123>;
// Pseudo valuetype to represent "float of any format"
-def fAny : ValueType<0 , 253>;
+def fAny : ValueType<0 , 124>;
// Pseudo valuetype to represent "integer of any bit width"
-def iAny : ValueType<0 , 254>;
+def iAny : ValueType<0 , 125>;
// Pseudo valuetype mapped to the current pointer size.
-def iPTR : ValueType<0 , 255>;
+def iPTR : ValueType<0 , 126>;
// Pseudo valuetype to represent "any type of any size".
-def Any : ValueType<0 , 256>;
+def Any : ValueType<0 , 127>;
diff --git a/include/llvm/CodeGen/WinEHFuncInfo.h b/include/llvm/CodeGen/WinEHFuncInfo.h
index 46c1029f62cf..dd730495a5f6 100644
--- a/include/llvm/CodeGen/WinEHFuncInfo.h
+++ b/include/llvm/CodeGen/WinEHFuncInfo.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/TinyPtrVector.h"
+#include "llvm/IR/Instructions.h"
namespace llvm {
class AllocaInst;
@@ -108,6 +109,7 @@ struct WinEHFuncInfo {
int EHRegNodeFrameIndex = INT_MAX;
int EHRegNodeEndOffset = INT_MAX;
+ int EHGuardFrameIndex = INT_MAX;
int SEHSetFrameOffset = INT_MAX;
WinEHFuncInfo();
diff --git a/include/llvm/Config/config.h.cmake b/include/llvm/Config/config.h.cmake
index 6a5ac889e6f0..45b30d9171d9 100644
--- a/include/llvm/Config/config.h.cmake
+++ b/include/llvm/Config/config.h.cmake
@@ -1,5 +1,3 @@
-/* include/llvm/Config/config.h.cmake corresponding to config.h.in. */
-
#ifndef CONFIG_H
#define CONFIG_H
@@ -15,15 +13,9 @@
/* Define to enable crash overrides */
#cmakedefine ENABLE_CRASH_OVERRIDES
-/* Define to disable C++ atexit */
-#cmakedefine DISABLE_LLVM_DYLIB_ATEXIT
-
/* Define if position independent code is enabled */
#cmakedefine ENABLE_PIC
-/* Define if timestamp information (e.g., __DATE__) is allowed */
-#cmakedefine ENABLE_TIMESTAMPS ${ENABLE_TIMESTAMPS}
-
/* Define to 1 if you have the `arc4random' function. */
#cmakedefine HAVE_DECL_ARC4RANDOM ${HAVE_DECL_ARC4RANDOM}
@@ -256,6 +248,9 @@
/* Define if you have the shl_load function. */
#undef HAVE_SHL_LOAD
+/* Define to 1 if you have the `sigaltstack' function. */
+#cmakedefine HAVE_SIGALTSTACK ${HAVE_SIGALTSTACK}
+
/* Define to 1 if you have the `siglongjmp' function. */
#cmakedefine HAVE_SIGLONGJMP ${HAVE_SIGLONGJMP}
@@ -327,6 +322,9 @@
/* Define if the setupterm() function is supported this platform. */
#cmakedefine HAVE_TERMINFO ${HAVE_TERMINFO}
+/* Define if the xar_open() function is supported this platform. */
+#cmakedefine HAVE_LIBXAR ${HAVE_LIBXAR}
+
/* Define to 1 if you have the <termios.h> header file. */
#cmakedefine HAVE_TERMIOS_H ${HAVE_TERMIOS_H}
@@ -336,6 +334,9 @@
/* Define to 1 if you have the <unistd.h> header file. */
#cmakedefine HAVE_UNISTD_H ${HAVE_UNISTD_H}
+/* Define to 1 if you have the `_Unwind_Backtrace' function. */
+#cmakedefine HAVE_UNWIND_BACKTRACE ${HAVE_UNWIND_BACKTRACE}
+
/* Define to 1 if you have the <utime.h> header file. */
#cmakedefine HAVE_UTIME_H ${HAVE_UTIME_H}
@@ -504,6 +505,9 @@
/* LLVM version string */
#define LLVM_VERSION_STRING "${PACKAGE_VERSION}"
+/* LLVM version information */
+#cmakedefine LLVM_VERSION_INFO "${LLVM_VERSION_INFO}"
+
/* Define if we link Polly to the tools */
#cmakedefine LINK_POLLY_INTO_TOOLS
@@ -542,6 +546,9 @@
/* Define to the version of this package. */
#cmakedefine PACKAGE_VERSION "${PACKAGE_VERSION}"
+/* Define to the vendor of this package. */
+#cmakedefine PACKAGE_VENDOR "${PACKAGE_VENDOR}"
+
/* Define as the return type of signal handlers (`int' or `void'). */
#cmakedefine RETSIGTYPE ${RETSIGTYPE}
@@ -557,9 +564,6 @@
/* Define to 1 if your <sys/time.h> declares `struct tm'. */
#undef TM_IN_SYS_TIME
-/* Type of 1st arg on ELM Callback */
-#cmakedefine WIN32_ELMCB_PCSTR ${WIN32_ELMCB_PCSTR}
-
/* Define to `int' if <sys/types.h> does not define. */
#undef pid_t
diff --git a/include/llvm/Config/config.h.in b/include/llvm/Config/config.h.in
deleted file mode 100644
index 498aa9ee6b5d..000000000000
--- a/include/llvm/Config/config.h.in
+++ /dev/null
@@ -1,538 +0,0 @@
-/* include/llvm/Config/config.h.in. Generated from autoconf/configure.ac by autoheader. */
-
-#ifndef CONFIG_H
-#define CONFIG_H
-
-/* Exported configuration */
-#include "llvm/Config/llvm-config.h"
-
-/* Bug report URL. */
-#undef BUG_REPORT_URL
-
-/* Default OpenMP runtime used by -fopenmp. */
-#undef CLANG_DEFAULT_OPENMP_RUNTIME
-
-/* Define if we have libxml2 */
-#undef CLANG_HAVE_LIBXML
-
-/* Multilib suffix for libdir. */
-#undef CLANG_LIBDIR_SUFFIX
-
-/* Relative directory for resource files */
-#undef CLANG_RESOURCE_DIR
-
-/* Directories clang will search for headers */
-#undef C_INCLUDE_DIRS
-
-/* Default <path> to all compiler invocations for --sysroot=<path>. */
-#undef DEFAULT_SYSROOT
-
-/* Define if you want backtraces on crash */
-#undef ENABLE_BACKTRACES
-
-/* Define to enable crash handling overrides */
-#undef ENABLE_CRASH_OVERRIDES
-
-/* Define if position independent code is enabled */
-#undef ENABLE_PIC
-
-/* Define if timestamp information (e.g., __DATE__) is allowed */
-#undef ENABLE_TIMESTAMPS
-
-/* Directory where gcc is installed. */
-#undef GCC_INSTALL_PREFIX
-
-/* Define to 1 if you have the `backtrace' function. */
-#undef HAVE_BACKTRACE
-
-/* Define to 1 if you have the <CrashReporterClient.h> header file. */
-#undef HAVE_CRASHREPORTERCLIENT_H
-
-/* can use __crashreporter_info__ */
-#undef HAVE_CRASHREPORTER_INFO
-
-/* Define to 1 if you have the <cxxabi.h> header file. */
-#undef HAVE_CXXABI_H
-
-/* Define to 1 if you have the declaration of `arc4random', and to 0 if you
- don't. */
-#undef HAVE_DECL_ARC4RANDOM
-
-/* Define to 1 if you have the declaration of `FE_ALL_EXCEPT', and to 0 if you
- don't. */
-#undef HAVE_DECL_FE_ALL_EXCEPT
-
-/* Define to 1 if you have the declaration of `FE_INEXACT', and to 0 if you
- don't. */
-#undef HAVE_DECL_FE_INEXACT
-
-/* Define to 1 if you have the declaration of `strerror_s', and to 0 if you
- don't. */
-#undef HAVE_DECL_STRERROR_S
-
-/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
- */
-#undef HAVE_DIRENT_H
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#undef HAVE_DLFCN_H
-
-/* Define if dlopen() is available on this platform. */
-#undef HAVE_DLOPEN
-
-/* Define if the dot program is available */
-#undef HAVE_DOT
-
-/* Define to 1 if you have the <errno.h> header file. */
-#undef HAVE_ERRNO_H
-
-/* Define to 1 if you have the <execinfo.h> header file. */
-#undef HAVE_EXECINFO_H
-
-/* Define to 1 if you have the <fcntl.h> header file. */
-#undef HAVE_FCNTL_H
-
-/* Define to 1 if you have the <fenv.h> header file. */
-#undef HAVE_FENV_H
-
-/* Define if libffi is available on this platform. */
-#undef HAVE_FFI_CALL
-
-/* Define to 1 if you have the <ffi/ffi.h> header file. */
-#undef HAVE_FFI_FFI_H
-
-/* Define to 1 if you have the <ffi.h> header file. */
-#undef HAVE_FFI_H
-
-/* Define to 1 if you have the `futimens' function. */
-#undef HAVE_FUTIMENS
-
-/* Define to 1 if you have the `futimes' function. */
-#undef HAVE_FUTIMES
-
-/* Define to 1 if you have the `getcwd' function. */
-#undef HAVE_GETCWD
-
-/* Define to 1 if you have the `getpagesize' function. */
-#undef HAVE_GETPAGESIZE
-
-/* Define to 1 if you have the `getrlimit' function. */
-#undef HAVE_GETRLIMIT
-
-/* Define to 1 if you have the `getrusage' function. */
-#undef HAVE_GETRUSAGE
-
-/* Define to 1 if you have the `gettimeofday' function. */
-#undef HAVE_GETTIMEOFDAY
-
-/* Define to 1 if the system has the type `int64_t'. */
-#undef HAVE_INT64_T
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#undef HAVE_INTTYPES_H
-
-/* Define to 1 if you have the `isatty' function. */
-#undef HAVE_ISATTY
-
-/* Define if libedit is available on this platform. */
-#undef HAVE_LIBEDIT
-
-/* Define to 1 if you have the `m' library (-lm). */
-#undef HAVE_LIBM
-
-/* Define to 1 if you have the `ole32' library (-lole32). */
-#undef HAVE_LIBOLE32
-
-/* Define to 1 if you have the `psapi' library (-lpsapi). */
-#undef HAVE_LIBPSAPI
-
-/* Define to 1 if you have the `pthread' library (-lpthread). */
-#undef HAVE_LIBPTHREAD
-
-/* Define to 1 if you have the `shell32' library (-lshell32). */
-#undef HAVE_LIBSHELL32
-
-/* Define to 1 if you have the `uuid' library (-luuid). */
-#undef HAVE_LIBUUID
-
-/* Define to 1 if you have the `z' library (-lz). */
-#undef HAVE_LIBZ
-
-/* Define if you can use -rdynamic. */
-#undef HAVE_LINK_EXPORT_DYNAMIC
-
-/* Define to 1 if you have the <link.h> header file. */
-#undef HAVE_LINK_H
-
-/* Define if you can use -Wl,-R. to pass -R. to the linker, in order to add
- the current directory to the dynamic linker search path. */
-#undef HAVE_LINK_R
-
-/* Define to 1 if you have the `longjmp' function. */
-#undef HAVE_LONGJMP
-
-/* Define to 1 if you have the <mach/mach.h> header file. */
-#undef HAVE_MACH_MACH_H
-
-/* Define if mallinfo() is available on this platform. */
-#undef HAVE_MALLINFO
-
-/* Define to 1 if you have the <malloc.h> header file. */
-#undef HAVE_MALLOC_H
-
-/* Define to 1 if you have the <malloc/malloc.h> header file. */
-#undef HAVE_MALLOC_MALLOC_H
-
-/* Define to 1 if you have the `malloc_zone_statistics' function. */
-#undef HAVE_MALLOC_ZONE_STATISTICS
-
-/* Define to 1 if you have the <memory.h> header file. */
-#undef HAVE_MEMORY_H
-
-/* Define to 1 if you have the `mkdtemp' function. */
-#undef HAVE_MKDTEMP
-
-/* Define to 1 if you have the `mkstemp' function. */
-#undef HAVE_MKSTEMP
-
-/* Define to 1 if you have the `mktemp' function. */
-#undef HAVE_MKTEMP
-
-/* Define to 1 if you have a working `mmap' system call. */
-#undef HAVE_MMAP
-
-/* Define if mmap() uses MAP_ANONYMOUS to map anonymous pages, or undefine if
- it uses MAP_ANON */
-#undef HAVE_MMAP_ANONYMOUS
-
-/* Define if mmap() can map files into memory */
-#undef HAVE_MMAP_FILE
-
-/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
-#undef HAVE_NDIR_H
-
-/* Define to 1 if you have the `posix_spawn' function. */
-#undef HAVE_POSIX_SPAWN
-
-/* Define to 1 if you have the `pread' function. */
-#undef HAVE_PREAD
-
-/* Define to have the %a format string */
-#undef HAVE_PRINTF_A
-
-/* Have pthread_getspecific */
-#undef HAVE_PTHREAD_GETSPECIFIC
-
-/* Define to 1 if you have the <pthread.h> header file. */
-#undef HAVE_PTHREAD_H
-
-/* Have pthread_mutex_lock */
-#undef HAVE_PTHREAD_MUTEX_LOCK
-
-/* Have pthread_rwlock_init */
-#undef HAVE_PTHREAD_RWLOCK_INIT
-
-/* Define to 1 if you have the `realpath' function. */
-#undef HAVE_REALPATH
-
-/* Define to 1 if you have the `sbrk' function. */
-#undef HAVE_SBRK
-
-/* Define to 1 if you have the `setenv' function. */
-#undef HAVE_SETENV
-
-/* Define to 1 if you have the `setjmp' function. */
-#undef HAVE_SETJMP
-
-/* Define to 1 if you have the <setjmp.h> header file. */
-#undef HAVE_SETJMP_H
-
-/* Define to 1 if you have the `setrlimit' function. */
-#undef HAVE_SETRLIMIT
-
-/* Define to 1 if you have the <signal.h> header file. */
-#undef HAVE_SIGNAL_H
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#undef HAVE_STDINT_H
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#undef HAVE_STDLIB_H
-
-/* Define to 1 if you have the `strerror' function. */
-#undef HAVE_STRERROR
-
-/* Define to 1 if you have the `strerror_r' function. */
-#undef HAVE_STRERROR_R
-
-/* Define to 1 if you have the <strings.h> header file. */
-#undef HAVE_STRINGS_H
-
-/* Define to 1 if you have the <string.h> header file. */
-#undef HAVE_STRING_H
-
-/* Define to 1 if you have the `strtoll' function. */
-#undef HAVE_STRTOLL
-
-/* Define to 1 if you have the `strtoq' function. */
-#undef HAVE_STRTOQ
-
-/* Define to 1 if you have the `sysconf' function. */
-#undef HAVE_SYSCONF
-
-/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
- */
-#undef HAVE_SYS_DIR_H
-
-/* Define to 1 if you have the <sys/ioctl.h> header file. */
-#undef HAVE_SYS_IOCTL_H
-
-/* Define to 1 if you have the <sys/mman.h> header file. */
-#undef HAVE_SYS_MMAN_H
-
-/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
- */
-#undef HAVE_SYS_NDIR_H
-
-/* Define to 1 if you have the <sys/param.h> header file. */
-#undef HAVE_SYS_PARAM_H
-
-/* Define to 1 if you have the <sys/resource.h> header file. */
-#undef HAVE_SYS_RESOURCE_H
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#undef HAVE_SYS_STAT_H
-
-/* Define to 1 if you have the <sys/time.h> header file. */
-#undef HAVE_SYS_TIME_H
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#undef HAVE_SYS_TYPES_H
-
-/* Define to 1 if you have the <sys/uio.h> header file. */
-#undef HAVE_SYS_UIO_H
-
-/* Define if the setupterm() function is supported this platform. */
-#undef HAVE_TERMINFO
-
-/* Define to 1 if you have the <termios.h> header file. */
-#undef HAVE_TERMIOS_H
-
-/* Define to 1 if the system has the type `uint64_t'. */
-#undef HAVE_UINT64_T
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#undef HAVE_UNISTD_H
-
-/* Define to 1 if the system has the type `u_int64_t'. */
-#undef HAVE_U_INT64_T
-
-/* Define to 1 if you have the <valgrind/valgrind.h> header file. */
-#undef HAVE_VALGRIND_VALGRIND_H
-
-/* Define to 1 if you have the `writev' function. */
-#undef HAVE_WRITEV
-
-/* Define to 1 if you have the <zlib.h> header file. */
-#undef HAVE_ZLIB_H
-
-/* Have host's _alloca */
-#undef HAVE__ALLOCA
-
-/* Have host's __alloca */
-#undef HAVE___ALLOCA
-
-/* Have host's __ashldi3 */
-#undef HAVE___ASHLDI3
-
-/* Have host's __ashrdi3 */
-#undef HAVE___ASHRDI3
-
-/* Have host's __chkstk */
-#undef HAVE___CHKSTK
-
-/* Have host's __chkstk_ms */
-#undef HAVE___CHKSTK_MS
-
-/* Have host's __cmpdi2 */
-#undef HAVE___CMPDI2
-
-/* Have host's __divdi3 */
-#undef HAVE___DIVDI3
-
-/* Define to 1 if you have the `__dso_handle' function. */
-#undef HAVE___DSO_HANDLE
-
-/* Have host's __fixdfdi */
-#undef HAVE___FIXDFDI
-
-/* Have host's __fixsfdi */
-#undef HAVE___FIXSFDI
-
-/* Have host's __floatdidf */
-#undef HAVE___FLOATDIDF
-
-/* Have host's __lshrdi3 */
-#undef HAVE___LSHRDI3
-
-/* Have host's __main */
-#undef HAVE___MAIN
-
-/* Have host's __moddi3 */
-#undef HAVE___MODDI3
-
-/* Have host's __udivdi3 */
-#undef HAVE___UDIVDI3
-
-/* Have host's __umoddi3 */
-#undef HAVE___UMODDI3
-
-/* Have host's ___chkstk */
-#undef HAVE____CHKSTK
-
-/* Have host's ___chkstk_ms */
-#undef HAVE____CHKSTK_MS
-
-/* Linker version detected at compile time. */
-#undef HOST_LINK_VERSION
-
-/* Installation directory for binary executables */
-#undef LLVM_BINDIR
-
-/* Time at which LLVM was configured */
-#undef LLVM_CONFIGTIME
-
-/* Installation directory for data files */
-#undef LLVM_DATADIR
-
-/* Target triple LLVM will generate code for by default */
-#undef LLVM_DEFAULT_TARGET_TRIPLE
-
-/* Installation directory for documentation */
-#undef LLVM_DOCSDIR
-
-/* Define to enable checks that alter the LLVM C++ ABI */
-#undef LLVM_ENABLE_ABI_BREAKING_CHECKS
-
-/* Define if threads enabled */
-#undef LLVM_ENABLE_THREADS
-
-/* Define if zlib is enabled */
-#undef LLVM_ENABLE_ZLIB
-
-/* Installation directory for config files */
-#undef LLVM_ETCDIR
-
-/* Has gcc/MSVC atomic intrinsics */
-#undef LLVM_HAS_ATOMICS
-
-/* Host triple LLVM will be executed on */
-#undef LLVM_HOST_TRIPLE
-
-/* Installation directory for include files */
-#undef LLVM_INCLUDEDIR
-
-/* Installation directory for .info files */
-#undef LLVM_INFODIR
-
-/* Installation directory for man pages */
-#undef LLVM_MANDIR
-
-/* LLVM architecture name for the native architecture, if available */
-#undef LLVM_NATIVE_ARCH
-
-/* LLVM name for the native AsmParser init function, if available */
-#undef LLVM_NATIVE_ASMPARSER
-
-/* LLVM name for the native AsmPrinter init function, if available */
-#undef LLVM_NATIVE_ASMPRINTER
-
-/* LLVM name for the native Disassembler init function, if available */
-#undef LLVM_NATIVE_DISASSEMBLER
-
-/* LLVM name for the native Target init function, if available */
-#undef LLVM_NATIVE_TARGET
-
-/* LLVM name for the native TargetInfo init function, if available */
-#undef LLVM_NATIVE_TARGETINFO
-
-/* LLVM name for the native target MC init function, if available */
-#undef LLVM_NATIVE_TARGETMC
-
-/* Define if this is Unixish platform */
-#undef LLVM_ON_UNIX
-
-/* Define if this is Win32ish platform */
-#undef LLVM_ON_WIN32
-
-/* Define to path to dot program if found or 'echo dot' otherwise */
-#undef LLVM_PATH_DOT
-
-/* Installation prefix directory */
-#undef LLVM_PREFIX
-
-/* Define if we have the Intel JIT API runtime support library */
-#undef LLVM_USE_INTEL_JITEVENTS
-
-/* Define if we have the oprofile JIT-support library */
-#undef LLVM_USE_OPROFILE
-
-/* Major version of the LLVM API */
-#undef LLVM_VERSION_MAJOR
-
-/* Minor version of the LLVM API */
-#undef LLVM_VERSION_MINOR
-
-/* Patch version of the LLVM API */
-#undef LLVM_VERSION_PATCH
-
-/* LLVM version string */
-#undef LLVM_VERSION_STRING
-
-/* The shared library extension */
-#undef LTDL_SHLIB_EXT
-
-/* Define if /dev/zero should be used when mapping RWX memory, or undefine if
- its not necessary */
-#undef NEED_DEV_ZERO_FOR_MMAP
-
-/* Define to the address where bug reports for this package should be sent. */
-#undef PACKAGE_BUGREPORT
-
-/* Define to the full name of this package. */
-#undef PACKAGE_NAME
-
-/* Define to the full name and version of this package. */
-#undef PACKAGE_STRING
-
-/* Define to the one symbol short name of this package. */
-#undef PACKAGE_TARNAME
-
-/* Define to the version of this package. */
-#undef PACKAGE_VERSION
-
-/* Define as the return type of signal handlers (`int' or `void'). */
-#undef RETSIGTYPE
-
-/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */
-#undef STAT_MACROS_BROKEN
-
-/* Define to 1 if you have the ANSI C header files. */
-#undef STDC_HEADERS
-
-/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
-#undef TIME_WITH_SYS_TIME
-
-/* Define to 1 if your <sys/time.h> declares `struct tm'. */
-#undef TM_IN_SYS_TIME
-
-/* Type of 1st arg on ELM Callback */
-#undef WIN32_ELMCB_PCSTR
-
-/* Define to `int' if <sys/types.h> does not define. */
-#undef pid_t
-
-/* Define to `unsigned int' if <sys/types.h> does not define. */
-#undef size_t
-
-#endif
diff --git a/include/llvm/Config/llvm-config.h.in b/include/llvm/Config/llvm-config.h.in
deleted file mode 100644
index 2dd5d0af7b58..000000000000
--- a/include/llvm/Config/llvm-config.h.in
+++ /dev/null
@@ -1,104 +0,0 @@
-/*===------- llvm/Config/llvm-config.h - llvm configuration -------*- C -*-===*/
-/* */
-/* The LLVM Compiler Infrastructure */
-/* */
-/* This file is distributed under the University of Illinois Open Source */
-/* License. See LICENSE.TXT for details. */
-/* */
-/*===----------------------------------------------------------------------===*/
-
-/* This file enumerates variables from the LLVM configuration so that they
- can be in exported headers and won't override package specific directives.
- This is a C header that can be included in the llvm-c headers. */
-
-#ifndef LLVM_CONFIG_H
-#define LLVM_CONFIG_H
-
-/* Installation directory for binary executables */
-#undef LLVM_BINDIR
-
-/* Time at which LLVM was configured */
-#undef LLVM_CONFIGTIME
-
-/* Installation directory for data files */
-#undef LLVM_DATADIR
-
-/* Target triple LLVM will generate code for by default */
-#undef LLVM_DEFAULT_TARGET_TRIPLE
-
-/* Installation directory for documentation */
-#undef LLVM_DOCSDIR
-
-/* Define to enable checks that alter the LLVM C++ ABI */
-#undef LLVM_ENABLE_ABI_BREAKING_CHECKS
-
-/* Define if threads enabled */
-#undef LLVM_ENABLE_THREADS
-
-/* Installation directory for config files */
-#undef LLVM_ETCDIR
-
-/* Has gcc/MSVC atomic intrinsics */
-#undef LLVM_HAS_ATOMICS
-
-/* Host triple LLVM will be executed on */
-#undef LLVM_HOST_TRIPLE
-
-/* Installation directory for include files */
-#undef LLVM_INCLUDEDIR
-
-/* Installation directory for .info files */
-#undef LLVM_INFODIR
-
-/* Installation directory for man pages */
-#undef LLVM_MANDIR
-
-/* LLVM architecture name for the native architecture, if available */
-#undef LLVM_NATIVE_ARCH
-
-/* LLVM name for the native AsmParser init function, if available */
-#undef LLVM_NATIVE_ASMPARSER
-
-/* LLVM name for the native AsmPrinter init function, if available */
-#undef LLVM_NATIVE_ASMPRINTER
-
-/* LLVM name for the native Disassembler init function, if available */
-#undef LLVM_NATIVE_DISASSEMBLER
-
-/* LLVM name for the native Target init function, if available */
-#undef LLVM_NATIVE_TARGET
-
-/* LLVM name for the native TargetInfo init function, if available */
-#undef LLVM_NATIVE_TARGETINFO
-
-/* LLVM name for the native target MC init function, if available */
-#undef LLVM_NATIVE_TARGETMC
-
-/* Define if this is Unixish platform */
-#undef LLVM_ON_UNIX
-
-/* Define if this is Win32ish platform */
-#undef LLVM_ON_WIN32
-
-/* Installation prefix directory */
-#undef LLVM_PREFIX
-
-/* Define if we have the Intel JIT API runtime support library */
-#undef LLVM_USE_INTEL_JITEVENTS
-
-/* Define if we have the oprofile JIT-support library */
-#undef LLVM_USE_OPROFILE
-
-/* Major version of the LLVM API */
-#undef LLVM_VERSION_MAJOR
-
-/* Minor version of the LLVM API */
-#undef LLVM_VERSION_MINOR
-
-/* Patch version of the LLVM API */
-#undef LLVM_VERSION_PATCH
-
-/* LLVM version string */
-#undef LLVM_VERSION_STRING
-
-#endif
diff --git a/include/llvm/DebugInfo/CodeView/ByteStream.h b/include/llvm/DebugInfo/CodeView/ByteStream.h
new file mode 100644
index 000000000000..f398c93723e7
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/ByteStream.h
@@ -0,0 +1,58 @@
+//===- ByteStream.h - Reads stream data from a byte sequence ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_BYTESTREAM_H
+#define LLVM_DEBUGINFO_CODEVIEW_BYTESTREAM_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/CodeView/StreamInterface.h"
+#include "llvm/Support/Error.h"
+#include <cstdint>
+#include <memory>
+#include <type_traits>
+
+namespace llvm {
+namespace codeview {
+class StreamReader;
+
+template <bool Writable = false> class ByteStream : public StreamInterface {
+ typedef typename std::conditional<Writable, MutableArrayRef<uint8_t>,
+ ArrayRef<uint8_t>>::type ArrayType;
+
+public:
+ ByteStream() {}
+ explicit ByteStream(ArrayType Data) : Data(Data) {}
+ ~ByteStream() override {}
+
+ Error readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) const override;
+ Error readLongestContiguousChunk(uint32_t Offset,
+ ArrayRef<uint8_t> &Buffer) const override;
+
+ Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Buffer) const override;
+
+ uint32_t getLength() const override;
+
+ Error commit() const override;
+
+ ArrayRef<uint8_t> data() const { return Data; }
+ StringRef str() const;
+
+private:
+ ArrayType Data;
+};
+
+extern template class ByteStream<true>;
+extern template class ByteStream<false>;
+
+} // end namespace pdb
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_CODEVIEW_BYTESTREAM_H
diff --git a/include/llvm/DebugInfo/CodeView/CVRecord.h b/include/llvm/DebugInfo/CodeView/CVRecord.h
new file mode 100644
index 000000000000..dba359fcbe82
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/CVRecord.h
@@ -0,0 +1,56 @@
+//===- RecordIterator.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_RECORDITERATOR_H
+#define LLVM_DEBUGINFO_CODEVIEW_RECORDITERATOR_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
+#include "llvm/DebugInfo/CodeView/StreamInterface.h"
+#include "llvm/DebugInfo/CodeView/StreamReader.h"
+#include "llvm/Support/Endian.h"
+
+namespace llvm {
+namespace codeview {
+
+template <typename Kind> struct CVRecord {
+ uint32_t Length;
+ Kind Type;
+ ArrayRef<uint8_t> Data;
+ ArrayRef<uint8_t> RawData;
+};
+
+template <typename Kind> struct VarStreamArrayExtractor<CVRecord<Kind>> {
+ Error operator()(StreamRef Stream, uint32_t &Len,
+ CVRecord<Kind> &Item) const {
+ const RecordPrefix *Prefix = nullptr;
+ StreamReader Reader(Stream);
+ uint32_t Offset = Reader.getOffset();
+
+ if (auto EC = Reader.readObject(Prefix))
+ return EC;
+ Item.Length = Prefix->RecordLen;
+ if (Item.Length < 2)
+ return make_error<CodeViewError>(cv_error_code::corrupt_record);
+ Item.Type = static_cast<Kind>(uint16_t(Prefix->RecordKind));
+
+ Reader.setOffset(Offset);
+ if (auto EC =
+ Reader.readBytes(Item.RawData, Item.Length + sizeof(uint16_t)))
+ return EC;
+ Item.Data = Item.RawData.slice(sizeof(RecordPrefix));
+ Len = Prefix->RecordLen + 2;
+ return Error::success();
+ }
+};
+}
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/CodeView/CVSymbolTypes.def b/include/llvm/DebugInfo/CodeView/CVSymbolTypes.def
new file mode 100644
index 000000000000..32813d861d90
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/CVSymbolTypes.def
@@ -0,0 +1,258 @@
+//===-- CVLeafTypes.def - All CodeView leaf types ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// See LEAF_ENUM_e in cvinfo.h. This should match the constants there.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CV_SYMBOL
+#define CV_SYMBOL(ename, value)
+#endif
+
+#ifndef SYMBOL_RECORD
+#define SYMBOL_RECORD(lf_ename, value, name) CV_SYMBOL(lf_ename, value)
+#endif
+
+#ifndef SYMBOL_RECORD_ALIAS
+#define SYMBOL_RECORD_ALIAS(lf_ename, value, name, alias_name) \
+ SYMBOL_RECORD(lf_ename, value, name)
+#endif
+
+// 16 bit symbol types. Not very useful, provided only for reference.
+CV_SYMBOL(S_COMPILE , 0x0001)
+CV_SYMBOL(S_REGISTER_16t , 0x0002)
+CV_SYMBOL(S_CONSTANT_16t , 0x0003)
+CV_SYMBOL(S_UDT_16t , 0x0004)
+CV_SYMBOL(S_SSEARCH , 0x0005)
+CV_SYMBOL(S_SKIP , 0x0007)
+CV_SYMBOL(S_CVRESERVE , 0x0008)
+CV_SYMBOL(S_OBJNAME_ST , 0x0009)
+CV_SYMBOL(S_ENDARG , 0x000a)
+CV_SYMBOL(S_COBOLUDT_16t , 0x000b)
+CV_SYMBOL(S_MANYREG_16t , 0x000c)
+CV_SYMBOL(S_RETURN , 0x000d)
+CV_SYMBOL(S_ENTRYTHIS , 0x000e)
+CV_SYMBOL(S_BPREL16 , 0x0100)
+CV_SYMBOL(S_LDATA16 , 0x0101)
+CV_SYMBOL(S_GDATA16 , 0x0102)
+CV_SYMBOL(S_PUB16 , 0x0103)
+CV_SYMBOL(S_LPROC16 , 0x0104)
+CV_SYMBOL(S_GPROC16 , 0x0105)
+CV_SYMBOL(S_THUNK16 , 0x0106)
+CV_SYMBOL(S_BLOCK16 , 0x0107)
+CV_SYMBOL(S_WITH16 , 0x0108)
+CV_SYMBOL(S_LABEL16 , 0x0109)
+CV_SYMBOL(S_CEXMODEL16 , 0x010a)
+CV_SYMBOL(S_VFTABLE16 , 0x010b)
+CV_SYMBOL(S_REGREL16 , 0x010c)
+CV_SYMBOL(S_BPREL32_16t , 0x0200)
+CV_SYMBOL(S_LDATA32_16t , 0x0201)
+CV_SYMBOL(S_GDATA32_16t , 0x0202)
+CV_SYMBOL(S_PUB32_16t , 0x0203)
+CV_SYMBOL(S_LPROC32_16t , 0x0204)
+CV_SYMBOL(S_GPROC32_16t , 0x0205)
+CV_SYMBOL(S_THUNK32_ST , 0x0206)
+CV_SYMBOL(S_BLOCK32_ST , 0x0207)
+CV_SYMBOL(S_WITH32_ST , 0x0208)
+CV_SYMBOL(S_LABEL32_ST , 0x0209)
+CV_SYMBOL(S_CEXMODEL32 , 0x020a)
+CV_SYMBOL(S_VFTABLE32_16t , 0x020b)
+CV_SYMBOL(S_REGREL32_16t , 0x020c)
+CV_SYMBOL(S_LTHREAD32_16t , 0x020d)
+CV_SYMBOL(S_GTHREAD32_16t , 0x020e)
+CV_SYMBOL(S_SLINK32 , 0x020f)
+CV_SYMBOL(S_LPROCMIPS_16t , 0x0300)
+CV_SYMBOL(S_GPROCMIPS_16t , 0x0301)
+CV_SYMBOL(S_PROCREF_ST , 0x0400)
+CV_SYMBOL(S_DATAREF_ST , 0x0401)
+CV_SYMBOL(S_ALIGN , 0x0402)
+CV_SYMBOL(S_LPROCREF_ST , 0x0403)
+CV_SYMBOL(S_OEM , 0x0404)
+
+// All post 16 bit symbol types have the 0x1000 bit set.
+CV_SYMBOL(S_TI16_MAX , 0x1000)
+
+// Mostly unused "start" symbol types.
+CV_SYMBOL(S_REGISTER_ST , 0x1001)
+CV_SYMBOL(S_CONSTANT_ST , 0x1002)
+CV_SYMBOL(S_UDT_ST , 0x1003)
+CV_SYMBOL(S_COBOLUDT_ST , 0x1004)
+CV_SYMBOL(S_MANYREG_ST , 0x1005)
+CV_SYMBOL(S_BPREL32_ST , 0x1006)
+CV_SYMBOL(S_LDATA32_ST , 0x1007)
+CV_SYMBOL(S_GDATA32_ST , 0x1008)
+CV_SYMBOL(S_PUB32_ST , 0x1009)
+CV_SYMBOL(S_LPROC32_ST , 0x100a)
+CV_SYMBOL(S_GPROC32_ST , 0x100b)
+CV_SYMBOL(S_VFTABLE32 , 0x100c)
+CV_SYMBOL(S_REGREL32_ST , 0x100d)
+CV_SYMBOL(S_LTHREAD32_ST , 0x100e)
+CV_SYMBOL(S_GTHREAD32_ST , 0x100f)
+CV_SYMBOL(S_LPROCMIPS_ST , 0x1010)
+CV_SYMBOL(S_GPROCMIPS_ST , 0x1011)
+
+CV_SYMBOL(S_COMPILE2_ST , 0x1013)
+CV_SYMBOL(S_MANYREG2_ST , 0x1014)
+CV_SYMBOL(S_LPROCIA64_ST , 0x1015)
+CV_SYMBOL(S_GPROCIA64_ST , 0x1016)
+CV_SYMBOL(S_LOCALSLOT_ST , 0x1017)
+CV_SYMBOL(S_PARAMSLOT_ST , 0x1018)
+CV_SYMBOL(S_ANNOTATION , 0x1019)
+CV_SYMBOL(S_GMANPROC_ST , 0x101a)
+CV_SYMBOL(S_LMANPROC_ST , 0x101b)
+CV_SYMBOL(S_RESERVED1 , 0x101c)
+CV_SYMBOL(S_RESERVED2 , 0x101d)
+CV_SYMBOL(S_RESERVED3 , 0x101e)
+CV_SYMBOL(S_RESERVED4 , 0x101f)
+CV_SYMBOL(S_LMANDATA_ST , 0x1020)
+CV_SYMBOL(S_GMANDATA_ST , 0x1021)
+CV_SYMBOL(S_MANFRAMEREL_ST, 0x1022)
+CV_SYMBOL(S_MANREGISTER_ST, 0x1023)
+CV_SYMBOL(S_MANSLOT_ST , 0x1024)
+CV_SYMBOL(S_MANMANYREG_ST , 0x1025)
+CV_SYMBOL(S_MANREGREL_ST , 0x1026)
+CV_SYMBOL(S_MANMANYREG2_ST, 0x1027)
+CV_SYMBOL(S_MANTYPREF , 0x1028)
+CV_SYMBOL(S_UNAMESPACE_ST , 0x1029)
+
+// End of S_*_ST symbols, which do not appear to be generated by modern
+// compilers.
+CV_SYMBOL(S_ST_MAX , 0x1100)
+
+
+CV_SYMBOL(S_WITH32 , 0x1104)
+CV_SYMBOL(S_MANYREG , 0x110a)
+CV_SYMBOL(S_LPROCMIPS , 0x1114)
+CV_SYMBOL(S_GPROCMIPS , 0x1115)
+CV_SYMBOL(S_MANYREG2 , 0x1117)
+CV_SYMBOL(S_LPROCIA64 , 0x1118)
+CV_SYMBOL(S_GPROCIA64 , 0x1119)
+CV_SYMBOL(S_LOCALSLOT , 0x111a)
+CV_SYMBOL(S_PARAMSLOT , 0x111b)
+
+// Managed code symbols.
+CV_SYMBOL(S_MANFRAMEREL , 0x111e)
+CV_SYMBOL(S_MANREGISTER , 0x111f)
+CV_SYMBOL(S_MANSLOT , 0x1120)
+CV_SYMBOL(S_MANMANYREG , 0x1121)
+CV_SYMBOL(S_MANREGREL , 0x1122)
+CV_SYMBOL(S_MANMANYREG2 , 0x1123)
+CV_SYMBOL(S_UNAMESPACE , 0x1124)
+CV_SYMBOL(S_DATAREF , 0x1126)
+CV_SYMBOL(S_ANNOTATIONREF , 0x1128)
+CV_SYMBOL(S_TOKENREF , 0x1129)
+CV_SYMBOL(S_GMANPROC , 0x112a)
+CV_SYMBOL(S_LMANPROC , 0x112b)
+CV_SYMBOL(S_ATTR_FRAMEREL , 0x112e)
+CV_SYMBOL(S_ATTR_REGISTER , 0x112f)
+CV_SYMBOL(S_ATTR_REGREL , 0x1130)
+CV_SYMBOL(S_ATTR_MANYREG , 0x1131)
+
+
+CV_SYMBOL(S_SEPCODE , 0x1132)
+CV_SYMBOL(S_LOCAL_2005 , 0x1133)
+CV_SYMBOL(S_DEFRANGE_2005 , 0x1134)
+CV_SYMBOL(S_DEFRANGE2_2005, 0x1135)
+CV_SYMBOL(S_DISCARDED , 0x113b)
+
+// Current symbol types for most procedures as of this writing.
+CV_SYMBOL(S_LPROCMIPS_ID , 0x1148)
+CV_SYMBOL(S_GPROCMIPS_ID , 0x1149)
+CV_SYMBOL(S_LPROCIA64_ID , 0x114a)
+CV_SYMBOL(S_GPROCIA64_ID , 0x114b)
+
+CV_SYMBOL(S_DEFRANGE_HLSL , 0x1150)
+CV_SYMBOL(S_GDATA_HLSL , 0x1151)
+CV_SYMBOL(S_LDATA_HLSL , 0x1152)
+CV_SYMBOL(S_LOCAL_DPC_GROUPSHARED, 0x1154)
+CV_SYMBOL(S_DEFRANGE_DPC_PTR_TAG, 0x1157)
+CV_SYMBOL(S_DPC_SYM_TAG_MAP, 0x1158)
+CV_SYMBOL(S_ARMSWITCHTABLE , 0x1159)
+CV_SYMBOL(S_POGODATA , 0x115c)
+CV_SYMBOL(S_INLINESITE2 , 0x115d)
+CV_SYMBOL(S_MOD_TYPEREF , 0x115f)
+CV_SYMBOL(S_REF_MINIPDB , 0x1160)
+CV_SYMBOL(S_PDBMAP , 0x1161)
+CV_SYMBOL(S_GDATA_HLSL32 , 0x1162)
+CV_SYMBOL(S_LDATA_HLSL32 , 0x1163)
+CV_SYMBOL(S_GDATA_HLSL32_EX, 0x1164)
+CV_SYMBOL(S_LDATA_HLSL32_EX, 0x1165)
+
+// Known symbol types
+SYMBOL_RECORD(S_END , 0x0006, ScopeEndSym)
+SYMBOL_RECORD_ALIAS(S_INLINESITE_END , 0x114e, InlineSiteEnd, ScopeEndSym)
+SYMBOL_RECORD_ALIAS(S_PROC_ID_END , 0x114f, ProcEnd, ScopeEndSym)
+
+SYMBOL_RECORD(S_THUNK32 , 0x1102, Thunk32Sym)
+SYMBOL_RECORD(S_TRAMPOLINE , 0x112c, TrampolineSym)
+SYMBOL_RECORD(S_SECTION , 0x1136, SectionSym)
+SYMBOL_RECORD(S_COFFGROUP , 0x1137, CoffGroupSym)
+SYMBOL_RECORD(S_EXPORT , 0x1138, ExportSym)
+
+SYMBOL_RECORD(S_LPROC32 , 0x110f, ProcSym)
+SYMBOL_RECORD_ALIAS(S_GPROC32 , 0x1110, GlobalProcSym, ProcSym)
+SYMBOL_RECORD_ALIAS(S_LPROC32_ID , 0x1146, ProcIdSym, ProcSym)
+SYMBOL_RECORD_ALIAS(S_GPROC32_ID , 0x1147, GlobalProcIdSym, ProcSym)
+SYMBOL_RECORD_ALIAS(S_LPROC32_DPC , 0x1155, DPCProcSym, ProcSym)
+SYMBOL_RECORD_ALIAS(S_LPROC32_DPC_ID , 0x1156, DPCProcIdSym, ProcSym)
+
+SYMBOL_RECORD(S_REGISTER , 0x1106, RegisterSym)
+SYMBOL_RECORD(S_PUB32 , 0x110e, PublicSym32)
+
+SYMBOL_RECORD(S_PROCREF , 0x1125, ProcRefSym)
+SYMBOL_RECORD_ALIAS(S_LPROCREF, 0x1127, LocalProcRef, ProcRefSym)
+
+
+SYMBOL_RECORD(S_ENVBLOCK , 0x113d, EnvBlockSym)
+
+SYMBOL_RECORD(S_INLINESITE , 0x114d, InlineSiteSym)
+SYMBOL_RECORD(S_LOCAL , 0x113e, LocalSym)
+SYMBOL_RECORD(S_DEFRANGE , 0x113f, DefRangeSym)
+SYMBOL_RECORD(S_DEFRANGE_SUBFIELD, 0x1140, DefRangeSubfieldSym)
+SYMBOL_RECORD(S_DEFRANGE_REGISTER, 0x1141, DefRangeRegisterSym)
+SYMBOL_RECORD(S_DEFRANGE_FRAMEPOINTER_REL, 0x1142, DefRangeFramePointerRelSym)
+SYMBOL_RECORD(S_DEFRANGE_SUBFIELD_REGISTER, 0x1143, DefRangeSubfieldRegisterSym)
+SYMBOL_RECORD(S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE, 0x1144, DefRangeFramePointerRelFullScopeSym)
+SYMBOL_RECORD(S_DEFRANGE_REGISTER_REL, 0x1145, DefRangeRegisterRelSym)
+SYMBOL_RECORD(S_BLOCK32 , 0x1103, BlockSym)
+SYMBOL_RECORD(S_LABEL32 , 0x1105, LabelSym)
+SYMBOL_RECORD(S_OBJNAME , 0x1101, ObjNameSym)
+SYMBOL_RECORD(S_COMPILE2 , 0x1116, Compile2Sym)
+SYMBOL_RECORD(S_COMPILE3 , 0x113c, Compile3Sym)
+SYMBOL_RECORD(S_FRAMEPROC , 0x1012, FrameProcSym)
+SYMBOL_RECORD(S_CALLSITEINFO , 0x1139, CallSiteInfoSym)
+SYMBOL_RECORD(S_FILESTATIC , 0x1153, FileStaticSym)
+SYMBOL_RECORD(S_HEAPALLOCSITE , 0x115e, HeapAllocationSiteSym)
+SYMBOL_RECORD(S_FRAMECOOKIE , 0x113a, FrameCookieSym)
+
+SYMBOL_RECORD(S_CALLEES , 0x115a, CallerSym)
+SYMBOL_RECORD_ALIAS(S_CALLERS , 0x115b, CalleeSym, CallerSym)
+
+SYMBOL_RECORD(S_UDT , 0x1108, UDTSym)
+SYMBOL_RECORD_ALIAS(S_COBOLUDT , 0x1109, CobolUDT, UDTSym)
+
+SYMBOL_RECORD(S_BUILDINFO , 0x114c, BuildInfoSym)
+SYMBOL_RECORD(S_BPREL32 , 0x110b, BPRelativeSym)
+SYMBOL_RECORD(S_REGREL32 , 0x1111, RegRelativeSym)
+
+SYMBOL_RECORD(S_CONSTANT , 0x1107, ConstantSym)
+SYMBOL_RECORD_ALIAS(S_MANCONSTANT , 0x112d, ManagedConstant, ConstantSym)
+
+SYMBOL_RECORD(S_LDATA32 , 0x110c, DataSym)
+SYMBOL_RECORD_ALIAS(S_GDATA32 , 0x110d, GlobalData, DataSym)
+SYMBOL_RECORD_ALIAS(S_LMANDATA , 0x111c, ManagedLocalData, DataSym)
+SYMBOL_RECORD_ALIAS(S_GMANDATA , 0x111d, ManagedGlobalData, DataSym)
+
+SYMBOL_RECORD(S_LTHREAD32 , 0x1112, ThreadLocalDataSym)
+SYMBOL_RECORD_ALIAS(S_GTHREAD32 , 0x1113, GlobalTLS, ThreadLocalDataSym)
+
+
+#undef CV_SYMBOL
+#undef SYMBOL_RECORD
+#undef SYMBOL_RECORD_ALIAS
diff --git a/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h b/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h
new file mode 100644
index 000000000000..7c88956c984e
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h
@@ -0,0 +1,103 @@
+//===- CVSymbolVisitor.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_CVSYMBOLVISITOR_H
+#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 {
+namespace codeview {
+
+template <typename Derived> class CVSymbolVisitor {
+public:
+ CVSymbolVisitor(SymbolVisitorDelegate *Delegate) : Delegate(Delegate) {}
+
+ bool hadError() const { return HadError; }
+
+ template <typename T>
+ bool consumeObject(ArrayRef<uint8_t> &Data, const T *&Res) {
+ if (Data.size() < sizeof(*Res)) {
+ HadError = true;
+ return false;
+ }
+ Res = reinterpret_cast<const T *>(Data.data());
+ Data = Data.drop_front(sizeof(*Res));
+ return true;
+ }
+
+/// Actions to take on known symbols. By default, they do nothing. Visit methods
+/// for member records take the FieldData by non-const reference and are
+/// expected to consume the trailing bytes used by the field.
+/// FIXME: Make the visitor interpret the trailing bytes so that clients don't
+/// need to.
+#define SYMBOL_RECORD(EnumName, EnumVal, Name) \
+ void visit##Name(SymbolRecordKind Kind, Name &Record) {}
+#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#include "CVSymbolTypes.def"
+
+ void visitSymbolRecord(const CVRecord<SymbolKind> &Record) {
+ ArrayRef<uint8_t> Data = Record.Data;
+ auto *DerivedThis = static_cast<Derived *>(this);
+ DerivedThis->visitSymbolBegin(Record.Type, Data);
+ uint32_t RecordOffset = Delegate ? Delegate->getRecordOffset(Data) : 0;
+ switch (Record.Type) {
+ default:
+ DerivedThis->visitUnknownSymbol(Record.Type, Data);
+ break;
+#define SYMBOL_RECORD(EnumName, EnumVal, Name) \
+ case EnumName: { \
+ SymbolRecordKind RK = static_cast<SymbolRecordKind>(EnumName); \
+ auto Result = Name::deserialize(RK, RecordOffset, Data); \
+ if (Result.getError()) \
+ return parseError(); \
+ DerivedThis->visit##Name(Record.Type, *Result); \
+ break; \
+ }
+#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
+ SYMBOL_RECORD(EnumVal, EnumVal, AliasName)
+#include "CVSymbolTypes.def"
+ }
+ DerivedThis->visitSymbolEnd(Record.Type, Record.Data);
+ }
+
+ /// Visits the symbol records in Data. Sets the error flag on parse failures.
+ void visitSymbolStream(const CVSymbolArray &Symbols) {
+ for (const auto &I : Symbols) {
+ visitSymbolRecord(I);
+ if (hadError())
+ break;
+ }
+ }
+
+ /// Action to take on unknown symbols. By default, they are ignored.
+ void visitUnknownSymbol(SymbolKind Kind, ArrayRef<uint8_t> Data) {}
+
+ /// Paired begin/end actions for all symbols. Receives all record data,
+ /// including the fixed-length record prefix.
+ void visitSymbolBegin(SymbolKind Leaf, ArrayRef<uint8_t> RecordData) {}
+ void visitSymbolEnd(SymbolKind Leaf, ArrayRef<uint8_t> OriginalSymData) {}
+
+ /// Helper for returning from a void function when the stream is corrupted.
+ void parseError() { HadError = true; }
+
+private:
+ SymbolVisitorDelegate *Delegate;
+ /// Whether a symbol stream parsing error was encountered.
+ bool HadError = false;
+};
+
+} // end namespace codeview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_CODEVIEW_CVSYMBOLVISITOR_H
diff --git a/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h b/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
new file mode 100644
index 000000000000..930ac6930c24
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
@@ -0,0 +1,44 @@
+//===- CVTypeVisitor.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H
+#define LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H
+
+#include "llvm/DebugInfo/CodeView/CVRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace codeview {
+
+class CVTypeVisitor {
+public:
+ explicit CVTypeVisitor(TypeVisitorCallbacks &Callbacks);
+
+ Error visitTypeRecord(const CVRecord<TypeLeafKind> &Record);
+
+ /// Visits the type records in Data. Sets the error flag on parse failures.
+ Error visitTypeStream(const CVTypeArray &Types);
+
+ Error skipPadding(ArrayRef<uint8_t> &Data);
+
+ /// Visits individual member records of a field list record. Member records do
+ /// not describe their own length, and need special handling.
+ Error visitFieldList(const CVRecord<TypeLeafKind> &Record);
+
+private:
+ /// The interface to the class that gets notified of each visitation.
+ TypeVisitorCallbacks &Callbacks;
+};
+
+} // end namespace codeview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H
diff --git a/include/llvm/DebugInfo/CodeView/CodeView.h b/include/llvm/DebugInfo/CodeView/CodeView.h
index 7728120d68de..1ee203b4f8fa 100644
--- a/include/llvm/DebugInfo/CodeView/CodeView.h
+++ b/include/llvm/DebugInfo/CodeView/CodeView.h
@@ -11,10 +11,156 @@
#define LLVM_DEBUGINFO_CODEVIEW_CODEVIEW_H
#include <cinttypes>
+#include <type_traits>
namespace llvm {
namespace codeview {
+/// Distinguishes individual records in .debug$T section or PDB type stream. The
+/// documentation and headers talk about this as the "leaf" type.
+enum class TypeRecordKind : uint16_t {
+#define TYPE_RECORD(lf_ename, value, name) name = value,
+#include "TypeRecords.def"
+ // FIXME: Add serialization support
+ FieldList = 0x1203,
+};
+
+/// Duplicate copy of the above enum, but using the official CV names. Useful
+/// for reference purposes and when dealing with unknown record types.
+enum TypeLeafKind : uint16_t {
+#define CV_TYPE(name, val) name = val,
+#include "TypeRecords.def"
+};
+
+/// Distinguishes individual records in the Symbols subsection of a .debug$S
+/// section. Equivalent to SYM_ENUM_e in cvinfo.h.
+enum class SymbolRecordKind : uint16_t {
+#define SYMBOL_RECORD(lf_ename, value, name) name = value,
+#include "CVSymbolTypes.def"
+};
+
+/// Duplicate copy of the above enum, but using the official CV names. Useful
+/// for reference purposes and when dealing with unknown record types.
+enum SymbolKind : uint16_t {
+#define CV_SYMBOL(name, val) name = val,
+#include "CVSymbolTypes.def"
+};
+
+#define CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(Class) \
+ inline Class operator|(Class a, Class b) { \
+ return static_cast<Class>( \
+ static_cast<std::underlying_type<Class>::type>(a) | \
+ static_cast<std::underlying_type<Class>::type>(b)); \
+ } \
+ inline Class operator&(Class a, Class b) { \
+ return static_cast<Class>( \
+ static_cast<std::underlying_type<Class>::type>(a) & \
+ static_cast<std::underlying_type<Class>::type>(b)); \
+ } \
+ inline Class operator~(Class a) { \
+ return static_cast<Class>( \
+ ~static_cast<std::underlying_type<Class>::type>(a)); \
+ } \
+ inline Class &operator|=(Class &a, Class b) { \
+ a = a | b; \
+ return a; \
+ } \
+ inline Class &operator&=(Class &a, Class b) { \
+ a = a & b; \
+ return a; \
+ }
+
+/// These values correspond to the CV_CPU_TYPE_e enumeration, and are documented
+/// here: https://msdn.microsoft.com/en-us/library/b2fc64ek.aspx
+enum class CPUType : uint16_t {
+ Intel8080 = 0x0,
+ Intel8086 = 0x1,
+ Intel80286 = 0x2,
+ Intel80386 = 0x3,
+ Intel80486 = 0x4,
+ Pentium = 0x5,
+ PentiumPro = 0x6,
+ Pentium3 = 0x7,
+ MIPS = 0x10,
+ MIPS16 = 0x11,
+ MIPS32 = 0x12,
+ MIPS64 = 0x13,
+ MIPSI = 0x14,
+ MIPSII = 0x15,
+ MIPSIII = 0x16,
+ MIPSIV = 0x17,
+ MIPSV = 0x18,
+ M68000 = 0x20,
+ M68010 = 0x21,
+ M68020 = 0x22,
+ M68030 = 0x23,
+ M68040 = 0x24,
+ Alpha = 0x30,
+ Alpha21164 = 0x31,
+ Alpha21164A = 0x32,
+ Alpha21264 = 0x33,
+ Alpha21364 = 0x34,
+ PPC601 = 0x40,
+ PPC603 = 0x41,
+ PPC604 = 0x42,
+ PPC620 = 0x43,
+ PPCFP = 0x44,
+ PPCBE = 0x45,
+ SH3 = 0x50,
+ SH3E = 0x51,
+ SH3DSP = 0x52,
+ SH4 = 0x53,
+ SHMedia = 0x54,
+ ARM3 = 0x60,
+ ARM4 = 0x61,
+ ARM4T = 0x62,
+ ARM5 = 0x63,
+ ARM5T = 0x64,
+ ARM6 = 0x65,
+ ARM_XMAC = 0x66,
+ ARM_WMMX = 0x67,
+ ARM7 = 0x68,
+ Omni = 0x70,
+ Ia64 = 0x80,
+ Ia64_2 = 0x81,
+ CEE = 0x90,
+ AM33 = 0xa0,
+ M32R = 0xb0,
+ TriCore = 0xc0,
+ X64 = 0xd0,
+ EBC = 0xe0,
+ Thumb = 0xf0,
+ ARMNT = 0xf4,
+ D3D11_Shader = 0x100,
+};
+
+/// These values correspond to the CV_CFL_LANG enumeration, and are documented
+/// here: https://msdn.microsoft.com/en-us/library/bw3aekw6.aspx
+enum SourceLanguage : uint8_t {
+ C = 0x00,
+ Cpp = 0x01,
+ Fortran = 0x02,
+ Masm = 0x03,
+ Pascal = 0x04,
+ Basic = 0x05,
+ Cobol = 0x06,
+ Link = 0x07,
+ Cvtres = 0x08,
+ Cvtpgd = 0x09,
+ CSharp = 0x0a,
+ VB = 0x0b,
+ ILAsm = 0x0c,
+ Java = 0x0d,
+ JScript = 0x0e,
+ MSIL = 0x0f,
+ HLSL = 0x10
+};
+
+/// These values correspond to the CV_call_e enumeration, and are documented
+/// at the following locations:
+/// https://msdn.microsoft.com/en-us/library/b2fc64ek.aspx
+/// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680207(v=vs.85).aspx
+///
enum class CallingConvention : uint8_t {
NearC = 0x00, // near right to left push, caller pops stack
FarC = 0x01, // far right to left push, caller pops stack
@@ -58,20 +204,7 @@ enum class ClassOptions : uint16_t {
Sealed = 0x0400,
Intrinsic = 0x2000
};
-
-inline ClassOptions operator|(ClassOptions a, ClassOptions b) {
- return static_cast<ClassOptions>(static_cast<uint16_t>(a) |
- static_cast<uint16_t>(b));
-}
-
-inline ClassOptions operator&(ClassOptions a, ClassOptions b) {
- return static_cast<ClassOptions>(static_cast<uint16_t>(a) &
- static_cast<uint16_t>(b));
-}
-
-inline ClassOptions operator~(ClassOptions a) {
- return static_cast<ClassOptions>(~static_cast<uint16_t>(a));
-}
+CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(ClassOptions)
enum class FrameProcedureOptions : uint32_t {
None = 0x00000000,
@@ -95,22 +228,7 @@ enum class FrameProcedureOptions : uint32_t {
GuardCfg = 0x00200000,
GuardCfw = 0x00400000
};
-
-inline FrameProcedureOptions operator|(FrameProcedureOptions a,
- FrameProcedureOptions b) {
- return static_cast<FrameProcedureOptions>(static_cast<uint32_t>(a) |
- static_cast<uint32_t>(b));
-}
-
-inline FrameProcedureOptions operator&(FrameProcedureOptions a,
- FrameProcedureOptions b) {
- return static_cast<FrameProcedureOptions>(static_cast<uint32_t>(a) &
- static_cast<uint32_t>(b));
-}
-
-inline FrameProcedureOptions operator~(FrameProcedureOptions a) {
- return static_cast<FrameProcedureOptions>(~static_cast<uint32_t>(a));
-}
+CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(FrameProcedureOptions)
enum class FunctionOptions : uint8_t {
None = 0x00,
@@ -118,20 +236,7 @@ enum class FunctionOptions : uint8_t {
Constructor = 0x02,
ConstructorWithVirtualBases = 0x04
};
-
-inline FunctionOptions operator|(FunctionOptions a, FunctionOptions b) {
- return static_cast<FunctionOptions>(static_cast<uint8_t>(a) |
- static_cast<uint8_t>(b));
-}
-
-inline FunctionOptions operator&(FunctionOptions a, FunctionOptions b) {
- return static_cast<FunctionOptions>(static_cast<uint8_t>(a) &
- static_cast<uint8_t>(b));
-}
-
-inline FunctionOptions operator~(FunctionOptions a) {
- return static_cast<FunctionOptions>(~static_cast<uint8_t>(a));
-}
+CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(FunctionOptions)
enum class HfaKind : uint8_t {
None = 0x00,
@@ -140,6 +245,7 @@ enum class HfaKind : uint8_t {
Other = 0x03
};
+/// Source-level access specifier. (CV_access_e)
enum class MemberAccess : uint8_t {
None = 0,
Private = 1,
@@ -147,6 +253,7 @@ enum class MemberAccess : uint8_t {
Public = 3
};
+/// Part of member attribute flags. (CV_methodprop_e)
enum class MethodKind : uint8_t {
Vanilla = 0x00,
Virtual = 0x01,
@@ -157,49 +264,30 @@ enum class MethodKind : uint8_t {
PureIntroducingVirtual = 0x06
};
+/// Equivalent to CV_fldattr_t bitfield.
enum class MethodOptions : uint16_t {
None = 0x0000,
+ AccessMask = 0x0003,
+ MethodKindMask = 0x001c,
Pseudo = 0x0020,
+ NoInherit = 0x0040,
+ NoConstruct = 0x0080,
CompilerGenerated = 0x0100,
Sealed = 0x0200
};
+CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(MethodOptions)
-inline MethodOptions operator|(MethodOptions a, MethodOptions b) {
- return static_cast<MethodOptions>(static_cast<uint16_t>(a) |
- static_cast<uint16_t>(b));
-}
-
-inline MethodOptions operator&(MethodOptions a, MethodOptions b) {
- return static_cast<MethodOptions>(static_cast<uint16_t>(a) &
- static_cast<uint16_t>(b));
-}
-
-inline MethodOptions operator~(MethodOptions a) {
- return static_cast<MethodOptions>(~static_cast<uint16_t>(a));
-}
-
+/// Equivalent to CV_modifier_t.
enum class ModifierOptions : uint16_t {
None = 0x0000,
Const = 0x0001,
Volatile = 0x0002,
Unaligned = 0x0004
};
-
-inline ModifierOptions operator|(ModifierOptions a, ModifierOptions b) {
- return static_cast<ModifierOptions>(static_cast<uint16_t>(a) |
- static_cast<uint16_t>(b));
-}
-
-inline ModifierOptions operator&(ModifierOptions a, ModifierOptions b) {
- return static_cast<ModifierOptions>(static_cast<uint16_t>(a) &
- static_cast<uint16_t>(b));
-}
-
-inline ModifierOptions operator~(ModifierOptions a) {
- return static_cast<ModifierOptions>(~static_cast<uint16_t>(a));
-}
+CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(ModifierOptions)
enum class ModuleSubstreamKind : uint32_t {
+ None = 0,
Symbols = 0xf1,
Lines = 0xf2,
StringTable = 0xf3,
@@ -207,9 +295,18 @@ enum class ModuleSubstreamKind : uint32_t {
FrameData = 0xf5,
InlineeLines = 0xf6,
CrossScopeImports = 0xf7,
- CrossScopeExports = 0xf8
+ CrossScopeExports = 0xf8,
+
+ // These appear to relate to .Net assembly info.
+ ILLines = 0xf9,
+ FuncMDTokenMap = 0xfa,
+ TypeMDTokenMap = 0xfb,
+ MergedAssemblyInput = 0xfc,
+
+ CoffSymbolRVA = 0xfd,
};
+/// Equivalent to CV_ptrtype_e.
enum class PointerKind : uint8_t {
Near16 = 0x00, // 16 bit pointer
Far16 = 0x01, // 16:16 far pointer
@@ -226,6 +323,7 @@ enum class PointerKind : uint8_t {
Near64 = 0x0c // 64 bit pointer
};
+/// Equivalent to CV_ptrmode_e.
enum class PointerMode : uint8_t {
Pointer = 0x00, // "normal" pointer
LValueReference = 0x01, // "old" reference
@@ -234,6 +332,7 @@ enum class PointerMode : uint8_t {
RValueReference = 0x04 // r-value reference
};
+/// Equivalent to misc lfPointerAttr bitfields.
enum class PointerOptions : uint32_t {
None = 0x00000000,
Flat32 = 0x00000100,
@@ -243,21 +342,9 @@ enum class PointerOptions : uint32_t {
Restrict = 0x00001000,
WinRTSmartPointer = 0x00080000
};
+CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(PointerOptions)
-inline PointerOptions operator|(PointerOptions a, PointerOptions b) {
- return static_cast<PointerOptions>(static_cast<uint16_t>(a) |
- static_cast<uint16_t>(b));
-}
-
-inline PointerOptions operator&(PointerOptions a, PointerOptions b) {
- return static_cast<PointerOptions>(static_cast<uint16_t>(a) &
- static_cast<uint16_t>(b));
-}
-
-inline PointerOptions operator~(PointerOptions a) {
- return static_cast<PointerOptions>(~static_cast<uint16_t>(a));
-}
-
+/// Equivalent to CV_pmtype_e.
enum class PointerToMemberRepresentation : uint16_t {
Unknown = 0x00, // not specified (pre VC8)
SingleInheritanceData = 0x01, // member data, single inheritance
@@ -270,82 +357,7 @@ enum class PointerToMemberRepresentation : uint16_t {
GeneralFunction = 0x08 // member function, most general
};
-enum class TypeRecordKind : uint16_t {
- None = 0,
-
- VirtualTableShape = 0x000a,
- Label = 0x000e,
- EndPrecompiledHeader = 0x0014,
-
- Modifier = 0x1001,
- Pointer = 0x1002,
- Procedure = 0x1008,
- MemberFunction = 0x1009,
-
- Oem = 0x100f,
- Oem2 = 0x1011,
-
- ArgumentList = 0x1201,
- FieldList = 0x1203,
- BitField = 0x1205,
- MethodList = 0x1206,
-
- BaseClass = 0x1400,
- VirtualBaseClass = 0x1401,
- IndirectVirtualBaseClass = 0x1402,
- Index = 0x1404,
- VirtualFunctionTablePointer = 0x1409,
-
- Enumerate = 0x1502,
- Array = 0x1503,
- Class = 0x1504,
- Structure = 0x1505,
- Union = 0x1506,
- Enum = 0x1507,
- Alias = 0x150a,
- Member = 0x150d,
- StaticMember = 0x150e,
- Method = 0x150f,
- NestedType = 0x1510,
- OneMethod = 0x1511,
- VirtualFunctionTable = 0x151d,
-
- FunctionId = 0x1601,
- MemberFunctionId = 0x1602,
- BuildInfo = 0x1603,
- SubstringList = 0x1604,
- StringId = 0x1605,
- UdtSourceLine = 0x1606,
-
- SByte = 0x8000,
- Int16 = 0x8001,
- UInt16 = 0x8002,
- Int32 = 0x8003,
- UInt32 = 0x8004,
- Single = 0x8005,
- Double = 0x8006,
- Float80 = 0x8007,
- Float128 = 0x8008,
- Int64 = 0x8009,
- UInt64 = 0x800a,
- Float48 = 0x800b,
- Complex32 = 0x800c,
- Complex64 = 0x800d,
- Complex80 = 0x800e,
- Complex128 = 0x800f,
- VarString = 0x8010,
-
- Int128 = 0x8017,
- UInt128 = 0x8018,
-
- Decimal = 0x8019,
- Date = 0x801a,
- Utf8String = 0x801b,
-
- Float16 = 0x801c
-};
-
-enum class VirtualTableSlotKind : uint8_t {
+enum class VFTableSlotKind : uint8_t {
Near16 = 0x00,
Far16 = 0x01,
This = 0x02,
@@ -361,6 +373,177 @@ enum class WindowsRTClassKind : uint8_t {
ValueClass = 0x02,
Interface = 0x03
};
+
+/// Corresponds to CV_LVARFLAGS bitfield.
+enum class LocalSymFlags : uint16_t {
+ None = 0,
+ IsParameter = 1 << 0,
+ IsAddressTaken = 1 << 1,
+ IsCompilerGenerated = 1 << 2,
+ IsAggregate = 1 << 3,
+ IsAggregated = 1 << 4,
+ IsAliased = 1 << 5,
+ IsAlias = 1 << 6,
+ IsReturnValue = 1 << 7,
+ IsOptimizedOut = 1 << 8,
+ IsEnregisteredGlobal = 1 << 9,
+ IsEnregisteredStatic = 1 << 10,
+};
+CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(LocalSymFlags)
+
+/// Corresponds to the CV_PROCFLAGS bitfield.
+enum class ProcSymFlags : uint8_t {
+ None = 0,
+ HasFP = 1 << 0,
+ HasIRET = 1 << 1,
+ HasFRET = 1 << 2,
+ IsNoReturn = 1 << 3,
+ IsUnreachable = 1 << 4,
+ HasCustomCallingConv = 1 << 5,
+ IsNoInline = 1 << 6,
+ HasOptimizedDebugInfo = 1 << 7,
+};
+CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(ProcSymFlags)
+
+/// Corresponds to COMPILESYM2::Flags bitfield.
+enum class CompileSym2Flags : uint32_t {
+ EC = 1 << 8,
+ NoDbgInfo = 1 << 9,
+ LTCG = 1 << 10,
+ NoDataAlign = 1 << 11,
+ ManagedPresent = 1 << 12,
+ SecurityChecks = 1 << 13,
+ HotPatch = 1 << 14,
+ CVTCIL = 1 << 15,
+ MSILModule = 1 << 16,
+};
+CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(CompileSym2Flags)
+
+/// Corresponds to COMPILESYM3::Flags bitfield.
+enum class CompileSym3Flags : uint32_t {
+ EC = 1 << 8,
+ NoDbgInfo = 1 << 9,
+ LTCG = 1 << 10,
+ NoDataAlign = 1 << 11,
+ ManagedPresent = 1 << 12,
+ SecurityChecks = 1 << 13,
+ HotPatch = 1 << 14,
+ CVTCIL = 1 << 15,
+ MSILModule = 1 << 16,
+ Sdl = 1 << 17,
+ PGO = 1 << 18,
+ Exp = 1 << 19,
+};
+CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(CompileSym3Flags)
+
+enum class ExportFlags : uint16_t {
+ IsConstant = 1 << 0,
+ IsData = 1 << 1,
+ IsPrivate = 1 << 2,
+ HasNoName = 1 << 3,
+ HasExplicitOrdinal = 1 << 4,
+ IsForwarder = 1 << 5
+};
+CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(ExportFlags)
+
+// Corresponds to BinaryAnnotationOpcode enum.
+enum class BinaryAnnotationsOpCode : uint32_t {
+ Invalid,
+ CodeOffset,
+ ChangeCodeOffsetBase,
+ ChangeCodeOffset,
+ ChangeCodeLength,
+ ChangeFile,
+ ChangeLineOffset,
+ ChangeLineEndDelta,
+ ChangeRangeKind,
+ ChangeColumnStart,
+ ChangeColumnEndDelta,
+ ChangeCodeOffsetAndLineOffset,
+ ChangeCodeLengthAndCodeOffset,
+ ChangeColumnEnd,
+};
+
+// Corresponds to CV_cookietype_e enum.
+enum class FrameCookieKind : uint8_t {
+ Copy,
+ XorStackPointer,
+ XorFramePointer,
+ XorR13,
+};
+
+// Corresponds to CV_HREG_e enum.
+enum class RegisterId : uint16_t {
+ Unknown = 0,
+ VFrame = 30006,
+ AL = 1,
+ CL = 2,
+ DL = 3,
+ BL = 4,
+ AH = 5,
+ CH = 6,
+ DH = 7,
+ BH = 8,
+ AX = 9,
+ CX = 10,
+ DX = 11,
+ BX = 12,
+ SP = 13,
+ BP = 14,
+ SI = 15,
+ DI = 16,
+ EAX = 17,
+ ECX = 18,
+ EDX = 19,
+ EBX = 20,
+ ESP = 21,
+ EBP = 22,
+ ESI = 23,
+ EDI = 24,
+ ES = 25,
+ CS = 26,
+ SS = 27,
+ DS = 28,
+ FS = 29,
+ GS = 30,
+ IP = 31,
+ RAX = 328,
+ RBX = 329,
+ RCX = 330,
+ RDX = 331,
+ RSI = 332,
+ RDI = 333,
+ RBP = 334,
+ RSP = 335,
+ R8 = 336,
+ R9 = 337,
+ R10 = 338,
+ R11 = 339,
+ R12 = 340,
+ R13 = 341,
+ R14 = 342,
+ R15 = 343,
+};
+
+/// These values correspond to the THUNK_ORDINAL enumeration.
+enum class ThunkOrdinal {
+ Standard,
+ ThisAdjustor,
+ Vcall,
+ Pcode,
+ UnknownLoad,
+ TrampIncremental,
+ BranchIsland
+};
+
+enum class TrampolineType { TrampIncremental, BranchIsland };
+
+// These values correspond to the CV_SourceChksum_t enumeration.
+enum class FileChecksumKind : uint8_t { None, MD5, SHA1, SHA256 };
+
+enum LineFlags : uint32_t {
+ HaveColumns = 1, // CV_LINES_HAVE_COLUMNS
+};
}
}
diff --git a/include/llvm/DebugInfo/CodeView/CodeViewError.h b/include/llvm/DebugInfo/CodeView/CodeViewError.h
new file mode 100644
index 000000000000..69ff29aab6f1
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/CodeViewError.h
@@ -0,0 +1,44 @@
+//===- CodeViewError.h - Error extensions for CodeView ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_CODEVIEW_CODEVIEWERROR_H
+#define LLVM_DEBUGINFO_PDB_CODEVIEW_CODEVIEWERROR_H
+
+#include "llvm/Support/Error.h"
+
+#include <string>
+
+namespace llvm {
+namespace codeview {
+enum class cv_error_code {
+ unspecified = 1,
+ insufficient_buffer,
+ operation_unsupported,
+ corrupt_record,
+};
+
+/// Base class for errors originating when parsing raw PDB files
+class CodeViewError : public ErrorInfo<CodeViewError> {
+public:
+ static char ID;
+ CodeViewError(cv_error_code C);
+ CodeViewError(const std::string &Context);
+ CodeViewError(cv_error_code C, const std::string &Context);
+
+ void log(raw_ostream &OS) const override;
+ const std::string &getErrorMessage() const;
+ std::error_code convertToErrorCode() const override;
+
+private:
+ std::string ErrMsg;
+ cv_error_code Code;
+};
+}
+}
+#endif
diff --git a/include/llvm/DebugInfo/CodeView/EnumTables.h b/include/llvm/DebugInfo/CodeView/EnumTables.h
new file mode 100644
index 000000000000..021288e57618
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/EnumTables.h
@@ -0,0 +1,42 @@
+//===- EnumTables.h Enum to string conversion tables ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_ENUMTABLES_H
+#define LLVM_DEBUGINFO_CODEVIEW_ENUMTABLES_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/Support/COFF.h"
+#include "llvm/Support/ScopedPrinter.h"
+
+#include <stdint.h>
+
+namespace llvm {
+namespace codeview {
+ArrayRef<EnumEntry<SymbolKind>> getSymbolTypeNames();
+ArrayRef<EnumEntry<uint16_t>> getRegisterNames();
+ArrayRef<EnumEntry<uint8_t>> getProcSymFlagNames();
+ArrayRef<EnumEntry<uint16_t>> getLocalFlagNames();
+ArrayRef<EnumEntry<uint8_t>> getFrameCookieKindNames();
+ArrayRef<EnumEntry<SourceLanguage>> getSourceLanguageNames();
+ArrayRef<EnumEntry<uint32_t>> getCompileSym2FlagNames();
+ArrayRef<EnumEntry<uint32_t>> getCompileSym3FlagNames();
+ArrayRef<EnumEntry<uint32_t>> getFileChecksumNames();
+ArrayRef<EnumEntry<unsigned>> getCPUTypeNames();
+ArrayRef<EnumEntry<uint32_t>> getFrameProcSymFlagNames();
+ArrayRef<EnumEntry<uint16_t>> getExportSymFlagNames();
+ArrayRef<EnumEntry<uint32_t>> getModuleSubstreamKindNames();
+ArrayRef<EnumEntry<uint8_t>> getThunkOrdinalNames();
+ArrayRef<EnumEntry<uint16_t>> getTrampolineNames();
+ArrayRef<EnumEntry<COFF::SectionCharacteristics>>
+getImageSectionCharacteristicNames();
+} // namespace codeview
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_CODEVIEW_ENUMTABLES_H
diff --git a/include/llvm/DebugInfo/CodeView/FieldListRecordBuilder.h b/include/llvm/DebugInfo/CodeView/FieldListRecordBuilder.h
index 1ed62487aecc..75a075157d22 100644
--- a/include/llvm/DebugInfo/CodeView/FieldListRecordBuilder.h
+++ b/include/llvm/DebugInfo/CodeView/FieldListRecordBuilder.h
@@ -11,6 +11,7 @@
#define LLVM_DEBUGINFO_CODEVIEW_FIELDLISTRECORDBUILDER_H
#include "llvm/DebugInfo/CodeView/ListRecordBuilder.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
namespace llvm {
namespace codeview {
@@ -46,31 +47,17 @@ private:
public:
FieldListRecordBuilder();
- void writeBaseClass(MemberAccess Access, TypeIndex Type, uint64_t Offset);
- void writeEnumerate(MemberAccess Access, uint64_t Value, StringRef Name);
- void writeIndirectVirtualBaseClass(MemberAccess Access, TypeIndex Type,
- TypeIndex VirtualBasePointerType,
- int64_t VirtualBasePointerOffset,
- uint64_t SlotIndex);
- void writeMember(MemberAccess Access, TypeIndex Type, uint64_t Offset,
- StringRef Name);
- void writeOneMethod(MemberAccess Access, MethodKind Kind,
- MethodOptions Options, TypeIndex Type,
- int32_t VTableSlotOffset, StringRef Name);
- void writeOneMethod(const MethodInfo &Method, StringRef Name);
- void writeMethod(uint16_t OverloadCount, TypeIndex MethodList,
- StringRef Name);
- void writeNestedType(TypeIndex Type, StringRef Name);
- void writeStaticMember(MemberAccess Access, TypeIndex Type, StringRef Name);
- void writeVirtualBaseClass(MemberAccess Access, TypeIndex Type,
- TypeIndex VirtualBasePointerType,
- int64_t VirtualBasePointerOffset,
- uint64_t SlotIndex);
- void writeVirtualBaseClass(TypeRecordKind Kind, MemberAccess Access,
- TypeIndex Type, TypeIndex VirtualBasePointerType,
- int64_t VirtualBasePointerOffset,
- uint64_t SlotIndex);
- void writeVirtualFunctionTablePointer(TypeIndex Type);
+ void reset() { ListRecordBuilder::reset(); }
+
+ void writeBaseClass(const BaseClassRecord &Record);
+ void writeEnumerator(const EnumeratorRecord &Record);
+ void writeDataMember(const DataMemberRecord &Record);
+ void writeOneMethod(const OneMethodRecord &Record);
+ void writeOverloadedMethod(const OverloadedMethodRecord &Record);
+ void writeNestedType(const NestedTypeRecord &Record);
+ void writeStaticDataMember(const StaticDataMemberRecord &Record);
+ void writeVirtualBaseClass(const VirtualBaseClassRecord &Record);
+ void writeVFPtr(const VFPtrRecord &Type);
};
}
}
diff --git a/include/llvm/DebugInfo/CodeView/Line.h b/include/llvm/DebugInfo/CodeView/Line.h
index a7cdbdaac32f..975b503fe30b 100644
--- a/include/llvm/DebugInfo/CodeView/Line.h
+++ b/include/llvm/DebugInfo/CodeView/Line.h
@@ -10,24 +10,32 @@
#ifndef LLVM_DEBUGINFO_CODEVIEW_LINE_H
#define LLVM_DEBUGINFO_CODEVIEW_LINE_H
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/Support/Endian.h"
#include <cinttypes>
namespace llvm {
namespace codeview {
+using llvm::support::ulittle32_t;
+
class LineInfo {
public:
- static const uint32_t AlwaysStepIntoLineNumber = 0xfeefee;
- static const uint32_t NeverStepIntoLineNumber = 0xf00f00;
+ enum : uint32_t {
+ AlwaysStepIntoLineNumber = 0xfeefee,
+ NeverStepIntoLineNumber = 0xf00f00
+ };
-private:
- static const uint32_t StartLineMask = 0x00ffffff;
- static const uint32_t EndLineDeltaMask = 0x7f000000;
- static const int EndLineDeltaShift = 24;
- static const uint32_t StatementFlag = 0x80000000u;
+ enum : int { EndLineDeltaShift = 24 };
+
+ enum : uint32_t {
+ StartLineMask = 0x00ffffff,
+ EndLineDeltaMask = 0x7f000000,
+ StatementFlag = 0x80000000u
+ };
-public:
LineInfo(uint32_t StartLine, uint32_t EndLine, bool IsStatement);
+ LineInfo(uint32_t LineData) : LineData(LineData) {}
uint32_t getStartLine() const { return LineData & StartLineMask; }
@@ -118,7 +126,29 @@ public:
bool isNeverStepInto() const { return LineInf.isNeverStepInto(); }
};
-}
-}
+
+enum class InlineeLinesSignature : uint32_t {
+ Normal, // CV_INLINEE_SOURCE_LINE_SIGNATURE
+ ExtraFiles // CV_INLINEE_SOURCE_LINE_SIGNATURE_EX
+};
+
+struct InlineeSourceLine {
+ TypeIndex Inlinee; // ID of the function that was inlined.
+ ulittle32_t FileID; // Offset into FileChecksums subsection.
+ ulittle32_t SourceLineNum; // First line of inlined code.
+ // If extra files present:
+ // ulittle32_t ExtraFileCount;
+ // ulittle32_t Files[];
+};
+
+struct FileChecksum {
+ ulittle32_t FileNameOffset; // Byte offset of filename in global string table.
+ uint8_t ChecksumSize; // Number of bytes of checksum.
+ uint8_t ChecksumKind; // FileChecksumKind
+ // Checksum bytes follow.
+};
+
+} // namespace codeview
+} // namespace llvm
#endif
diff --git a/include/llvm/DebugInfo/CodeView/ListRecordBuilder.h b/include/llvm/DebugInfo/CodeView/ListRecordBuilder.h
index df0a2e08a418..00bf03d417a2 100644
--- a/include/llvm/DebugInfo/CodeView/ListRecordBuilder.h
+++ b/include/llvm/DebugInfo/CodeView/ListRecordBuilder.h
@@ -14,6 +14,7 @@
namespace llvm {
namespace codeview {
+class TypeTableBuilder;
class ListRecordBuilder {
private:
@@ -28,14 +29,35 @@ protected:
public:
llvm::StringRef str() { return Builder.str(); }
+ void reset() {
+ Builder.reset(Kind);
+ ContinuationOffsets.clear();
+ SubrecordStart = 0;
+ }
+
+ void writeListContinuation(const ListContinuationRecord &R);
+
+ /// Writes this list record as a possible sequence of records.
+ TypeIndex writeListRecord(TypeTableBuilder &Table);
+
protected:
void finishSubRecord();
TypeRecordBuilder &getBuilder() { return Builder; }
private:
+ size_t getLastContinuationStart() const {
+ return ContinuationOffsets.empty() ? 0 : ContinuationOffsets.back();
+ }
+ size_t getLastContinuationEnd() const { return Builder.size(); }
+ size_t getLastContinuationSize() const {
+ return getLastContinuationEnd() - getLastContinuationStart();
+ }
+
+ TypeRecordKind Kind;
TypeRecordBuilder Builder;
SmallVector<size_t, 4> ContinuationOffsets;
+ size_t SubrecordStart = 0;
};
}
}
diff --git a/include/llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h b/include/llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h
index 5bfe2a068672..002f885c7c5a 100644
--- a/include/llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h
+++ b/include/llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h
@@ -10,12 +10,9 @@
#ifndef LLVM_DEBUGINFO_CODEVIEW_MEMORYTYPETABLEBUILDER_H
#define LLVM_DEBUGINFO_CODEVIEW_MEMORYTYPETABLEBUILDER_H
-#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
-#include <functional>
-#include <memory>
-#include <unordered_map>
#include <vector>
namespace llvm {
@@ -23,46 +20,29 @@ namespace codeview {
class MemoryTypeTableBuilder : public TypeTableBuilder {
public:
- class Record {
- public:
- explicit Record(llvm::StringRef RData);
-
- const char *data() const { return Data.get(); }
- uint16_t size() const { return Size; }
-
- private:
- uint16_t Size;
- std::unique_ptr<char[]> Data;
- };
-
-private:
- class RecordHash : std::unary_function<llvm::StringRef, size_t> {
- public:
- size_t operator()(llvm::StringRef Val) const {
- return static_cast<size_t>(llvm::hash_value(Val));
- }
- };
-
-public:
MemoryTypeTableBuilder() {}
+ bool empty() const { return Records.empty(); }
+
template <typename TFunc> void ForEachRecord(TFunc Func) {
uint32_t Index = TypeIndex::FirstNonSimpleIndex;
- for (const std::unique_ptr<Record> &R : Records) {
- Func(TypeIndex(Index), R.get());
+ for (StringRef R : Records) {
+ Func(TypeIndex(Index), R);
++Index;
}
}
-private:
- virtual TypeIndex writeRecord(llvm::StringRef Data) override;
+protected:
+ TypeIndex writeRecord(llvm::StringRef Data) override;
private:
- std::vector<std::unique_ptr<Record>> Records;
- std::unordered_map<llvm::StringRef, TypeIndex, RecordHash> HashedRecords;
+ std::vector<StringRef> Records;
+ BumpPtrAllocator RecordStorage;
+ DenseMap<StringRef, TypeIndex> HashedRecords;
};
-}
-}
-#endif
+} // end namespace codeview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_CODEVIEW_MEMORYTYPETABLEBUILDER_H
diff --git a/include/llvm/DebugInfo/CodeView/ModuleSubstream.h b/include/llvm/DebugInfo/CodeView/ModuleSubstream.h
new file mode 100644
index 000000000000..6affac801d4d
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/ModuleSubstream.h
@@ -0,0 +1,87 @@
+//===- ModuleSubstream.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAM_H
+#define LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAM_H
+
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/StreamArray.h"
+#include "llvm/DebugInfo/CodeView/StreamRef.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace codeview {
+
+// Corresponds to the `CV_DebugSSubsectionHeader_t` structure.
+struct ModuleSubsectionHeader {
+ support::ulittle32_t Kind; // codeview::ModuleSubstreamKind enum
+ support::ulittle32_t Length; // number of bytes occupied by this record.
+};
+
+// Corresponds to the `CV_DebugSLinesHeader_t` structure.
+struct LineSubstreamHeader {
+ support::ulittle32_t RelocOffset; // Code offset of line contribution.
+ support::ulittle16_t RelocSegment; // Code segment of line contribution.
+ support::ulittle16_t Flags; // See LineFlags enumeration.
+ support::ulittle32_t CodeSize; // Code size of this line contribution.
+};
+
+// Corresponds to the `CV_DebugSLinesFileBlockHeader_t` structure.
+struct LineFileBlockHeader {
+ support::ulittle32_t NameIndex; // Index in DBI name buffer of filename.
+ support::ulittle32_t NumLines; // Number of lines
+ support::ulittle32_t BlockSize; // Code size of block, in bytes.
+ // The following two variable length arrays appear immediately after the
+ // header. The structure definitions follow.
+ // LineNumberEntry Lines[NumLines];
+ // ColumnNumberEntry Columns[NumLines];
+};
+
+// Corresponds to `CV_Line_t` structure
+struct LineNumberEntry {
+ support::ulittle32_t Offset; // Offset to start of code bytes for line number
+ support::ulittle32_t Flags; // Start:24, End:7, IsStatement:1
+};
+
+// Corresponds to `CV_Column_t` structure
+struct ColumnNumberEntry {
+ support::ulittle16_t StartColumn;
+ support::ulittle16_t EndColumn;
+};
+
+class ModuleSubstream {
+public:
+ ModuleSubstream();
+ ModuleSubstream(ModuleSubstreamKind Kind, StreamRef Data);
+ static Error initialize(StreamRef Stream, ModuleSubstream &Info);
+ uint32_t getRecordLength() const;
+ ModuleSubstreamKind getSubstreamKind() const;
+ StreamRef getRecordData() const;
+
+private:
+ ModuleSubstreamKind Kind;
+ StreamRef Data;
+};
+
+template <> struct VarStreamArrayExtractor<ModuleSubstream> {
+ Error operator()(StreamRef Stream, uint32_t &Length,
+ ModuleSubstream &Info) const {
+ if (auto EC = ModuleSubstream::initialize(Stream, Info))
+ return EC;
+ Length = Info.getRecordLength();
+ return Error::success();
+ }
+};
+
+typedef VarStreamArray<ModuleSubstream> ModuleSubstreamArray;
+}
+}
+
+#endif // LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAM_H
diff --git a/include/llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h b/include/llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h
new file mode 100644
index 000000000000..6df230903712
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h
@@ -0,0 +1,121 @@
+//===- ModuleSubstreamVisitor.h ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAMVISITOR_H
+#define LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAMVISITOR_H
+
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/CodeView/Line.h"
+#include "llvm/DebugInfo/CodeView/ModuleSubstream.h"
+#include "llvm/DebugInfo/CodeView/StreamReader.h"
+#include "llvm/DebugInfo/CodeView/StreamRef.h"
+
+namespace llvm {
+namespace codeview {
+
+struct LineColumnEntry {
+ support::ulittle32_t NameIndex;
+ FixedStreamArray<LineNumberEntry> LineNumbers;
+ FixedStreamArray<ColumnNumberEntry> Columns;
+};
+
+template <> class VarStreamArrayExtractor<LineColumnEntry> {
+public:
+ VarStreamArrayExtractor(const LineSubstreamHeader *Header) : Header(Header) {}
+
+ Error operator()(StreamRef Stream, uint32_t &Len,
+ LineColumnEntry &Item) const {
+ const LineFileBlockHeader *BlockHeader;
+ StreamReader Reader(Stream);
+ if (auto EC = Reader.readObject(BlockHeader))
+ return EC;
+ bool HasColumn = Header->Flags & LineFlags::HaveColumns;
+ uint32_t LineInfoSize =
+ BlockHeader->NumLines *
+ (sizeof(LineNumberEntry) + (HasColumn ? sizeof(ColumnNumberEntry) : 0));
+ if (BlockHeader->BlockSize < sizeof(LineFileBlockHeader))
+ return make_error<CodeViewError>(cv_error_code::corrupt_record,
+ "Invalid line block record size");
+ uint32_t Size = BlockHeader->BlockSize - sizeof(LineFileBlockHeader);
+ if (LineInfoSize > Size)
+ return make_error<CodeViewError>(cv_error_code::corrupt_record,
+ "Invalid line block record size");
+ // The value recorded in BlockHeader->BlockSize includes the size of
+ // LineFileBlockHeader.
+ Len = BlockHeader->BlockSize;
+ Item.NameIndex = BlockHeader->NameIndex;
+ if (auto EC = Reader.readArray(Item.LineNumbers, BlockHeader->NumLines))
+ return EC;
+ if (HasColumn) {
+ if (auto EC = Reader.readArray(Item.Columns, BlockHeader->NumLines))
+ return EC;
+ }
+ return Error::success();
+ }
+
+private:
+ const LineSubstreamHeader *Header;
+};
+
+struct FileChecksumEntry {
+ uint32_t FileNameOffset; // Byte offset of filename in global stringtable.
+ FileChecksumKind Kind; // The type of checksum.
+ ArrayRef<uint8_t> Checksum; // The bytes of the checksum.
+};
+
+template <> class VarStreamArrayExtractor<FileChecksumEntry> {
+public:
+ Error operator()(StreamRef Stream, uint32_t &Len,
+ FileChecksumEntry &Item) const {
+ const FileChecksum *Header;
+ StreamReader Reader(Stream);
+ if (auto EC = Reader.readObject(Header))
+ return EC;
+ Item.FileNameOffset = Header->FileNameOffset;
+ Item.Kind = static_cast<FileChecksumKind>(Header->ChecksumKind);
+ if (auto EC = Reader.readBytes(Item.Checksum, Header->ChecksumSize))
+ return EC;
+ Len = sizeof(FileChecksum) + Header->ChecksumSize;
+ return Error::success();
+ }
+};
+
+typedef VarStreamArray<LineColumnEntry> LineInfoArray;
+typedef VarStreamArray<FileChecksumEntry> FileChecksumArray;
+
+class IModuleSubstreamVisitor {
+public:
+ virtual ~IModuleSubstreamVisitor() {}
+
+ virtual Error visitUnknown(ModuleSubstreamKind Kind, StreamRef Data) = 0;
+ virtual Error visitSymbols(StreamRef Data);
+ virtual Error visitLines(StreamRef Data, const LineSubstreamHeader *Header,
+ const LineInfoArray &Lines);
+ virtual Error visitStringTable(StreamRef Data);
+ virtual Error visitFileChecksums(StreamRef Data,
+ const FileChecksumArray &Checksums);
+ virtual Error visitFrameData(StreamRef Data);
+ virtual Error visitInlineeLines(StreamRef Data);
+ virtual Error visitCrossScopeImports(StreamRef Data);
+ virtual Error visitCrossScopeExports(StreamRef Data);
+ virtual Error visitILLines(StreamRef Data);
+ virtual Error visitFuncMDTokenMap(StreamRef Data);
+ virtual Error visitTypeMDTokenMap(StreamRef Data);
+ virtual Error visitMergedAssemblyInput(StreamRef Data);
+ virtual Error visitCoffSymbolRVA(StreamRef Data);
+};
+
+Error visitModuleSubstream(const ModuleSubstream &R,
+ IModuleSubstreamVisitor &V);
+
+} // namespace codeview
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAMVISITOR_H
diff --git a/include/llvm/DebugInfo/CodeView/RecordSerialization.h b/include/llvm/DebugInfo/CodeView/RecordSerialization.h
new file mode 100644
index 000000000000..84179f5f81f7
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/RecordSerialization.h
@@ -0,0 +1,278 @@
+//===- RecordSerialization.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_RECORDSERIALIZATION_H
+#define LLVM_DEBUGINFO_CODEVIEW_RECORDSERIALIZATION_H
+
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include <cinttypes>
+#include <tuple>
+
+namespace llvm {
+namespace codeview {
+using llvm::support::little32_t;
+using llvm::support::ulittle16_t;
+using llvm::support::ulittle32_t;
+
+struct RecordPrefix {
+ ulittle16_t RecordLen; // Record length, starting from &Leaf.
+ ulittle16_t RecordKind; // Record kind enum (SymRecordKind or TypeRecordKind)
+};
+
+/// Reinterpret a byte array as an array of characters. Does not interpret as
+/// a C string, as StringRef has several helpers (split) that make that easy.
+StringRef getBytesAsCharacters(ArrayRef<uint8_t> LeafData);
+StringRef getBytesAsCString(ArrayRef<uint8_t> LeafData);
+
+/// Consumes sizeof(T) bytes from the given byte sequence. Returns an error if
+/// there are not enough bytes remaining. Reinterprets the consumed bytes as a
+/// T object and points 'Res' at them.
+template <typename T, typename U>
+inline std::error_code consumeObject(U &Data, const T *&Res) {
+ if (Data.size() < sizeof(*Res))
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+ Res = reinterpret_cast<const T *>(Data.data());
+ Data = Data.drop_front(sizeof(*Res));
+ return std::error_code();
+}
+
+inline std::error_code consume(ArrayRef<uint8_t> &Data) {
+ return std::error_code();
+}
+
+/// Decodes a numeric "leaf" value. These are integer literals encountered in
+/// the type stream. If the value is positive and less than LF_NUMERIC (1 <<
+/// 15), it is emitted directly in Data. Otherwise, it has a tag like LF_CHAR
+/// that indicates the bitwidth and sign of the numeric data.
+std::error_code consume(ArrayRef<uint8_t> &Data, APSInt &Num);
+std::error_code consume(StringRef &Data, APSInt &Num);
+
+/// Decodes a numeric leaf value that is known to be a particular type.
+std::error_code consume_numeric(ArrayRef<uint8_t> &Data, uint64_t &Value);
+
+/// Decodes signed and unsigned fixed-length integers.
+std::error_code consume(ArrayRef<uint8_t> &Data, uint32_t &Item);
+std::error_code consume(StringRef &Data, uint32_t &Item);
+std::error_code consume(ArrayRef<uint8_t> &Data, int32_t &Item);
+
+/// Decodes a null terminated string.
+std::error_code consume(ArrayRef<uint8_t> &Data, StringRef &Item);
+
+/// Decodes an arbitrary object whose layout matches that of the underlying
+/// byte sequence, and returns a pointer to the object.
+template <typename T>
+std::error_code consume(ArrayRef<uint8_t> &Data, T *&Item) {
+ return consumeObject(Data, Item);
+}
+
+template <typename T, typename U> struct serialize_conditional_impl {
+ serialize_conditional_impl(T &Item, U Func) : Item(Item), Func(Func) {}
+
+ std::error_code deserialize(ArrayRef<uint8_t> &Data) const {
+ if (!Func())
+ return std::error_code();
+ return consume(Data, Item);
+ }
+
+ T &Item;
+ U Func;
+};
+
+template <typename T, typename U>
+serialize_conditional_impl<T, U> serialize_conditional(T &Item, U Func) {
+ return serialize_conditional_impl<T, U>(Item, Func);
+}
+
+template <typename T, typename U> struct serialize_array_impl {
+ serialize_array_impl(ArrayRef<T> &Item, U Func) : Item(Item), Func(Func) {}
+
+ std::error_code deserialize(ArrayRef<uint8_t> &Data) const {
+ uint32_t N = Func();
+ if (N == 0)
+ return std::error_code();
+
+ uint32_t Size = sizeof(T) * N;
+
+ if (Size / sizeof(T) != N)
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+
+ if (Data.size() < Size)
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+
+ Item = ArrayRef<T>(reinterpret_cast<const T *>(Data.data()), N);
+ Data = Data.drop_front(Size);
+ return std::error_code();
+ }
+
+ ArrayRef<T> &Item;
+ U Func;
+};
+
+template <typename T> struct serialize_vector_tail_impl {
+ serialize_vector_tail_impl(std::vector<T> &Item) : Item(Item) {}
+
+ std::error_code deserialize(ArrayRef<uint8_t> &Data) const {
+ T Field;
+ // Stop when we run out of bytes or we hit record padding bytes.
+ while (!Data.empty() && Data.front() < LF_PAD0) {
+ if (auto EC = consume(Data, Field))
+ return EC;
+ Item.push_back(Field);
+ }
+ return std::error_code();
+ }
+
+ std::vector<T> &Item;
+};
+
+struct serialize_null_term_string_array_impl {
+ serialize_null_term_string_array_impl(std::vector<StringRef> &Item)
+ : Item(Item) {}
+
+ std::error_code deserialize(ArrayRef<uint8_t> &Data) const {
+ if (Data.empty())
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+
+ StringRef Field;
+ // Stop when we run out of bytes or we hit record padding bytes.
+ while (Data.front() != 0) {
+ if (auto EC = consume(Data, Field))
+ return EC;
+ Item.push_back(Field);
+ if (Data.empty())
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+ }
+ Data = Data.drop_front(1);
+ return std::error_code();
+ }
+
+ std::vector<StringRef> &Item;
+};
+
+template <typename T> struct serialize_arrayref_tail_impl {
+ serialize_arrayref_tail_impl(ArrayRef<T> &Item) : Item(Item) {}
+
+ std::error_code deserialize(ArrayRef<uint8_t> &Data) const {
+ uint32_t Count = Data.size() / sizeof(T);
+ Item = ArrayRef<T>(reinterpret_cast<const T *>(Data.begin()), Count);
+ return std::error_code();
+ }
+
+ ArrayRef<T> &Item;
+};
+
+template <typename T> struct serialize_numeric_impl {
+ serialize_numeric_impl(T &Item) : Item(Item) {}
+
+ std::error_code deserialize(ArrayRef<uint8_t> &Data) const {
+ return consume_numeric(Data, Item);
+ }
+
+ T &Item;
+};
+
+template <typename T, typename U>
+serialize_array_impl<T, U> serialize_array(ArrayRef<T> &Item, U Func) {
+ return serialize_array_impl<T, U>(Item, Func);
+}
+
+inline serialize_null_term_string_array_impl
+serialize_null_term_string_array(std::vector<StringRef> &Item) {
+ return serialize_null_term_string_array_impl(Item);
+}
+
+template <typename T>
+serialize_vector_tail_impl<T> serialize_array_tail(std::vector<T> &Item) {
+ return serialize_vector_tail_impl<T>(Item);
+}
+
+template <typename T>
+serialize_arrayref_tail_impl<T> serialize_array_tail(ArrayRef<T> &Item) {
+ return serialize_arrayref_tail_impl<T>(Item);
+}
+
+template <typename T> serialize_numeric_impl<T> serialize_numeric(T &Item) {
+ return serialize_numeric_impl<T>(Item);
+}
+
+// This field is only present in the byte record if the condition is true. The
+// condition is evaluated lazily, so it can depend on items that were
+// deserialized
+// earlier.
+#define CV_CONDITIONAL_FIELD(I, C) \
+ serialize_conditional(I, [&]() { return !!(C); })
+
+// This is an array of N items, where N is evaluated lazily, so it can refer
+// to a field deserialized earlier.
+#define CV_ARRAY_FIELD_N(I, N) serialize_array(I, [&]() { return N; })
+
+// This is an array that exhausts the remainder of the input buffer.
+#define CV_ARRAY_FIELD_TAIL(I) serialize_array_tail(I)
+
+// This is an array that consumes null terminated strings until a double null
+// is encountered.
+#define CV_STRING_ARRAY_NULL_TERM(I) serialize_null_term_string_array(I)
+
+#define CV_NUMERIC_FIELD(I) serialize_numeric(I)
+
+template <typename T, typename U>
+std::error_code consume(ArrayRef<uint8_t> &Data,
+ const serialize_conditional_impl<T, U> &Item) {
+ return Item.deserialize(Data);
+}
+
+template <typename T, typename U>
+std::error_code consume(ArrayRef<uint8_t> &Data,
+ const serialize_array_impl<T, U> &Item) {
+ return Item.deserialize(Data);
+}
+
+inline std::error_code
+consume(ArrayRef<uint8_t> &Data,
+ const serialize_null_term_string_array_impl &Item) {
+ return Item.deserialize(Data);
+}
+
+template <typename T>
+std::error_code consume(ArrayRef<uint8_t> &Data,
+ const serialize_vector_tail_impl<T> &Item) {
+ return Item.deserialize(Data);
+}
+
+template <typename T>
+std::error_code consume(ArrayRef<uint8_t> &Data,
+ const serialize_arrayref_tail_impl<T> &Item) {
+ return Item.deserialize(Data);
+}
+
+template <typename T>
+std::error_code consume(ArrayRef<uint8_t> &Data,
+ const serialize_numeric_impl<T> &Item) {
+ return Item.deserialize(Data);
+}
+
+template <typename T, typename U, typename... Args>
+std::error_code consume(ArrayRef<uint8_t> &Data, T &&X, U &&Y,
+ Args &&... Rest) {
+ if (auto EC = consume(Data, X))
+ return EC;
+ return consume(Data, Y, std::forward<Args>(Rest)...);
+}
+
+#define CV_DESERIALIZE(...) \
+ if (auto EC = consume(__VA_ARGS__)) \
+ return EC;
+}
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/CodeView/StreamArray.h b/include/llvm/DebugInfo/CodeView/StreamArray.h
new file mode 100644
index 000000000000..0b9349aac753
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/StreamArray.h
@@ -0,0 +1,275 @@
+//===- StreamArray.h - Array backed by an arbitrary stream ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_STREAMARRAY_H
+#define LLVM_DEBUGINFO_CODEVIEW_STREAMARRAY_H
+
+#include "llvm/DebugInfo/CodeView/StreamRef.h"
+#include "llvm/Support/Error.h"
+
+#include <functional>
+#include <type_traits>
+
+namespace llvm {
+namespace codeview {
+
+/// VarStreamArrayExtractor is intended to be specialized to provide customized
+/// extraction logic. On input it receives a StreamRef pointing to the
+/// beginning of the next record, but where the length of the record is not yet
+/// known. Upon completion, it should return an appropriate Error instance if
+/// a record could not be extracted, or if one could be extracted it should
+/// return success and set Len to the number of bytes this record occupied in
+/// the underlying stream, and it should fill out the fields of the value type
+/// Item appropriately to represent the current record.
+///
+/// You can specialize this template for your own custom value types to avoid
+/// having to specify a second template argument to VarStreamArray (documented
+/// below).
+template <typename T> struct VarStreamArrayExtractor {
+ // Method intentionally deleted. You must provide an explicit specialization
+ // with the following method implemented.
+ Error operator()(StreamRef Stream, uint32_t &Len, T &Item) const = delete;
+};
+
+/// VarStreamArray represents an array of variable length records backed by a
+/// stream. This could be a contiguous sequence of bytes in memory, it could
+/// be a file on disk, or it could be a PDB stream where bytes are stored as
+/// discontiguous blocks in a file. Usually it is desirable to treat arrays
+/// as contiguous blocks of memory, but doing so with large PDB files, for
+/// example, could mean allocating huge amounts of memory just to allow
+/// re-ordering of stream data to be contiguous before iterating over it. By
+/// abstracting this out, we need not duplicate this memory, and we can
+/// iterate over arrays in arbitrarily formatted streams. Elements are parsed
+/// lazily on iteration, so there is no upfront cost associated with building
+/// a VarStreamArray, no matter how large it may be.
+///
+/// You create a VarStreamArray by specifying a ValueType and an Extractor type.
+/// If you do not specify an Extractor type, it expects you to specialize
+/// VarStreamArrayExtractor<T> for your ValueType.
+///
+/// By default an Extractor is default constructed in the class, but in some
+/// cases you might find it useful for an Extractor to maintain state across
+/// extractions. In this case you can provide your own Extractor through a
+/// secondary constructor. The following examples show various ways of
+/// creating a VarStreamArray.
+///
+/// // Will use VarStreamArrayExtractor<MyType> as the extractor.
+/// VarStreamArray<MyType> MyTypeArray;
+///
+/// // Will use a default-constructed MyExtractor as the extractor.
+/// VarStreamArray<MyType, MyExtractor> MyTypeArray2;
+///
+/// // Will use the specific instance of MyExtractor provided.
+/// // MyExtractor need not be default-constructible in this case.
+/// MyExtractor E(SomeContext);
+/// VarStreamArray<MyType, MyExtractor> MyTypeArray3(E);
+///
+template <typename ValueType, typename Extractor> class VarStreamArrayIterator;
+
+template <typename ValueType,
+ typename Extractor = VarStreamArrayExtractor<ValueType>>
+class VarStreamArray {
+ friend class VarStreamArrayIterator<ValueType, Extractor>;
+
+public:
+ typedef VarStreamArrayIterator<ValueType, Extractor> Iterator;
+
+ VarStreamArray() {}
+ explicit VarStreamArray(const Extractor &E) : E(E) {}
+
+ explicit VarStreamArray(StreamRef Stream) : Stream(Stream) {}
+ VarStreamArray(StreamRef Stream, const Extractor &E) : Stream(Stream), E(E) {}
+
+ VarStreamArray(const VarStreamArray<ValueType, Extractor> &Other)
+ : Stream(Other.Stream), E(Other.E) {}
+
+ Iterator begin(bool *HadError = nullptr) const {
+ return Iterator(*this, E, HadError);
+ }
+
+ Iterator end() const { return Iterator(E); }
+
+ const Extractor &getExtractor() const { return E; }
+
+ StreamRef getUnderlyingStream() const { return Stream; }
+
+private:
+ StreamRef Stream;
+ Extractor E;
+};
+
+template <typename ValueType, typename Extractor> class VarStreamArrayIterator {
+ typedef VarStreamArrayIterator<ValueType, Extractor> IterType;
+ typedef VarStreamArray<ValueType, Extractor> ArrayType;
+
+public:
+ VarStreamArrayIterator(const ArrayType &Array, const Extractor &E,
+ bool *HadError = nullptr)
+ : IterRef(Array.Stream), Array(&Array), HadError(HadError), Extract(E) {
+ if (IterRef.getLength() == 0)
+ moveToEnd();
+ else {
+ auto EC = Extract(IterRef, ThisLen, ThisValue);
+ if (EC) {
+ consumeError(std::move(EC));
+ markError();
+ }
+ }
+ }
+ VarStreamArrayIterator() {}
+ explicit VarStreamArrayIterator(const Extractor &E) : Extract(E) {}
+ ~VarStreamArrayIterator() {}
+
+ bool operator==(const IterType &R) const {
+ if (Array && R.Array) {
+ // Both have a valid array, make sure they're same.
+ assert(Array == R.Array);
+ return IterRef == R.IterRef;
+ }
+
+ // Both iterators are at the end.
+ if (!Array && !R.Array)
+ return true;
+
+ // One is not at the end and one is.
+ return false;
+ }
+
+ bool operator!=(const IterType &R) { return !(*this == R); }
+
+ const ValueType &operator*() const {
+ assert(Array && !HasError);
+ return ThisValue;
+ }
+
+ IterType &operator++() {
+ // We are done with the current record, discard it so that we are
+ // positioned at the next record.
+ IterRef = IterRef.drop_front(ThisLen);
+ if (IterRef.getLength() == 0) {
+ // There is nothing after the current record, we must make this an end
+ // iterator.
+ moveToEnd();
+ } else {
+ // There is some data after the current record.
+ auto EC = Extract(IterRef, ThisLen, ThisValue);
+ if (EC) {
+ consumeError(std::move(EC));
+ markError();
+ } else if (ThisLen == 0) {
+ // An empty record? Make this an end iterator.
+ moveToEnd();
+ }
+ }
+ return *this;
+ }
+
+ IterType operator++(int) {
+ IterType Original = *this;
+ ++*this;
+ return Original;
+ }
+
+private:
+ void moveToEnd() {
+ Array = nullptr;
+ ThisLen = 0;
+ }
+ void markError() {
+ moveToEnd();
+ HasError = true;
+ if (HadError != nullptr)
+ *HadError = true;
+ }
+
+ ValueType ThisValue;
+ StreamRef IterRef;
+ const ArrayType *Array{nullptr};
+ uint32_t ThisLen{0};
+ bool HasError{false};
+ bool *HadError{nullptr};
+ Extractor Extract;
+};
+
+template <typename T> class FixedStreamArrayIterator;
+
+template <typename T> class FixedStreamArray {
+ friend class FixedStreamArrayIterator<T>;
+
+public:
+ FixedStreamArray() : Stream() {}
+ FixedStreamArray(StreamRef Stream) : Stream(Stream) {
+ assert(Stream.getLength() % sizeof(T) == 0);
+ }
+
+ const T &operator[](uint32_t Index) const {
+ assert(Index < size());
+ uint32_t Off = Index * sizeof(T);
+ ArrayRef<uint8_t> Data;
+ if (auto EC = Stream.readBytes(Off, sizeof(T), Data)) {
+ assert(false && "Unexpected failure reading from stream");
+ // This should never happen since we asserted that the stream length was
+ // an exact multiple of the element size.
+ consumeError(std::move(EC));
+ }
+ return *reinterpret_cast<const T *>(Data.data());
+ }
+
+ uint32_t size() const { return Stream.getLength() / sizeof(T); }
+
+ FixedStreamArrayIterator<T> begin() const {
+ return FixedStreamArrayIterator<T>(*this, 0);
+ }
+ FixedStreamArrayIterator<T> end() const {
+ return FixedStreamArrayIterator<T>(*this, size());
+ }
+
+ StreamRef getUnderlyingStream() const { return Stream; }
+
+private:
+ StreamRef Stream;
+};
+
+template <typename T> class FixedStreamArrayIterator {
+public:
+ FixedStreamArrayIterator(const FixedStreamArray<T> &Array, uint32_t Index)
+ : Array(Array), Index(Index) {}
+
+ bool operator==(const FixedStreamArrayIterator<T> &R) {
+ assert(&Array == &R.Array);
+ return Index == R.Index;
+ }
+
+ bool operator!=(const FixedStreamArrayIterator<T> &R) {
+ return !(*this == R);
+ }
+
+ const T &operator*() const { return Array[Index]; }
+
+ FixedStreamArrayIterator<T> &operator++() {
+ assert(Index < Array.size());
+ ++Index;
+ return *this;
+ }
+
+ FixedStreamArrayIterator<T> operator++(int) {
+ FixedStreamArrayIterator<T> Original = *this;
+ ++*this;
+ return Original;
+ }
+
+private:
+ const FixedStreamArray<T> &Array;
+ uint32_t Index;
+};
+
+} // namespace codeview
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_CODEVIEW_STREAMARRAY_H
diff --git a/include/llvm/DebugInfo/CodeView/StreamInterface.h b/include/llvm/DebugInfo/CodeView/StreamInterface.h
new file mode 100644
index 000000000000..241aec457870
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/StreamInterface.h
@@ -0,0 +1,55 @@
+//===- StreamInterface.h - Base interface for a stream of data --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_STREAMINTERFACE_H
+#define LLVM_DEBUGINFO_CODEVIEW_STREAMINTERFACE_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/Error.h"
+#include <cstdint>
+
+namespace llvm {
+namespace codeview {
+
+/// StreamInterface abstracts the notion of a data stream. This way, an
+/// implementation could implement trivial reading from a contiguous memory
+/// buffer or, as in the case of PDB files, reading from a set of possibly
+/// discontiguous blocks. The implementation is required to return references
+/// to stable memory, so if this is not possible (for example in the case of
+/// a PDB file with discontiguous blocks, it must keep its own pool of temp
+/// storage.
+class StreamInterface {
+public:
+ virtual ~StreamInterface() {}
+
+ // Given an offset into the stream and a number of bytes, attempt to read
+ // the bytes and set the output ArrayRef to point to a reference into the
+ // stream, without copying any data.
+ virtual Error readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) const = 0;
+
+ // Given an offset into the stream, read as much as possible without copying
+ // any data.
+ virtual Error readLongestContiguousChunk(uint32_t Offset,
+ ArrayRef<uint8_t> &Buffer) const = 0;
+
+ // Attempt to write the given bytes into the stream at the desired offset.
+ // This will always necessitate a copy. Cannot shrink or grow the stream,
+ // only writes into existing allocated space.
+ virtual Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) const = 0;
+
+ virtual uint32_t getLength() const = 0;
+
+ virtual Error commit() const = 0;
+};
+
+} // end namespace codeview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_CODEVIEW_STREAMINTERFACE_H
diff --git a/include/llvm/DebugInfo/CodeView/StreamReader.h b/include/llvm/DebugInfo/CodeView/StreamReader.h
new file mode 100644
index 000000000000..2f497c2c43f1
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/StreamReader.h
@@ -0,0 +1,111 @@
+//===- StreamReader.h - Reads bytes and objects from a stream ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_STREAMREADER_H
+#define LLVM_DEBUGINFO_CODEVIEW_STREAMREADER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/CodeView/StreamArray.h"
+#include "llvm/DebugInfo/CodeView/StreamInterface.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+
+#include <string>
+
+namespace llvm {
+namespace codeview {
+
+class StreamRef;
+
+class StreamReader {
+public:
+ StreamReader(StreamRef Stream);
+
+ Error readLongestContiguousChunk(ArrayRef<uint8_t> &Buffer);
+ Error readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size);
+ Error readInteger(uint16_t &Dest);
+ Error readInteger(uint32_t &Dest);
+ Error readZeroString(StringRef &Dest);
+ Error readFixedString(StringRef &Dest, uint32_t Length);
+ Error readStreamRef(StreamRef &Ref);
+ Error readStreamRef(StreamRef &Ref, uint32_t Length);
+
+ template <typename T> Error readEnum(T &Dest) {
+ typename std::underlying_type<T>::type N;
+ if (auto EC = readInteger(N))
+ return EC;
+ Dest = static_cast<T>(N);
+ return Error::success();
+ }
+
+ template <typename T> Error readObject(const T *&Dest) {
+ ArrayRef<uint8_t> Buffer;
+ if (auto EC = readBytes(Buffer, sizeof(T)))
+ return EC;
+ Dest = reinterpret_cast<const T *>(Buffer.data());
+ return Error::success();
+ }
+
+ template <typename T>
+ Error readArray(ArrayRef<T> &Array, uint32_t NumElements) {
+ ArrayRef<uint8_t> Bytes;
+ if (NumElements == 0) {
+ Array = ArrayRef<T>();
+ return Error::success();
+ }
+
+ if (NumElements > UINT32_MAX/sizeof(T))
+ return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
+
+ if (auto EC = readBytes(Bytes, NumElements * sizeof(T)))
+ return EC;
+ Array = ArrayRef<T>(reinterpret_cast<const T *>(Bytes.data()), NumElements);
+ return Error::success();
+ }
+
+ template <typename T, typename U>
+ Error readArray(VarStreamArray<T, U> &Array, uint32_t Size) {
+ StreamRef S;
+ if (auto EC = readStreamRef(S, Size))
+ return EC;
+ Array = VarStreamArray<T, U>(S, Array.getExtractor());
+ return Error::success();
+ }
+
+ template <typename T>
+ Error readArray(FixedStreamArray<T> &Array, uint32_t NumItems) {
+ if (NumItems == 0) {
+ Array = FixedStreamArray<T>();
+ return Error::success();
+ }
+ uint32_t Length = NumItems * sizeof(T);
+ if (Length / sizeof(T) != NumItems)
+ return make_error<CodeViewError>(cv_error_code::corrupt_record);
+ if (Offset + Length > Stream.getLength())
+ return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
+ StreamRef View = Stream.slice(Offset, Length);
+ Array = FixedStreamArray<T>(View);
+ Offset += Length;
+ return Error::success();
+ }
+
+ void setOffset(uint32_t Off) { Offset = Off; }
+ uint32_t getOffset() const { return Offset; }
+ uint32_t getLength() const { return Stream.getLength(); }
+ uint32_t bytesRemaining() const { return getLength() - getOffset(); }
+
+private:
+ StreamRef Stream;
+ uint32_t Offset;
+};
+} // namespace codeview
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_CODEVIEW_STREAMREADER_H
diff --git a/include/llvm/DebugInfo/CodeView/StreamRef.h b/include/llvm/DebugInfo/CodeView/StreamRef.h
new file mode 100644
index 000000000000..a4f244a32289
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/StreamRef.h
@@ -0,0 +1,104 @@
+//===- StreamRef.h - A copyable reference to a stream -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_STREAMREF_H
+#define LLVM_DEBUGINFO_CODEVIEW_STREAMREF_H
+
+#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/CodeView/StreamInterface.h"
+
+namespace llvm {
+namespace codeview {
+
+class StreamRef {
+public:
+ StreamRef() : Stream(nullptr), ViewOffset(0), Length(0) {}
+ StreamRef(const StreamInterface &Stream)
+ : Stream(&Stream), ViewOffset(0), Length(Stream.getLength()) {}
+ StreamRef(const StreamInterface &Stream, uint32_t Offset, uint32_t Length)
+ : Stream(&Stream), ViewOffset(Offset), Length(Length) {}
+
+ // Use StreamRef.slice() instead.
+ StreamRef(const StreamRef &S, uint32_t Offset, uint32_t Length) = delete;
+
+ Error readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) const {
+ if (ViewOffset + Offset < Offset)
+ return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
+ if (Size + Offset > Length)
+ return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
+ return Stream->readBytes(ViewOffset + Offset, Size, Buffer);
+ }
+
+ // Given an offset into the stream, read as much as possible without copying
+ // any data.
+ Error readLongestContiguousChunk(uint32_t Offset,
+ ArrayRef<uint8_t> &Buffer) const {
+ if (Offset >= Length)
+ return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
+
+ if (auto EC = Stream->readLongestContiguousChunk(Offset, Buffer))
+ return EC;
+ // This StreamRef might refer to a smaller window over a larger stream. In
+ // that case we will have read out more bytes than we should return, because
+ // we should not read past the end of the current view.
+ uint32_t MaxLength = Length - Offset;
+ if (Buffer.size() > MaxLength)
+ Buffer = Buffer.slice(0, MaxLength);
+ return Error::success();
+ }
+
+ Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) const {
+ if (Data.size() + Offset > Length)
+ return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
+ return Stream->writeBytes(ViewOffset + Offset, Data);
+ }
+
+ uint32_t getLength() const { return Length; }
+
+ Error commit() const { return Stream->commit(); }
+
+ StreamRef drop_front(uint32_t N) const {
+ if (!Stream)
+ return StreamRef();
+
+ N = std::min(N, Length);
+ return StreamRef(*Stream, ViewOffset + N, Length - N);
+ }
+
+ StreamRef keep_front(uint32_t N) const {
+ if (!Stream)
+ return StreamRef();
+ N = std::min(N, Length);
+ return StreamRef(*Stream, ViewOffset, N);
+ }
+
+ StreamRef slice(uint32_t Offset, uint32_t Len) const {
+ return drop_front(Offset).keep_front(Len);
+ }
+
+ bool operator==(const StreamRef &Other) const {
+ if (Stream != Other.Stream)
+ return false;
+ if (ViewOffset != Other.ViewOffset)
+ return false;
+ if (Length != Other.Length)
+ return false;
+ return true;
+ }
+
+private:
+ const StreamInterface *Stream;
+ uint32_t ViewOffset;
+ uint32_t Length;
+};
+}
+}
+
+#endif // LLVM_DEBUGINFO_CODEVIEW_STREAMREF_H
diff --git a/include/llvm/DebugInfo/CodeView/StreamWriter.h b/include/llvm/DebugInfo/CodeView/StreamWriter.h
new file mode 100644
index 000000000000..4d393d2ef790
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/StreamWriter.h
@@ -0,0 +1,86 @@
+//===- StreamWriter.h - Writes bytes and objects to a stream ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_STREAMWRITER_H
+#define LLVM_DEBUGINFO_CODEVIEW_STREAMWRITER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/CodeView/StreamArray.h"
+#include "llvm/DebugInfo/CodeView/StreamInterface.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+
+#include <string>
+
+namespace llvm {
+namespace codeview {
+
+class StreamRef;
+
+class StreamWriter {
+public:
+ StreamWriter(StreamRef Stream);
+
+ Error writeBytes(ArrayRef<uint8_t> Buffer);
+ Error writeInteger(uint16_t Dest);
+ Error writeInteger(uint32_t Dest);
+ Error writeZeroString(StringRef Str);
+ Error writeFixedString(StringRef Str);
+ Error writeStreamRef(StreamRef Ref);
+ Error writeStreamRef(StreamRef Ref, uint32_t Size);
+
+ template <typename T> Error writeEnum(T Num) {
+ return writeInteger(
+ static_cast<typename std::underlying_type<T>::type>(Num));
+ }
+
+ template <typename T> Error writeObject(const T &Obj) {
+ static_assert(!std::is_pointer<T>::value,
+ "writeObject should not be used with pointers, to write "
+ "the pointed-to value dereference the pointer before calling "
+ "writeObject");
+ return writeBytes(
+ ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&Obj), sizeof(T)));
+ }
+
+ template <typename T> Error writeArray(ArrayRef<T> Array) {
+ if (Array.size() == 0)
+ return Error::success();
+
+ if (Array.size() > UINT32_MAX / sizeof(T))
+ return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
+
+ return writeBytes(
+ ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Array.data()),
+ Array.size() * sizeof(T)));
+ }
+
+ template <typename T, typename U>
+ Error writeArray(VarStreamArray<T, U> Array) {
+ return writeStreamRef(Array.getUnderlyingStream());
+ }
+
+ template <typename T> Error writeArray(FixedStreamArray<T> Array) {
+ return writeStreamRef(Array.getUnderlyingStream());
+ }
+
+ void setOffset(uint32_t Off) { Offset = Off; }
+ uint32_t getOffset() const { return Offset; }
+ uint32_t getLength() const { return Stream.getLength(); }
+ uint32_t bytesRemaining() const { return getLength() - getOffset(); }
+
+private:
+ StreamRef Stream;
+ uint32_t Offset;
+};
+} // namespace codeview
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_CODEVIEW_STREAMREADER_H
diff --git a/include/llvm/DebugInfo/CodeView/SymbolDumpDelegate.h b/include/llvm/DebugInfo/CodeView/SymbolDumpDelegate.h
new file mode 100644
index 000000000000..30b0a40451cb
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/SymbolDumpDelegate.h
@@ -0,0 +1,37 @@
+//===-- SymbolDumpDelegate.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_SYMBOLDUMPDELEGATE_H
+#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLDUMPDELEGATE_H
+
+#include "SymbolVisitorDelegate.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+
+#include <stdint.h>
+
+namespace llvm {
+
+namespace codeview {
+
+class SymbolDumpDelegate : public SymbolVisitorDelegate {
+public:
+ virtual ~SymbolDumpDelegate() {}
+
+ virtual void printRelocatedField(StringRef Label, uint32_t RelocOffset,
+ uint32_t Offset,
+ StringRef *RelocSym = nullptr) = 0;
+ virtual void printBinaryBlockWithRelocs(StringRef Label,
+ ArrayRef<uint8_t> Block) = 0;
+};
+} // end namespace codeview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLDUMPDELEGATE_H
diff --git a/include/llvm/DebugInfo/CodeView/SymbolDumper.h b/include/llvm/DebugInfo/CodeView/SymbolDumper.h
new file mode 100644
index 000000000000..648e40f55810
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/SymbolDumper.h
@@ -0,0 +1,54 @@
+//===-- SymbolDumper.h - CodeView symbol info dumper ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_SYMBOLDUMPER_H
+#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLDUMPER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+
+namespace llvm {
+class ScopedPrinter;
+
+namespace codeview {
+class CVTypeDumper;
+
+/// Dumper for CodeView symbol streams found in COFF object files and PDB files.
+class CVSymbolDumper {
+public:
+ CVSymbolDumper(ScopedPrinter &W, CVTypeDumper &CVTD,
+ std::unique_ptr<SymbolDumpDelegate> ObjDelegate,
+ bool PrintRecordBytes)
+ : W(W), CVTD(CVTD), ObjDelegate(std::move(ObjDelegate)),
+ PrintRecordBytes(PrintRecordBytes) {}
+
+ /// Dumps one type record. Returns false if there was a type parsing error,
+ /// and true otherwise. This should be called in order, since the dumper
+ /// maintains state about previous records which are necessary for cross
+ /// type references.
+ bool dump(const CVRecord<SymbolKind> &Record);
+
+ /// Dumps the type records in Data. Returns false if there was a type stream
+ /// parse error, and true otherwise.
+ bool dump(const CVSymbolArray &Symbols);
+
+private:
+ ScopedPrinter &W;
+ CVTypeDumper &CVTD;
+ std::unique_ptr<SymbolDumpDelegate> ObjDelegate;
+
+ bool PrintRecordBytes;
+};
+} // end namespace codeview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLDUMPER_H
diff --git a/include/llvm/DebugInfo/CodeView/SymbolRecord.h b/include/llvm/DebugInfo/CodeView/SymbolRecord.h
new file mode 100644
index 000000000000..77e894fba4a9
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/SymbolRecord.h
@@ -0,0 +1,1452 @@
+//===- SymbolRecord.h -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H
+#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H
+
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/DebugInfo/CodeView/CVRecord.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
+#include "llvm/DebugInfo/CodeView/StreamArray.h"
+#include "llvm/DebugInfo/CodeView/StreamInterface.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace codeview {
+
+using llvm::support::ulittle16_t;
+using llvm::support::ulittle32_t;
+using llvm::support::little32_t;
+
+class SymbolRecord {
+protected:
+ explicit SymbolRecord(SymbolRecordKind Kind) : Kind(Kind) {}
+
+public:
+ SymbolRecordKind getKind() const { return Kind; }
+
+private:
+ SymbolRecordKind Kind;
+};
+
+// S_GPROC32, S_LPROC32, S_GPROC32_ID, S_LPROC32_ID, S_LPROC32_DPC or
+// S_LPROC32_DPC_ID
+class ProcSym : public SymbolRecord {
+public:
+ struct Hdr {
+ ulittle32_t PtrParent;
+ ulittle32_t PtrEnd;
+ ulittle32_t PtrNext;
+ ulittle32_t CodeSize;
+ ulittle32_t DbgStart;
+ ulittle32_t DbgEnd;
+ TypeIndex FunctionType;
+ ulittle32_t CodeOffset;
+ ulittle16_t Segment;
+ uint8_t Flags; // ProcSymFlags enum
+ // Name: The null-terminated name follows.
+ };
+
+ ProcSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H,
+ StringRef Name)
+ : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H), Name(Name) {
+ }
+
+ static ErrorOr<ProcSym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ StringRef Name;
+ CV_DESERIALIZE(Data, H, Name);
+
+ return ProcSym(Kind, RecordOffset, H, Name);
+ }
+
+ uint32_t getRelocationOffset() const {
+ return RecordOffset + offsetof(Hdr, CodeOffset);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+ StringRef Name;
+};
+
+// S_THUNK32
+class Thunk32Sym : public SymbolRecord {
+public:
+ struct Hdr {
+ ulittle32_t Parent;
+ ulittle32_t End;
+ ulittle32_t Next;
+ ulittle32_t Off;
+ ulittle16_t Seg;
+ ulittle16_t Len;
+ uint8_t Ord; // ThunkOrdinal enumeration
+ // Name: The null-terminated name follows.
+ // Variant portion of thunk
+ };
+
+ Thunk32Sym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H,
+ StringRef Name, ArrayRef<uint8_t> VariantData)
+ : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H), Name(Name),
+ VariantData(VariantData) {}
+
+ static ErrorOr<Thunk32Sym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ StringRef Name;
+ ArrayRef<uint8_t> VariantData;
+
+ CV_DESERIALIZE(Data, H, Name, CV_ARRAY_FIELD_TAIL(VariantData));
+
+ return Thunk32Sym(Kind, RecordOffset, H, Name, VariantData);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+ StringRef Name;
+ ArrayRef<uint8_t> VariantData;
+};
+
+// S_TRAMPOLINE
+class TrampolineSym : public SymbolRecord {
+public:
+ struct Hdr {
+ ulittle16_t Type; // TrampolineType enum
+ ulittle16_t Size;
+ ulittle32_t ThunkOff;
+ ulittle32_t TargetOff;
+ ulittle16_t ThunkSection;
+ ulittle16_t TargetSection;
+ };
+
+ TrampolineSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H)
+ : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H) {}
+
+ static ErrorOr<TrampolineSym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+
+ CV_DESERIALIZE(Data, H);
+
+ return TrampolineSym(Kind, RecordOffset, H);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+};
+
+// S_SECTION
+class SectionSym : public SymbolRecord {
+public:
+ struct Hdr {
+ ulittle16_t SectionNumber;
+ uint8_t Alignment;
+ uint8_t Reserved; // Must be 0
+ ulittle32_t Rva;
+ ulittle32_t Length;
+ ulittle32_t Characteristics;
+ // Name: The null-terminated name follows.
+ };
+
+ SectionSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H,
+ StringRef Name)
+ : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H), Name(Name) {
+ }
+
+ static ErrorOr<SectionSym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ StringRef Name;
+
+ CV_DESERIALIZE(Data, H, Name);
+
+ return SectionSym(Kind, RecordOffset, H, Name);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+ StringRef Name;
+};
+
+// S_COFFGROUP
+class CoffGroupSym : public SymbolRecord {
+public:
+ struct Hdr {
+ ulittle32_t Size;
+ ulittle32_t Characteristics;
+ ulittle32_t Offset;
+ ulittle16_t Segment;
+ // Name: The null-terminated name follows.
+ };
+
+ CoffGroupSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H,
+ StringRef Name)
+ : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H), Name(Name) {
+ }
+
+ static ErrorOr<CoffGroupSym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ StringRef Name;
+
+ CV_DESERIALIZE(Data, H, Name);
+
+ return CoffGroupSym(Kind, RecordOffset, H, Name);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+ StringRef Name;
+};
+
+class ScopeEndSym : public SymbolRecord {
+public:
+ ScopeEndSym(SymbolRecordKind Kind, uint32_t RecordOffset)
+ : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
+
+ static ErrorOr<ScopeEndSym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ return ScopeEndSym(Kind, RecordOffset);
+ }
+ uint32_t RecordOffset;
+};
+
+class CallerSym : public SymbolRecord {
+public:
+ struct Hdr {
+ ulittle32_t Count;
+ };
+
+ CallerSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *Header,
+ ArrayRef<TypeIndex> Indices)
+ : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*Header),
+ Indices(Indices) {}
+
+ static ErrorOr<CallerSym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *Header;
+ ArrayRef<TypeIndex> Indices;
+
+ CV_DESERIALIZE(Data, Header, CV_ARRAY_FIELD_N(Indices, Header->Count));
+
+ return CallerSym(Kind, RecordOffset, Header, Indices);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+ ArrayRef<TypeIndex> Indices;
+};
+
+struct BinaryAnnotationIterator {
+ struct AnnotationData {
+ BinaryAnnotationsOpCode OpCode;
+ StringRef Name;
+ uint32_t U1;
+ uint32_t U2;
+ int32_t S1;
+ };
+
+ BinaryAnnotationIterator(ArrayRef<uint8_t> Annotations) : Data(Annotations) {}
+ BinaryAnnotationIterator() {}
+ BinaryAnnotationIterator(const BinaryAnnotationIterator &Other)
+ : Data(Other.Data) {}
+
+ bool operator==(BinaryAnnotationIterator Other) const {
+ return Data == Other.Data;
+ }
+
+ bool operator!=(BinaryAnnotationIterator Other) const {
+ return !(*this == Other);
+ }
+
+ BinaryAnnotationIterator &operator=(const BinaryAnnotationIterator Other) {
+ Data = Other.Data;
+ return *this;
+ }
+
+ BinaryAnnotationIterator &operator++() {
+ if (!ParseCurrentAnnotation()) {
+ *this = BinaryAnnotationIterator();
+ return *this;
+ }
+ Data = Next;
+ Next = ArrayRef<uint8_t>();
+ Current.reset();
+ return *this;
+ }
+
+ BinaryAnnotationIterator operator++(int) {
+ BinaryAnnotationIterator Orig(*this);
+ ++(*this);
+ return Orig;
+ }
+
+ const AnnotationData &operator*() {
+ ParseCurrentAnnotation();
+ return Current.getValue();
+ }
+
+private:
+ static uint32_t GetCompressedAnnotation(ArrayRef<uint8_t> &Annotations) {
+ if (Annotations.empty())
+ return -1;
+
+ uint8_t FirstByte = Annotations.front();
+ Annotations = Annotations.drop_front();
+
+ if ((FirstByte & 0x80) == 0x00)
+ return FirstByte;
+
+ if (Annotations.empty())
+ return -1;
+
+ uint8_t SecondByte = Annotations.front();
+ Annotations = Annotations.drop_front();
+
+ if ((FirstByte & 0xC0) == 0x80)
+ return ((FirstByte & 0x3F) << 8) | SecondByte;
+
+ if (Annotations.empty())
+ return -1;
+
+ uint8_t ThirdByte = Annotations.front();
+ Annotations = Annotations.drop_front();
+
+ if (Annotations.empty())
+ return -1;
+
+ uint8_t FourthByte = Annotations.front();
+ Annotations = Annotations.drop_front();
+
+ if ((FirstByte & 0xE0) == 0xC0)
+ return ((FirstByte & 0x1F) << 24) | (SecondByte << 16) |
+ (ThirdByte << 8) | FourthByte;
+
+ return -1;
+ };
+
+ static int32_t DecodeSignedOperand(uint32_t Operand) {
+ if (Operand & 1)
+ return -(Operand >> 1);
+ return Operand >> 1;
+ };
+
+ static int32_t DecodeSignedOperand(ArrayRef<uint8_t> &Annotations) {
+ return DecodeSignedOperand(GetCompressedAnnotation(Annotations));
+ };
+
+ bool ParseCurrentAnnotation() {
+ if (Current.hasValue())
+ return true;
+
+ Next = Data;
+ uint32_t Op = GetCompressedAnnotation(Next);
+ AnnotationData Result;
+ Result.OpCode = static_cast<BinaryAnnotationsOpCode>(Op);
+ switch (Result.OpCode) {
+ case BinaryAnnotationsOpCode::Invalid:
+ Result.Name = "Invalid";
+ Next = ArrayRef<uint8_t>();
+ break;
+ case BinaryAnnotationsOpCode::CodeOffset:
+ Result.Name = "CodeOffset";
+ Result.U1 = GetCompressedAnnotation(Next);
+ break;
+ case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
+ Result.Name = "ChangeCodeOffsetBase";
+ Result.U1 = GetCompressedAnnotation(Next);
+ break;
+ case BinaryAnnotationsOpCode::ChangeCodeOffset:
+ Result.Name = "ChangeCodeOffset";
+ Result.U1 = GetCompressedAnnotation(Next);
+ break;
+ case BinaryAnnotationsOpCode::ChangeCodeLength:
+ Result.Name = "ChangeCodeLength";
+ Result.U1 = GetCompressedAnnotation(Next);
+ break;
+ case BinaryAnnotationsOpCode::ChangeFile:
+ Result.Name = "ChangeFile";
+ Result.U1 = GetCompressedAnnotation(Next);
+ break;
+ case BinaryAnnotationsOpCode::ChangeLineEndDelta:
+ Result.Name = "ChangeLineEndDelta";
+ Result.U1 = GetCompressedAnnotation(Next);
+ break;
+ case BinaryAnnotationsOpCode::ChangeRangeKind:
+ Result.Name = "ChangeRangeKind";
+ Result.U1 = GetCompressedAnnotation(Next);
+ break;
+ case BinaryAnnotationsOpCode::ChangeColumnStart:
+ Result.Name = "ChangeColumnStart";
+ Result.U1 = GetCompressedAnnotation(Next);
+ break;
+ case BinaryAnnotationsOpCode::ChangeColumnEnd:
+ Result.Name = "ChangeColumnEnd";
+ Result.U1 = GetCompressedAnnotation(Next);
+ break;
+ case BinaryAnnotationsOpCode::ChangeLineOffset:
+ Result.Name = "ChangeLineOffset";
+ Result.S1 = DecodeSignedOperand(Next);
+ break;
+ case BinaryAnnotationsOpCode::ChangeColumnEndDelta:
+ Result.Name = "ChangeColumnEndDelta";
+ Result.S1 = DecodeSignedOperand(Next);
+ break;
+ case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: {
+ Result.Name = "ChangeCodeOffsetAndLineOffset";
+ uint32_t Annotation = GetCompressedAnnotation(Next);
+ Result.S1 = DecodeSignedOperand(Annotation >> 4);
+ Result.U1 = Annotation & 0xf;
+ break;
+ }
+ case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: {
+ Result.Name = "ChangeCodeLengthAndCodeOffset";
+ Result.U1 = GetCompressedAnnotation(Next);
+ Result.U2 = GetCompressedAnnotation(Next);
+ break;
+ }
+ }
+ Current = Result;
+ return true;
+ }
+
+ Optional<AnnotationData> Current;
+ ArrayRef<uint8_t> Data;
+ ArrayRef<uint8_t> Next;
+};
+
+// S_INLINESITE
+class InlineSiteSym : public SymbolRecord {
+public:
+ struct Hdr {
+ ulittle32_t PtrParent;
+ ulittle32_t PtrEnd;
+ TypeIndex Inlinee;
+ // BinaryAnnotations
+ };
+
+ InlineSiteSym(uint32_t RecordOffset, const Hdr *H,
+ ArrayRef<uint8_t> Annotations)
+ : SymbolRecord(SymbolRecordKind::InlineSiteSym),
+ RecordOffset(RecordOffset), Header(*H), Annotations(Annotations) {}
+
+ static ErrorOr<InlineSiteSym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ ArrayRef<uint8_t> Annotations;
+ CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Annotations));
+
+ return InlineSiteSym(RecordOffset, H, Annotations);
+ }
+
+ llvm::iterator_range<BinaryAnnotationIterator> annotations() const {
+ return llvm::make_range(BinaryAnnotationIterator(Annotations),
+ BinaryAnnotationIterator());
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+
+private:
+ ArrayRef<uint8_t> Annotations;
+};
+
+// S_PUB32
+class PublicSym32 : public SymbolRecord {
+public:
+ struct Hdr {
+ ulittle32_t Index; // Type index, or Metadata token if a managed symbol
+ ulittle32_t Off;
+ ulittle16_t Seg;
+ // Name: The null-terminated name follows.
+ };
+
+ PublicSym32(uint32_t RecordOffset, const Hdr *H, StringRef Name)
+ : SymbolRecord(SymbolRecordKind::PublicSym32), RecordOffset(RecordOffset),
+ Header(*H), Name(Name) {}
+
+ static ErrorOr<PublicSym32> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ StringRef Name;
+ CV_DESERIALIZE(Data, H, Name);
+
+ return PublicSym32(RecordOffset, H, Name);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+ StringRef Name;
+};
+
+// S_REGISTER
+class RegisterSym : public SymbolRecord {
+public:
+ struct Hdr {
+ ulittle32_t Index; // Type index or Metadata token
+ ulittle16_t Register; // RegisterId enumeration
+ // Name: The null-terminated name follows.
+ };
+
+ RegisterSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
+ : SymbolRecord(SymbolRecordKind::RegisterSym), RecordOffset(RecordOffset),
+ Header(*H), Name(Name) {}
+
+ static ErrorOr<RegisterSym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ StringRef Name;
+ CV_DESERIALIZE(Data, H, Name);
+
+ return RegisterSym(RecordOffset, H, Name);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+ StringRef Name;
+};
+
+// S_PROCREF, S_LPROCREF
+class ProcRefSym : public SymbolRecord {
+public:
+ struct Hdr {
+ ulittle32_t SumName; // SUC of the name (?)
+ ulittle32_t SymOffset; // Offset of actual symbol in $$Symbols
+ ulittle16_t Mod; // Module containing the actual symbol
+ // Name: The null-terminated name follows.
+ };
+
+ ProcRefSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
+ : SymbolRecord(SymbolRecordKind::ProcRefSym), RecordOffset(RecordOffset),
+ Header(*H), Name(Name) {}
+
+ static ErrorOr<ProcRefSym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ StringRef Name;
+ CV_DESERIALIZE(Data, H, Name);
+
+ return ProcRefSym(RecordOffset, H, Name);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+ StringRef Name;
+};
+
+// S_LOCAL
+class LocalSym : public SymbolRecord {
+public:
+ struct Hdr {
+ TypeIndex Type;
+ ulittle16_t Flags; // LocalSymFlags enum
+ // Name: The null-terminated name follows.
+ };
+
+ LocalSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
+ : SymbolRecord(SymbolRecordKind::LocalSym), RecordOffset(RecordOffset),
+ Header(*H), Name(Name) {}
+
+ static ErrorOr<LocalSym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ StringRef Name;
+ CV_DESERIALIZE(Data, H, Name);
+
+ return LocalSym(RecordOffset, H, Name);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+ StringRef Name;
+};
+
+struct LocalVariableAddrRange {
+ ulittle32_t OffsetStart;
+ ulittle16_t ISectStart;
+ ulittle16_t Range;
+};
+
+struct LocalVariableAddrGap {
+ ulittle16_t GapStartOffset;
+ ulittle16_t Range;
+};
+
+enum : uint16_t { MaxDefRange = 0xf000 };
+
+// S_DEFRANGE
+class DefRangeSym : public SymbolRecord {
+public:
+ struct Hdr {
+ ulittle32_t Program;
+ LocalVariableAddrRange Range;
+ // LocalVariableAddrGap Gaps[];
+ };
+
+ DefRangeSym(uint32_t RecordOffset, const Hdr *H,
+ ArrayRef<LocalVariableAddrGap> Gaps)
+ : SymbolRecord(SymbolRecordKind::DefRangeSym), RecordOffset(RecordOffset),
+ Header(*H), Gaps(Gaps) {}
+
+ static ErrorOr<DefRangeSym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ ArrayRef<LocalVariableAddrGap> Gaps;
+ CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
+
+ return DefRangeSym(RecordOffset, H, Gaps);
+ }
+
+ uint32_t getRelocationOffset() const {
+ return RecordOffset + offsetof(Hdr, Range);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+ ArrayRef<LocalVariableAddrGap> Gaps;
+};
+
+// S_DEFRANGE_SUBFIELD
+class DefRangeSubfieldSym : public SymbolRecord {
+public:
+ struct Hdr {
+ ulittle32_t Program;
+ ulittle16_t OffsetInParent;
+ LocalVariableAddrRange Range;
+ // LocalVariableAddrGap Gaps[];
+ };
+ DefRangeSubfieldSym(uint32_t RecordOffset, const Hdr *H,
+ ArrayRef<LocalVariableAddrGap> Gaps)
+ : SymbolRecord(SymbolRecordKind::DefRangeSubfieldSym),
+ RecordOffset(RecordOffset), Header(*H), Gaps(Gaps) {}
+
+ static ErrorOr<DefRangeSubfieldSym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ ArrayRef<LocalVariableAddrGap> Gaps;
+ CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
+
+ return DefRangeSubfieldSym(RecordOffset, H, Gaps);
+ }
+
+ uint32_t getRelocationOffset() const {
+ return RecordOffset + offsetof(Hdr, Range);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+ ArrayRef<LocalVariableAddrGap> Gaps;
+};
+
+// S_DEFRANGE_REGISTER
+class DefRangeRegisterSym : public SymbolRecord {
+public:
+ struct Hdr {
+ ulittle16_t Register;
+ ulittle16_t MayHaveNoName;
+ LocalVariableAddrRange Range;
+ // LocalVariableAddrGap Gaps[];
+ };
+
+ DefRangeRegisterSym(uint32_t RecordOffset, const Hdr *H,
+ ArrayRef<LocalVariableAddrGap> Gaps)
+ : SymbolRecord(SymbolRecordKind::DefRangeRegisterSym),
+ RecordOffset(RecordOffset), Header(*H), Gaps(Gaps) {}
+
+ DefRangeRegisterSym(uint16_t Register, uint16_t MayHaveNoName,
+ uint32_t OffsetStart, uint16_t ISectStart, uint16_t Range,
+ ArrayRef<LocalVariableAddrGap> Gaps)
+ : SymbolRecord(SymbolRecordKind::DefRangeRegisterSym), RecordOffset(0),
+ Gaps(Gaps) {
+ Header.Register = Register;
+ Header.MayHaveNoName = MayHaveNoName;
+ Header.Range.OffsetStart = OffsetStart;
+ Header.Range.ISectStart = ISectStart;
+ Header.Range.Range = Range;
+ }
+
+ static ErrorOr<DefRangeRegisterSym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ ArrayRef<LocalVariableAddrGap> Gaps;
+ CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
+
+ return DefRangeRegisterSym(RecordOffset, H, Gaps);
+ }
+
+ uint32_t getRelocationOffset() const {
+ return RecordOffset + offsetof(Hdr, Range);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+ ArrayRef<LocalVariableAddrGap> Gaps;
+};
+
+// S_DEFRANGE_SUBFIELD_REGISTER
+class DefRangeSubfieldRegisterSym : public SymbolRecord {
+public:
+ struct Hdr {
+ ulittle16_t Register; // Register to which the variable is relative
+ ulittle16_t MayHaveNoName;
+ ulittle32_t OffsetInParent;
+ LocalVariableAddrRange Range;
+ // LocalVariableAddrGap Gaps[];
+ };
+
+ DefRangeSubfieldRegisterSym(uint32_t RecordOffset, const Hdr *H,
+ ArrayRef<LocalVariableAddrGap> Gaps)
+ : SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym),
+ RecordOffset(RecordOffset), Header(*H), Gaps(Gaps) {}
+
+ DefRangeSubfieldRegisterSym(uint16_t Register, uint16_t MayHaveNoName,
+ uint32_t OffsetInParent,
+ ArrayRef<LocalVariableAddrGap> Gaps)
+ : SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym),
+ RecordOffset(0), Gaps(Gaps) {
+ Header.Register = Register;
+ Header.MayHaveNoName = MayHaveNoName;
+ Header.OffsetInParent = OffsetInParent;
+ }
+
+ static ErrorOr<DefRangeSubfieldRegisterSym>
+ deserialize(SymbolRecordKind Kind, uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ ArrayRef<LocalVariableAddrGap> Gaps;
+ CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
+
+ return DefRangeSubfieldRegisterSym(RecordOffset, H, Gaps);
+ }
+
+ uint32_t getRelocationOffset() const {
+ return RecordOffset + offsetof(Hdr, Range);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+ ArrayRef<LocalVariableAddrGap> Gaps;
+};
+
+// S_DEFRANGE_FRAMEPOINTER_REL
+class DefRangeFramePointerRelSym : public SymbolRecord {
+public:
+ struct Hdr {
+ little32_t Offset; // Offset from the frame pointer register
+ LocalVariableAddrRange Range;
+ // LocalVariableAddrGap Gaps[];
+ };
+
+ DefRangeFramePointerRelSym(uint32_t RecordOffset, const Hdr *H,
+ ArrayRef<LocalVariableAddrGap> Gaps)
+ : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelSym),
+ RecordOffset(RecordOffset), Header(*H), Gaps(Gaps) {}
+
+ static ErrorOr<DefRangeFramePointerRelSym>
+ deserialize(SymbolRecordKind Kind, uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ ArrayRef<LocalVariableAddrGap> Gaps;
+ CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
+
+ return DefRangeFramePointerRelSym(RecordOffset, H, Gaps);
+ }
+
+ uint32_t getRelocationOffset() const {
+ return RecordOffset + offsetof(Hdr, Range);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+ ArrayRef<LocalVariableAddrGap> Gaps;
+};
+
+// S_DEFRANGE_REGISTER_REL
+class DefRangeRegisterRelSym : public SymbolRecord {
+public:
+ struct Hdr {
+ ulittle16_t BaseRegister;
+ ulittle16_t Flags;
+ little32_t BasePointerOffset;
+ LocalVariableAddrRange Range;
+ // LocalVariableAddrGap Gaps[];
+ };
+
+ DefRangeRegisterRelSym(uint32_t RecordOffset, const Hdr *H,
+ ArrayRef<LocalVariableAddrGap> Gaps)
+ : SymbolRecord(SymbolRecordKind::DefRangeRegisterRelSym),
+ RecordOffset(RecordOffset), Header(*H), Gaps(Gaps) {}
+
+ DefRangeRegisterRelSym(uint16_t BaseRegister, uint16_t Flags,
+ int32_t BasePointerOffset, uint32_t OffsetStart,
+ uint16_t ISectStart, uint16_t Range,
+ ArrayRef<LocalVariableAddrGap> Gaps)
+ : SymbolRecord(SymbolRecordKind::DefRangeRegisterRelSym), RecordOffset(0),
+ Gaps(Gaps) {
+ Header.BaseRegister = BaseRegister;
+ Header.Flags = Flags;
+ Header.BasePointerOffset = BasePointerOffset;
+ Header.Range.OffsetStart = OffsetStart;
+ Header.Range.ISectStart = ISectStart;
+ Header.Range.Range = Range;
+ }
+
+ static ErrorOr<DefRangeRegisterRelSym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ ArrayRef<LocalVariableAddrGap> Gaps;
+ CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
+
+ return DefRangeRegisterRelSym(RecordOffset, H, Gaps);
+ }
+
+ bool hasSpilledUDTMember() const { return Header.Flags & 1; }
+ uint16_t offsetInParent() const { return Header.Flags >> 4; }
+
+ uint32_t getRelocationOffset() const {
+ return RecordOffset + offsetof(Hdr, Range);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+ ArrayRef<LocalVariableAddrGap> Gaps;
+};
+
+// S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
+class DefRangeFramePointerRelFullScopeSym : public SymbolRecord {
+public:
+ struct Hdr {
+ little32_t Offset; // Offset from the frame pointer register
+ };
+
+ DefRangeFramePointerRelFullScopeSym(uint32_t RecordOffset, const Hdr *H)
+ : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelFullScopeSym),
+ RecordOffset(RecordOffset), Header(*H) {}
+
+ static ErrorOr<DefRangeFramePointerRelFullScopeSym>
+ deserialize(SymbolRecordKind Kind, uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ CV_DESERIALIZE(Data, H);
+
+ return DefRangeFramePointerRelFullScopeSym(RecordOffset, H);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+};
+
+// S_BLOCK32
+class BlockSym : public SymbolRecord {
+public:
+ struct Hdr {
+ ulittle32_t PtrParent;
+ ulittle32_t PtrEnd;
+ ulittle32_t CodeSize;
+ ulittle32_t CodeOffset;
+ ulittle16_t Segment;
+ // Name: The null-terminated name follows.
+ };
+
+ BlockSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
+ : SymbolRecord(SymbolRecordKind::BlockSym), RecordOffset(RecordOffset),
+ Header(*H), Name(Name) {}
+
+ static ErrorOr<BlockSym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ StringRef Name;
+ CV_DESERIALIZE(Data, H, Name);
+
+ return BlockSym(RecordOffset, H, Name);
+ }
+
+ uint32_t getRelocationOffset() const {
+ return RecordOffset + offsetof(Hdr, CodeOffset);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+ StringRef Name;
+};
+
+// S_LABEL32
+class LabelSym : public SymbolRecord {
+public:
+ struct Hdr {
+ ulittle32_t CodeOffset;
+ ulittle16_t Segment;
+ uint8_t Flags; // CV_PROCFLAGS
+ // Name: The null-terminated name follows.
+ };
+
+ LabelSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
+ : SymbolRecord(SymbolRecordKind::LabelSym), RecordOffset(RecordOffset),
+ Header(*H), Name(Name) {}
+
+ static ErrorOr<LabelSym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ StringRef Name;
+ CV_DESERIALIZE(Data, H, Name);
+
+ return LabelSym(RecordOffset, H, Name);
+ }
+
+ uint32_t getRelocationOffset() const {
+ return RecordOffset + offsetof(Hdr, CodeOffset);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+ StringRef Name;
+};
+
+// S_OBJNAME
+class ObjNameSym : public SymbolRecord {
+public:
+ struct Hdr {
+ ulittle32_t Signature;
+ // Name: The null-terminated name follows.
+ };
+
+ ObjNameSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
+ : SymbolRecord(SymbolRecordKind::ObjNameSym), RecordOffset(RecordOffset),
+ Header(*H), Name(Name) {}
+
+ static ErrorOr<ObjNameSym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ StringRef Name;
+ CV_DESERIALIZE(Data, H, Name);
+
+ return ObjNameSym(RecordOffset, H, Name);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+ StringRef Name;
+};
+
+// S_ENVBLOCK
+class EnvBlockSym : public SymbolRecord {
+public:
+ struct Hdr {
+ uint8_t Reserved;
+ // Sequence of zero terminated strings.
+ };
+
+ EnvBlockSym(uint32_t RecordOffset, const Hdr *H,
+ const std::vector<StringRef> &Fields)
+ : SymbolRecord(SymbolRecordKind::EnvBlockSym), RecordOffset(RecordOffset),
+ Header(*H), Fields(Fields) {}
+
+ static ErrorOr<EnvBlockSym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ std::vector<StringRef> Fields;
+ CV_DESERIALIZE(Data, H, CV_STRING_ARRAY_NULL_TERM(Fields));
+
+ return EnvBlockSym(RecordOffset, H, Fields);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+ std::vector<StringRef> Fields;
+};
+
+// S_EXPORT
+class ExportSym : public SymbolRecord {
+public:
+ struct Hdr {
+ ulittle16_t Ordinal;
+ ulittle16_t Flags; // ExportFlags
+ // Name: The null-terminated name follows.
+ };
+
+ ExportSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
+ : SymbolRecord(SymbolRecordKind::ExportSym), RecordOffset(RecordOffset),
+ Header(*H), Name(Name) {}
+
+ static ErrorOr<ExportSym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ StringRef Name;
+ CV_DESERIALIZE(Data, H, Name);
+
+ return ExportSym(RecordOffset, H, Name);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+ StringRef Name;
+};
+
+// S_FILESTATIC
+class FileStaticSym : public SymbolRecord {
+public:
+ struct Hdr {
+ ulittle32_t Index; // Type Index
+ ulittle32_t ModFilenameOffset; // Index of mod filename in string table
+ ulittle16_t Flags; // LocalSymFlags enum
+ // Name: The null-terminated name follows.
+ };
+
+ FileStaticSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
+ : SymbolRecord(SymbolRecordKind::FileStaticSym),
+ RecordOffset(RecordOffset), Header(*H), Name(Name) {}
+
+ static ErrorOr<FileStaticSym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ StringRef Name;
+ CV_DESERIALIZE(Data, H, Name);
+
+ return FileStaticSym(RecordOffset, H, Name);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+ StringRef Name;
+};
+
+// S_COMPILE2
+class Compile2Sym : public SymbolRecord {
+public:
+ struct Hdr {
+ ulittle32_t flags; // CompileSym2Flags enum
+ uint8_t getLanguage() const { return flags & 0xFF; }
+ unsigned short Machine; // CPUType enum
+ unsigned short VersionFrontendMajor;
+ unsigned short VersionFrontendMinor;
+ unsigned short VersionFrontendBuild;
+ unsigned short VersionBackendMajor;
+ unsigned short VersionBackendMinor;
+ unsigned short VersionBackendBuild;
+ // Version: The null-terminated version string follows.
+ // Optional block of zero terminated strings terminated with a double zero.
+ };
+
+ Compile2Sym(uint32_t RecordOffset, const Hdr *H, StringRef Version)
+ : SymbolRecord(SymbolRecordKind::Compile2Sym), RecordOffset(RecordOffset),
+ Header(*H), Version(Version) {}
+
+ static ErrorOr<Compile2Sym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ StringRef Version;
+ CV_DESERIALIZE(Data, H, Version);
+
+ return Compile2Sym(RecordOffset, H, Version);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+ StringRef Version;
+};
+
+// S_COMPILE3
+class Compile3Sym : public SymbolRecord {
+public:
+ struct Hdr {
+ ulittle32_t flags; // CompileSym3Flags enum
+ uint8_t getLanguage() const { return flags & 0xff; }
+ ulittle16_t Machine; // CPUType enum
+ ulittle16_t VersionFrontendMajor;
+ ulittle16_t VersionFrontendMinor;
+ ulittle16_t VersionFrontendBuild;
+ ulittle16_t VersionFrontendQFE;
+ ulittle16_t VersionBackendMajor;
+ ulittle16_t VersionBackendMinor;
+ ulittle16_t VersionBackendBuild;
+ ulittle16_t VersionBackendQFE;
+ // VersionString: The null-terminated version string follows.
+ };
+
+ Compile3Sym(uint32_t RecordOffset, const Hdr *H, StringRef Version)
+ : SymbolRecord(SymbolRecordKind::Compile3Sym), RecordOffset(RecordOffset),
+ Header(*H), Version(Version) {}
+
+ static ErrorOr<Compile3Sym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ StringRef Version;
+ CV_DESERIALIZE(Data, H, Version);
+
+ return Compile3Sym(RecordOffset, H, Version);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+ StringRef Version;
+};
+
+// S_FRAMEPROC
+class FrameProcSym : public SymbolRecord {
+public:
+ struct Hdr {
+ ulittle32_t TotalFrameBytes;
+ ulittle32_t PaddingFrameBytes;
+ ulittle32_t OffsetToPadding;
+ ulittle32_t BytesOfCalleeSavedRegisters;
+ ulittle32_t OffsetOfExceptionHandler;
+ ulittle16_t SectionIdOfExceptionHandler;
+ ulittle32_t Flags;
+ };
+
+ FrameProcSym(uint32_t RecordOffset, const Hdr *H)
+ : SymbolRecord(SymbolRecordKind::FrameProcSym),
+ RecordOffset(RecordOffset), Header(*H) {}
+
+ static ErrorOr<FrameProcSym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ CV_DESERIALIZE(Data, H);
+
+ return FrameProcSym(RecordOffset, H);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+};
+
+// S_CALLSITEINFO
+class CallSiteInfoSym : public SymbolRecord {
+public:
+ struct Hdr {
+ ulittle32_t CodeOffset;
+ ulittle16_t Segment;
+ ulittle16_t Reserved;
+ TypeIndex Type;
+ };
+
+ CallSiteInfoSym(uint32_t RecordOffset, const Hdr *H)
+ : SymbolRecord(SymbolRecordKind::CallSiteInfoSym),
+ RecordOffset(RecordOffset), Header(*H) {}
+
+ static ErrorOr<CallSiteInfoSym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ CV_DESERIALIZE(Data, H);
+
+ return CallSiteInfoSym(RecordOffset, H);
+ }
+
+ uint32_t getRelocationOffset() const {
+ return RecordOffset + offsetof(Hdr, CodeOffset);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+};
+
+// S_HEAPALLOCSITE
+class HeapAllocationSiteSym : public SymbolRecord {
+public:
+ struct Hdr {
+ ulittle32_t CodeOffset;
+ ulittle16_t Segment;
+ ulittle16_t CallInstructionSize;
+ TypeIndex Type;
+ };
+
+ HeapAllocationSiteSym(uint32_t RecordOffset, const Hdr *H)
+ : SymbolRecord(SymbolRecordKind::HeapAllocationSiteSym),
+ RecordOffset(RecordOffset), Header(*H) {}
+
+ static ErrorOr<HeapAllocationSiteSym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ CV_DESERIALIZE(Data, H);
+
+ return HeapAllocationSiteSym(RecordOffset, H);
+ }
+
+ uint32_t getRelocationOffset() const {
+ return RecordOffset + offsetof(Hdr, CodeOffset);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+};
+
+// S_FRAMECOOKIE
+class FrameCookieSym : public SymbolRecord {
+public:
+ struct Hdr {
+ ulittle32_t CodeOffset;
+ ulittle16_t Register;
+ uint8_t CookieKind;
+ uint8_t Flags;
+ };
+
+ FrameCookieSym(uint32_t RecordOffset, const Hdr *H)
+ : SymbolRecord(SymbolRecordKind::FrameCookieSym),
+ RecordOffset(RecordOffset), Header(*H) {}
+
+ static ErrorOr<FrameCookieSym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ CV_DESERIALIZE(Data, H);
+
+ return FrameCookieSym(RecordOffset, H);
+ }
+
+ uint32_t getRelocationOffset() const {
+ return RecordOffset + offsetof(Hdr, CodeOffset);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+};
+
+// S_UDT, S_COBOLUDT
+class UDTSym : public SymbolRecord {
+public:
+ struct Hdr {
+ TypeIndex Type; // Type of the UDT
+ // Name: The null-terminated name follows.
+ };
+
+ UDTSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
+ : SymbolRecord(SymbolRecordKind::UDTSym), RecordOffset(RecordOffset),
+ Header(*H), Name(Name) {}
+
+ static ErrorOr<UDTSym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ StringRef Name;
+ CV_DESERIALIZE(Data, H, Name);
+
+ return UDTSym(RecordOffset, H, Name);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+ StringRef Name;
+};
+
+// S_BUILDINFO
+class BuildInfoSym : public SymbolRecord {
+public:
+ struct Hdr {
+ ulittle32_t BuildId;
+ };
+
+ BuildInfoSym(uint32_t RecordOffset, const Hdr *H)
+ : SymbolRecord(SymbolRecordKind::BuildInfoSym),
+ RecordOffset(RecordOffset), Header(*H) {}
+
+ static ErrorOr<BuildInfoSym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ CV_DESERIALIZE(Data, H);
+
+ return BuildInfoSym(RecordOffset, H);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+};
+
+// S_BPREL32
+class BPRelativeSym : public SymbolRecord {
+public:
+ struct Hdr {
+ little32_t Offset; // Offset from the base pointer register
+ TypeIndex Type; // Type of the variable
+ // Name: The null-terminated name follows.
+ };
+
+ BPRelativeSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
+ : SymbolRecord(SymbolRecordKind::BPRelativeSym),
+ RecordOffset(RecordOffset), Header(*H), Name(Name) {}
+
+ static ErrorOr<BPRelativeSym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ StringRef Name;
+ CV_DESERIALIZE(Data, H, Name);
+
+ return BPRelativeSym(RecordOffset, H, Name);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+ StringRef Name;
+};
+
+// S_REGREL32
+class RegRelativeSym : public SymbolRecord {
+public:
+ struct Hdr {
+ ulittle32_t Offset; // Offset from the register
+ TypeIndex Type; // Type of the variable
+ ulittle16_t Register; // Register to which the variable is relative
+ // Name: The null-terminated name follows.
+ };
+
+ RegRelativeSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
+ : SymbolRecord(SymbolRecordKind::RegRelativeSym),
+ RecordOffset(RecordOffset), Header(*H), Name(Name) {}
+
+ static ErrorOr<RegRelativeSym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ StringRef Name;
+ CV_DESERIALIZE(Data, H, Name);
+
+ return RegRelativeSym(RecordOffset, H, Name);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+ StringRef Name;
+};
+
+// S_CONSTANT, S_MANCONSTANT
+class ConstantSym : public SymbolRecord {
+public:
+ struct Hdr {
+ TypeIndex Type;
+ // Value: The value of the constant.
+ // Name: The null-terminated name follows.
+ };
+
+ ConstantSym(uint32_t RecordOffset, const Hdr *H, const APSInt &Value,
+ StringRef Name)
+ : SymbolRecord(SymbolRecordKind::ConstantSym), RecordOffset(RecordOffset),
+ Header(*H), Value(Value), Name(Name) {}
+
+ static ErrorOr<ConstantSym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ APSInt Value;
+ StringRef Name;
+ CV_DESERIALIZE(Data, H, Value, Name);
+
+ return ConstantSym(RecordOffset, H, Value, Name);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+ APSInt Value;
+ StringRef Name;
+};
+
+// S_LDATA32, S_GDATA32, S_LMANDATA, S_GMANDATA
+class DataSym : public SymbolRecord {
+public:
+ struct Hdr {
+ TypeIndex Type;
+ ulittle32_t DataOffset;
+ ulittle16_t Segment;
+ // Name: The null-terminated name follows.
+ };
+
+ DataSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
+ : SymbolRecord(SymbolRecordKind::DataSym), RecordOffset(RecordOffset),
+ Header(*H), Name(Name) {}
+
+ static ErrorOr<DataSym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ StringRef Name;
+ CV_DESERIALIZE(Data, H, Name);
+
+ return DataSym(RecordOffset, H, Name);
+ }
+
+ uint32_t getRelocationOffset() const {
+ return RecordOffset + offsetof(Hdr, DataOffset);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+ StringRef Name;
+};
+
+// S_LTHREAD32, S_GTHREAD32
+class ThreadLocalDataSym : public SymbolRecord {
+public:
+ struct Hdr {
+ TypeIndex Type;
+ ulittle32_t DataOffset;
+ ulittle16_t Segment;
+ // Name: The null-terminated name follows.
+ };
+
+ ThreadLocalDataSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
+ : SymbolRecord(SymbolRecordKind::ThreadLocalDataSym),
+ RecordOffset(RecordOffset), Header(*H), Name(Name) {}
+
+ static ErrorOr<ThreadLocalDataSym> deserialize(SymbolRecordKind Kind,
+ uint32_t RecordOffset,
+ ArrayRef<uint8_t> &Data) {
+ const Hdr *H = nullptr;
+ StringRef Name;
+ CV_DESERIALIZE(Data, H, Name);
+
+ return ThreadLocalDataSym(RecordOffset, H, Name);
+ }
+
+ uint32_t getRelocationOffset() const {
+ return RecordOffset + offsetof(Hdr, DataOffset);
+ }
+
+ uint32_t RecordOffset;
+ Hdr Header;
+ StringRef Name;
+};
+
+typedef CVRecord<SymbolKind> CVSymbol;
+typedef VarStreamArray<CVSymbol> CVSymbolArray;
+
+} // namespace codeview
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h b/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h
new file mode 100644
index 000000000000..a4965168c3db
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h
@@ -0,0 +1,33 @@
+//===-- SymbolVisitorDelegate.h ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_SYMBOLVISITORDELEGATE_H
+#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLVISITORDELEGATE_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+
+#include <stdint.h>
+
+namespace llvm {
+
+namespace codeview {
+
+class SymbolVisitorDelegate {
+public:
+ virtual ~SymbolVisitorDelegate() {}
+
+ virtual uint32_t getRecordOffset(ArrayRef<uint8_t> Record) = 0;
+ virtual StringRef getFileNameForFileOffset(uint32_t FileOffset) = 0;
+ virtual StringRef getStringTable() = 0;
+};
+} // end namespace codeview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLVISITORDELEGATE_H
diff --git a/include/llvm/DebugInfo/CodeView/TypeDumper.h b/include/llvm/DebugInfo/CodeView/TypeDumper.h
new file mode 100644
index 000000000000..ca79ab076e5e
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/TypeDumper.h
@@ -0,0 +1,105 @@
+//===-- TypeDumper.h - CodeView type info dumper ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPEDUMPER_H
+#define LLVM_DEBUGINFO_CODEVIEW_TYPEDUMPER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
+
+namespace llvm {
+class ScopedPrinter;
+
+namespace codeview {
+
+/// Dumper for CodeView type streams found in COFF object files and PDB files.
+class CVTypeDumper : public TypeVisitorCallbacks {
+public:
+ CVTypeDumper(ScopedPrinter *W, bool PrintRecordBytes)
+ : W(W), PrintRecordBytes(PrintRecordBytes) {}
+
+ StringRef getTypeName(TypeIndex TI);
+ void printTypeIndex(StringRef FieldName, TypeIndex TI);
+
+ /// Dumps one type record. Returns false if there was a type parsing error,
+ /// and true otherwise. This should be called in order, since the dumper
+ /// maintains state about previous records which are necessary for cross
+ /// type references.
+ Error dump(const CVRecord<TypeLeafKind> &Record);
+
+ /// Dumps the type records in Types. Returns false if there was a type stream
+ /// parse error, and true otherwise.
+ Error dump(const CVTypeArray &Types);
+
+ /// Dumps the type records in Data. Returns false if there was a type stream
+ /// parse error, and true otherwise. Use this method instead of the
+ /// CVTypeArray overload when type records are laid out contiguously in
+ /// memory.
+ Error dump(ArrayRef<uint8_t> Data);
+
+ /// Gets the type index for the next type record.
+ unsigned getNextTypeIndex() const {
+ return 0x1000 + CVUDTNames.size();
+ }
+
+ /// Records the name of a type, and reserves its type index.
+ void recordType(StringRef Name) { CVUDTNames.push_back(Name); }
+
+ /// Saves the name in a StringSet and creates a stable StringRef.
+ StringRef saveName(StringRef TypeName) {
+ return TypeNames.insert(TypeName).first->getKey();
+ }
+
+ void setPrinter(ScopedPrinter *P);
+ ScopedPrinter *getPrinter() { return W; }
+
+ /// Action to take on unknown types. By default, they are ignored.
+ Error visitUnknownType(const CVRecord<TypeLeafKind> &Record) override;
+ Error visitUnknownMember(const CVRecord<TypeLeafKind> &Record) override;
+
+ /// Paired begin/end actions for all types. Receives all record data,
+ /// including the fixed-length record prefix.
+ Error visitTypeBegin(const CVRecord<TypeLeafKind> &Record) override;
+ Error visitTypeEnd(const CVRecord<TypeLeafKind> &Record) override;
+
+#define TYPE_RECORD(EnumName, EnumVal, Name) \
+ Error visit##Name(Name##Record &Record) override;
+#define MEMBER_RECORD(EnumName, EnumVal, Name) \
+ TYPE_RECORD(EnumName, EnumVal, Name)
+#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#include "TypeRecords.def"
+
+private:
+ void printMemberAttributes(MemberAttributes Attrs);
+ void printMemberAttributes(MemberAccess Access, MethodKind Kind,
+ MethodOptions Options);
+
+ ScopedPrinter *W;
+
+ bool PrintRecordBytes = false;
+
+ /// Name of the current type. Only valid before visitTypeEnd.
+ StringRef Name;
+
+ /// All user defined type records in .debug$T live in here. Type indices
+ /// greater than 0x1000 are user defined. Subtract 0x1000 from the index to
+ /// index into this vector.
+ SmallVector<StringRef, 10> CVUDTNames;
+
+ StringSet<> TypeNames;
+};
+
+} // end namespace codeview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_CODEVIEW_TYPEDUMPER_H
diff --git a/include/llvm/DebugInfo/CodeView/TypeIndex.h b/include/llvm/DebugInfo/CodeView/TypeIndex.h
index d3a541be4c62..c2ebf3848892 100644
--- a/include/llvm/DebugInfo/CodeView/TypeIndex.h
+++ b/include/llvm/DebugInfo/CodeView/TypeIndex.h
@@ -10,6 +10,7 @@
#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPEINDEX_H
#define LLVM_DEBUGINFO_CODEVIEW_TYPEINDEX_H
+#include "llvm/Support/Endian.h"
#include <cassert>
#include <cinttypes>
@@ -26,6 +27,8 @@ enum class SimpleTypeKind : uint32_t {
UnsignedCharacter = 0x0020, // 8 bit unsigned
NarrowCharacter = 0x0070, // really a char
WideCharacter = 0x0071, // wide char
+ Character16 = 0x007a, // char16_t
+ Character32 = 0x007b, // char32_t
SByte = 0x0068, // 8 bit signed int
Byte = 0x0069, // 8 bit unsigned int
@@ -41,6 +44,8 @@ enum class SimpleTypeKind : uint32_t {
UInt64Quad = 0x0023, // 64 bit unsigned
Int64 = 0x0076, // 64 bit signed int
UInt64 = 0x0077, // 64 bit unsigned int
+ Int128Oct = 0x0014, // 128 bit signed int
+ UInt128Oct = 0x0024, // 128 bit unsigned int
Int128 = 0x0078, // 128 bit signed int
UInt128 = 0x0079, // 128 bit unsigned int
@@ -52,15 +57,19 @@ enum class SimpleTypeKind : uint32_t {
Float80 = 0x0042, // 80 bit real
Float128 = 0x0043, // 128 bit real
- Complex32 = 0x0050, // 32 bit complex
- Complex64 = 0x0051, // 64 bit complex
- Complex80 = 0x0052, // 80 bit complex
- Complex128 = 0x0053, // 128 bit complex
-
- Boolean8 = 0x0030, // 8 bit boolean
- Boolean16 = 0x0031, // 16 bit boolean
- Boolean32 = 0x0032, // 32 bit boolean
- Boolean64 = 0x0033 // 64 bit boolean
+ Complex16 = 0x0056, // 16 bit complex
+ Complex32 = 0x0050, // 32 bit complex
+ Complex32PartialPrecision = 0x0055, // 32 bit PP complex
+ Complex48 = 0x0054, // 48 bit complex
+ Complex64 = 0x0051, // 64 bit complex
+ Complex80 = 0x0052, // 80 bit complex
+ Complex128 = 0x0053, // 128 bit complex
+
+ Boolean8 = 0x0030, // 8 bit boolean
+ Boolean16 = 0x0031, // 16 bit boolean
+ Boolean32 = 0x0032, // 32 bit boolean
+ Boolean64 = 0x0033, // 64 bit boolean
+ Boolean128 = 0x0034, // 128 bit boolean
};
enum class SimpleTypeMode : uint32_t {
@@ -74,6 +83,9 @@ enum class SimpleTypeMode : uint32_t {
NearPointer128 = 0x00000700 // 128 bit near pointer
};
+/// A 32-bit type reference. Types are indexed by their order of appearance in
+/// .debug$T plus 0x1000. Type indices less than 0x1000 are "simple" types,
+/// composed of a SimpleTypeMode byte followed by a SimpleTypeKind byte.
class TypeIndex {
public:
static const uint32_t FirstNonSimpleIndex = 0x1000;
@@ -91,6 +103,8 @@ public:
uint32_t getIndex() const { return Index; }
bool isSimple() const { return Index < FirstNonSimpleIndex; }
+ bool isNoneType() const { return *this == None(); }
+
SimpleTypeKind getSimpleKind() const {
assert(isSimple());
return static_cast<SimpleTypeKind>(Index & SimpleKindMask);
@@ -101,6 +115,7 @@ public:
return static_cast<SimpleTypeMode>(Index & SimpleModeMask);
}
+ static TypeIndex None() { return TypeIndex(SimpleTypeKind::None); }
static TypeIndex Void() { return TypeIndex(SimpleTypeKind::Void); }
static TypeIndex VoidPointer32() {
return TypeIndex(SimpleTypeKind::Void, SimpleTypeMode::NearPointer32);
@@ -143,33 +158,34 @@ public:
static TypeIndex Float32() { return TypeIndex(SimpleTypeKind::Float32); }
static TypeIndex Float64() { return TypeIndex(SimpleTypeKind::Float64); }
-private:
- uint32_t Index;
-};
+ friend inline bool operator==(const TypeIndex &A, const TypeIndex &B) {
+ return A.getIndex() == B.getIndex();
+ }
-inline bool operator==(const TypeIndex &A, const TypeIndex &B) {
- return A.getIndex() == B.getIndex();
-}
+ friend inline bool operator!=(const TypeIndex &A, const TypeIndex &B) {
+ return A.getIndex() != B.getIndex();
+ }
-inline bool operator!=(const TypeIndex &A, const TypeIndex &B) {
- return A.getIndex() != B.getIndex();
-}
+ friend inline bool operator<(const TypeIndex &A, const TypeIndex &B) {
+ return A.getIndex() < B.getIndex();
+ }
-inline bool operator<(const TypeIndex &A, const TypeIndex &B) {
- return A.getIndex() < B.getIndex();
-}
+ friend inline bool operator<=(const TypeIndex &A, const TypeIndex &B) {
+ return A.getIndex() <= B.getIndex();
+ }
-inline bool operator<=(const TypeIndex &A, const TypeIndex &B) {
- return A.getIndex() <= B.getIndex();
-}
+ friend inline bool operator>(const TypeIndex &A, const TypeIndex &B) {
+ return A.getIndex() > B.getIndex();
+ }
-inline bool operator>(const TypeIndex &A, const TypeIndex &B) {
- return A.getIndex() > B.getIndex();
-}
+ friend inline bool operator>=(const TypeIndex &A, const TypeIndex &B) {
+ return A.getIndex() >= B.getIndex();
+ }
+
+private:
+ support::ulittle32_t Index;
+};
-inline bool operator>=(const TypeIndex &A, const TypeIndex &B) {
- return A.getIndex() >= B.getIndex();
-}
}
}
diff --git a/include/llvm/DebugInfo/CodeView/TypeRecord.h b/include/llvm/DebugInfo/CodeView/TypeRecord.h
index 21755f5d9b09..42751fbd4af1 100644
--- a/include/llvm/DebugInfo/CodeView/TypeRecord.h
+++ b/include/llvm/DebugInfo/CodeView/TypeRecord.h
@@ -10,15 +10,96 @@
#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPERECORD_H
#define LLVM_DEBUGINFO_CODEVIEW_TYPERECORD_H
+#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/CodeView/CVRecord.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/Support/ErrorOr.h"
#include <cinttypes>
+#include <utility>
namespace llvm {
namespace codeview {
+using llvm::support::little32_t;
+using llvm::support::ulittle16_t;
+using llvm::support::ulittle32_t;
+
+/// Equvalent to CV_fldattr_t in cvinfo.h.
+struct MemberAttributes {
+ ulittle16_t Attrs;
+ enum {
+ MethodKindShift = 2,
+ };
+
+ /// Get the access specifier. Valid for any kind of member.
+ MemberAccess getAccess() const {
+ return MemberAccess(unsigned(Attrs) & unsigned(MethodOptions::AccessMask));
+ }
+
+ /// Indicates if a method is defined with friend, virtual, static, etc.
+ MethodKind getMethodKind() const {
+ return MethodKind(
+ (unsigned(Attrs) & unsigned(MethodOptions::MethodKindMask)) >>
+ MethodKindShift);
+ }
+
+ /// Get the flags that are not included in access control or method
+ /// properties.
+ MethodOptions getFlags() const {
+ return MethodOptions(
+ unsigned(Attrs) &
+ ~unsigned(MethodOptions::AccessMask | MethodOptions::MethodKindMask));
+ }
+
+ /// Is this method virtual.
+ bool isVirtual() const {
+ auto MP = getMethodKind();
+ return MP != MethodKind::Vanilla && MP != MethodKind::Friend &&
+ MP != MethodKind::Static;
+ }
+
+ /// Does this member introduce a new virtual method.
+ bool isIntroducedVirtual() const {
+ auto MP = getMethodKind();
+ return MP == MethodKind::IntroducingVirtual ||
+ MP == MethodKind::PureIntroducingVirtual;
+ }
+};
+
+// Does not correspond to any tag, this is the tail of an LF_POINTER record
+// if it represents a member pointer.
+class MemberPointerInfo {
+public:
+ MemberPointerInfo() {}
+
+ MemberPointerInfo(TypeIndex ContainingType,
+ PointerToMemberRepresentation Representation)
+ : ContainingType(ContainingType), Representation(Representation) {}
+
+ /// Rewrite member type indices with IndexMap. Returns false if a type index
+ /// is not in the map.
+ bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
+
+ static ErrorOr<MemberPointerInfo> deserialize(ArrayRef<uint8_t> &Data);
+
+ TypeIndex getContainingType() const { return ContainingType; }
+ PointerToMemberRepresentation getRepresentation() const {
+ return Representation;
+ }
+
+private:
+ struct Layout {
+ TypeIndex ClassType;
+ ulittle16_t Representation; // PointerToMemberRepresentation
+ };
+
+ TypeIndex ContainingType;
+ PointerToMemberRepresentation Representation;
+};
+
class TypeRecord {
protected:
explicit TypeRecord(TypeRecordKind Kind) : Kind(Kind) {}
@@ -30,20 +111,34 @@ private:
TypeRecordKind Kind;
};
+// LF_MODIFIER
class ModifierRecord : public TypeRecord {
public:
- ModifierRecord(TypeIndex ModifiedType, ModifierOptions Options)
+ ModifierRecord(TypeIndex ModifiedType, ModifierOptions Modifiers)
: TypeRecord(TypeRecordKind::Modifier), ModifiedType(ModifiedType),
- Options(Options) {}
+ Modifiers(Modifiers) {}
+
+ /// Rewrite member type indices with IndexMap. Returns false if a type index
+ /// is not in the map.
+ bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
+
+ static ErrorOr<ModifierRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data);
TypeIndex getModifiedType() const { return ModifiedType; }
- ModifierOptions getOptions() const { return Options; }
+ ModifierOptions getModifiers() const { return Modifiers; }
private:
+ struct Layout {
+ TypeIndex ModifiedType;
+ ulittle16_t Modifiers; // ModifierOptions
+ };
+
TypeIndex ModifiedType;
- ModifierOptions Options;
+ ModifierOptions Modifiers;
};
+// LF_PROCEDURE
class ProcedureRecord : public TypeRecord {
public:
ProcedureRecord(TypeIndex ReturnType, CallingConvention CallConv,
@@ -53,6 +148,15 @@ public:
CallConv(CallConv), Options(Options), ParameterCount(ParameterCount),
ArgumentList(ArgumentList) {}
+ /// Rewrite member type indices with IndexMap. Returns false if a type index
+ /// is not in the map.
+ bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
+
+ static ErrorOr<ProcedureRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data);
+
+ static uint32_t getLayoutSize() { return 2 + sizeof(Layout); }
+
TypeIndex getReturnType() const { return ReturnType; }
CallingConvention getCallConv() const { return CallConv; }
FunctionOptions getOptions() const { return Options; }
@@ -60,6 +164,14 @@ public:
TypeIndex getArgumentList() const { return ArgumentList; }
private:
+ struct Layout {
+ TypeIndex ReturnType;
+ CallingConvention CallConv;
+ FunctionOptions Options;
+ ulittle16_t NumParameters;
+ TypeIndex ArgListType;
+ };
+
TypeIndex ReturnType;
CallingConvention CallConv;
FunctionOptions Options;
@@ -67,6 +179,7 @@ private:
TypeIndex ArgumentList;
};
+// LF_MFUNCTION
class MemberFunctionRecord : public TypeRecord {
public:
MemberFunctionRecord(TypeIndex ReturnType, TypeIndex ClassType,
@@ -79,6 +192,13 @@ public:
ArgumentList(ArgumentList),
ThisPointerAdjustment(ThisPointerAdjustment) {}
+ /// Rewrite member type indices with IndexMap. Returns false if a type index
+ /// is not in the map.
+ bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
+
+ static ErrorOr<MemberFunctionRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data);
+
TypeIndex getReturnType() const { return ReturnType; }
TypeIndex getClassType() const { return ClassType; }
TypeIndex getThisType() const { return ThisType; }
@@ -89,6 +209,17 @@ public:
int32_t getThisPointerAdjustment() const { return ThisPointerAdjustment; }
private:
+ struct Layout {
+ TypeIndex ReturnType;
+ TypeIndex ClassType;
+ TypeIndex ThisType;
+ CallingConvention CallConv;
+ FunctionOptions Options;
+ ulittle16_t NumParameters;
+ TypeIndex ArgListType;
+ little32_t ThisAdjustment;
+ };
+
TypeIndex ReturnType;
TypeIndex ClassType;
TypeIndex ThisType;
@@ -99,78 +230,210 @@ private:
int32_t ThisPointerAdjustment;
};
-class ArgumentListRecord : public TypeRecord {
+// LF_MFUNC_ID
+class MemberFuncIdRecord : public TypeRecord {
public:
- explicit ArgumentListRecord(llvm::ArrayRef<TypeIndex> ArgumentTypes)
- : TypeRecord(TypeRecordKind::ArgumentList), ArgumentTypes(ArgumentTypes) {
- }
+ MemberFuncIdRecord(TypeIndex ClassType, TypeIndex FunctionType,
+ StringRef Name)
+ : TypeRecord(TypeRecordKind::MemberFuncId), ClassType(ClassType),
+ FunctionType(FunctionType), Name(Name) {}
- llvm::ArrayRef<TypeIndex> getArgumentTypes() const { return ArgumentTypes; }
+ /// Rewrite member type indices with IndexMap. Returns false if a type index
+ /// is not in the map.
+ bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
+
+ static ErrorOr<MemberFuncIdRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data);
+ TypeIndex getClassType() const { return ClassType; }
+ TypeIndex getFunctionType() const { return FunctionType; }
+ StringRef getName() const { return Name; }
private:
- llvm::ArrayRef<TypeIndex> ArgumentTypes;
+ struct Layout {
+ TypeIndex ClassType;
+ TypeIndex FunctionType;
+ // Name: The null-terminated name follows.
+ };
+ TypeIndex ClassType;
+ TypeIndex FunctionType;
+ StringRef Name;
};
-class PointerRecordBase : public TypeRecord {
+// LF_ARGLIST, LF_SUBSTR_LIST
+class ArgListRecord : public TypeRecord {
public:
- PointerRecordBase(TypeIndex ReferentType, PointerKind Kind, PointerMode Mode,
- PointerOptions Options, uint8_t Size)
+ ArgListRecord(TypeRecordKind Kind, ArrayRef<TypeIndex> Indices)
+ : TypeRecord(Kind), StringIndices(Indices) {}
+
+ /// Rewrite member type indices with IndexMap. Returns false if a type index
+ /// is not in the map.
+ bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
+
+ static ErrorOr<ArgListRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data);
+
+ ArrayRef<TypeIndex> getIndices() const { return StringIndices; }
+
+ static uint32_t getLayoutSize() { return 2 + sizeof(Layout); }
+
+private:
+ struct Layout {
+ ulittle32_t NumArgs; // Number of arguments
+ // ArgTypes[]: Type indicies of arguments
+ };
+
+ std::vector<TypeIndex> StringIndices;
+};
+
+// LF_POINTER
+class PointerRecord : public TypeRecord {
+public:
+ static const uint32_t PointerKindShift = 0;
+ static const uint32_t PointerKindMask = 0x1F;
+
+ static const uint32_t PointerModeShift = 5;
+ static const uint32_t PointerModeMask = 0x07;
+
+ static const uint32_t PointerSizeShift = 13;
+ static const uint32_t PointerSizeMask = 0xFF;
+
+ PointerRecord(TypeIndex ReferentType, PointerKind Kind, PointerMode Mode,
+ PointerOptions Options, uint8_t Size)
+ : PointerRecord(ReferentType, Kind, Mode, Options, Size,
+ MemberPointerInfo()) {}
+
+ PointerRecord(TypeIndex ReferentType, PointerKind Kind, PointerMode Mode,
+ PointerOptions Options, uint8_t Size,
+ const MemberPointerInfo &Member)
: TypeRecord(TypeRecordKind::Pointer), ReferentType(ReferentType),
- PtrKind(Kind), Mode(Mode), Options(Options), Size(Size) {}
+ PtrKind(Kind), Mode(Mode), Options(Options), Size(Size),
+ MemberInfo(Member) {}
+
+ /// Rewrite member type indices with IndexMap. Returns false if a type index
+ /// is not in the map.
+ bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
+
+ static ErrorOr<PointerRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data);
TypeIndex getReferentType() const { return ReferentType; }
PointerKind getPointerKind() const { return PtrKind; }
PointerMode getMode() const { return Mode; }
PointerOptions getOptions() const { return Options; }
uint8_t getSize() const { return Size; }
+ MemberPointerInfo getMemberInfo() const { return MemberInfo; }
+
+ bool isPointerToMember() const {
+ return Mode == PointerMode::PointerToDataMember ||
+ Mode == PointerMode::PointerToMemberFunction;
+ }
+ bool isFlat() const {
+ return !!(uint32_t(Options) & uint32_t(PointerOptions::Flat32));
+ }
+ bool isConst() const {
+ return !!(uint32_t(Options) & uint32_t(PointerOptions::Const));
+ }
+ bool isVolatile() const {
+ return !!(uint32_t(Options) & uint32_t(PointerOptions::Volatile));
+ }
+ bool isUnaligned() const {
+ return !!(uint32_t(Options) & uint32_t(PointerOptions::Unaligned));
+ }
private:
+ struct Layout {
+ TypeIndex PointeeType;
+ ulittle32_t Attrs; // pointer attributes
+ // if pointer to member:
+ // PointerToMemberTail
+ PointerKind getPtrKind() const {
+ return PointerKind(Attrs & PointerKindMask);
+ }
+ PointerMode getPtrMode() const {
+ return PointerMode((Attrs >> PointerModeShift) & PointerModeMask);
+ }
+ uint8_t getPtrSize() const {
+ return (Attrs >> PointerSizeShift) & PointerSizeMask;
+ }
+ bool isFlat() const { return Attrs & (1 << 8); }
+ bool isVolatile() const { return Attrs & (1 << 9); }
+ bool isConst() const { return Attrs & (1 << 10); }
+ bool isUnaligned() const { return Attrs & (1 << 11); }
+
+ bool isPointerToDataMember() const {
+ return getPtrMode() == PointerMode::PointerToDataMember;
+ }
+ bool isPointerToMemberFunction() const {
+ return getPtrMode() == PointerMode::PointerToMemberFunction;
+ }
+ bool isPointerToMember() const {
+ return isPointerToMemberFunction() || isPointerToDataMember();
+ }
+ };
+
TypeIndex ReferentType;
PointerKind PtrKind;
PointerMode Mode;
PointerOptions Options;
uint8_t Size;
+ MemberPointerInfo MemberInfo;
};
-class PointerRecord : public PointerRecordBase {
+// LF_NESTTYPE
+class NestedTypeRecord : public TypeRecord {
public:
- PointerRecord(TypeIndex ReferentType, PointerKind Kind, PointerMode Mode,
- PointerOptions Options, uint8_t Size)
- : PointerRecordBase(ReferentType, Kind, Mode, Options, Size) {}
-};
+ NestedTypeRecord(TypeIndex Type, StringRef Name)
+ : TypeRecord(TypeRecordKind::NestedType), Type(Type), Name(Name) {}
-class PointerToMemberRecord : public PointerRecordBase {
-public:
- PointerToMemberRecord(TypeIndex ReferentType, PointerKind Kind,
- PointerMode Mode, PointerOptions Options, uint8_t Size,
- TypeIndex ContainingType,
- PointerToMemberRepresentation Representation)
- : PointerRecordBase(ReferentType, Kind, Mode, Options, Size),
- ContainingType(ContainingType), Representation(Representation) {}
+ /// Rewrite member type indices with IndexMap. Returns false if a type index
+ /// is not in the map.
+ bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
- TypeIndex getContainingType() const { return ContainingType; }
- PointerToMemberRepresentation getRepresentation() const {
- return Representation;
- }
+ static ErrorOr<NestedTypeRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data);
+
+ TypeIndex getNestedType() const { return Type; }
+ StringRef getName() const { return Name; }
private:
- TypeIndex ContainingType;
- PointerToMemberRepresentation Representation;
+ struct Layout {
+ ulittle16_t Pad0; // Should be zero
+ TypeIndex Type; // Type index of nested type
+ // Name: Null-terminated string
+ };
+
+ TypeIndex Type;
+ StringRef Name;
};
+// LF_ARRAY
class ArrayRecord : public TypeRecord {
public:
ArrayRecord(TypeIndex ElementType, TypeIndex IndexType, uint64_t Size,
- llvm::StringRef Name)
+ StringRef Name)
: TypeRecord(TypeRecordKind::Array), ElementType(ElementType),
IndexType(IndexType), Size(Size), Name(Name) {}
+ /// Rewrite member type indices with IndexMap. Returns false if a type index
+ /// is not in the map.
+ bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
+
+ static ErrorOr<ArrayRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data);
+
TypeIndex getElementType() const { return ElementType; }
TypeIndex getIndexType() const { return IndexType; }
uint64_t getSize() const { return Size; }
llvm::StringRef getName() const { return Name; }
private:
+ struct Layout {
+ TypeIndex ElementType;
+ TypeIndex IndexType;
+ // SizeOf: LF_NUMERIC encoded size in bytes. Not element count!
+ // Name: The null-terminated name follows.
+ };
+
TypeIndex ElementType;
TypeIndex IndexType;
uint64_t Size;
@@ -185,6 +448,15 @@ protected:
FieldList(FieldList), Name(Name), UniqueName(UniqueName) {}
public:
+ /// Rewrite member type indices with IndexMap. Returns false if a type index
+ /// is not in the map.
+ bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
+
+ static const int HfaKindShift = 11;
+ static const int HfaKindMask = 0x1800;
+ static const int WinRTKindShift = 14;
+ static const int WinRTKindMask = 0xC000;
+
uint16_t getMemberCount() const { return MemberCount; }
ClassOptions getOptions() const { return Options; }
TypeIndex getFieldList() const { return FieldList; }
@@ -199,17 +471,24 @@ private:
StringRef UniqueName;
};
-class AggregateRecord : public TagRecord {
+// LF_CLASS, LF_STRUCTURE, LF_INTERFACE
+class ClassRecord : public TagRecord {
public:
- AggregateRecord(TypeRecordKind Kind, uint16_t MemberCount,
- ClassOptions Options, HfaKind Hfa,
- WindowsRTClassKind WinRTKind, TypeIndex FieldList,
- TypeIndex DerivationList, TypeIndex VTableShape,
- uint64_t Size, StringRef Name, StringRef UniqueName)
+ ClassRecord(TypeRecordKind Kind, uint16_t MemberCount, ClassOptions Options,
+ HfaKind Hfa, WindowsRTClassKind WinRTKind, TypeIndex FieldList,
+ TypeIndex DerivationList, TypeIndex VTableShape, uint64_t Size,
+ StringRef Name, StringRef UniqueName)
: TagRecord(Kind, MemberCount, Options, FieldList, Name, UniqueName),
Hfa(Hfa), WinRTKind(WinRTKind), DerivationList(DerivationList),
VTableShape(VTableShape), Size(Size) {}
+ /// Rewrite member type indices with IndexMap. Returns false if a type index
+ /// is not in the map.
+ bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
+
+ static ErrorOr<ClassRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data);
+
HfaKind getHfa() const { return Hfa; }
WindowsRTClassKind getWinRTKind() const { return WinRTKind; }
TypeIndex getDerivationList() const { return DerivationList; }
@@ -217,6 +496,21 @@ public:
uint64_t getSize() const { return Size; }
private:
+ struct Layout {
+ ulittle16_t MemberCount; // Number of members in FieldList.
+ ulittle16_t Properties; // ClassOptions bitset
+ TypeIndex FieldList; // LF_FIELDLIST: List of all kinds of members
+ TypeIndex DerivedFrom; // LF_DERIVED: List of known derived classes
+ TypeIndex VShape; // LF_VTSHAPE: Shape of the vftable
+ // SizeOf: The 'sizeof' the UDT in bytes is encoded as an LF_NUMERIC
+ // integer.
+ // Name: The null-terminated name follows.
+
+ bool hasUniqueName() const {
+ return Properties & uint16_t(ClassOptions::HasUniqueName);
+ }
+ };
+
HfaKind Hfa;
WindowsRTClassKind WinRTKind;
TypeIndex DerivationList;
@@ -224,6 +518,40 @@ private:
uint64_t Size;
};
+// LF_UNION
+struct UnionRecord : public TagRecord {
+ UnionRecord(uint16_t MemberCount, ClassOptions Options, HfaKind Hfa,
+ TypeIndex FieldList, uint64_t Size, StringRef Name,
+ StringRef UniqueName)
+ : TagRecord(TypeRecordKind::Union, MemberCount, Options, FieldList, Name,
+ UniqueName),
+ Hfa(Hfa), Size(Size) {}
+
+ static ErrorOr<UnionRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data);
+
+ HfaKind getHfa() const { return Hfa; }
+ uint64_t getSize() const { return Size; }
+
+private:
+ struct Layout {
+ ulittle16_t MemberCount; // Number of members in FieldList.
+ ulittle16_t Properties; // ClassOptions bitset
+ TypeIndex FieldList; // LF_FIELDLIST: List of all kinds of members
+ // SizeOf: The 'sizeof' the UDT in bytes is encoded as an LF_NUMERIC
+ // integer.
+ // Name: The null-terminated name follows.
+
+ bool hasUniqueName() const {
+ return Properties & uint16_t(ClassOptions::HasUniqueName);
+ }
+ };
+
+ HfaKind Hfa;
+ uint64_t Size;
+};
+
+// LF_ENUM
class EnumRecord : public TagRecord {
public:
EnumRecord(uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList,
@@ -232,38 +560,642 @@ public:
UniqueName),
UnderlyingType(UnderlyingType) {}
+ /// Rewrite member type indices with IndexMap. Returns false if a type index is not in the map.
+ bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
+
+ static ErrorOr<EnumRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data);
+
TypeIndex getUnderlyingType() const { return UnderlyingType; }
private:
+ struct Layout {
+ ulittle16_t NumEnumerators; // Number of enumerators
+ ulittle16_t Properties;
+ TypeIndex UnderlyingType;
+ TypeIndex FieldListType;
+ // Name: The null-terminated name follows.
+
+ bool hasUniqueName() const {
+ return Properties & uint16_t(ClassOptions::HasUniqueName);
+ }
+ };
+
TypeIndex UnderlyingType;
};
-class BitFieldRecord : TypeRecord {
+// LF_BITFIELD
+class BitFieldRecord : public TypeRecord {
public:
BitFieldRecord(TypeIndex Type, uint8_t BitSize, uint8_t BitOffset)
: TypeRecord(TypeRecordKind::BitField), Type(Type), BitSize(BitSize),
BitOffset(BitOffset) {}
+ /// Rewrite member type indices with IndexMap. Returns false if a type index
+ /// is not in the map.
+ bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
+
+ static ErrorOr<BitFieldRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data);
+
TypeIndex getType() const { return Type; }
uint8_t getBitOffset() const { return BitOffset; }
uint8_t getBitSize() const { return BitSize; }
private:
+ struct Layout {
+ TypeIndex Type;
+ uint8_t BitSize;
+ uint8_t BitOffset;
+ };
+
TypeIndex Type;
uint8_t BitSize;
uint8_t BitOffset;
};
-class VirtualTableShapeRecord : TypeRecord {
+// LF_VTSHAPE
+class VFTableShapeRecord : public TypeRecord {
+public:
+ explicit VFTableShapeRecord(ArrayRef<VFTableSlotKind> Slots)
+ : TypeRecord(TypeRecordKind::VFTableShape), SlotsRef(Slots) {}
+ explicit VFTableShapeRecord(std::vector<VFTableSlotKind> Slots)
+ : TypeRecord(TypeRecordKind::VFTableShape), Slots(std::move(Slots)) {}
+
+ /// Rewrite member type indices with IndexMap. Returns false if a type index
+ /// is not in the map.
+ bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
+
+ static ErrorOr<VFTableShapeRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data);
+
+ ArrayRef<VFTableSlotKind> getSlots() const {
+ if (!SlotsRef.empty())
+ return SlotsRef;
+ return Slots;
+ }
+ uint32_t getEntryCount() const { return getSlots().size(); }
+
+private:
+ struct Layout {
+ // Number of vftable entries. Each method may have more than one entry due
+ // to
+ // things like covariant return types.
+ ulittle16_t VFEntryCount;
+ // Descriptors[]: 4-bit virtual method descriptors of type CV_VTS_desc_e.
+ };
+
+private:
+ ArrayRef<VFTableSlotKind> SlotsRef;
+ std::vector<VFTableSlotKind> Slots;
+};
+
+// LF_TYPESERVER2
+class TypeServer2Record : public TypeRecord {
+public:
+ TypeServer2Record(StringRef Guid, uint32_t Age, StringRef Name)
+ : TypeRecord(TypeRecordKind::TypeServer2), Guid(Guid), Age(Age),
+ Name(Name) {}
+
+ /// Rewrite member type indices with IndexMap. Returns false if a type index
+ /// is not in the map.
+ bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
+
+ static ErrorOr<TypeServer2Record> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data);
+
+ StringRef getGuid() const { return Guid; }
+
+ uint32_t getAge() const { return Age; }
+
+ StringRef getName() const { return Name; }
+
+private:
+ struct Layout {
+ char Guid[16]; // GUID
+ ulittle32_t Age;
+ // Name: Name of the PDB as a null-terminated string
+ };
+
+ StringRef Guid;
+ uint32_t Age;
+ StringRef Name;
+};
+
+// LF_STRING_ID
+class StringIdRecord : public TypeRecord {
+public:
+ StringIdRecord(TypeIndex Id, StringRef String)
+ : TypeRecord(TypeRecordKind::StringId), Id(Id), String(String) {}
+
+ /// Rewrite member type indices with IndexMap. Returns false if a type index
+ /// is not in the map.
+ bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
+
+ static ErrorOr<StringIdRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data);
+
+ TypeIndex getId() const { return Id; }
+
+ StringRef getString() const { return String; }
+
+private:
+ struct Layout {
+ TypeIndex id;
+ // Name: Name of the PDB as a null-terminated string
+ };
+
+ TypeIndex Id;
+ StringRef String;
+};
+
+// LF_FUNC_ID
+class FuncIdRecord : public TypeRecord {
+public:
+ FuncIdRecord(TypeIndex ParentScope, TypeIndex FunctionType, StringRef Name)
+ : TypeRecord(TypeRecordKind::FuncId), ParentScope(ParentScope),
+ FunctionType(FunctionType), Name(Name) {}
+
+ /// Rewrite member type indices with IndexMap. Returns false if a type index
+ /// is not in the map.
+ bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
+
+ static ErrorOr<FuncIdRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data);
+
+ TypeIndex getParentScope() const { return ParentScope; }
+
+ TypeIndex getFunctionType() const { return FunctionType; }
+
+ StringRef getName() const { return Name; }
+
+private:
+ struct Layout {
+ TypeIndex ParentScope;
+ TypeIndex FunctionType;
+ // Name: The null-terminated name follows.
+ };
+
+ TypeIndex ParentScope;
+ TypeIndex FunctionType;
+ StringRef Name;
+};
+
+// LF_UDT_SRC_LINE
+class UdtSourceLineRecord : public TypeRecord {
public:
- explicit VirtualTableShapeRecord(ArrayRef<VirtualTableSlotKind> Slots)
- : TypeRecord(TypeRecordKind::VirtualTableShape), Slots(Slots) {}
+ UdtSourceLineRecord(TypeIndex UDT, TypeIndex SourceFile, uint32_t LineNumber)
+ : TypeRecord(TypeRecordKind::UdtSourceLine), UDT(UDT),
+ SourceFile(SourceFile), LineNumber(LineNumber) {}
- ArrayRef<VirtualTableSlotKind> getSlots() const { return Slots; }
+ /// Rewrite member type indices with IndexMap. Returns false if a type index
+ /// is not in the map.
+ bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
+
+ static ErrorOr<UdtSourceLineRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data);
+
+ TypeIndex getUDT() const { return UDT; }
+ TypeIndex getSourceFile() const { return SourceFile; }
+ uint32_t getLineNumber() const { return LineNumber; }
private:
- ArrayRef<VirtualTableSlotKind> Slots;
+ struct Layout {
+ TypeIndex UDT; // The user-defined type
+ TypeIndex SourceFile; // StringID containing the source filename
+ ulittle32_t LineNumber;
+ };
+
+ TypeIndex UDT;
+ TypeIndex SourceFile;
+ uint32_t LineNumber;
};
+
+// LF_UDT_MOD_SRC_LINE
+class UdtModSourceLineRecord : public TypeRecord {
+public:
+ UdtModSourceLineRecord(TypeIndex UDT, TypeIndex SourceFile,
+ uint32_t LineNumber, uint16_t Module)
+ : TypeRecord(TypeRecordKind::UdtSourceLine), UDT(UDT),
+ SourceFile(SourceFile), LineNumber(LineNumber), Module(Module) {}
+
+ bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
+
+ static ErrorOr<UdtModSourceLineRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ CV_DESERIALIZE(Data, L);
+
+ return UdtModSourceLineRecord(L->UDT, L->SourceFile, L->LineNumber,
+ L->Module);
+ }
+
+ TypeIndex getUDT() const { return UDT; }
+ TypeIndex getSourceFile() const { return SourceFile; }
+ uint32_t getLineNumber() const { return LineNumber; }
+ uint16_t getModule() const { return Module; }
+
+private:
+ struct Layout {
+ TypeIndex UDT; // The user-defined type
+ TypeIndex SourceFile; // StringID containing the source filename
+ ulittle32_t LineNumber;
+ ulittle16_t Module; // Module that contributes this UDT definition
+ };
+
+ TypeIndex UDT;
+ TypeIndex SourceFile;
+ uint32_t LineNumber;
+ uint16_t Module;
+};
+
+// LF_BUILDINFO
+class BuildInfoRecord : public TypeRecord {
+public:
+ BuildInfoRecord(ArrayRef<TypeIndex> ArgIndices)
+ : TypeRecord(TypeRecordKind::BuildInfo),
+ ArgIndices(ArgIndices.begin(), ArgIndices.end()) {}
+
+ /// Rewrite member type indices with IndexMap. Returns false if a type index
+ /// is not in the map.
+ bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
+
+ static ErrorOr<BuildInfoRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data);
+
+ ArrayRef<TypeIndex> getArgs() const { return ArgIndices; }
+
+private:
+ struct Layout {
+ ulittle16_t NumArgs; // Number of arguments
+ // ArgTypes[]: Type indicies of arguments
+ };
+ SmallVector<TypeIndex, 4> ArgIndices;
+};
+
+// LF_VFTABLE
+class VFTableRecord : public TypeRecord {
+public:
+ VFTableRecord(TypeIndex CompleteClass, TypeIndex OverriddenVFTable,
+ uint32_t VFPtrOffset, StringRef Name,
+ ArrayRef<StringRef> Methods)
+ : TypeRecord(TypeRecordKind::VFTable),
+ CompleteClass(CompleteClass), OverriddenVFTable(OverriddenVFTable),
+ VFPtrOffset(VFPtrOffset), Name(Name), MethodNamesRef(Methods) {}
+ VFTableRecord(TypeIndex CompleteClass, TypeIndex OverriddenVFTable,
+ uint32_t VFPtrOffset, StringRef Name,
+ const std::vector<StringRef> &Methods)
+ : TypeRecord(TypeRecordKind::VFTable),
+ CompleteClass(CompleteClass), OverriddenVFTable(OverriddenVFTable),
+ VFPtrOffset(VFPtrOffset), Name(Name), MethodNames(Methods) {}
+
+ /// Rewrite member type indices with IndexMap. Returns false if a type index
+ /// is not in the map.
+ bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
+
+ static ErrorOr<VFTableRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data);
+
+ TypeIndex getCompleteClass() const { return CompleteClass; }
+ TypeIndex getOverriddenVTable() const { return OverriddenVFTable; }
+ uint32_t getVFPtrOffset() const { return VFPtrOffset; }
+ StringRef getName() const { return Name; }
+ ArrayRef<StringRef> getMethodNames() const {
+ if (!MethodNamesRef.empty())
+ return MethodNamesRef;
+ return MethodNames;
+ }
+
+private:
+ struct Layout {
+ TypeIndex CompleteClass; // Class that owns this vftable.
+ TypeIndex OverriddenVFTable; // VFTable that this overrides.
+ ulittle32_t VFPtrOffset; // VFPtr offset in CompleteClass
+ ulittle32_t NamesLen; // Length of subsequent names array in bytes.
+ // Names: A sequence of null-terminated strings. First string is vftable
+ // names.
+ };
+
+ TypeIndex CompleteClass;
+ TypeIndex OverriddenVFTable;
+ ulittle32_t VFPtrOffset;
+ StringRef Name;
+ ArrayRef<StringRef> MethodNamesRef;
+ std::vector<StringRef> MethodNames;
+};
+
+// LF_ONEMETHOD
+class OneMethodRecord : public TypeRecord {
+public:
+ OneMethodRecord(TypeIndex Type, MethodKind Kind, MethodOptions Options,
+ MemberAccess Access, int32_t VFTableOffset, StringRef Name)
+ : TypeRecord(TypeRecordKind::OneMethod), Type(Type), Kind(Kind),
+ Options(Options), Access(Access), VFTableOffset(VFTableOffset),
+ Name(Name) {}
+
+ /// Rewrite member type indices with IndexMap. Returns false if a type index
+ /// is not in the map.
+ bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
+
+ static ErrorOr<OneMethodRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data);
+
+ TypeIndex getType() const { return Type; }
+ MethodKind getKind() const { return Kind; }
+ MethodOptions getOptions() const { return Options; }
+ MemberAccess getAccess() const { return Access; }
+ int32_t getVFTableOffset() const { return VFTableOffset; }
+ StringRef getName() const { return Name; }
+
+ bool isIntroducingVirtual() const {
+ return Kind == MethodKind::IntroducingVirtual ||
+ Kind == MethodKind::PureIntroducingVirtual;
+ }
+
+private:
+ struct Layout {
+ MemberAttributes Attrs;
+ TypeIndex Type;
+ // If is introduced virtual method:
+ // VFTableOffset: int32_t offset in vftable
+ // Name: Null-terminated string
+ };
+
+ TypeIndex Type;
+ MethodKind Kind;
+ MethodOptions Options;
+ MemberAccess Access;
+ int32_t VFTableOffset;
+ StringRef Name;
+};
+
+// LF_METHODLIST
+class MethodOverloadListRecord : public TypeRecord {
+public:
+ MethodOverloadListRecord(ArrayRef<OneMethodRecord> Methods)
+ : TypeRecord(TypeRecordKind::MethodOverloadList), Methods(Methods) {}
+
+ /// Rewrite member type indices with IndexMap. Returns false if a type index
+ /// is not in the map.
+ bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
+
+ static ErrorOr<MethodOverloadListRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data);
+
+ ArrayRef<OneMethodRecord> getMethods() const { return Methods; }
+
+private:
+ struct Layout {
+ MemberAttributes Attrs;
+ ulittle16_t Padding;
+
+ TypeIndex Type;
+ // If is introduced virtual method:
+ // VFTableOffset: int32_t offset in vftable
+ };
+
+ std::vector<OneMethodRecord> Methods;
+};
+
+/// For method overload sets. LF_METHOD
+class OverloadedMethodRecord : public TypeRecord {
+public:
+ OverloadedMethodRecord(uint16_t NumOverloads, TypeIndex MethodList,
+ StringRef Name)
+ : TypeRecord(TypeRecordKind::OverloadedMethod),
+ NumOverloads(NumOverloads), MethodList(MethodList), Name(Name) {}
+
+ /// Rewrite member type indices with IndexMap. Returns false if a type index
+ /// is not in the map.
+ bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
+
+ static ErrorOr<OverloadedMethodRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data);
+
+ uint16_t getNumOverloads() const { return NumOverloads; }
+ TypeIndex getMethodList() const { return MethodList; }
+ StringRef getName() const { return Name; }
+
+private:
+ struct Layout {
+ ulittle16_t MethodCount; // Size of overload set
+ TypeIndex MethList; // Type index of methods in overload set
+ // Name: Null-terminated string
+ };
+
+ uint16_t NumOverloads;
+ TypeIndex MethodList;
+ StringRef Name;
+};
+
+// LF_MEMBER
+class DataMemberRecord : public TypeRecord {
+public:
+ DataMemberRecord(MemberAccess Access, TypeIndex Type, uint64_t Offset,
+ StringRef Name)
+ : TypeRecord(TypeRecordKind::DataMember), Access(Access), Type(Type),
+ FieldOffset(Offset), Name(Name) {}
+
+ /// Rewrite member type indices with IndexMap. Returns false if a type index
+ /// is not in the map.
+ bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
+
+ static ErrorOr<DataMemberRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data);
+
+ MemberAccess getAccess() const { return Access; }
+ TypeIndex getType() const { return Type; }
+ uint64_t getFieldOffset() const { return FieldOffset; }
+ StringRef getName() const { return Name; }
+
+private:
+ struct Layout {
+ MemberAttributes Attrs; // Access control attributes, etc
+ TypeIndex Type;
+ // FieldOffset: LF_NUMERIC encoded byte offset
+ // Name: Null-terminated string
+ };
+
+ MemberAccess Access;
+ TypeIndex Type;
+ uint64_t FieldOffset;
+ StringRef Name;
+};
+
+// LF_STMEMBER
+class StaticDataMemberRecord : public TypeRecord {
+public:
+ StaticDataMemberRecord(MemberAccess Access, TypeIndex Type, StringRef Name)
+ : TypeRecord(TypeRecordKind::StaticDataMember), Access(Access),
+ Type(Type), Name(Name) {}
+
+ /// Rewrite member type indices with IndexMap. Returns false if a type index
+ /// is not in the map.
+ bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
+
+ static ErrorOr<StaticDataMemberRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data);
+
+ MemberAccess getAccess() const { return Access; }
+ TypeIndex getType() const { return Type; }
+ StringRef getName() const { return Name; }
+
+private:
+ struct Layout {
+ MemberAttributes Attrs; // Access control attributes, etc
+ TypeIndex Type;
+ // Name: Null-terminated string
+ };
+
+ MemberAccess Access;
+ TypeIndex Type;
+ StringRef Name;
+};
+
+// LF_ENUMERATE
+class EnumeratorRecord : public TypeRecord {
+public:
+ EnumeratorRecord(MemberAccess Access, APSInt Value, StringRef Name)
+ : TypeRecord(TypeRecordKind::Enumerator), Access(Access),
+ Value(std::move(Value)), Name(Name) {}
+
+ /// Rewrite member type indices with IndexMap. Returns false if a type index
+ /// is not in the map.
+ bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
+
+ static ErrorOr<EnumeratorRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data);
+
+ MemberAccess getAccess() const { return Access; }
+ APSInt getValue() const { return Value; }
+ StringRef getName() const { return Name; }
+
+private:
+ struct Layout {
+ MemberAttributes Attrs; // Access control attributes, etc
+ // EnumValue: LF_NUMERIC encoded enumerator value
+ // Name: Null-terminated string
+ };
+
+ MemberAccess Access;
+ APSInt Value;
+ StringRef Name;
+};
+
+// LF_VFUNCTAB
+class VFPtrRecord : public TypeRecord {
+public:
+ VFPtrRecord(TypeIndex Type)
+ : TypeRecord(TypeRecordKind::VFPtr), Type(Type) {}
+
+ /// Rewrite member type indices with IndexMap. Returns false if a type index
+ /// is not in the map.
+ bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
+
+ static ErrorOr<VFPtrRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data);
+
+ TypeIndex getType() const { return Type; }
+
+private:
+ struct Layout {
+ ulittle16_t Pad0;
+ TypeIndex Type; // Type of vfptr
+ };
+ TypeIndex Type;
+};
+
+// LF_BCLASS, LF_BINTERFACE
+class BaseClassRecord : public TypeRecord {
+public:
+ BaseClassRecord(MemberAccess Access, TypeIndex Type, uint64_t Offset)
+ : TypeRecord(TypeRecordKind::BaseClass), Access(Access), Type(Type),
+ Offset(Offset) {}
+
+ /// Rewrite member type indices with IndexMap. Returns false if a type index
+ /// is not in the map.
+ bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
+
+ static ErrorOr<BaseClassRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data);
+
+ MemberAccess getAccess() const { return Access; }
+ TypeIndex getBaseType() const { return Type; }
+ uint64_t getBaseOffset() const { return Offset; }
+
+private:
+ struct Layout {
+ MemberAttributes Attrs; // Access control attributes, etc
+ TypeIndex BaseType; // Base class type
+ // BaseOffset: LF_NUMERIC encoded byte offset of base from derived.
+ };
+ MemberAccess Access;
+ TypeIndex Type;
+ uint64_t Offset;
+};
+
+// LF_VBCLASS, LF_IVBCLASS
+class VirtualBaseClassRecord : public TypeRecord {
+public:
+ VirtualBaseClassRecord(MemberAccess Access, TypeIndex BaseType,
+ TypeIndex VBPtrType, uint64_t Offset, uint64_t Index)
+ : TypeRecord(TypeRecordKind::VirtualBaseClass), Access(Access),
+ BaseType(BaseType), VBPtrType(VBPtrType), VBPtrOffset(Offset),
+ VTableIndex(Index) {}
+
+ /// Rewrite member type indices with IndexMap. Returns false if a type index
+ /// is not in the map.
+ bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
+
+ static ErrorOr<VirtualBaseClassRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data);
+
+ MemberAccess getAccess() const { return Access; }
+ TypeIndex getBaseType() const { return BaseType; }
+ TypeIndex getVBPtrType() const { return VBPtrType; }
+ uint64_t getVBPtrOffset() const { return VBPtrOffset; }
+ uint64_t getVTableIndex() const { return VTableIndex; }
+
+private:
+ struct Layout {
+ MemberAttributes Attrs; // Access control attributes, etc.
+ TypeIndex BaseType; // Base class type
+ TypeIndex VBPtrType; // Virtual base pointer type
+ // VBPtrOffset: Offset of vbptr from vfptr encoded as LF_NUMERIC.
+ // VBTableIndex: Index of vbase within vbtable encoded as LF_NUMERIC.
+ };
+ MemberAccess Access;
+ TypeIndex BaseType;
+ TypeIndex VBPtrType;
+ uint64_t VBPtrOffset;
+ uint64_t VTableIndex;
+};
+
+/// LF_INDEX - Used to chain two large LF_FIELDLIST or LF_METHODLIST records
+/// together. The first will end in an LF_INDEX record that points to the next.
+class ListContinuationRecord : public TypeRecord {
+public:
+ ListContinuationRecord(TypeIndex ContinuationIndex)
+ : TypeRecord(TypeRecordKind::ListContinuation),
+ ContinuationIndex(ContinuationIndex) {}
+
+ TypeIndex getContinuationIndex() const { return ContinuationIndex; }
+
+ bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
+
+ static ErrorOr<ListContinuationRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data);
+
+private:
+ struct Layout {
+ ulittle16_t Pad0;
+ TypeIndex ContinuationIndex;
+ };
+ TypeIndex ContinuationIndex;
+};
+
+typedef CVRecord<TypeLeafKind> CVType;
+typedef VarStreamArray<CVType> CVTypeArray;
}
}
diff --git a/include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h b/include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h
index 1f48cf70666d..eb7993baab89 100644
--- a/include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h
+++ b/include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h
@@ -10,9 +10,10 @@
#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPERECORDBUILDER_H
#define LLVM_DEBUGINFO_CODEVIEW_TYPERECORDBUILDER_H
+#include "llvm/ADT/SmallVector.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
-#include "llvm/ADT/SmallVector.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/raw_ostream.h"
@@ -39,13 +40,25 @@ public:
void writeEncodedInteger(int64_t Value);
void writeEncodedSignedInteger(int64_t Value);
void writeEncodedUnsignedInteger(uint64_t Value);
- void writeNullTerminatedString(const char *Value);
void writeNullTerminatedString(StringRef Value);
+ void writeGuid(StringRef Guid);
+ void writeBytes(StringRef Value) { Stream << Value; }
llvm::StringRef str();
uint64_t size() const { return Stream.tell(); }
+ void truncate(uint64_t Size) {
+ // This works because raw_svector_ostream is not buffered.
+ assert(Size < Buffer.size());
+ Buffer.resize(Size);
+ }
+
+ void reset(TypeRecordKind K) {
+ Buffer.clear();
+ writeTypeRecordKind(K);
+ }
+
private:
llvm::SmallVector<char, 256> Buffer;
llvm::raw_svector_ostream Stream;
diff --git a/include/llvm/DebugInfo/CodeView/TypeRecords.def b/include/llvm/DebugInfo/CodeView/TypeRecords.def
new file mode 100644
index 000000000000..0959f4bf19c7
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/TypeRecords.def
@@ -0,0 +1,252 @@
+
+//===-- CVLeafTypes.def - All CodeView leaf types ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// See LEAF_ENUM_e in cvinfo.h. This should match the constants there.
+//
+//===----------------------------------------------------------------------===//
+
+// If the type is known, then we have a record describing it in TypeRecord.h.
+
+#ifndef CV_TYPE
+#define CV_TYPE(lf_ename, value)
+#endif
+
+// If the type is known, then we have a record describing it in TypeRecord.h.
+#ifndef TYPE_RECORD
+#define TYPE_RECORD(lf_ename, value, name) CV_TYPE(lf_ename, value)
+#endif
+
+#ifndef TYPE_RECORD_ALIAS
+#define TYPE_RECORD_ALIAS(lf_ename, value, name, alias_name) \
+ TYPE_RECORD(lf_ename, value, name)
+#endif
+
+#ifndef MEMBER_RECORD
+#define MEMBER_RECORD(lf_ename, value, name) TYPE_RECORD(lf_ename, value, name)
+#endif
+
+#ifndef MEMBER_RECORD_ALIAS
+#define MEMBER_RECORD_ALIAS(lf_ename, value, name, alias_name) \
+ MEMBER_RECORD(lf_ename, value, name)
+#endif
+
+TYPE_RECORD(LF_POINTER, 0x1002, Pointer)
+TYPE_RECORD(LF_MODIFIER, 0x1001, Modifier)
+TYPE_RECORD(LF_PROCEDURE, 0x1008, Procedure)
+TYPE_RECORD(LF_MFUNCTION, 0x1009, MemberFunction)
+TYPE_RECORD(LF_ARGLIST, 0x1201, ArgList)
+
+TYPE_RECORD(LF_ARRAY, 0x1503, Array)
+TYPE_RECORD(LF_CLASS, 0x1504, Class)
+TYPE_RECORD_ALIAS(LF_STRUCTURE, 0x1505, Struct, Class)
+TYPE_RECORD_ALIAS(LF_INTERFACE, 0x1519, Interface, Class)
+TYPE_RECORD(LF_UNION, 0x1506, Union)
+TYPE_RECORD(LF_ENUM, 0x1507, Enum)
+TYPE_RECORD(LF_TYPESERVER2, 0x1515, TypeServer2)
+TYPE_RECORD(LF_VFTABLE, 0x151d, VFTable)
+TYPE_RECORD(LF_VTSHAPE, 0x000a, VFTableShape)
+
+TYPE_RECORD(LF_BITFIELD, 0x1205, BitField)
+
+// Member type records. These are generally not length prefixed, and appear
+// inside of a field list record.
+MEMBER_RECORD(LF_BCLASS, 0x1400, BaseClass)
+MEMBER_RECORD_ALIAS(LF_BINTERFACE, 0x151a, BaseInterface, BaseClass)
+
+MEMBER_RECORD(LF_VBCLASS, 0x1401, VirtualBaseClass)
+MEMBER_RECORD_ALIAS(LF_IVBCLASS, 0x1402, IndirectVirtualBaseClass,
+ VirtualBaseClass)
+
+MEMBER_RECORD(LF_VFUNCTAB, 0x1409, VFPtr)
+MEMBER_RECORD(LF_STMEMBER, 0x150e, StaticDataMember)
+MEMBER_RECORD(LF_METHOD, 0x150f, OverloadedMethod)
+MEMBER_RECORD(LF_MEMBER, 0x150d, DataMember)
+MEMBER_RECORD(LF_NESTTYPE, 0x1510, NestedType)
+MEMBER_RECORD(LF_ONEMETHOD, 0x1511, OneMethod)
+MEMBER_RECORD(LF_ENUMERATE, 0x1502, Enumerator)
+MEMBER_RECORD(LF_INDEX, 0x1404, ListContinuation)
+
+// ID leaf records. Subsequent leaf types may be referenced from .debug$S.
+TYPE_RECORD(LF_FUNC_ID, 0x1601, FuncId)
+TYPE_RECORD(LF_MFUNC_ID, 0x1602, MemberFuncId)
+TYPE_RECORD(LF_BUILDINFO, 0x1603, BuildInfo)
+// FIXME: We reuse the structure of ArgListRecord for substring lists, but it
+// makes for confusing dumper output.
+TYPE_RECORD_ALIAS(LF_SUBSTR_LIST, 0x1604, StringList, ArgList)
+TYPE_RECORD(LF_STRING_ID, 0x1605, StringId)
+TYPE_RECORD(LF_UDT_SRC_LINE, 0x1606, UdtSourceLine)
+TYPE_RECORD(LF_UDT_MOD_SRC_LINE, 0x1607, UdtModSourceLine)
+
+
+TYPE_RECORD(LF_METHODLIST, 0x1206, MethodOverloadList)
+
+
+// 16 bit type records.
+CV_TYPE(LF_MODIFIER_16t, 0x0001)
+CV_TYPE(LF_POINTER_16t, 0x0002)
+CV_TYPE(LF_ARRAY_16t, 0x0003)
+CV_TYPE(LF_CLASS_16t, 0x0004)
+CV_TYPE(LF_STRUCTURE_16t, 0x0005)
+CV_TYPE(LF_UNION_16t, 0x0006)
+CV_TYPE(LF_ENUM_16t, 0x0007)
+CV_TYPE(LF_PROCEDURE_16t, 0x0008)
+CV_TYPE(LF_MFUNCTION_16t, 0x0009)
+CV_TYPE(LF_COBOL0_16t, 0x000b)
+CV_TYPE(LF_COBOL1, 0x000c)
+CV_TYPE(LF_BARRAY_16t, 0x000d)
+CV_TYPE(LF_LABEL, 0x000e)
+CV_TYPE(LF_NULLLEAF, 0x000f) // LF_NULL
+CV_TYPE(LF_NOTTRAN, 0x0010)
+CV_TYPE(LF_DIMARRAY_16t, 0x0011)
+CV_TYPE(LF_VFTPATH_16t, 0x0012)
+CV_TYPE(LF_PRECOMP_16t, 0x0013)
+CV_TYPE(LF_ENDPRECOMP, 0x0014)
+CV_TYPE(LF_OEM_16t, 0x0015)
+CV_TYPE(LF_TYPESERVER_ST, 0x0016)
+
+CV_TYPE(LF_SKIP_16t, 0x0200)
+CV_TYPE(LF_ARGLIST_16t, 0x0201)
+CV_TYPE(LF_DEFARG_16t, 0x0202)
+CV_TYPE(LF_LIST, 0x0203)
+CV_TYPE(LF_FIELDLIST_16t, 0x0204)
+CV_TYPE(LF_DERIVED_16t, 0x0205)
+CV_TYPE(LF_BITFIELD_16t, 0x0206)
+CV_TYPE(LF_METHODLIST_16t, 0x0207)
+CV_TYPE(LF_DIMCONU_16t, 0x0208)
+CV_TYPE(LF_DIMCONLU_16t, 0x0209)
+CV_TYPE(LF_DIMVARU_16t, 0x020a)
+CV_TYPE(LF_DIMVARLU_16t, 0x020b)
+CV_TYPE(LF_REFSYM, 0x020c)
+
+// 16 bit member types. Generally not length prefixed.
+CV_TYPE(LF_BCLASS_16t, 0x0400)
+CV_TYPE(LF_VBCLASS_16t, 0x0401)
+CV_TYPE(LF_IVBCLASS_16t, 0x0402)
+CV_TYPE(LF_ENUMERATE_ST, 0x0403)
+CV_TYPE(LF_FRIENDFCN_16t, 0x0404)
+CV_TYPE(LF_INDEX_16t, 0x0405)
+CV_TYPE(LF_MEMBER_16t, 0x0406)
+CV_TYPE(LF_STMEMBER_16t, 0x0407)
+CV_TYPE(LF_METHOD_16t, 0x0408)
+CV_TYPE(LF_NESTTYPE_16t, 0x0409)
+CV_TYPE(LF_VFUNCTAB_16t, 0x040a)
+CV_TYPE(LF_FRIENDCLS_16t, 0x040b)
+CV_TYPE(LF_ONEMETHOD_16t, 0x040c)
+CV_TYPE(LF_VFUNCOFF_16t, 0x040d)
+
+CV_TYPE(LF_TI16_MAX, 0x1000)
+
+CV_TYPE(LF_ARRAY_ST, 0x1003)
+CV_TYPE(LF_CLASS_ST, 0x1004)
+CV_TYPE(LF_STRUCTURE_ST, 0x1005)
+CV_TYPE(LF_UNION_ST, 0x1006)
+CV_TYPE(LF_ENUM_ST, 0x1007)
+CV_TYPE(LF_COBOL0, 0x100a)
+CV_TYPE(LF_BARRAY, 0x100b)
+CV_TYPE(LF_DIMARRAY_ST, 0x100c)
+CV_TYPE(LF_VFTPATH, 0x100d)
+CV_TYPE(LF_PRECOMP_ST, 0x100e)
+CV_TYPE(LF_OEM, 0x100f)
+CV_TYPE(LF_ALIAS_ST, 0x1010)
+CV_TYPE(LF_OEM2, 0x1011)
+
+CV_TYPE(LF_SKIP, 0x1200)
+CV_TYPE(LF_DEFARG_ST, 0x1202)
+CV_TYPE(LF_FIELDLIST, 0x1203)
+CV_TYPE(LF_DERIVED, 0x1204)
+CV_TYPE(LF_DIMCONU, 0x1207)
+CV_TYPE(LF_DIMCONLU, 0x1208)
+CV_TYPE(LF_DIMVARU, 0x1209)
+CV_TYPE(LF_DIMVARLU, 0x120a)
+
+// Member type records. These are generally not length prefixed, and appear
+// inside of a field list record.
+CV_TYPE(LF_FRIENDFCN_ST, 0x1403)
+CV_TYPE(LF_MEMBER_ST, 0x1405)
+CV_TYPE(LF_STMEMBER_ST, 0x1406)
+CV_TYPE(LF_METHOD_ST, 0x1407)
+CV_TYPE(LF_NESTTYPE_ST, 0x1408)
+CV_TYPE(LF_FRIENDCLS, 0x140a)
+CV_TYPE(LF_ONEMETHOD_ST, 0x140b)
+CV_TYPE(LF_VFUNCOFF, 0x140c)
+CV_TYPE(LF_NESTTYPEEX_ST, 0x140d)
+CV_TYPE(LF_MEMBERMODIFY_ST, 0x140e)
+CV_TYPE(LF_MANAGED_ST, 0x140f)
+
+CV_TYPE(LF_ST_MAX, 0x1500)
+CV_TYPE(LF_TYPESERVER, 0x1501)
+CV_TYPE(LF_DIMARRAY, 0x1508)
+CV_TYPE(LF_PRECOMP, 0x1509)
+CV_TYPE(LF_ALIAS, 0x150a)
+CV_TYPE(LF_DEFARG, 0x150b)
+CV_TYPE(LF_FRIENDFCN, 0x150c)
+CV_TYPE(LF_NESTTYPEEX, 0x1512)
+CV_TYPE(LF_MEMBERMODIFY, 0x1513)
+CV_TYPE(LF_MANAGED, 0x1514)
+CV_TYPE(LF_STRIDED_ARRAY, 0x1516)
+CV_TYPE(LF_HLSL, 0x1517)
+CV_TYPE(LF_MODIFIER_EX, 0x1518)
+CV_TYPE(LF_VECTOR, 0x151b)
+CV_TYPE(LF_MATRIX, 0x151c)
+
+// ID leaf records. Subsequent leaf types may be referenced from .debug$S.
+
+// Numeric leaf types. These are generally contained in other records, and not
+// encountered in the main type stream.
+
+CV_TYPE(LF_NUMERIC, 0x8000)
+CV_TYPE(LF_CHAR, 0x8000)
+CV_TYPE(LF_SHORT, 0x8001)
+CV_TYPE(LF_USHORT, 0x8002)
+CV_TYPE(LF_LONG, 0x8003)
+CV_TYPE(LF_ULONG, 0x8004)
+CV_TYPE(LF_REAL32, 0x8005)
+CV_TYPE(LF_REAL64, 0x8006)
+CV_TYPE(LF_REAL80, 0x8007)
+CV_TYPE(LF_REAL128, 0x8008)
+CV_TYPE(LF_QUADWORD, 0x8009)
+CV_TYPE(LF_UQUADWORD, 0x800a)
+CV_TYPE(LF_REAL48, 0x800b)
+CV_TYPE(LF_COMPLEX32, 0x800c)
+CV_TYPE(LF_COMPLEX64, 0x800d)
+CV_TYPE(LF_COMPLEX80, 0x800e)
+CV_TYPE(LF_COMPLEX128, 0x800f)
+CV_TYPE(LF_VARSTRING, 0x8010)
+CV_TYPE(LF_OCTWORD, 0x8017)
+CV_TYPE(LF_UOCTWORD, 0x8018)
+CV_TYPE(LF_DECIMAL, 0x8019)
+CV_TYPE(LF_DATE, 0x801a)
+CV_TYPE(LF_UTF8STRING, 0x801b)
+CV_TYPE(LF_REAL16, 0x801c)
+
+// Padding bytes. These are emitted into alignment bytes in the type stream.
+
+CV_TYPE(LF_PAD0, 0xf0)
+CV_TYPE(LF_PAD1, 0xf1)
+CV_TYPE(LF_PAD2, 0xf2)
+CV_TYPE(LF_PAD3, 0xf3)
+CV_TYPE(LF_PAD4, 0xf4)
+CV_TYPE(LF_PAD5, 0xf5)
+CV_TYPE(LF_PAD6, 0xf6)
+CV_TYPE(LF_PAD7, 0xf7)
+CV_TYPE(LF_PAD8, 0xf8)
+CV_TYPE(LF_PAD9, 0xf9)
+CV_TYPE(LF_PAD10, 0xfa)
+CV_TYPE(LF_PAD11, 0xfb)
+CV_TYPE(LF_PAD12, 0xfc)
+CV_TYPE(LF_PAD13, 0xfd)
+CV_TYPE(LF_PAD14, 0xfe)
+CV_TYPE(LF_PAD15, 0xff)
+
+#undef CV_TYPE
+#undef TYPE_RECORD
+#undef TYPE_RECORD_ALIAS
+#undef MEMBER_RECORD
+#undef MEMBER_RECORD_ALIAS
diff --git a/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h b/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
new file mode 100644
index 000000000000..af396c79d074
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
@@ -0,0 +1,26 @@
+//===- TypeStreamMerger.h ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPESTREAMMERGER_H
+#define LLVM_DEBUGINFO_CODEVIEW_TYPESTREAMMERGER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
+
+namespace llvm {
+namespace codeview {
+
+/// Merges one type stream into another. Returns true on success.
+bool mergeTypeStreams(TypeTableBuilder &DestStream, const CVTypeArray &Types);
+
+} // end namespace codeview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_CODEVIEW_TYPESTREAMMERGER_H
diff --git a/include/llvm/DebugInfo/CodeView/TypeSymbolEmitter.h b/include/llvm/DebugInfo/CodeView/TypeSymbolEmitter.h
index 9de110e8236f..dfba83d62fce 100644
--- a/include/llvm/DebugInfo/CodeView/TypeSymbolEmitter.h
+++ b/include/llvm/DebugInfo/CodeView/TypeSymbolEmitter.h
@@ -10,11 +10,12 @@
#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPESYMBOLEMITTER_H
#define LLVM_DEBUGINFO_CODEVIEW_TYPESYMBOLEMITTER_H
-#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
namespace llvm {
+class StringRef;
+
namespace codeview {
class TypeSymbolEmitter {
diff --git a/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h b/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h
index 2c950e8af792..5b2aa6186147 100644
--- a/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h
+++ b/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h
@@ -10,13 +10,15 @@
#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H
#define LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H
-#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/Support/Compiler.h"
namespace llvm {
+
+class StringRef;
+
namespace codeview {
class FieldListRecordBuilder;
@@ -38,20 +40,28 @@ public:
TypeIndex writeModifier(const ModifierRecord &Record);
TypeIndex writeProcedure(const ProcedureRecord &Record);
TypeIndex writeMemberFunction(const MemberFunctionRecord &Record);
- TypeIndex writeArgumentList(const ArgumentListRecord &Record);
- TypeIndex writeRecord(TypeRecordBuilder &builder);
+ TypeIndex writeArgList(const ArgListRecord &Record);
TypeIndex writePointer(const PointerRecord &Record);
- TypeIndex writePointerToMember(const PointerToMemberRecord &Record);
TypeIndex writeArray(const ArrayRecord &Record);
- TypeIndex writeAggregate(const AggregateRecord &Record);
+ TypeIndex writeClass(const ClassRecord &Record);
+ TypeIndex writeUnion(const UnionRecord &Record);
TypeIndex writeEnum(const EnumRecord &Record);
TypeIndex writeBitField(const BitFieldRecord &Record);
- TypeIndex writeVirtualTableShape(const VirtualTableShapeRecord &Record);
+ TypeIndex writeVFTableShape(const VFTableShapeRecord &Record);
+ TypeIndex writeStringId(const StringIdRecord &Record);
+ TypeIndex writeVFTable(const VFTableRecord &Record);
+ TypeIndex writeUdtSourceLine(const UdtSourceLineRecord &Record);
+ TypeIndex writeUdtModSourceLine(const UdtModSourceLineRecord &Record);
+ TypeIndex writeFuncId(const FuncIdRecord &Record);
+ TypeIndex writeMemberFuncId(const MemberFuncIdRecord &Record);
+ TypeIndex writeBuildInfo(const BuildInfoRecord &Record);
+ TypeIndex writeMethodOverloadList(const MethodOverloadListRecord &Record);
+ TypeIndex writeTypeServer2(const TypeServer2Record &Record);
TypeIndex writeFieldList(FieldListRecordBuilder &FieldList);
- TypeIndex writeMethodList(MethodListRecordBuilder &MethodList);
-private:
+ TypeIndex writeRecord(TypeRecordBuilder &builder);
+
virtual TypeIndex writeRecord(llvm::StringRef record) = 0;
};
}
diff --git a/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h b/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h
new file mode 100644
index 000000000000..310847ec5d2d
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h
@@ -0,0 +1,63 @@
+//===- TypeVisitorCallbacks.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPEVISITORCALLBACKS_H
+#define LLVM_DEBUGINFO_CODEVIEW_TYPEVISITORCALLBACKS_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/CVRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace codeview {
+class TypeVisitorCallbacks {
+ friend class CVTypeVisitor;
+
+public:
+ virtual ~TypeVisitorCallbacks() {}
+
+ /// Action to take on unknown types. By default, they are ignored.
+ virtual Error visitUnknownType(const CVRecord<TypeLeafKind> &Record) {
+ return Error::success();
+ }
+ virtual Error visitUnknownMember(const CVRecord<TypeLeafKind> &Record) {
+ return Error::success();
+ }
+
+ /// Paired begin/end actions for all types. Receives all record data,
+ /// including the fixed-length record prefix.
+ virtual Error visitTypeBegin(const CVRecord<TypeLeafKind> &Record) {
+ return Error::success();
+ }
+ virtual Error visitTypeEnd(const CVRecord<TypeLeafKind> &Record) {
+ return Error::success();
+ }
+
+ virtual Error visitFieldListBegin(const CVRecord<TypeLeafKind> &Record) {
+ return Error::success();
+ }
+
+ virtual Error visitFieldListEnd(const CVRecord<TypeLeafKind> &Record) {
+ return Error::success();
+ }
+
+#define TYPE_RECORD(EnumName, EnumVal, Name) \
+ virtual Error visit##Name(Name##Record &Record) { return Error::success(); }
+#define MEMBER_RECORD(EnumName, EnumVal, Name) \
+ TYPE_RECORD(EnumName, EnumVal, Name)
+#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#include "TypeRecords.def"
+};
+}
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/DIContext.h b/include/llvm/DebugInfo/DIContext.h
index 6659a97a042b..2f88371979ea 100644
--- a/include/llvm/DebugInfo/DIContext.h
+++ b/include/llvm/DebugInfo/DIContext.h
@@ -15,10 +15,8 @@
#ifndef LLVM_DEBUGINFO_DICONTEXT_H
#define LLVM_DEBUGINFO_DICONTEXT_H
-#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Object/ObjectFile.h"
-#include "llvm/Object/RelocVisitor.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/DataTypes.h"
#include <string>
@@ -140,7 +138,8 @@ public:
DIContext(DIContextKind K) : Kind(K) {}
virtual ~DIContext() {}
- virtual void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All) = 0;
+ virtual void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All,
+ bool DumpEH = false) = 0;
virtual DILineInfo getLineInfoForAddress(uint64_t Address,
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
diff --git a/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h b/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h
index bae3154b3b5f..bba3abe6e9e9 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h
@@ -19,10 +19,10 @@ public:
DWARFCompileUnit(DWARFContext &Context, const DWARFSection &Section,
const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS,
StringRef SOS, StringRef AOS, StringRef LS, bool LE,
- const DWARFUnitSectionBase &UnitSection,
+ bool IsDWO, const DWARFUnitSectionBase &UnitSection,
const DWARFUnitIndex::Entry *Entry)
- : DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LS, LE, UnitSection,
- Entry) {}
+ : DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LS, LE, IsDWO,
+ UnitSection, Entry) {}
void dump(raw_ostream &OS);
static const DWARFSectionKind Section = DW_SECT_INFO;
// VTable anchor.
diff --git a/include/llvm/DebugInfo/DWARF/DWARFContext.h b/include/llvm/DebugInfo/DWARF/DWARFContext.h
index c91012bc9a24..741a31cb582b 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFContext.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFContext.h
@@ -22,7 +22,6 @@
#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
#include "llvm/DebugInfo/DWARF/DWARFSection.h"
#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
-#include <vector>
namespace llvm {
@@ -40,7 +39,7 @@ typedef DenseMap<uint64_t, std::pair<uint8_t, int64_t> > RelocAddrMap;
class DWARFContext : public DIContext {
DWARFUnitSection<DWARFCompileUnit> CUs;
- std::vector<DWARFUnitSection<DWARFTypeUnit>> TUs;
+ std::deque<DWARFUnitSection<DWARFTypeUnit>> TUs;
std::unique_ptr<DWARFUnitIndex> CUIndex;
std::unique_ptr<DWARFUnitIndex> TUIndex;
std::unique_ptr<DWARFDebugAbbrev> Abbrev;
@@ -48,10 +47,11 @@ class DWARFContext : public DIContext {
std::unique_ptr<DWARFDebugAranges> Aranges;
std::unique_ptr<DWARFDebugLine> Line;
std::unique_ptr<DWARFDebugFrame> DebugFrame;
+ std::unique_ptr<DWARFDebugFrame> EHFrame;
std::unique_ptr<DWARFDebugMacro> Macro;
DWARFUnitSection<DWARFCompileUnit> DWOCUs;
- std::vector<DWARFUnitSection<DWARFTypeUnit>> DWOTUs;
+ std::deque<DWARFUnitSection<DWARFTypeUnit>> DWOTUs;
std::unique_ptr<DWARFDebugAbbrev> AbbrevDWO;
std::unique_ptr<DWARFDebugLocDWO> LocDWO;
@@ -81,11 +81,12 @@ public:
return DICtx->getKind() == CK_DWARF;
}
- void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All) override;
+ void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All,
+ bool DumpEH = false) override;
typedef DWARFUnitSection<DWARFCompileUnit>::iterator_range cu_iterator_range;
typedef DWARFUnitSection<DWARFTypeUnit>::iterator_range tu_iterator_range;
- typedef iterator_range<std::vector<DWARFUnitSection<DWARFTypeUnit>>::iterator> tu_section_iterator_range;
+ typedef iterator_range<decltype(TUs)::iterator> tu_section_iterator_range;
/// Get compile units in this context.
cu_iterator_range compile_units() {
@@ -168,6 +169,9 @@ public:
/// Get a pointer to the parsed frame information object.
const DWARFDebugFrame *getDebugFrame();
+ /// Get a pointer to the parsed eh frame information object.
+ const DWARFDebugFrame *getEHFrame();
+
/// Get a pointer to the parsed DebugMacro object.
const DWARFDebugMacro *getDebugMacro();
@@ -191,6 +195,7 @@ public:
virtual const DWARFSection &getLocSection() = 0;
virtual StringRef getARangeSection() = 0;
virtual StringRef getDebugFrameSection() = 0;
+ virtual StringRef getEHFrameSection() = 0;
virtual const DWARFSection &getLineSection() = 0;
virtual StringRef getStringSection() = 0;
virtual StringRef getRangeSection() = 0;
@@ -242,6 +247,7 @@ class DWARFContextInMemory : public DWARFContext {
DWARFSection LocSection;
StringRef ARangeSection;
StringRef DebugFrameSection;
+ StringRef EHFrameSection;
DWARFSection LineSection;
StringRef StringSection;
StringRef RangeSection;
@@ -281,6 +287,7 @@ public:
const DWARFSection &getLocSection() override { return LocSection; }
StringRef getARangeSection() override { return ARangeSection; }
StringRef getDebugFrameSection() override { return DebugFrameSection; }
+ StringRef getEHFrameSection() override { return EHFrameSection; }
const DWARFSection &getLineSection() override { return LineSection; }
StringRef getStringSection() override { return StringSection; }
StringRef getRangeSection() override { return RangeSection; }
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h b/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h
index 21142089da6b..67c4a2bb3e67 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h
@@ -11,7 +11,6 @@
#define LLVM_LIB_DEBUGINFO_DWARFDEBUGABBREV_H
#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
-#include <list>
#include <map>
#include <vector>
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h b/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
index be925cbe7519..cd76c909ddae 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
@@ -19,11 +19,13 @@ namespace llvm {
class FrameEntry;
-/// \brief A parsed .debug_frame section
+/// \brief A parsed .debug_frame or .eh_frame section
///
class DWARFDebugFrame {
+ // True if this is parsing an eh_frame section.
+ bool IsEH;
public:
- DWARFDebugFrame();
+ DWARFDebugFrame(bool IsEH);
~DWARFDebugFrame();
/// \brief Dump the section data into the given stream.
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h b/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h
index f7910962a03f..731c521b9edb 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h
@@ -11,7 +11,6 @@
#define LLVM_DEBUGINFO_DWARF_DWARFDEBUGMACRO_H
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/Dwarf.h"
diff --git a/include/llvm/DebugInfo/DWARF/DWARFFormValue.h b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
index 3c32a3e5b794..b2f750dd7945 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
@@ -10,12 +10,12 @@
#ifndef LLVM_DEBUGINFO_DWARFFORMVALUE_H
#define LLVM_DEBUGINFO_DWARFFORMVALUE_H
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Support/DataExtractor.h"
namespace llvm {
+template <typename T> class ArrayRef;
class DWARFUnit;
class raw_ostream;
diff --git a/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h b/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h
index 894a88dce440..a697edd32072 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h
@@ -21,11 +21,11 @@ private:
public:
DWARFTypeUnit(DWARFContext &Context, const DWARFSection &Section,
const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS,
- StringRef SOS, StringRef AOS, StringRef LS, bool LE,
+ StringRef SOS, StringRef AOS, StringRef LS, bool LE, bool IsDWO,
const DWARFUnitSectionBase &UnitSection,
const DWARFUnitIndex::Entry *Entry)
- : DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LS, LE, UnitSection,
- Entry) {}
+ : DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LS, LE, IsDWO,
+ UnitSection, Entry) {}
uint32_t getHeaderSize() const override {
return DWARFUnit::getHeaderSize() + 12;
}
diff --git a/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/include/llvm/DebugInfo/DWARF/DWARFUnit.h
index 681b2aa19a79..9c3fe3be6aa6 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFUnit.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFUnit.h
@@ -47,7 +47,7 @@ protected:
virtual void parseImpl(DWARFContext &Context, const DWARFSection &Section,
const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS,
StringRef SOS, StringRef AOS, StringRef LS,
- bool isLittleEndian) = 0;
+ bool isLittleEndian, bool isDWO) = 0;
~DWARFUnitSectionBase() = default;
};
@@ -59,13 +59,9 @@ const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context,
template<typename UnitType>
class DWARFUnitSection final : public SmallVector<std::unique_ptr<UnitType>, 1>,
public DWARFUnitSectionBase {
- bool Parsed;
+ bool Parsed = false;
public:
- DWARFUnitSection() : Parsed(false) {}
- DWARFUnitSection(DWARFUnitSection &&DUS) :
- SmallVector<std::unique_ptr<UnitType>, 1>(std::move(DUS)), Parsed(DUS.Parsed) {}
-
typedef llvm::SmallVectorImpl<std::unique_ptr<UnitType>> UnitVector;
typedef typename UnitVector::iterator iterator;
typedef llvm::iterator_range<typename UnitVector::iterator> iterator_range;
@@ -84,7 +80,8 @@ public:
private:
void parseImpl(DWARFContext &Context, const DWARFSection &Section,
const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS,
- StringRef SOS, StringRef AOS, StringRef LS, bool LE) override {
+ StringRef SOS, StringRef AOS, StringRef LS, bool LE,
+ bool IsDWO) override {
if (Parsed)
return;
const auto &Index = getDWARFUnitIndex(Context, UnitType::Section);
@@ -92,7 +89,7 @@ private:
uint32_t Offset = 0;
while (Data.isValidOffset(Offset)) {
auto U = llvm::make_unique<UnitType>(Context, Section, DA, RS, SS, SOS,
- AOS, LS, LE, *this,
+ AOS, LS, LE, IsDWO, *this,
Index.getFromOffset(Offset));
if (!U->extract(Data, &Offset))
break;
@@ -117,6 +114,7 @@ class DWARFUnit {
StringRef AddrOffsetSection;
uint32_t AddrOffsetSectionBase;
bool isLittleEndian;
+ bool isDWO;
const DWARFUnitSectionBase &UnitSection;
uint32_t Offset;
@@ -148,7 +146,7 @@ protected:
public:
DWARFUnit(DWARFContext &Context, const DWARFSection &Section,
const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS,
- StringRef SOS, StringRef AOS, StringRef LS, bool LE,
+ StringRef SOS, StringRef AOS, StringRef LS, bool LE, bool IsDWO,
const DWARFUnitSectionBase &UnitSection,
const DWARFUnitIndex::Entry *IndexEntry = nullptr);
@@ -249,7 +247,7 @@ public:
/// \brief Return the DIE object for a given offset inside the
/// unit's DIE vector.
///
- /// The unit needs to have his DIEs extracted for this method to work.
+ /// The unit needs to have its DIEs extracted for this method to work.
const DWARFDebugInfoEntryMinimal *getDIEForOffset(uint32_t Offset) const {
assert(!DieArray.empty());
auto it = std::lower_bound(
diff --git a/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h b/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h
index a85c2f9f0a23..9f051cd7081c 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h
@@ -10,6 +10,7 @@
#ifndef LLVM_LIB_DEBUGINFO_DWARFUNITINDEX_H
#define LLVM_LIB_DEBUGINFO_DWARFUNITINDEX_H
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
@@ -56,6 +57,10 @@ public:
public:
const SectionContribution *getOffset(DWARFSectionKind Sec) const;
const SectionContribution *getOffset() const;
+ const SectionContribution *getOffsets() const {
+ return Contributions.get();
+ }
+ uint64_t getSignature() const { return Signature; }
};
private:
@@ -75,6 +80,12 @@ public:
: InfoColumnKind(InfoColumnKind) {}
void dump(raw_ostream &OS) const;
const Entry *getFromOffset(uint32_t Offset) const;
+ ArrayRef<DWARFSectionKind> getColumnKinds() const {
+ return makeArrayRef(ColumnKinds.get(), Header.NumColumns);
+ }
+ ArrayRef<Entry> getRows() const {
+ return makeArrayRef(Rows.get(), Header.NumBuckets);
+ }
};
}
diff --git a/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h b/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h
index b5fa8c33414d..50f5c40bcac9 100644
--- a/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h
+++ b/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h
@@ -15,6 +15,7 @@
#include <memory>
namespace llvm {
+namespace pdb {
template <typename ChildType>
class ConcreteSymbolEnumerator : public IPDBEnumChildren<ChildType> {
@@ -55,5 +56,6 @@ private:
std::unique_ptr<IPDBEnumSymbols> Enumerator;
};
}
+}
#endif
diff --git a/include/llvm/DebugInfo/PDB/DIA/DIADataStream.h b/include/llvm/DebugInfo/PDB/DIA/DIADataStream.h
index 7b2bc146b32d..930bea6060b2 100644
--- a/include/llvm/DebugInfo/PDB/DIA/DIADataStream.h
+++ b/include/llvm/DebugInfo/PDB/DIA/DIADataStream.h
@@ -14,6 +14,7 @@
#include "llvm/DebugInfo/PDB/IPDBDataStream.h"
namespace llvm {
+namespace pdb {
class DIADataStream : public IPDBDataStream {
public:
explicit DIADataStream(CComPtr<IDiaEnumDebugStreamData> DiaStreamData);
@@ -29,5 +30,6 @@ private:
CComPtr<IDiaEnumDebugStreamData> StreamData;
};
}
+}
#endif
diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h b/include/llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h
index 375bcdd7e3bd..941e16a35fac 100644
--- a/include/llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h
+++ b/include/llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h
@@ -14,6 +14,7 @@
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
namespace llvm {
+namespace pdb {
class IPDBDataStream;
@@ -31,5 +32,6 @@ private:
CComPtr<IDiaEnumDebugStreams> Enumerator;
};
}
+}
#endif
diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h b/include/llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h
index 4cc85eda477f..106b84cecfff 100644
--- a/include/llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h
+++ b/include/llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h
@@ -14,7 +14,7 @@
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
namespace llvm {
-
+namespace pdb {
class IPDBLineNumber;
class DIAEnumLineNumbers : public IPDBEnumChildren<IPDBLineNumber> {
@@ -31,5 +31,6 @@ private:
CComPtr<IDiaEnumLineNumbers> Enumerator;
};
}
+}
#endif
diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h b/include/llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h
index 88625f64e49e..6c00d6a5e29d 100644
--- a/include/llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h
+++ b/include/llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h
@@ -14,7 +14,7 @@
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
namespace llvm {
-
+namespace pdb {
class DIASession;
class DIAEnumSourceFiles : public IPDBEnumChildren<IPDBSourceFile> {
@@ -33,5 +33,6 @@ private:
CComPtr<IDiaEnumSourceFiles> Enumerator;
};
}
+}
#endif
diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h b/include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h
index fe343f778aad..b206ff59a6a4 100644
--- a/include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h
+++ b/include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h
@@ -14,7 +14,7 @@
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
namespace llvm {
-
+namespace pdb {
class DIASession;
class DIAEnumSymbols : public IPDBEnumChildren<PDBSymbol> {
@@ -33,5 +33,6 @@ private:
CComPtr<IDiaEnumSymbols> Enumerator;
};
}
+}
#endif
diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAError.h b/include/llvm/DebugInfo/PDB/DIA/DIAError.h
new file mode 100644
index 000000000000..f198d07e99d4
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/DIA/DIAError.h
@@ -0,0 +1,46 @@
+//===- DIAError.h - Error extensions for PDB DIA implementation -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_DIA_DIAERROR_H
+#define LLVM_DEBUGINFO_PDB_DIA_DIAERROR_H
+
+#include "llvm/Support/Error.h"
+
+#include <string>
+
+namespace llvm {
+namespace pdb {
+enum class dia_error_code {
+ unspecified = 1,
+ could_not_create_impl,
+ invalid_file_format,
+ invalid_parameter,
+ already_loaded,
+ debug_info_mismatch,
+};
+
+/// Base class for errors originating in DIA SDK, e.g. COM calls
+class DIAError : public ErrorInfo<DIAError> {
+public:
+ static char ID;
+ DIAError(dia_error_code C);
+ DIAError(const std::string &Context);
+ DIAError(dia_error_code C, const std::string &Context);
+
+ void log(raw_ostream &OS) const override;
+ const std::string &getErrorMessage() const;
+ std::error_code convertToErrorCode() const override;
+
+private:
+ std::string ErrMsg;
+ dia_error_code Code;
+};
+}
+}
+#endif
diff --git a/include/llvm/DebugInfo/PDB/DIA/DIALineNumber.h b/include/llvm/DebugInfo/PDB/DIA/DIALineNumber.h
index 5950a0d3835f..a59e3a19c8c2 100644
--- a/include/llvm/DebugInfo/PDB/DIA/DIALineNumber.h
+++ b/include/llvm/DebugInfo/PDB/DIA/DIALineNumber.h
@@ -14,6 +14,7 @@
#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
namespace llvm {
+namespace pdb {
class DIALineNumber : public IPDBLineNumber {
public:
explicit DIALineNumber(CComPtr<IDiaLineNumber> DiaLineNumber);
@@ -35,5 +36,5 @@ private:
CComPtr<IDiaLineNumber> LineNumber;
};
}
-
+}
#endif
diff --git a/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h b/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h
index 9308b8e82657..1e40c46f8a27 100644
--- a/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h
+++ b/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h
@@ -14,6 +14,7 @@
#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
namespace llvm {
+namespace pdb {
class DIASession;
class DIARawSymbol : public IPDBRawSymbol {
public:
@@ -58,7 +59,7 @@ public:
uint32_t getLiveRangeStartAddressOffset() const override;
uint32_t getLiveRangeStartAddressSection() const override;
uint32_t getLiveRangeStartRelativeVirtualAddress() const override;
- PDB_RegisterId getLocalBasePointerRegisterId() const override;
+ codeview::RegisterId getLocalBasePointerRegisterId() const override;
uint32_t getLowerBoundId() const override;
uint32_t getMemorySpaceKind() const override;
std::string getName() const override;
@@ -73,7 +74,7 @@ public:
uint32_t getOffsetInUdt() const override;
PDB_Cpu getPlatform() const override;
uint32_t getRank() const override;
- PDB_RegisterId getRegisterId() const override;
+ codeview::RegisterId getRegisterId() const override;
uint32_t getRegisterType() const override;
uint32_t getRelativeVirtualAddress() const override;
uint32_t getSamplerSlot() const override;
@@ -109,7 +110,7 @@ public:
int32_t getVirtualBasePointerOffset() const override;
PDB_LocType getLocationType() const override;
PDB_Machine getMachineType() const override;
- PDB_ThunkOrdinal getThunkOrdinal() const override;
+ codeview::ThunkOrdinal getThunkOrdinal() const override;
uint64_t getLength() const override;
uint64_t getLiveRangeLength() const override;
uint64_t getVirtualAddress() const override;
@@ -202,5 +203,6 @@ private:
CComPtr<IDiaSymbol> Symbol;
};
}
+}
#endif
diff --git a/include/llvm/DebugInfo/PDB/DIA/DIASession.h b/include/llvm/DebugInfo/PDB/DIA/DIASession.h
index 9a8600fb85ec..3f5818631e7b 100644
--- a/include/llvm/DebugInfo/PDB/DIA/DIASession.h
+++ b/include/llvm/DebugInfo/PDB/DIA/DIASession.h
@@ -11,18 +11,23 @@
#define LLVM_DEBUGINFO_PDB_DIA_DIASESSION_H
#include "DIASupport.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/Support/Error.h"
+
+#include <system_error>
namespace llvm {
+class StringRef;
+
+namespace pdb {
class DIASession : public IPDBSession {
public:
explicit DIASession(CComPtr<IDiaSession> DiaSession);
- static PDB_ErrorCode createFromPdb(StringRef Path,
- std::unique_ptr<IPDBSession> &Session);
- static PDB_ErrorCode createFromExe(StringRef Path,
- std::unique_ptr<IPDBSession> &Session);
+ static Error createFromPdb(StringRef Path,
+ std::unique_ptr<IPDBSession> &Session);
+ static Error createFromExe(StringRef Path,
+ std::unique_ptr<IPDBSession> &Session);
uint64_t getLoadAddress() const override;
void setLoadAddress(uint64_t Address) override;
@@ -33,8 +38,24 @@ public:
findSymbolByAddress(uint64_t Address, PDB_SymType Type) const override;
std::unique_ptr<IPDBEnumLineNumbers>
+ findLineNumbers(const PDBSymbolCompiland &Compiland,
+ const IPDBSourceFile &File) const override;
+ std::unique_ptr<IPDBEnumLineNumbers>
findLineNumbersByAddress(uint64_t Address, uint32_t Length) const override;
+ std::unique_ptr<IPDBEnumSourceFiles>
+ findSourceFiles(const PDBSymbolCompiland *Compiland, llvm::StringRef Pattern,
+ PDB_NameSearchFlags Flags) const override;
+ std::unique_ptr<IPDBSourceFile>
+ findOneSourceFile(const PDBSymbolCompiland *Compiland,
+ llvm::StringRef Pattern,
+ PDB_NameSearchFlags Flags) const override;
+ std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>>
+ findCompilandsForSourceFile(llvm::StringRef Pattern,
+ PDB_NameSearchFlags Flags) const override;
+ std::unique_ptr<PDBSymbolCompiland>
+ findOneCompilandForSourceFile(llvm::StringRef Pattern,
+ PDB_NameSearchFlags Flags) const override;
std::unique_ptr<IPDBEnumSourceFiles> getAllSourceFiles() const override;
std::unique_ptr<IPDBEnumSourceFiles> getSourceFilesForCompiland(
const PDBSymbolCompiland &Compiland) const override;
@@ -47,5 +68,5 @@ private:
CComPtr<IDiaSession> Session;
};
}
-
+}
#endif
diff --git a/include/llvm/DebugInfo/PDB/DIA/DIASourceFile.h b/include/llvm/DebugInfo/PDB/DIA/DIASourceFile.h
index c424e27493c1..1088ea54981c 100644
--- a/include/llvm/DebugInfo/PDB/DIA/DIASourceFile.h
+++ b/include/llvm/DebugInfo/PDB/DIA/DIASourceFile.h
@@ -14,6 +14,7 @@
#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
namespace llvm {
+namespace pdb {
class DIASession;
class DIASourceFile : public IPDBSourceFile {
@@ -25,12 +26,16 @@ public:
uint32_t getUniqueId() const override;
std::string getChecksum() const override;
PDB_Checksum getChecksumType() const override;
- std::unique_ptr<IPDBEnumSymbols> getCompilands() const override;
+ std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>>
+ getCompilands() const override;
+
+ CComPtr<IDiaSourceFile> getDiaFile() const { return SourceFile; }
private:
const DIASession &Session;
CComPtr<IDiaSourceFile> SourceFile;
};
}
+}
#endif
diff --git a/include/llvm/DebugInfo/PDB/DIA/DIASupport.h b/include/llvm/DebugInfo/PDB/DIA/DIASupport.h
index 407a34551cc7..3b4a348289df 100644
--- a/include/llvm/DebugInfo/PDB/DIA/DIASupport.h
+++ b/include/llvm/DebugInfo/PDB/DIA/DIASupport.h
@@ -22,6 +22,14 @@
#define NOMINMAX
#endif
+// llvm/Support/Debug.h unconditionally #defines DEBUG as a macro.
+// DIA headers #define it if it is not already defined, so we have
+// an order of includes problem. The real fix is to make LLVM use
+// something less generic than DEBUG, such as LLVM_DEBUG(), but it's
+// fairly prevalent. So for now, we save the definition state and
+// restore it.
+#pragma push_macro("DEBUG")
+
// atlbase.h has to come before windows.h
#include <atlbase.h>
#include <windows.h>
@@ -29,5 +37,8 @@
// DIA headers must come after windows headers.
#include <cvconst.h>
#include <dia2.h>
+#include <diacreate.h>
+
+#pragma pop_macro("DEBUG")
#endif // LLVM_DEBUGINFO_PDB_DIA_DIASUPPORT_H
diff --git a/include/llvm/DebugInfo/PDB/GenericError.h b/include/llvm/DebugInfo/PDB/GenericError.h
new file mode 100644
index 000000000000..959c26161044
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/GenericError.h
@@ -0,0 +1,42 @@
+//===- Error.h - system_error extensions for PDB ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_ERROR_H
+#define LLVM_DEBUGINFO_PDB_ERROR_H
+
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace pdb {
+
+enum class generic_error_code {
+ invalid_path = 1,
+ dia_sdk_not_present,
+ unspecified,
+};
+
+/// Base class for errors originating when parsing raw PDB files
+class GenericError : public ErrorInfo<GenericError> {
+public:
+ static char ID;
+ GenericError(generic_error_code C);
+ GenericError(const std::string &Context);
+ GenericError(generic_error_code C, const std::string &Context);
+
+ void log(raw_ostream &OS) const override;
+ const std::string &getErrorMessage() const;
+ std::error_code convertToErrorCode() const override;
+
+private:
+ std::string ErrMsg;
+ generic_error_code Code;
+};
+}
+}
+#endif
diff --git a/include/llvm/DebugInfo/PDB/IPDBDataStream.h b/include/llvm/DebugInfo/PDB/IPDBDataStream.h
index 808a0f3ec3a9..9594dc1591a7 100644
--- a/include/llvm/DebugInfo/PDB/IPDBDataStream.h
+++ b/include/llvm/DebugInfo/PDB/IPDBDataStream.h
@@ -15,6 +15,7 @@
#include "llvm/ADT/SmallVector.h"
namespace llvm {
+namespace pdb {
/// IPDBDataStream defines an interface used to represent a stream consisting
/// of a name and a series of records whose formats depend on the particular
@@ -33,5 +34,6 @@ public:
virtual IPDBDataStream *clone() const = 0;
};
}
+}
#endif
diff --git a/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h b/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h
index 645ac96e23a5..8e9f6f883679 100644
--- a/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h
+++ b/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h
@@ -14,6 +14,7 @@
#include <memory>
namespace llvm {
+namespace pdb {
template <typename ChildType> class IPDBEnumChildren {
public:
@@ -29,5 +30,6 @@ public:
virtual MyType *clone() const = 0;
};
}
+}
#endif
diff --git a/include/llvm/DebugInfo/PDB/IPDBLineNumber.h b/include/llvm/DebugInfo/PDB/IPDBLineNumber.h
index 92cd58d86649..e20080f2fbfc 100644
--- a/include/llvm/DebugInfo/PDB/IPDBLineNumber.h
+++ b/include/llvm/DebugInfo/PDB/IPDBLineNumber.h
@@ -13,7 +13,7 @@
#include "PDBTypes.h"
namespace llvm {
-
+namespace pdb {
class IPDBLineNumber {
public:
virtual ~IPDBLineNumber();
@@ -32,5 +32,6 @@ public:
virtual bool isStatement() const = 0;
};
}
+}
#endif
diff --git a/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h b/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h
index 139bff56fd5d..49866b8bb2f2 100644
--- a/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h
+++ b/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h
@@ -13,12 +13,14 @@
#include "PDBTypes.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
#include <memory>
namespace llvm {
-
class raw_ostream;
+namespace pdb {
+
/// IPDBRawSymbol defines an interface used to represent an arbitrary symbol.
/// It exposes a monolithic interface consisting of accessors for the union of
/// all properties that are valid for any symbol type. This interface is then
@@ -66,7 +68,7 @@ public:
virtual uint32_t getLiveRangeStartAddressOffset() const = 0;
virtual uint32_t getLiveRangeStartAddressSection() const = 0;
virtual uint32_t getLiveRangeStartRelativeVirtualAddress() const = 0;
- virtual PDB_RegisterId getLocalBasePointerRegisterId() const = 0;
+ virtual codeview::RegisterId getLocalBasePointerRegisterId() const = 0;
virtual uint32_t getLowerBoundId() const = 0;
virtual uint32_t getMemorySpaceKind() const = 0;
virtual std::string getName() const = 0;
@@ -81,7 +83,7 @@ public:
virtual uint32_t getOffsetInUdt() const = 0;
virtual PDB_Cpu getPlatform() const = 0;
virtual uint32_t getRank() const = 0;
- virtual PDB_RegisterId getRegisterId() const = 0;
+ virtual codeview::RegisterId getRegisterId() const = 0;
virtual uint32_t getRegisterType() const = 0;
virtual uint32_t getRelativeVirtualAddress() const = 0;
virtual uint32_t getSamplerSlot() const = 0;
@@ -117,7 +119,7 @@ public:
virtual int32_t getVirtualBasePointerOffset() const = 0;
virtual PDB_LocType getLocationType() const = 0;
virtual PDB_Machine getMachineType() const = 0;
- virtual PDB_ThunkOrdinal getThunkOrdinal() const = 0;
+ virtual codeview::ThunkOrdinal getThunkOrdinal() const = 0;
virtual uint64_t getLength() const = 0;
virtual uint64_t getLiveRangeLength() const = 0;
virtual uint64_t getVirtualAddress() const = 0;
@@ -206,6 +208,7 @@ public:
virtual std::string getUnused() const = 0;
};
+} // namespace pdb
} // namespace llvm
#endif
diff --git a/include/llvm/DebugInfo/PDB/IPDBSession.h b/include/llvm/DebugInfo/PDB/IPDBSession.h
index a130a38a6538..3d2c37eff2e3 100644
--- a/include/llvm/DebugInfo/PDB/IPDBSession.h
+++ b/include/llvm/DebugInfo/PDB/IPDBSession.h
@@ -11,11 +11,12 @@
#define LLVM_DEBUGINFO_PDB_IPDBSESSION_H
#include "PDBTypes.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
#include <memory>
namespace llvm {
-
+namespace pdb {
class PDBSymbolCompiland;
class PDBSymbolExe;
@@ -45,9 +46,27 @@ public:
virtual std::unique_ptr<PDBSymbol>
findSymbolByAddress(uint64_t Address, PDB_SymType Type) const = 0;
+
+ virtual std::unique_ptr<IPDBEnumLineNumbers>
+ findLineNumbers(const PDBSymbolCompiland &Compiland,
+ const IPDBSourceFile &File) const = 0;
virtual std::unique_ptr<IPDBEnumLineNumbers>
findLineNumbersByAddress(uint64_t Address, uint32_t Length) const = 0;
+ virtual std::unique_ptr<IPDBEnumSourceFiles>
+ findSourceFiles(const PDBSymbolCompiland *Compiland, llvm::StringRef Pattern,
+ PDB_NameSearchFlags Flags) const = 0;
+ virtual std::unique_ptr<IPDBSourceFile>
+ findOneSourceFile(const PDBSymbolCompiland *Compiland,
+ llvm::StringRef Pattern,
+ PDB_NameSearchFlags Flags) const = 0;
+ virtual std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>>
+ findCompilandsForSourceFile(llvm::StringRef Pattern,
+ PDB_NameSearchFlags Flags) const = 0;
+ virtual std::unique_ptr<PDBSymbolCompiland>
+ findOneCompilandForSourceFile(llvm::StringRef Pattern,
+ PDB_NameSearchFlags Flags) const = 0;
+
virtual std::unique_ptr<IPDBEnumSourceFiles> getAllSourceFiles() const = 0;
virtual std::unique_ptr<IPDBEnumSourceFiles>
getSourceFilesForCompiland(const PDBSymbolCompiland &Compiland) const = 0;
@@ -57,5 +76,6 @@ public:
virtual std::unique_ptr<IPDBEnumDataStreams> getDebugStreams() const = 0;
};
}
+}
#endif
diff --git a/include/llvm/DebugInfo/PDB/IPDBSourceFile.h b/include/llvm/DebugInfo/PDB/IPDBSourceFile.h
index 55000eff02f0..3676c4030b13 100644
--- a/include/llvm/DebugInfo/PDB/IPDBSourceFile.h
+++ b/include/llvm/DebugInfo/PDB/IPDBSourceFile.h
@@ -15,9 +15,10 @@
#include <string>
namespace llvm {
-
class raw_ostream;
+namespace pdb {
+
/// IPDBSourceFile defines an interface used to represent source files whose
/// information are stored in the PDB.
class IPDBSourceFile {
@@ -30,8 +31,10 @@ public:
virtual uint32_t getUniqueId() const = 0;
virtual std::string getChecksum() const = 0;
virtual PDB_Checksum getChecksumType() const = 0;
- virtual std::unique_ptr<IPDBEnumSymbols> getCompilands() const = 0;
+ virtual std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>>
+ getCompilands() const = 0;
};
}
+}
#endif
diff --git a/include/llvm/DebugInfo/PDB/PDB.h b/include/llvm/DebugInfo/PDB/PDB.h
index 5df3be85e381..1f5a066b9a1b 100644
--- a/include/llvm/DebugInfo/PDB/PDB.h
+++ b/include/llvm/DebugInfo/PDB/PDB.h
@@ -11,16 +11,20 @@
#define LLVM_DEBUGINFO_PDB_PDB_H
#include "PDBTypes.h"
+#include "llvm/Support/Error.h"
#include <memory>
+#include <system_error>
namespace llvm {
class StringRef;
-PDB_ErrorCode loadDataForPDB(PDB_ReaderType Type, StringRef Path,
- std::unique_ptr<IPDBSession> &Session);
+namespace pdb {
-PDB_ErrorCode loadDataForEXE(PDB_ReaderType Type, StringRef Path,
- std::unique_ptr<IPDBSession> &Session);
-}
+Error loadDataForPDB(PDB_ReaderType Type, StringRef Path,
+ std::unique_ptr<IPDBSession> &Session);
+Error loadDataForEXE(PDB_ReaderType Type, StringRef Path,
+ std::unique_ptr<IPDBSession> &Session);
+}
+}
#endif
diff --git a/include/llvm/DebugInfo/PDB/PDBContext.h b/include/llvm/DebugInfo/PDB/PDBContext.h
index 9404a5922449..836e39248438 100644
--- a/include/llvm/DebugInfo/PDB/PDBContext.h
+++ b/include/llvm/DebugInfo/PDB/PDBContext.h
@@ -17,43 +17,46 @@ namespace llvm {
namespace object {
class COFFObjectFile;
-}
-
-/// PDBContext
-/// This data structure is the top level entity that deals with PDB debug
-/// information parsing. This data structure exists only when there is a
-/// need for a transparent interface to different debug information formats
-/// (e.g. PDB and DWARF). More control and power over the debug information
-/// access can be had by using the PDB interfaces directly.
-class PDBContext : public DIContext {
-
- PDBContext(PDBContext &) = delete;
- PDBContext &operator=(PDBContext &) = delete;
-
-public:
- PDBContext(const object::COFFObjectFile &Object,
- std::unique_ptr<IPDBSession> PDBSession);
-
- static bool classof(const DIContext *DICtx) {
- return DICtx->getKind() == CK_PDB;
}
- void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All) override;
-
- DILineInfo getLineInfoForAddress(
- uint64_t Address,
- DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
- DILineInfoTable getLineInfoForAddressRange(
- uint64_t Address, uint64_t Size,
- DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
- DIInliningInfo getInliningInfoForAddress(
- uint64_t Address,
- DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
-
-private:
- std::string getFunctionName(uint64_t Address, DINameKind NameKind) const;
- std::unique_ptr<IPDBSession> Session;
-};
+ namespace pdb {
+ /// PDBContext
+ /// This data structure is the top level entity that deals with PDB debug
+ /// information parsing. This data structure exists only when there is a
+ /// need for a transparent interface to different debug information formats
+ /// (e.g. PDB and DWARF). More control and power over the debug information
+ /// access can be had by using the PDB interfaces directly.
+ class PDBContext : public DIContext {
+
+ PDBContext(PDBContext &) = delete;
+ PDBContext &operator=(PDBContext &) = delete;
+
+ public:
+ PDBContext(const object::COFFObjectFile &Object,
+ std::unique_ptr<IPDBSession> PDBSession);
+
+ static bool classof(const DIContext *DICtx) {
+ return DICtx->getKind() == CK_PDB;
+ }
+
+ void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All,
+ bool DumpEH = false) override;
+
+ DILineInfo getLineInfoForAddress(
+ uint64_t Address,
+ DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
+ DILineInfoTable getLineInfoForAddressRange(
+ uint64_t Address, uint64_t Size,
+ DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
+ DIInliningInfo getInliningInfoForAddress(
+ uint64_t Address,
+ DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
+
+ private:
+ std::string getFunctionName(uint64_t Address, DINameKind NameKind) const;
+ std::unique_ptr<IPDBSession> Session;
+ };
+ }
}
#endif
diff --git a/include/llvm/DebugInfo/PDB/PDBExtras.h b/include/llvm/DebugInfo/PDB/PDBExtras.h
index 48ce1c127196..5a7422d9e9e4 100644
--- a/include/llvm/DebugInfo/PDB/PDBExtras.h
+++ b/include/llvm/DebugInfo/PDB/PDBExtras.h
@@ -11,28 +11,33 @@
#define LLVM_DEBUGINFO_PDB_PDBEXTRAS_H
#include "PDBTypes.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/Support/raw_ostream.h"
#include <unordered_map>
namespace llvm {
+
+namespace pdb {
typedef std::unordered_map<PDB_SymType, int> TagStats;
raw_ostream &operator<<(raw_ostream &OS, const PDB_VariantType &Value);
raw_ostream &operator<<(raw_ostream &OS, const PDB_CallingConv &Conv);
raw_ostream &operator<<(raw_ostream &OS, const PDB_DataKind &Data);
-raw_ostream &operator<<(raw_ostream &OS, const PDB_RegisterId &Reg);
+raw_ostream &operator<<(raw_ostream &OS, const codeview::RegisterId &Reg);
raw_ostream &operator<<(raw_ostream &OS, const PDB_LocType &Loc);
-raw_ostream &operator<<(raw_ostream &OS, const PDB_ThunkOrdinal &Thunk);
+raw_ostream &operator<<(raw_ostream &OS, const codeview::ThunkOrdinal &Thunk);
raw_ostream &operator<<(raw_ostream &OS, const PDB_Checksum &Checksum);
raw_ostream &operator<<(raw_ostream &OS, const PDB_Lang &Lang);
raw_ostream &operator<<(raw_ostream &OS, const PDB_SymType &Tag);
raw_ostream &operator<<(raw_ostream &OS, const PDB_MemberAccess &Access);
raw_ostream &operator<<(raw_ostream &OS, const PDB_UdtType &Type);
raw_ostream &operator<<(raw_ostream &OS, const PDB_UniqueId &Id);
+raw_ostream &operator<<(raw_ostream &OS, const PDB_Machine &Machine);
raw_ostream &operator<<(raw_ostream &OS, const Variant &Value);
raw_ostream &operator<<(raw_ostream &OS, const VersionInfo &Version);
raw_ostream &operator<<(raw_ostream &OS, const TagStats &Stats);
}
+}
#endif
diff --git a/include/llvm/DebugInfo/PDB/PDBSymDumper.h b/include/llvm/DebugInfo/PDB/PDBSymDumper.h
index 65110f39366f..095c33cfe8b5 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymDumper.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymDumper.h
@@ -15,6 +15,7 @@
namespace llvm {
class raw_ostream;
+namespace pdb {
class PDBSymDumper {
public:
@@ -57,5 +58,6 @@ private:
bool RequireImpl;
};
}
+}
#endif
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbol.h b/include/llvm/DebugInfo/PDB/PDBSymbol.h
index 4360c5431e69..bf5118806540 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbol.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbol.h
@@ -15,9 +15,7 @@
#include "PDBExtras.h"
#include "PDBTypes.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
-#include <unordered_map>
#define FORWARD_SYMBOL_METHOD(MethodName) \
auto MethodName() const->decltype(RawSymbol->MethodName()) { \
@@ -26,9 +24,12 @@
namespace llvm {
-class IPDBRawSymbol;
+class StringRef;
class raw_ostream;
+namespace pdb {
+class IPDBRawSymbol;
+
#define DECLARE_PDB_SYMBOL_CONCRETE_TYPE(TagValue) \
static const PDB_SymType Tag = TagValue; \
static bool classof(const PDBSymbol *S) { return S->getSymTag() == Tag; }
@@ -41,7 +42,8 @@ class raw_ostream;
/// https://msdn.microsoft.com/en-us/library/370hs6k4.aspx
class PDBSymbol {
protected:
- PDBSymbol(const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol);
+ PDBSymbol(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> Symbol);
public:
static std::unique_ptr<PDBSymbol>
@@ -57,6 +59,7 @@ public:
void defaultDump(raw_ostream &OS, int Indent) const;
PDB_SymType getSymTag() const;
+ uint32_t getSymIndexId() const;
template <typename T> std::unique_ptr<T> findOneChild() const {
auto Enumerator(findAllChildren<T>());
@@ -93,5 +96,6 @@ protected:
};
} // namespace llvm
+}
#endif
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h b/include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h
index c055dd7f3d49..3169146e5b12 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h
@@ -11,11 +11,11 @@
#include "PDBSymbol.h"
#include "PDBTypes.h"
-#include <string>
namespace llvm {
class raw_ostream;
+namespace pdb {
class PDBSymbolAnnotation : public PDBSymbol {
public:
@@ -30,10 +30,10 @@ public:
FORWARD_SYMBOL_METHOD(getAddressSection)
FORWARD_SYMBOL_METHOD(getDataKind)
FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress)
- FORWARD_SYMBOL_METHOD(getSymIndexId)
// FORWARD_SYMBOL_METHOD(getValue)
FORWARD_SYMBOL_METHOD(getVirtualAddress)
};
}
+}
#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLANNOTATION_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolBlock.h b/include/llvm/DebugInfo/PDB/PDBSymbolBlock.h
index 2ca12501d9f6..d0ff62ca7c3f 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolBlock.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolBlock.h
@@ -11,12 +11,13 @@
#include "PDBSymbol.h"
#include "PDBTypes.h"
-#include <string>
namespace llvm {
class raw_ostream;
+namespace pdb {
+
class PDBSymbolBlock : public PDBSymbol {
public:
PDBSymbolBlock(const IPDBSession &PDBSession,
@@ -33,9 +34,9 @@ public:
FORWARD_SYMBOL_METHOD(getLocationType)
FORWARD_SYMBOL_METHOD(getName)
FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress)
- FORWARD_SYMBOL_METHOD(getSymIndexId)
FORWARD_SYMBOL_METHOD(getVirtualAddress)
};
}
+}
#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLBLOCK_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h b/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h
index f8c796ae5bdc..f1983b3f7bf5 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h
@@ -17,6 +17,8 @@ namespace llvm {
class raw_ostream;
+namespace pdb {
+
class PDBSymbolCompiland : public PDBSymbol {
public:
PDBSymbolCompiland(const IPDBSession &PDBSession,
@@ -30,9 +32,10 @@ public:
FORWARD_SYMBOL_METHOD(getLexicalParentId)
FORWARD_SYMBOL_METHOD(getLibraryName)
FORWARD_SYMBOL_METHOD(getName)
- FORWARD_SYMBOL_METHOD(getSourceFileName)
- FORWARD_SYMBOL_METHOD(getSymIndexId)
+
+ std::string getSourceFileName() const;
};
}
+}
#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILAND_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h b/include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h
index 7f29d6bde990..bb4a78f68e2f 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h
@@ -16,6 +16,7 @@
namespace llvm {
class raw_ostream;
+namespace pdb {
class PDBSymbolCompilandDetails : public PDBSymbol {
public:
@@ -47,9 +48,10 @@ public:
FORWARD_SYMBOL_METHOD(getLanguage)
FORWARD_SYMBOL_METHOD(getLexicalParentId)
FORWARD_SYMBOL_METHOD(getPlatform)
- FORWARD_SYMBOL_METHOD(getSymIndexId)
+ FORWARD_SYMBOL_METHOD(getSourceFileName)
};
} // namespace llvm
+}
#endif // LLVM_DEBUGINFO_PDB_PDBFUNCTION_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h b/include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h
index 7e2ea9018edb..a71a0ba2df58 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h
@@ -16,7 +16,7 @@
namespace llvm {
class raw_ostream;
-
+namespace pdb {
class PDBSymbolCompilandEnv : public PDBSymbol {
public:
PDBSymbolCompilandEnv(const IPDBSession &PDBSession,
@@ -28,10 +28,10 @@ public:
FORWARD_SYMBOL_METHOD(getLexicalParentId)
FORWARD_SYMBOL_METHOD(getName)
- FORWARD_SYMBOL_METHOD(getSymIndexId)
std::string getValue() const;
};
} // namespace llvm
+}
#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILANDENV_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolCustom.h b/include/llvm/DebugInfo/PDB/PDBSymbolCustom.h
index 86bfd5707a31..54f089404262 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolCustom.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolCustom.h
@@ -18,6 +18,7 @@ namespace llvm {
class raw_ostream;
+namespace pdb {
/// PDBSymbolCustom represents symbols that are compiler-specific and do not
/// fit anywhere else in the lexical hierarchy.
/// https://msdn.microsoft.com/en-us/library/d88sf09h.aspx
@@ -31,9 +32,9 @@ public:
void dump(PDBSymDumper &Dumper) const override;
void getDataBytes(llvm::SmallVector<uint8_t, 32> &bytes);
- FORWARD_SYMBOL_METHOD(getSymIndexId)
};
} // namespace llvm
+}
#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLCUSTOM_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolData.h b/include/llvm/DebugInfo/PDB/PDBSymbolData.h
index 79cbbf0e1683..36f32ab51c11 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolData.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolData.h
@@ -17,6 +17,8 @@ namespace llvm {
class raw_ostream;
+namespace pdb {
+
class PDBSymbolData : public PDBSymbol {
public:
PDBSymbolData(const IPDBSession &PDBSession,
@@ -47,7 +49,6 @@ public:
FORWARD_SYMBOL_METHOD(getRegisterId)
FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress)
FORWARD_SYMBOL_METHOD(getSlot)
- FORWARD_SYMBOL_METHOD(getSymIndexId)
FORWARD_SYMBOL_METHOD(getToken)
FORWARD_SYMBOL_METHOD(getTypeId)
FORWARD_SYMBOL_METHOD(isUnalignedType)
@@ -57,5 +58,6 @@ public:
};
} // namespace llvm
+}
#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLDATA_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolExe.h b/include/llvm/DebugInfo/PDB/PDBSymbolExe.h
index 7c5f302ad634..5b3f50d153eb 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolExe.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolExe.h
@@ -12,12 +12,13 @@
#include "PDBSymbol.h"
#include "PDBTypes.h"
-#include <string>
namespace llvm {
class raw_ostream;
+namespace pdb {
+
class PDBSymbolExe : public PDBSymbol {
public:
PDBSymbolExe(const IPDBSession &PDBSession,
@@ -35,12 +36,12 @@ public:
FORWARD_SYMBOL_METHOD(getName)
FORWARD_SYMBOL_METHOD(getSignature)
FORWARD_SYMBOL_METHOD(getSymbolsFileName)
- FORWARD_SYMBOL_METHOD(getSymIndexId)
private:
void dumpChildren(raw_ostream &OS, StringRef Label, PDB_SymType ChildType,
int Indent) const;
};
} // namespace llvm
+}
#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLEXE_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h b/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h
index 9db41d53532a..7170bcbe846c 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h
@@ -17,6 +17,8 @@ namespace llvm {
class raw_ostream;
+namespace pdb {
+
class PDBSymbolFunc : public PDBSymbol {
public:
PDBSymbolFunc(const IPDBSession &PDBSession,
@@ -64,7 +66,6 @@ public:
FORWARD_SYMBOL_METHOD(hasOptimizedCodeDebugInfo)
FORWARD_SYMBOL_METHOD(isPureVirtual)
FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress)
- FORWARD_SYMBOL_METHOD(getSymIndexId)
FORWARD_SYMBOL_METHOD(getToken)
FORWARD_SYMBOL_METHOD(getTypeId)
FORWARD_SYMBOL_METHOD(isUnalignedType)
@@ -76,5 +77,6 @@ public:
};
} // namespace llvm
+}
#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNC_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h b/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h
index 34d551cda74c..464389503bef 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h
@@ -17,6 +17,8 @@ namespace llvm {
class raw_ostream;
+namespace pdb {
+
class PDBSymbolFuncDebugEnd : public PDBSymbol {
public:
PDBSymbolFuncDebugEnd(const IPDBSession &PDBSession,
@@ -40,10 +42,10 @@ public:
FORWARD_SYMBOL_METHOD(getOffset)
FORWARD_SYMBOL_METHOD(hasOptimizedCodeDebugInfo)
FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress)
- FORWARD_SYMBOL_METHOD(getSymIndexId)
FORWARD_SYMBOL_METHOD(getVirtualAddress)
};
} // namespace llvm
+}
#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNCDEBUGEND_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h b/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h
index 7671be480dac..c2e3dd39be6c 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h
@@ -16,6 +16,7 @@
namespace llvm {
class raw_ostream;
+namespace pdb {
class PDBSymbolFuncDebugStart : public PDBSymbol {
public:
@@ -40,10 +41,10 @@ public:
FORWARD_SYMBOL_METHOD(getOffset)
FORWARD_SYMBOL_METHOD(hasOptimizedCodeDebugInfo)
FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress)
- FORWARD_SYMBOL_METHOD(getSymIndexId)
FORWARD_SYMBOL_METHOD(getVirtualAddress)
};
} // namespace llvm
+}
#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNCDEBUGSTART_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolLabel.h b/include/llvm/DebugInfo/PDB/PDBSymbolLabel.h
index 9d9903a11b0c..3aeae10b47bc 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolLabel.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolLabel.h
@@ -16,6 +16,7 @@
namespace llvm {
class raw_ostream;
+namespace pdb {
class PDBSymbolLabel : public PDBSymbol {
public:
@@ -40,10 +41,10 @@ public:
FORWARD_SYMBOL_METHOD(getOffset)
FORWARD_SYMBOL_METHOD(hasOptimizedCodeDebugInfo)
FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress)
- FORWARD_SYMBOL_METHOD(getSymIndexId)
FORWARD_SYMBOL_METHOD(getVirtualAddress)
};
} // namespace llvm
+}
#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLLABEL_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h b/include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h
index 70dfcb5ddf4c..be0734445973 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h
@@ -16,6 +16,7 @@
namespace llvm {
class raw_ostream;
+namespace pdb {
class PDBSymbolPublicSymbol : public PDBSymbol {
public:
@@ -36,12 +37,12 @@ public:
FORWARD_SYMBOL_METHOD(isManagedCode)
FORWARD_SYMBOL_METHOD(isMSILCode)
FORWARD_SYMBOL_METHOD(getName)
- FORWARD_SYMBOL_METHOD(getSymIndexId)
FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress)
FORWARD_SYMBOL_METHOD(getVirtualAddress)
FORWARD_SYMBOL_METHOD(getUndecoratedName)
};
} // namespace llvm
+}
#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLPUBLICSYMBOL_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h b/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h
index bd5a9b2aa8b3..63f7a09fc881 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h
@@ -12,11 +12,11 @@
#include "PDBSymbol.h"
#include "PDBTypes.h"
-#include <string>
namespace llvm {
class raw_ostream;
+namespace pdb {
class PDBSymbolThunk : public PDBSymbol {
public:
@@ -39,7 +39,6 @@ public:
FORWARD_SYMBOL_METHOD(getName)
FORWARD_SYMBOL_METHOD(isPureVirtual)
FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress)
- FORWARD_SYMBOL_METHOD(getSymIndexId)
FORWARD_SYMBOL_METHOD(getTargetOffset)
FORWARD_SYMBOL_METHOD(getTargetRelativeVirtualAddress)
FORWARD_SYMBOL_METHOD(getTargetVirtualAddress)
@@ -53,5 +52,6 @@ public:
FORWARD_SYMBOL_METHOD(isVolatileType)
};
} // namespace llvm
+}
#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTHUNK_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h
index 513a9ec05ff8..57db03661fb7 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h
@@ -16,6 +16,7 @@
namespace llvm {
class raw_ostream;
+namespace pdb {
class PDBSymbolTypeArray : public PDBSymbol {
public:
@@ -34,12 +35,12 @@ public:
FORWARD_SYMBOL_METHOD(getLength)
FORWARD_SYMBOL_METHOD(getLexicalParentId)
FORWARD_SYMBOL_METHOD(getRank)
- FORWARD_SYMBOL_METHOD(getSymIndexId)
FORWARD_SYMBOL_METHOD(getTypeId)
FORWARD_SYMBOL_METHOD(isUnalignedType)
FORWARD_SYMBOL_METHOD(isVolatileType)
};
} // namespace llvm
+}
#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEARRAY_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h
index 2a9a8a0788a8..aaa3ab7988d7 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h
@@ -16,6 +16,7 @@
namespace llvm {
class raw_ostream;
+namespace pdb {
class PDBSymbolTypeBaseClass : public PDBSymbol {
public:
@@ -42,7 +43,6 @@ public:
FORWARD_SYMBOL_METHOD(hasOverloadedOperator)
FORWARD_SYMBOL_METHOD(isPacked)
FORWARD_SYMBOL_METHOD(isScoped)
- FORWARD_SYMBOL_METHOD(getSymIndexId)
FORWARD_SYMBOL_METHOD(getTypeId)
FORWARD_SYMBOL_METHOD(getUdtKind)
FORWARD_SYMBOL_METHOD(isUnalignedType)
@@ -56,5 +56,6 @@ public:
};
} // namespace llvm
+}
#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEBASECLASS_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h
index 69a2028a1b1d..c8f59f1f140a 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h
@@ -16,6 +16,7 @@
namespace llvm {
class raw_ostream;
+namespace pdb {
class PDBSymbolTypeBuiltin : public PDBSymbol {
public:
@@ -30,11 +31,11 @@ public:
FORWARD_SYMBOL_METHOD(isConstType)
FORWARD_SYMBOL_METHOD(getLength)
FORWARD_SYMBOL_METHOD(getLexicalParentId)
- FORWARD_SYMBOL_METHOD(getSymIndexId)
FORWARD_SYMBOL_METHOD(isUnalignedType)
FORWARD_SYMBOL_METHOD(isVolatileType)
};
} // namespace llvm
+}
#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEBUILTIN_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h
index c41c48933e0d..199b3f8b304e 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h
@@ -16,6 +16,7 @@
namespace llvm {
class raw_ostream;
+namespace pdb {
class PDBSymbolTypeCustom : public PDBSymbol {
public:
@@ -28,9 +29,9 @@ public:
FORWARD_SYMBOL_METHOD(getOemId)
FORWARD_SYMBOL_METHOD(getOemSymbolId)
- FORWARD_SYMBOL_METHOD(getSymIndexId)
};
} // namespace llvm
+}
#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPECUSTOM_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h
index 3f22ed8d731e..e635eb5bbf6f 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h
@@ -16,6 +16,7 @@
namespace llvm {
class raw_ostream;
+namespace pdb {
class PDBSymbolTypeDimension : public PDBSymbol {
public:
@@ -28,9 +29,9 @@ public:
FORWARD_SYMBOL_METHOD(getLowerBoundId)
FORWARD_SYMBOL_METHOD(getUpperBoundId)
- FORWARD_SYMBOL_METHOD(getSymIndexId)
};
} // namespace llvm
+}
#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEDIMENSION_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h
index 3188c711915c..ade2887bac14 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h
@@ -16,6 +16,7 @@
namespace llvm {
class raw_ostream;
+namespace pdb {
class PDBSymbolTypeEnum : public PDBSymbol {
public:
@@ -44,12 +45,12 @@ public:
FORWARD_SYMBOL_METHOD(hasOverloadedOperator)
FORWARD_SYMBOL_METHOD(isPacked)
FORWARD_SYMBOL_METHOD(isScoped)
- FORWARD_SYMBOL_METHOD(getSymIndexId)
FORWARD_SYMBOL_METHOD(getTypeId)
FORWARD_SYMBOL_METHOD(isUnalignedType)
FORWARD_SYMBOL_METHOD(isVolatileType)
};
} // namespace llvm
+}
#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEENUM_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h
index 4d393d7b6c5c..196d149ed2a2 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h
@@ -16,6 +16,7 @@
namespace llvm {
class raw_ostream;
+namespace pdb {
class PDBSymbolTypeFriend : public PDBSymbol {
public:
@@ -28,10 +29,10 @@ public:
FORWARD_SYMBOL_METHOD(getClassParentId)
FORWARD_SYMBOL_METHOD(getName)
- FORWARD_SYMBOL_METHOD(getSymIndexId)
FORWARD_SYMBOL_METHOD(getTypeId)
};
} // namespace llvm
+}
#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFRIEND_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h
index 14f79d99b6f8..5561341d7e77 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h
@@ -16,6 +16,7 @@
namespace llvm {
class raw_ostream;
+namespace pdb {
class PDBSymbolTypeFunctionArg : public PDBSymbol {
public:
@@ -28,10 +29,10 @@ public:
FORWARD_SYMBOL_METHOD(getClassParentId)
FORWARD_SYMBOL_METHOD(getLexicalParentId)
- FORWARD_SYMBOL_METHOD(getSymIndexId)
FORWARD_SYMBOL_METHOD(getTypeId)
};
} // namespace llvm
+}
#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFUNCTIONARG_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h
index 4bb4265a22f6..516011ff8b3d 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h
@@ -16,6 +16,7 @@
namespace llvm {
class raw_ostream;
+namespace pdb {
class PDBSymbolTypeFunctionSig : public PDBSymbol {
public:
@@ -38,7 +39,6 @@ public:
FORWARD_SYMBOL_METHOD(getCount)
FORWARD_SYMBOL_METHOD(getLexicalParentId)
// FORWARD_SYMBOL_METHOD(getObjectPointerType)
- FORWARD_SYMBOL_METHOD(getSymIndexId)
FORWARD_SYMBOL_METHOD(getThisAdjust)
FORWARD_SYMBOL_METHOD(getTypeId)
FORWARD_SYMBOL_METHOD(isUnalignedType)
@@ -46,5 +46,6 @@ public:
};
} // namespace llvm
+}
#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFUNCTIONSIG_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h
index cbfcec82a637..31cf5363dde1 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h
@@ -16,6 +16,7 @@
namespace llvm {
class raw_ostream;
+namespace pdb {
class PDBSymbolTypeManaged : public PDBSymbol {
public:
@@ -27,9 +28,9 @@ public:
void dump(PDBSymDumper &Dumper) const override;
FORWARD_SYMBOL_METHOD(getName)
- FORWARD_SYMBOL_METHOD(getSymIndexId)
};
} // namespace llvm
+}
#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEMANAGED_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h
index 33578bad0245..7a57272adb79 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h
@@ -16,6 +16,7 @@
namespace llvm {
class raw_ostream;
+namespace pdb {
class PDBSymbolTypePointer : public PDBSymbol {
public:
@@ -32,12 +33,12 @@ public:
FORWARD_SYMBOL_METHOD(getLength)
FORWARD_SYMBOL_METHOD(getLexicalParentId)
FORWARD_SYMBOL_METHOD(isReference)
- FORWARD_SYMBOL_METHOD(getSymIndexId)
FORWARD_SYMBOL_METHOD(getTypeId)
FORWARD_SYMBOL_METHOD(isUnalignedType)
FORWARD_SYMBOL_METHOD(isVolatileType)
};
} // namespace llvm
+}
#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEPOINTER_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h
index 5ad83bb1ec26..5ed4f8d21d90 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h
@@ -16,6 +16,7 @@
namespace llvm {
class raw_ostream;
+namespace pdb {
class PDBSymbolTypeTypedef : public PDBSymbol {
public:
@@ -41,7 +42,6 @@ public:
FORWARD_SYMBOL_METHOD(isPacked)
FORWARD_SYMBOL_METHOD(isReference)
FORWARD_SYMBOL_METHOD(isScoped)
- FORWARD_SYMBOL_METHOD(getSymIndexId)
FORWARD_SYMBOL_METHOD(getTypeId)
FORWARD_SYMBOL_METHOD(getUdtKind)
FORWARD_SYMBOL_METHOD(isUnalignedType)
@@ -50,5 +50,6 @@ public:
};
} // namespace llvm
+}
#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPETYPEDEF_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h
index 99cc307a83e3..1874dfef34f7 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h
@@ -17,6 +17,7 @@ namespace llvm {
class raw_ostream;
+namespace pdb {
class PDBSymbolTypeUDT : public PDBSymbol {
public:
PDBSymbolTypeUDT(const IPDBSession &PDBSession,
@@ -40,13 +41,12 @@ public:
FORWARD_SYMBOL_METHOD(hasOverloadedOperator)
FORWARD_SYMBOL_METHOD(isPacked)
FORWARD_SYMBOL_METHOD(isScoped)
- FORWARD_SYMBOL_METHOD(getSymIndexId)
FORWARD_SYMBOL_METHOD(getUdtKind)
FORWARD_SYMBOL_METHOD(isUnalignedType)
FORWARD_SYMBOL_METHOD(getVirtualTableShapeId)
FORWARD_SYMBOL_METHOD(isVolatileType)
};
-
+}
} // namespace llvm
#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEUDT_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h
index 6efc549f0cb7..baf7ab79d60e 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h
@@ -16,6 +16,7 @@
namespace llvm {
class raw_ostream;
+namespace pdb {
class PDBSymbolTypeVTable : public PDBSymbol {
public:
@@ -29,12 +30,12 @@ public:
FORWARD_SYMBOL_METHOD(getClassParentId)
FORWARD_SYMBOL_METHOD(isConstType)
FORWARD_SYMBOL_METHOD(getLexicalParentId)
- FORWARD_SYMBOL_METHOD(getSymIndexId)
FORWARD_SYMBOL_METHOD(getTypeId)
FORWARD_SYMBOL_METHOD(isUnalignedType)
FORWARD_SYMBOL_METHOD(isVolatileType)
};
} // namespace llvm
+}
#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEVTABLE_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h
index f407595a4cc8..431fc1ac8625 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h
@@ -16,6 +16,7 @@
namespace llvm {
class raw_ostream;
+namespace pdb {
class PDBSymbolTypeVTableShape : public PDBSymbol {
public:
@@ -29,11 +30,11 @@ public:
FORWARD_SYMBOL_METHOD(isConstType)
FORWARD_SYMBOL_METHOD(getCount)
FORWARD_SYMBOL_METHOD(getLexicalParentId)
- FORWARD_SYMBOL_METHOD(getSymIndexId)
FORWARD_SYMBOL_METHOD(isUnalignedType)
FORWARD_SYMBOL_METHOD(isVolatileType)
};
} // namespace llvm
+}
#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEVTABLESHAPE_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h b/include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h
index 94bd2c14079f..de43e47badbd 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h
@@ -15,6 +15,7 @@
namespace llvm {
class raw_ostream;
+namespace pdb {
class PDBSymbolUnknown : public PDBSymbol {
public:
@@ -30,5 +31,6 @@ public:
};
} // namespace llvm
+}
#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLUNKNOWN_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h b/include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h
index 7072f342bef3..a273fe159c12 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h
@@ -16,6 +16,7 @@
namespace llvm {
class raw_ostream;
+namespace pdb {
class PDBSymbolUsingNamespace : public PDBSymbol {
public:
@@ -28,9 +29,9 @@ public:
FORWARD_SYMBOL_METHOD(getLexicalParentId)
FORWARD_SYMBOL_METHOD(getName)
- FORWARD_SYMBOL_METHOD(getSymIndexId)
};
} // namespace llvm
+}
#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLUSINGNAMESPACE_H
diff --git a/include/llvm/DebugInfo/PDB/PDBTypes.h b/include/llvm/DebugInfo/PDB/PDBTypes.h
index a932a56bb953..a9325a434366 100644
--- a/include/llvm/DebugInfo/PDB/PDBTypes.h
+++ b/include/llvm/DebugInfo/PDB/PDBTypes.h
@@ -11,11 +11,13 @@
#define LLVM_DEBUGINFO_PDB_PDBTYPES_H
#include "llvm/Config/llvm-config.h"
-#include "llvm/Support/Endian.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
#include <functional>
-#include <stdint.h>
+#include <cstdint>
+#include <cstring>
namespace llvm {
+namespace pdb {
class PDBSymDumper;
class PDBSymbol;
@@ -68,14 +70,14 @@ class PDBSymbolUnknown;
/// of PDB_ReaderType::DIA is supported.
enum class PDB_ReaderType {
DIA = 0,
+ Raw = 1,
};
/// Defines a 128-bit unique identifier. This maps to a GUID on Windows, but
/// is abstracted here for the purposes of non-Windows platforms that don't have
/// the GUID structure defined.
struct PDB_UniqueId {
- uint64_t HighPart;
- uint64_t LowPart;
+ char Guid[16];
};
/// An enumeration indicating the type of data contained in this table.
@@ -108,67 +110,7 @@ enum class PDB_Checksum { None = 0, MD5 = 1, SHA1 = 2 };
/// These values correspond to the CV_CPU_TYPE_e enumeration, and are documented
/// here: https://msdn.microsoft.com/en-us/library/b2fc64ek.aspx
-enum class PDB_Cpu {
- Intel8080 = 0x0,
- Intel8086 = 0x1,
- Intel80286 = 0x2,
- Intel80386 = 0x3,
- Intel80486 = 0x4,
- Pentium = 0x5,
- PentiumPro = 0x6,
- Pentium3 = 0x7,
- MIPS = 0x10,
- MIPS16 = 0x11,
- MIPS32 = 0x12,
- MIPS64 = 0x13,
- MIPSI = 0x14,
- MIPSII = 0x15,
- MIPSIII = 0x16,
- MIPSIV = 0x17,
- MIPSV = 0x18,
- M68000 = 0x20,
- M68010 = 0x21,
- M68020 = 0x22,
- M68030 = 0x23,
- M68040 = 0x24,
- Alpha = 0x30,
- Alpha21164 = 0x31,
- Alpha21164A = 0x32,
- Alpha21264 = 0x33,
- Alpha21364 = 0x34,
- PPC601 = 0x40,
- PPC603 = 0x41,
- PPC604 = 0x42,
- PPC620 = 0x43,
- PPCFP = 0x44,
- PPCBE = 0x45,
- SH3 = 0x50,
- SH3E = 0x51,
- SH3DSP = 0x52,
- SH4 = 0x53,
- SHMedia = 0x54,
- ARM3 = 0x60,
- ARM4 = 0x61,
- ARM4T = 0x62,
- ARM5 = 0x63,
- ARM5T = 0x64,
- ARM6 = 0x65,
- ARM_XMAC = 0x66,
- ARM_WMMX = 0x67,
- ARM7 = 0x68,
- Omni = 0x70,
- Ia64 = 0x80,
- Ia64_2 = 0x81,
- CEE = 0x90,
- AM33 = 0xa0,
- M32R = 0xb0,
- TriCore = 0xc0,
- X64 = 0xd0,
- EBC = 0xe0,
- Thumb = 0xf0,
- ARMNT = 0xf4,
- D3D11_Shader = 0x100,
-};
+typedef codeview::CPUType PDB_Cpu;
enum class PDB_Machine {
Invalid = 0xffff,
@@ -200,56 +142,11 @@ enum class PDB_Machine {
/// https://msdn.microsoft.com/en-us/library/b2fc64ek.aspx
/// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680207(v=vs.85).aspx
///
-enum class PDB_CallingConv {
- NearCdecl = 0x00,
- FarCdecl = 0x01,
- NearPascal = 0x02,
- FarPascal = 0x03,
- NearFastcall = 0x04,
- FarFastcall = 0x05,
- Skipped = 0x06,
- NearStdcall = 0x07,
- FarStdcall = 0x08,
- NearSyscall = 0x09,
- FarSyscall = 0x0a,
- Thiscall = 0x0b,
- MipsCall = 0x0c,
- Generic = 0x0d,
- Alphacall = 0x0e,
- Ppccall = 0x0f,
- SuperHCall = 0x10,
- Armcall = 0x11,
- AM33call = 0x12,
- Tricall = 0x13,
- Sh5call = 0x14,
- M32R = 0x15,
- Clrcall = 0x16,
- Inline = 0x17,
- NearVectorcall = 0x18,
- Reserved = 0x19,
-};
+typedef codeview::CallingConvention PDB_CallingConv;
/// These values correspond to the CV_CFL_LANG enumeration, and are documented
/// here: https://msdn.microsoft.com/en-us/library/bw3aekw6.aspx
-enum class PDB_Lang {
- C = 0x00,
- Cpp = 0x01,
- Fortran = 0x02,
- Masm = 0x03,
- Pascal = 0x04,
- Basic = 0x05,
- Cobol = 0x06,
- Link = 0x07,
- Cvtres = 0x08,
- Cvtpgd = 0x09,
- CSharp = 0x0a,
- VB = 0x0b,
- ILAsm = 0x0c,
- Java = 0x0d,
- JScript = 0x0e,
- MSIL = 0x0f,
- HLSL = 0x10
-};
+typedef codeview::SourceLanguage PDB_Lang;
/// These values correspond to the DataKind enumeration, and are documented
/// here: https://msdn.microsoft.com/en-us/library/b2x2t313.aspx
@@ -320,18 +217,6 @@ enum class PDB_LocType {
Max
};
-/// These values correspond to the THUNK_ORDINAL enumeration, and are documented
-/// here: https://msdn.microsoft.com/en-us/library/dh0k8hft.aspx
-enum class PDB_ThunkOrdinal {
- Standard,
- ThisAdjustor,
- Vcall,
- Pcode,
- UnknownLoad,
- TrampIncremental,
- BranchIsland
-};
-
/// These values correspond to the UdtKind enumeration, and are documented
/// here: https://msdn.microsoft.com/en-us/library/wcstk66t.aspx
enum class PDB_UdtType { Struct, Class, Union, Interface };
@@ -367,72 +252,8 @@ enum class PDB_BuiltinType {
HResult = 31
};
-enum class PDB_RegisterId {
- Unknown = 0,
- VFrame = 30006,
- AL = 1,
- CL = 2,
- DL = 3,
- BL = 4,
- AH = 5,
- CH = 6,
- DH = 7,
- BH = 8,
- AX = 9,
- CX = 10,
- DX = 11,
- BX = 12,
- SP = 13,
- BP = 14,
- SI = 15,
- DI = 16,
- EAX = 17,
- ECX = 18,
- EDX = 19,
- EBX = 20,
- ESP = 21,
- EBP = 22,
- ESI = 23,
- EDI = 24,
- ES = 25,
- CS = 26,
- SS = 27,
- DS = 28,
- FS = 29,
- GS = 30,
- IP = 31,
- RAX = 328,
- RBX = 329,
- RCX = 330,
- RDX = 331,
- RSI = 332,
- RDI = 333,
- RBP = 334,
- RSP = 335,
- R8 = 336,
- R9 = 337,
- R10 = 338,
- R11 = 339,
- R12 = 340,
- R13 = 341,
- R14 = 342,
- R15 = 343,
-};
-
enum class PDB_MemberAccess { Private = 1, Protected = 2, Public = 3 };
-enum class PDB_ErrorCode {
- Success,
- NoPdbImpl,
- InvalidPath,
- InvalidFileFormat,
- InvalidParameter,
- AlreadyLoaded,
- UnknownError,
- NoMemory,
- DebugInfoMismatch
-};
-
struct VersionInfo {
uint32_t Major;
uint32_t Minor;
@@ -454,11 +275,19 @@ enum PDB_VariantType {
UInt32,
UInt64,
Bool,
+ String
};
struct Variant {
- Variant()
- : Type(PDB_VariantType::Empty) {
+ Variant() : Type(PDB_VariantType::Empty) {}
+
+ Variant(const Variant &Other) : Type(PDB_VariantType::Empty) {
+ *this = Other;
+ }
+
+ ~Variant() {
+ if (Type == PDB_VariantType::String)
+ delete[] Value.String;
}
PDB_VariantType Type;
@@ -474,10 +303,13 @@ struct Variant {
uint16_t UInt16;
uint32_t UInt32;
uint64_t UInt64;
- };
+ char *String;
+ } Value;
+
#define VARIANT_EQUAL_CASE(Enum) \
case PDB_VariantType::Enum: \
- return Enum == Other.Enum;
+ return Value.Enum == Other.Value.Enum;
+
bool operator==(const Variant &Other) const {
if (Type != Other.Type)
return false;
@@ -493,55 +325,43 @@ struct Variant {
VARIANT_EQUAL_CASE(UInt16)
VARIANT_EQUAL_CASE(UInt32)
VARIANT_EQUAL_CASE(UInt64)
+ VARIANT_EQUAL_CASE(String)
default:
return true;
}
}
+
#undef VARIANT_EQUAL_CASE
+
bool operator!=(const Variant &Other) const { return !(*this == Other); }
+ Variant &operator=(const Variant &Other) {
+ if (this == &Other)
+ return *this;
+ if (Type == PDB_VariantType::String)
+ delete[] Value.String;
+ Type = Other.Type;
+ Value = Other.Value;
+ if (Other.Type == PDB_VariantType::String &&
+ Other.Value.String != nullptr) {
+ Value.String = new char[strlen(Other.Value.String) + 1];
+ ::strcpy(Value.String, Other.Value.String);
+ }
+ return *this;
+ }
};
-namespace PDB {
-static const char Magic[] = {'M', 'i', 'c', 'r', 'o', 's', 'o', 'f',
- 't', ' ', 'C', '/', 'C', '+', '+', ' ',
- 'M', 'S', 'F', ' ', '7', '.', '0', '0',
- '\r', '\n', '\x1a', 'D', 'S', '\0', '\0', '\0'};
-
-// The superblock is overlaid at the beginning of the file (offset 0).
-// It starts with a magic header and is followed by information which describes
-// the layout of the file system.
-struct SuperBlock {
- char MagicBytes[sizeof(Magic)];
- // The file system is split into a variable number of fixed size elements.
- // These elements are referred to as blocks. The size of a block may vary
- // from system to system.
- support::ulittle32_t BlockSize;
- // This field's purpose is not yet known.
- support::ulittle32_t Unknown0;
- // This contains the number of blocks resident in the file system. In
- // practice, NumBlocks * BlockSize is equivalent to the size of the PDB file.
- support::ulittle32_t NumBlocks;
- // This contains the number of bytes which make up the directory.
- support::ulittle32_t NumDirectoryBytes;
- // This field's purpose is not yet known.
- support::ulittle32_t Unknown1;
- // This contains the block # of the block map.
- support::ulittle32_t BlockMapAddr;
-};
+} // end namespace llvm
}
-} // namespace llvm
-
namespace std {
-template <> struct hash<llvm::PDB_SymType> {
- typedef llvm::PDB_SymType argument_type;
+template <> struct hash<llvm::pdb::PDB_SymType> {
+ typedef llvm::pdb::PDB_SymType argument_type;
typedef std::size_t result_type;
result_type operator()(const argument_type &Arg) const {
return std::hash<int>()(static_cast<int>(Arg));
}
};
-}
-
+} // end namespace std
-#endif
+#endif // LLVM_DEBUGINFO_PDB_PDBTYPES_H
diff --git a/include/llvm/DebugInfo/PDB/Raw/DbiStream.h b/include/llvm/DebugInfo/PDB/Raw/DbiStream.h
new file mode 100644
index 000000000000..6ab3c8067558
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Raw/DbiStream.h
@@ -0,0 +1,149 @@
+//===- DbiStream.h - PDB Dbi Stream (Stream 3) Access -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBDBISTREAM_H
+#define LLVM_DEBUGINFO_PDB_RAW_PDBDBISTREAM_H
+
+#include "llvm/DebugInfo/CodeView/ModuleSubstream.h"
+#include "llvm/DebugInfo/CodeView/StreamArray.h"
+#include "llvm/DebugInfo/CodeView/StreamRef.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
+#include "llvm/DebugInfo/PDB/Raw/NameHashTable.h"
+#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace object {
+struct FpoData;
+struct coff_section;
+}
+
+namespace pdb {
+class DbiStreamBuilder;
+class PDBFile;
+class ISectionContribVisitor;
+
+class DbiStream {
+ friend class DbiStreamBuilder;
+
+ struct HeaderInfo {
+ support::little32_t VersionSignature;
+ support::ulittle32_t VersionHeader;
+ support::ulittle32_t Age; // Should match InfoStream.
+ support::ulittle16_t GlobalSymbolStreamIndex; // Global symbol stream #
+ support::ulittle16_t BuildNumber; // See DbiBuildNo structure.
+ support::ulittle16_t PublicSymbolStreamIndex; // Public symbols stream #
+ support::ulittle16_t PdbDllVersion; // version of mspdbNNN.dll
+ support::ulittle16_t SymRecordStreamIndex; // Symbol records stream #
+ support::ulittle16_t PdbDllRbld; // rbld number of mspdbNNN.dll
+ support::little32_t ModiSubstreamSize; // Size of module info stream
+ support::little32_t SecContrSubstreamSize; // Size of sec. contrib stream
+ support::little32_t SectionMapSize; // Size of sec. map substream
+ support::little32_t FileInfoSize; // Size of file info substream
+ support::little32_t TypeServerSize; // Size of type server map
+ support::ulittle32_t MFCTypeServerIndex; // Index of MFC Type Server
+ support::little32_t OptionalDbgHdrSize; // Size of DbgHeader info
+ support::little32_t ECSubstreamSize; // Size of EC stream (what is EC?)
+ support::ulittle16_t Flags; // See DbiFlags enum.
+ support::ulittle16_t MachineType; // See PDB_MachineType enum.
+
+ support::ulittle32_t Reserved; // Pad to 64 bytes
+ };
+
+public:
+ DbiStream(PDBFile &File, std::unique_ptr<MappedBlockStream> Stream);
+ ~DbiStream();
+ Error reload();
+
+ PdbRaw_DbiVer getDbiVersion() const;
+ uint32_t getAge() const;
+ uint16_t getPublicSymbolStreamIndex() const;
+ uint16_t getGlobalSymbolStreamIndex() const;
+
+ uint16_t getFlags() const;
+ bool isIncrementallyLinked() const;
+ bool hasCTypes() const;
+ bool isStripped() const;
+
+ uint16_t getBuildNumber() const;
+ uint16_t getBuildMajorVersion() const;
+ uint16_t getBuildMinorVersion() const;
+
+ uint16_t getPdbDllRbld() const;
+ uint32_t getPdbDllVersion() const;
+
+ uint32_t getSymRecordStreamIndex() const;
+
+ PDB_Machine getMachineType() const;
+
+ enum { InvalidStreamIndex = 0xffff };
+
+ /// If the given stream type is present, returns its stream index. If it is
+ /// not present, returns InvalidStreamIndex.
+ uint32_t getDebugStreamIndex(DbgHeaderType Type) const;
+
+ ArrayRef<ModuleInfoEx> modules() const;
+
+ Expected<StringRef> getFileNameForIndex(uint32_t Index) const;
+
+ codeview::FixedStreamArray<object::coff_section> getSectionHeaders();
+
+ codeview::FixedStreamArray<object::FpoData> getFpoRecords();
+
+ codeview::FixedStreamArray<SecMapEntry> getSectionMap() const;
+ void visitSectionContributions(ISectionContribVisitor &Visitor) const;
+
+ Error commit();
+
+private:
+ Error initializeSectionContributionData();
+ Error initializeSectionHeadersData();
+ Error initializeSectionMapData();
+ Error initializeFileInfo();
+ Error initializeFpoRecords();
+
+ PDBFile &Pdb;
+ std::unique_ptr<MappedBlockStream> Stream;
+
+ std::vector<ModuleInfoEx> ModuleInfos;
+ NameHashTable ECNames;
+
+ codeview::StreamRef ModInfoSubstream;
+ codeview::StreamRef SecContrSubstream;
+ codeview::StreamRef SecMapSubstream;
+ codeview::StreamRef FileInfoSubstream;
+ codeview::StreamRef TypeServerMapSubstream;
+ codeview::StreamRef ECSubstream;
+
+ codeview::StreamRef NamesBuffer;
+
+ codeview::FixedStreamArray<support::ulittle16_t> DbgStreams;
+
+ PdbRaw_DbiSecContribVer SectionContribVersion;
+ codeview::FixedStreamArray<SectionContrib> SectionContribs;
+ codeview::FixedStreamArray<SectionContrib2> SectionContribs2;
+ codeview::FixedStreamArray<SecMapEntry> SectionMap;
+ codeview::FixedStreamArray<support::little32_t> FileNameOffsets;
+
+ std::unique_ptr<MappedBlockStream> SectionHeaderStream;
+ codeview::FixedStreamArray<object::coff_section> SectionHeaders;
+
+ std::unique_ptr<MappedBlockStream> FpoStream;
+ codeview::FixedStreamArray<object::FpoData> FpoRecords;
+
+ const HeaderInfo *Header;
+};
+}
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h b/include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h
new file mode 100644
index 000000000000..2c7350f3c3e7
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h
@@ -0,0 +1,56 @@
+//===- DbiStreamBuilder.h - PDB Dbi Stream Creation -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBDBISTREAMBUILDER_H
+#define LLVM_DEBUGINFO_PDB_RAW_PDBDBISTREAMBUILDER_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/Support/Error.h"
+
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
+
+namespace llvm {
+namespace pdb {
+class DbiStream;
+class PDBFile;
+
+class DbiStreamBuilder {
+public:
+ DbiStreamBuilder();
+
+ DbiStreamBuilder(const DbiStreamBuilder &) = delete;
+ DbiStreamBuilder &operator=(const DbiStreamBuilder &) = delete;
+
+ void setVersionHeader(PdbRaw_DbiVer V);
+ void setAge(uint32_t A);
+ void setBuildNumber(uint16_t B);
+ void setPdbDllVersion(uint16_t V);
+ void setPdbDllRbld(uint16_t R);
+ void setFlags(uint16_t F);
+ void setMachineType(PDB_Machine M);
+
+ uint32_t calculateSerializedLength() const;
+
+ Expected<std::unique_ptr<DbiStream>> build(PDBFile &File);
+
+private:
+ Optional<PdbRaw_DbiVer> VerHeader;
+ uint32_t Age;
+ uint16_t BuildNumber;
+ uint16_t PdbDllVersion;
+ uint16_t PdbDllRbld;
+ uint16_t Flags;
+ PDB_Machine MachineType;
+};
+}
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/Raw/DirectoryStreamData.h b/include/llvm/DebugInfo/PDB/Raw/DirectoryStreamData.h
new file mode 100644
index 000000000000..0f354315122c
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Raw/DirectoryStreamData.h
@@ -0,0 +1,37 @@
+//===- DirectoryStreamData.h ---------------------------------- *- C++ --*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_DIRECTORYSTREAMDATA_H
+#define LLVM_DEBUGINFO_PDB_RAW_DIRECTORYSTREAMDATA_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/PDB/Raw/IPDBStreamData.h"
+#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
+#include "llvm/Support/Endian.h"
+
+namespace llvm {
+namespace pdb {
+class IPDBFile;
+
+class DirectoryStreamData : public IPDBStreamData {
+public:
+ DirectoryStreamData(const PDBFile &File) : File(File) {}
+
+ virtual uint32_t getLength() { return File.getNumDirectoryBytes(); }
+ virtual llvm::ArrayRef<llvm::support::ulittle32_t> getStreamBlocks() {
+ return File.getDirectoryBlockArray();
+ }
+
+private:
+ const PDBFile &File;
+};
+}
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/Raw/EnumTables.h b/include/llvm/DebugInfo/PDB/Raw/EnumTables.h
new file mode 100644
index 000000000000..c018445630fe
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Raw/EnumTables.h
@@ -0,0 +1,22 @@
+//===- EnumTables.h - Enum to string conversion tables ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_ENUMTABLES_H
+#define LLVM_DEBUGINFO_PDB_RAW_ENUMTABLES_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/ScopedPrinter.h"
+
+namespace llvm {
+namespace pdb {
+ArrayRef<EnumEntry<uint16_t>> getOMFSegMapDescFlagNames();
+}
+}
+
+#endif // LLVM_DEBUGINFO_PDB_RAW_ENUMTABLES_H
diff --git a/include/llvm/DebugInfo/PDB/Raw/Hash.h b/include/llvm/DebugInfo/PDB/Raw/Hash.h
new file mode 100644
index 000000000000..0340554d7b0b
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Raw/Hash.h
@@ -0,0 +1,25 @@
+//===- Hash.h - PDB hash functions ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_HASH_H
+#define LLVM_DEBUGINFO_PDB_RAW_HASH_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include <stdint.h>
+
+namespace llvm {
+namespace pdb {
+uint32_t hashStringV1(StringRef Str);
+uint32_t hashStringV2(StringRef Str);
+uint32_t hashBufferV8(ArrayRef<uint8_t> Data);
+}
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/Raw/IPDBFile.h b/include/llvm/DebugInfo/PDB/Raw/IPDBFile.h
new file mode 100644
index 000000000000..fccea2ac2470
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Raw/IPDBFile.h
@@ -0,0 +1,44 @@
+//===- IPDBFile.h - Abstract base class for a PDB file ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_IPDBFILE_H
+#define LLVM_DEBUGINFO_PDB_RAW_IPDBFILE_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/CodeView/StreamArray.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+
+#include <stdint.h>
+
+namespace llvm {
+namespace pdb {
+
+class IPDBFile {
+public:
+ virtual ~IPDBFile() {}
+
+ virtual uint32_t getBlockSize() const = 0;
+ virtual uint32_t getBlockCount() const = 0;
+
+ virtual uint32_t getNumStreams() const = 0;
+ virtual uint32_t getStreamByteSize(uint32_t StreamIndex) const = 0;
+ virtual ArrayRef<support::ulittle32_t>
+ getStreamBlockList(uint32_t StreamIndex) const = 0;
+
+ virtual Expected<ArrayRef<uint8_t>> getBlockData(uint32_t BlockIndex,
+ uint32_t NumBytes) const = 0;
+ virtual Error setBlockData(uint32_t BlockIndex, uint32_t Offset,
+ ArrayRef<uint8_t> Data) const = 0;
+};
+}
+}
+
+#endif // LLVM_DEBUGINFO_PDB_RAW_IPDBFILE_H
diff --git a/include/llvm/DebugInfo/PDB/Raw/IPDBStreamData.h b/include/llvm/DebugInfo/PDB/Raw/IPDBStreamData.h
new file mode 100644
index 000000000000..ab3c9f770755
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Raw/IPDBStreamData.h
@@ -0,0 +1,38 @@
+//===- IPDBStreamData.h - Base interface for PDB Stream Data ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_IPDBSTREAMDATA_H
+#define LLVM_DEBUGINFO_PDB_RAW_IPDBSTREAMDATA_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/Endian.h"
+
+namespace llvm {
+namespace pdb {
+/// IPDBStream abstracts the notion of PDB stream data. Although we already
+/// have another stream abstraction (namely in the form of StreamInterface
+/// and MappedBlockStream), they assume that the stream data is referenced
+/// the same way. Namely, by looking in the directory to get the list of
+/// stream blocks, and by looking in the array of stream lengths to get the
+/// length. This breaks down for the directory itself, however, since its
+/// length and list of blocks are stored elsewhere. By abstracting the
+/// notion of stream data further, we can use a MappedBlockStream to read
+/// from the directory itself, or from an indexed stream which references
+/// the directory.
+class IPDBStreamData {
+public:
+ virtual ~IPDBStreamData() {}
+
+ virtual uint32_t getLength() = 0;
+ virtual ArrayRef<support::ulittle32_t> getStreamBlocks() = 0;
+};
+}
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/Raw/ISectionContribVisitor.h b/include/llvm/DebugInfo/PDB/Raw/ISectionContribVisitor.h
new file mode 100644
index 000000000000..355a25a38ef8
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Raw/ISectionContribVisitor.h
@@ -0,0 +1,28 @@
+//===- ISectionContribVisitor.h ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_ISECTIONCONTRIBVISITOR_H
+#define LLVM_DEBUGINFO_PDB_RAW_ISECTIONCONTRIBVISITOR_H
+
+namespace llvm {
+namespace pdb {
+struct SectionContrib;
+struct SectionContrib2;
+
+class ISectionContribVisitor {
+public:
+ virtual ~ISectionContribVisitor() {}
+
+ virtual void visit(const SectionContrib &C) = 0;
+ virtual void visit(const SectionContrib2 &C) = 0;
+};
+} // namespace pdb
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_RAW_ISECTIONCONTRIBVISITOR_H
diff --git a/include/llvm/DebugInfo/PDB/Raw/IndexedStreamData.h b/include/llvm/DebugInfo/PDB/Raw/IndexedStreamData.h
new file mode 100644
index 000000000000..30563bc5b898
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Raw/IndexedStreamData.h
@@ -0,0 +1,34 @@
+//===- IndexedStreamData.h - Standard PDB Stream Data -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_INDEXEDSTREAMDATA_H
+#define LLVM_DEBUGINFO_PDB_RAW_INDEXEDSTREAMDATA_H
+
+#include "llvm/DebugInfo/PDB/Raw/IPDBStreamData.h"
+
+namespace llvm {
+namespace pdb {
+class IPDBFile;
+
+class IndexedStreamData : public IPDBStreamData {
+public:
+ IndexedStreamData(uint32_t StreamIdx, const IPDBFile &File);
+ virtual ~IndexedStreamData() {}
+
+ uint32_t getLength() override;
+ ArrayRef<support::ulittle32_t> getStreamBlocks() override;
+
+private:
+ uint32_t StreamIdx;
+ const IPDBFile &File;
+};
+}
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/Raw/InfoStream.h b/include/llvm/DebugInfo/PDB/Raw/InfoStream.h
new file mode 100644
index 000000000000..1980bec7153e
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Raw/InfoStream.h
@@ -0,0 +1,77 @@
+//===- InfoStream.h - PDB Info Stream (Stream 1) Access ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBINFOSTREAM_H
+#define LLVM_DEBUGINFO_PDB_RAW_PDBINFOSTREAM_H
+
+#include "llvm/ADT/StringMap.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Raw/NameMap.h"
+#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
+
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace pdb {
+class InfoStreamBuilder;
+class PDBFile;
+
+class InfoStream {
+ friend class InfoStreamBuilder;
+
+ struct HeaderInfo {
+ support::ulittle32_t Version;
+ support::ulittle32_t Signature;
+ support::ulittle32_t Age;
+ PDB_UniqueId Guid;
+ };
+
+public:
+ InfoStream(std::unique_ptr<MappedBlockStream> Stream);
+
+ Error reload();
+ Error commit();
+
+ PdbRaw_ImplVer getVersion() const;
+ uint32_t getSignature() const;
+ uint32_t getAge() const;
+ PDB_UniqueId getGuid() const;
+
+ uint32_t getNamedStreamIndex(llvm::StringRef Name) const;
+ iterator_range<StringMapConstIterator<uint32_t>> named_streams() const;
+
+private:
+ std::unique_ptr<MappedBlockStream> Stream;
+
+ // PDB file format version. We only support VC70. See the enumeration
+ // `PdbRaw_ImplVer` for the other possible values.
+ uint32_t Version;
+
+ // A 32-bit signature unique across all PDBs. This is generated with
+ // a call to time() when the PDB is written, but obviously this is not
+ // universally unique.
+ uint32_t Signature;
+
+ // The number of times the PDB has been written. Might also be used to
+ // ensure that the PDB matches the executable.
+ uint32_t Age;
+
+ // Due to the aforementioned limitations with `Signature`, this is a new
+ // signature present on VC70 and higher PDBs which is guaranteed to be
+ // universally unique.
+ PDB_UniqueId Guid;
+
+ NameMap NamedStreams;
+};
+}
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h b/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h
new file mode 100644
index 000000000000..e9869bb27863
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h
@@ -0,0 +1,53 @@
+//===- InfoStreamBuilder.h - PDB Info Stream Creation -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBINFOSTREAMBUILDER_H
+#define LLVM_DEBUGINFO_PDB_RAW_PDBINFOSTREAMBUILDER_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/Support/Error.h"
+
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+#include "llvm/DebugInfo/PDB/Raw/NameMapBuilder.h"
+#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
+
+namespace llvm {
+namespace pdb {
+class PDBFile;
+
+class InfoStreamBuilder {
+public:
+ InfoStreamBuilder();
+ InfoStreamBuilder(const InfoStreamBuilder &) = delete;
+ InfoStreamBuilder &operator=(const InfoStreamBuilder &) = delete;
+
+ void setVersion(PdbRaw_ImplVer V);
+ void setSignature(uint32_t S);
+ void setAge(uint32_t A);
+ void setGuid(PDB_UniqueId G);
+
+ NameMapBuilder &getNamedStreamsBuilder();
+
+ uint32_t calculateSerializedLength() const;
+
+ Expected<std::unique_ptr<InfoStream>> build(PDBFile &File);
+
+private:
+ Optional<PdbRaw_ImplVer> Ver;
+ Optional<uint32_t> Sig;
+ Optional<uint32_t> Age;
+ Optional<PDB_UniqueId> Guid;
+
+ NameMapBuilder NamedStreams;
+};
+}
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/Raw/MappedBlockStream.h b/include/llvm/DebugInfo/PDB/Raw/MappedBlockStream.h
new file mode 100644
index 000000000000..36424c0d16ab
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Raw/MappedBlockStream.h
@@ -0,0 +1,68 @@
+//===- MappedBlockStream.h - Reads stream data from a PDBFile ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_MAPPEDBLOCKSTREAM_H
+#define LLVM_DEBUGINFO_PDB_RAW_MAPPEDBLOCKSTREAM_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/CodeView/StreamInterface.h"
+#include "llvm/DebugInfo/PDB/Raw/IPDBStreamData.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include <cstdint>
+#include <vector>
+
+namespace llvm {
+namespace pdb {
+
+class IPDBFile;
+class PDBFile;
+
+class MappedBlockStream : public codeview::StreamInterface {
+public:
+ Error readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) const override;
+ Error readLongestContiguousChunk(uint32_t Offset,
+ ArrayRef<uint8_t> &Buffer) const override;
+ Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Buffer) const override;
+
+ uint32_t getLength() const override;
+ Error commit() const override;
+
+ uint32_t getNumBytesCopied() const;
+
+ static Expected<std::unique_ptr<MappedBlockStream>>
+ createIndexedStream(uint32_t StreamIdx, const IPDBFile &File);
+ static Expected<std::unique_ptr<MappedBlockStream>>
+ createDirectoryStream(const PDBFile &File);
+
+ llvm::BumpPtrAllocator &getAllocator() { return Pool; }
+
+protected:
+ MappedBlockStream(std::unique_ptr<IPDBStreamData> Data, const IPDBFile &File);
+
+ Error readBytes(uint32_t Offset, MutableArrayRef<uint8_t> Buffer) const;
+ bool tryReadContiguously(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) const;
+
+ const IPDBFile &Pdb;
+ std::unique_ptr<IPDBStreamData> Data;
+
+ typedef MutableArrayRef<uint8_t> CacheEntry;
+ mutable llvm::BumpPtrAllocator Pool;
+ mutable DenseMap<uint32_t, std::vector<CacheEntry>> CacheMap;
+};
+
+} // end namespace pdb
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_RAW_MAPPEDBLOCKSTREAM_H
diff --git a/include/llvm/DebugInfo/PDB/Raw/ModInfo.h b/include/llvm/DebugInfo/PDB/Raw/ModInfo.h
new file mode 100644
index 000000000000..b8da0bfabf38
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Raw/ModInfo.h
@@ -0,0 +1,79 @@
+//===- ModInfo.h - PDB module information -----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_MODINFO_H
+#define LLVM_DEBUGINFO_PDB_RAW_MODINFO_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/CodeView/StreamArray.h"
+#include "llvm/DebugInfo/CodeView/StreamRef.h"
+#include <cstdint>
+#include <vector>
+
+namespace llvm {
+namespace pdb {
+
+class ModInfo {
+private:
+ struct FileLayout;
+
+public:
+ ModInfo();
+ ModInfo(const ModInfo &Info);
+ ~ModInfo();
+
+ static Error initialize(codeview::StreamRef Stream, ModInfo &Info);
+
+ bool hasECInfo() const;
+ uint16_t getTypeServerIndex() const;
+ uint16_t getModuleStreamIndex() const;
+ uint32_t getSymbolDebugInfoByteSize() const;
+ uint32_t getLineInfoByteSize() const;
+ uint32_t getC13LineInfoByteSize() const;
+ uint32_t getNumberOfFiles() const;
+ uint32_t getSourceFileNameIndex() const;
+ uint32_t getPdbFilePathNameIndex() const;
+
+ StringRef getModuleName() const;
+ StringRef getObjFileName() const;
+
+ uint32_t getRecordLength() const;
+
+private:
+ StringRef ModuleName;
+ StringRef ObjFileName;
+ const FileLayout *Layout;
+};
+
+struct ModuleInfoEx {
+ ModuleInfoEx(const ModInfo &Info) : Info(Info) {}
+ ModuleInfoEx(const ModuleInfoEx &Ex)
+ : Info(Ex.Info), SourceFiles(Ex.SourceFiles) {}
+
+ ModInfo Info;
+ std::vector<StringRef> SourceFiles;
+};
+
+} // end namespace pdb
+
+namespace codeview {
+template <> struct VarStreamArrayExtractor<pdb::ModInfo> {
+ Error operator()(StreamRef Stream, uint32_t &Length,
+ pdb::ModInfo &Info) const {
+ if (auto EC = pdb::ModInfo::initialize(Stream, Info))
+ return EC;
+ Length = Info.getRecordLength();
+ return Error::success();
+ }
+};
+}
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_RAW_MODINFO_H
diff --git a/include/llvm/DebugInfo/PDB/Raw/ModStream.h b/include/llvm/DebugInfo/PDB/Raw/ModStream.h
new file mode 100644
index 000000000000..d22962cc1e28
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Raw/ModStream.h
@@ -0,0 +1,57 @@
+//===- ModStream.h - PDB Module Info Stream Access ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_MODSTREAM_H
+#define LLVM_DEBUGINFO_PDB_RAW_MODSTREAM_H
+
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/DebugInfo/CodeView/CVRecord.h"
+#include "llvm/DebugInfo/CodeView/ModuleSubstream.h"
+#include "llvm/DebugInfo/CodeView/StreamArray.h"
+#include "llvm/DebugInfo/CodeView/StreamRef.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace pdb {
+class PDBFile;
+class ModInfo;
+
+class ModStream {
+public:
+ ModStream(const ModInfo &Module, std::unique_ptr<MappedBlockStream> Stream);
+ ~ModStream();
+
+ Error reload();
+
+ iterator_range<codeview::CVSymbolArray::Iterator>
+ symbols(bool *HadError) const;
+
+ iterator_range<codeview::ModuleSubstreamArray::Iterator>
+ lines(bool *HadError) const;
+
+ Error commit();
+
+private:
+ const ModInfo &Mod;
+
+ std::unique_ptr<MappedBlockStream> Stream;
+
+ codeview::CVSymbolArray SymbolsSubstream;
+ codeview::StreamRef LinesSubstream;
+ codeview::StreamRef C13LinesSubstream;
+ codeview::StreamRef GlobalRefsSubstream;
+
+ codeview::ModuleSubstreamArray LineInfo;
+};
+}
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/Raw/MsfBuilder.h b/include/llvm/DebugInfo/PDB/Raw/MsfBuilder.h
new file mode 100644
index 000000000000..92d9bc042cce
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Raw/MsfBuilder.h
@@ -0,0 +1,141 @@
+//===- MSFBuilder.h - MSF Directory & Metadata Builder ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_MSFBUILDER_H
+#define LLVM_DEBUGINFO_PDB_RAW_MSFBUILDER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitVector.h"
+
+#include "llvm/DebugInfo/PDB/Raw/MsfCommon.h"
+#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
+
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+
+#include <utility>
+#include <vector>
+
+namespace llvm {
+namespace pdb {
+class MsfBuilder {
+public:
+ /// \brief Create a new `MsfBuilder`.
+ ///
+ /// \param BlockSize The internal block size used by the PDB file. See
+ /// isValidBlockSize() for a list of valid block sizes.
+ ///
+ /// \param MinBlockCount Causes the builder to reserve up front space for
+ /// at least `MinBlockCount` blocks. This is useful when using `MsfBuilder`
+ /// to read an existing PDB that you want to write back out later. The
+ /// original PDB file's SuperBlock contains the exact number of blocks used
+ /// by the file, so is a good hint as to how many blocks the new PDB file
+ /// will contain. Furthermore, it is actually necessary in this case. To
+ /// preserve stability of the file's layout, it is helpful to try to keep
+ /// all streams mapped to their original block numbers. To ensure that this
+ /// is possible, space for all blocks must be allocated beforehand so that
+ /// streams can be assigned to them.
+ ///
+ /// \param CanGrow If true, any operation which results in an attempt to
+ /// locate a free block when all available blocks have been exhausted will
+ /// allocate a new block, thereby growing the size of the final PDB file.
+ /// When false, any such attempt will result in an error. This is especially
+ /// useful in testing scenarios when you know your test isn't going to do
+ /// anything to increase the size of the file, so having an Error returned if
+ /// it were to happen would catch a programming error
+ ///
+ /// \returns an llvm::Error representing whether the operation succeeded or
+ /// failed. Currently the only way this can fail is if an invalid block size
+ /// is specified, or `MinBlockCount` does not leave enough room for the
+ /// mandatory reserved blocks required by an MSF file.
+ static Expected<MsfBuilder> create(BumpPtrAllocator &Allocator,
+ uint32_t BlockSize,
+ uint32_t MinBlockCount = 0,
+ bool CanGrow = true);
+
+ /// Request the block map to be at a specific block address. This is useful
+ /// when editing a PDB and you want the layout to be as stable as possible.
+ Error setBlockMapAddr(uint32_t Addr);
+ Error setDirectoryBlocksHint(ArrayRef<uint32_t> DirBlocks);
+ void setFreePageMap(uint32_t Fpm);
+ void setUnknown1(uint32_t Unk1);
+
+ /// Add a stream to the MSF file with the given size, occupying the given
+ /// list of blocks. This is useful when reading a PDB file and you want a
+ /// particular stream to occupy the original set of blocks. If the given
+ /// blocks are already allocated, or if the number of blocks specified is
+ /// incorrect for the given stream size, this function will return an Error.
+ Error addStream(uint32_t Size, ArrayRef<uint32_t> Blocks);
+
+ /// Add a stream to the MSF file with the given size, occupying any available
+ /// blocks that the builder decides to use. This is useful when building a
+ /// new PDB file from scratch and you don't care what blocks a stream occupies
+ /// but you just want it to work.
+ Error addStream(uint32_t Size);
+
+ /// Update the size of an existing stream. This will allocate or deallocate
+ /// blocks as needed to match the requested size. This can fail if `CanGrow`
+ /// was set to false when initializing the `MsfBuilder`.
+ Error setStreamSize(uint32_t Idx, uint32_t Size);
+
+ /// Get the total number of streams in the MSF layout. This should return 1
+ /// for every call to `addStream`.
+ uint32_t getNumStreams() const;
+
+ /// Get the size of a stream by index.
+ uint32_t getStreamSize(uint32_t StreamIdx) const;
+
+ /// Get the list of blocks allocated to a particular stream.
+ ArrayRef<uint32_t> getStreamBlocks(uint32_t StreamIdx) const;
+
+ /// Get the total number of blocks that will be allocated to actual data in
+ /// this MSF file.
+ uint32_t getNumUsedBlocks() const;
+
+ /// Get the total number of blocks that exist in the MSF file but are not
+ /// allocated to any valid data.
+ uint32_t getNumFreeBlocks() const;
+
+ /// Get the total number of blocks in the MSF file. In practice this is equal
+ /// to `getNumUsedBlocks() + getNumFreeBlocks()`.
+ uint32_t getTotalBlockCount() const;
+
+ /// Check whether a particular block is allocated or free.
+ bool isBlockFree(uint32_t Idx) const;
+
+ /// Finalize the layout and build the headers and structures that describe the
+ /// MSF layout and can be written directly to the MSF file.
+ Expected<msf::Layout> build();
+
+private:
+ MsfBuilder(uint32_t BlockSize, uint32_t MinBlockCount, bool CanGrow,
+ BumpPtrAllocator &Allocator);
+
+ Error allocateBlocks(uint32_t NumBlocks, MutableArrayRef<uint32_t> Blocks);
+ uint32_t computeDirectoryByteSize() const;
+
+ typedef std::vector<uint32_t> BlockList;
+
+ BumpPtrAllocator &Allocator;
+
+ bool IsGrowable;
+ uint32_t FreePageMap;
+ uint32_t Unknown1;
+ uint32_t BlockSize;
+ uint32_t MininumBlocks;
+ uint32_t BlockMapAddr;
+ BitVector FreeBlocks;
+ std::vector<uint32_t> DirectoryBlocks;
+ std::vector<std::pair<uint32_t, BlockList>> StreamData;
+};
+}
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/Raw/MsfCommon.h b/include/llvm/DebugInfo/PDB/Raw/MsfCommon.h
new file mode 100644
index 000000000000..2f6a6986eba9
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Raw/MsfCommon.h
@@ -0,0 +1,90 @@
+//===- MsfCommon.h - Common types and functions for MSF files ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_MSFCOMMON_H
+#define LLVM_DEBUGINFO_PDB_RAW_MSFCOMMON_H
+
+#include "llvm/ADT/ArrayRef.h"
+
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MathExtras.h"
+
+#include <vector>
+
+namespace llvm {
+namespace pdb {
+namespace msf {
+static const char Magic[] = {'M', 'i', 'c', 'r', 'o', 's', 'o', 'f',
+ 't', ' ', 'C', '/', 'C', '+', '+', ' ',
+ 'M', 'S', 'F', ' ', '7', '.', '0', '0',
+ '\r', '\n', '\x1a', 'D', 'S', '\0', '\0', '\0'};
+
+// The superblock is overlaid at the beginning of the file (offset 0).
+// It starts with a magic header and is followed by information which
+// describes the layout of the file system.
+struct SuperBlock {
+ char MagicBytes[sizeof(Magic)];
+ // The file system is split into a variable number of fixed size elements.
+ // These elements are referred to as blocks. The size of a block may vary
+ // from system to system.
+ support::ulittle32_t BlockSize;
+ // The index of the free block map.
+ support::ulittle32_t FreeBlockMapBlock;
+ // This contains the number of blocks resident in the file system. In
+ // practice, NumBlocks * BlockSize is equivalent to the size of the PDB
+ // file.
+ support::ulittle32_t NumBlocks;
+ // This contains the number of bytes which make up the directory.
+ support::ulittle32_t NumDirectoryBytes;
+ // This field's purpose is not yet known.
+ support::ulittle32_t Unknown1;
+ // This contains the block # of the block map.
+ support::ulittle32_t BlockMapAddr;
+};
+
+struct Layout {
+ SuperBlock *SB;
+ ArrayRef<support::ulittle32_t> DirectoryBlocks;
+ ArrayRef<support::ulittle32_t> StreamSizes;
+ std::vector<ArrayRef<support::ulittle32_t>> StreamMap;
+};
+
+inline bool isValidBlockSize(uint32_t Size) {
+ switch (Size) {
+ case 512:
+ case 1024:
+ case 2048:
+ case 4096:
+ return true;
+ }
+ return false;
+}
+
+// Super Block, Fpm0, Fpm1, and Block Map
+inline uint32_t getMinimumBlockCount() { return 4; }
+
+// Super Block, Fpm0, and Fpm1 are reserved. The Block Map, although required
+// need not be at block 3.
+inline uint32_t getFirstUnreservedBlock() { return 3; }
+
+inline uint64_t bytesToBlocks(uint64_t NumBytes, uint64_t BlockSize) {
+ return alignTo(NumBytes, BlockSize) / BlockSize;
+}
+
+inline uint64_t blockToOffset(uint64_t BlockNumber, uint64_t BlockSize) {
+ return BlockNumber * BlockSize;
+}
+
+Error validateSuperBlock(const SuperBlock &SB);
+}
+}
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/Raw/NameHashTable.h b/include/llvm/DebugInfo/PDB/Raw/NameHashTable.h
new file mode 100644
index 000000000000..c9e060a3a70f
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Raw/NameHashTable.h
@@ -0,0 +1,54 @@
+//===- NameHashTable.h - PDB Name Hash Table --------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_NAMEHASHTABLE_H
+#define LLVM_DEBUGINFO_PDB_RAW_NAMEHASHTABLE_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/CodeView/StreamArray.h"
+#include "llvm/DebugInfo/CodeView/StreamRef.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include <cstdint>
+#include <vector>
+
+namespace llvm {
+namespace codeview {
+class StreamReader;
+}
+namespace pdb {
+
+class NameHashTable {
+public:
+ NameHashTable();
+
+ Error load(codeview::StreamReader &Stream);
+
+ uint32_t getNameCount() const { return NameCount; }
+ uint32_t getHashVersion() const { return HashVersion; }
+ uint32_t getSignature() const { return Signature; }
+
+ StringRef getStringForID(uint32_t ID) const;
+ uint32_t getIDForString(StringRef Str) const;
+
+ codeview::FixedStreamArray<support::ulittle32_t> name_ids() const;
+
+private:
+ codeview::StreamRef NamesBuffer;
+ codeview::FixedStreamArray<support::ulittle32_t> IDs;
+ uint32_t Signature;
+ uint32_t HashVersion;
+ uint32_t NameCount;
+};
+
+} // end namespace pdb
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_RAW_NAMEHASHTABLE_H
diff --git a/include/llvm/DebugInfo/PDB/Raw/NameMap.h b/include/llvm/DebugInfo/PDB/Raw/NameMap.h
new file mode 100644
index 000000000000..8a9b0d187ace
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Raw/NameMap.h
@@ -0,0 +1,45 @@
+//===- NameMap.h - PDB Name Map ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBNAMEMAP_H
+#define LLVM_DEBUGINFO_PDB_RAW_PDBNAMEMAP_H
+
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+#include <cstdint>
+
+namespace llvm {
+namespace codeview {
+class StreamReader;
+class StreamWriter;
+}
+namespace pdb {
+class NameMapBuilder;
+class NameMap {
+ friend NameMapBuilder;
+
+public:
+ NameMap();
+
+ Error load(codeview::StreamReader &Stream);
+ Error commit(codeview::StreamWriter &Writer);
+
+ bool tryGetValue(StringRef Name, uint32_t &Value) const;
+
+ iterator_range<StringMapConstIterator<uint32_t>> entries() const;
+
+private:
+ StringMap<uint32_t> Mapping;
+};
+
+} // end namespace pdb
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_RAW_PDBNAMEMAP_H
diff --git a/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h b/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h
new file mode 100644
index 000000000000..bf49bfd9bf2e
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h
@@ -0,0 +1,41 @@
+//===- NameMapBuilder.h - PDB Name Map Builder ------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBNAMEMAPBUILDER_H
+#define LLVM_DEBUGINFO_PDB_RAW_PDBNAMEMAPBUILDER_H
+
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Error.h"
+
+#include <cstdint>
+#include <memory>
+
+namespace llvm {
+namespace pdb {
+class NameMap;
+
+class NameMapBuilder {
+public:
+ NameMapBuilder();
+
+ void addMapping(StringRef Name, uint32_t Mapping);
+
+ Expected<std::unique_ptr<NameMap>> build();
+
+ uint32_t calculateSerializedLength() const;
+
+private:
+ StringMap<uint32_t> Map;
+ uint32_t StringDataBytes = 0;
+};
+
+} // end namespace pdb
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_RAW_PDBNAMEMAPBUILDER_H
diff --git a/include/llvm/DebugInfo/PDB/Raw/PDBFile.h b/include/llvm/DebugInfo/PDB/Raw/PDBFile.h
new file mode 100644
index 000000000000..f4d7eb47d3b9
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Raw/PDBFile.h
@@ -0,0 +1,113 @@
+//===- PDBFile.h - Low level interface to a PDB file ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBFILE_H
+#define LLVM_DEBUGINFO_PDB_RAW_PDBFILE_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/DebugInfo/CodeView/StreamArray.h"
+#include "llvm/DebugInfo/CodeView/StreamInterface.h"
+#include "llvm/DebugInfo/PDB/Raw/IPDBFile.h"
+#include "llvm/DebugInfo/PDB/Raw/MsfCommon.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MathExtras.h"
+
+#include <memory>
+
+namespace llvm {
+
+namespace codeview {
+class StreamInterface;
+}
+
+namespace pdb {
+class DbiStream;
+class InfoStream;
+class MappedBlockStream;
+class NameHashTable;
+class PDBFileBuilder;
+class PublicsStream;
+class SymbolStream;
+class TpiStream;
+
+class PDBFile : public IPDBFile {
+ friend PDBFileBuilder;
+
+public:
+ explicit PDBFile(std::unique_ptr<codeview::StreamInterface> PdbFileBuffer);
+ ~PDBFile() override;
+
+ uint32_t getFreeBlockMapBlock() const;
+ uint32_t getUnknown1() const;
+
+ uint32_t getBlockSize() const override;
+ uint32_t getBlockCount() const override;
+ uint32_t getNumDirectoryBytes() const;
+ uint32_t getBlockMapIndex() const;
+ uint32_t getNumDirectoryBlocks() const;
+ uint64_t getBlockMapOffset() const;
+
+ uint32_t getNumStreams() const override;
+ uint32_t getStreamByteSize(uint32_t StreamIndex) const override;
+ ArrayRef<support::ulittle32_t>
+ getStreamBlockList(uint32_t StreamIndex) const override;
+ uint32_t getFileSize() const;
+
+ Expected<ArrayRef<uint8_t>> getBlockData(uint32_t BlockIndex,
+ uint32_t NumBytes) const override;
+ Error setBlockData(uint32_t BlockIndex, uint32_t Offset,
+ ArrayRef<uint8_t> Data) const override;
+
+ ArrayRef<support::ulittle32_t> getStreamSizes() const { return StreamSizes; }
+ ArrayRef<ArrayRef<support::ulittle32_t>> getStreamMap() const {
+ return StreamMap;
+ }
+
+ ArrayRef<support::ulittle32_t> getDirectoryBlockArray() const;
+
+ Error parseFileHeaders();
+ Error parseStreamData();
+
+ Expected<InfoStream &> getPDBInfoStream();
+ Expected<DbiStream &> getPDBDbiStream();
+ Expected<TpiStream &> getPDBTpiStream();
+ Expected<TpiStream &> getPDBIpiStream();
+ Expected<PublicsStream &> getPDBPublicsStream();
+ Expected<SymbolStream &> getPDBSymbolStream();
+ Expected<NameHashTable &> getStringTable();
+
+ Error commit();
+
+private:
+ Error setSuperBlock(const msf::SuperBlock *Block);
+
+ BumpPtrAllocator Allocator;
+
+ std::unique_ptr<codeview::StreamInterface> Buffer;
+ const msf::SuperBlock *SB;
+ ArrayRef<support::ulittle32_t> StreamSizes;
+ ArrayRef<support::ulittle32_t> DirectoryBlocks;
+ std::vector<ArrayRef<support::ulittle32_t>> StreamMap;
+
+ std::unique_ptr<InfoStream> Info;
+ std::unique_ptr<DbiStream> Dbi;
+ std::unique_ptr<TpiStream> Tpi;
+ std::unique_ptr<TpiStream> Ipi;
+ std::unique_ptr<PublicsStream> Publics;
+ std::unique_ptr<SymbolStream> Symbols;
+ std::unique_ptr<MappedBlockStream> DirectoryStream;
+ std::unique_ptr<MappedBlockStream> StringTableStream;
+ std::unique_ptr<NameHashTable> StringTable;
+};
+}
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h b/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h
new file mode 100644
index 000000000000..47c755b43269
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h
@@ -0,0 +1,59 @@
+//===- PDBFileBuilder.h - PDB File Creation ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBFILEBUILDER_H
+#define LLVM_DEBUGINFO_PDB_RAW_PDBFILEBUILDER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+
+#include "llvm/DebugInfo/PDB/Raw/MsfBuilder.h"
+#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
+
+#include <memory>
+#include <vector>
+
+namespace llvm {
+namespace codeview {
+class StreamInterface;
+}
+namespace pdb {
+class DbiStreamBuilder;
+class InfoStreamBuilder;
+class PDBFile;
+
+class PDBFileBuilder {
+public:
+ explicit PDBFileBuilder(
+ std::unique_ptr<codeview::StreamInterface> FileBuffer);
+ PDBFileBuilder(const PDBFileBuilder &) = delete;
+ PDBFileBuilder &operator=(const PDBFileBuilder &) = delete;
+
+ Error initialize(const msf::SuperBlock &Super);
+
+ MsfBuilder &getMsfBuilder();
+ InfoStreamBuilder &getInfoBuilder();
+ DbiStreamBuilder &getDbiBuilder();
+
+ Expected<std::unique_ptr<PDBFile>> build();
+
+private:
+ std::unique_ptr<InfoStreamBuilder> Info;
+ std::unique_ptr<DbiStreamBuilder> Dbi;
+
+ std::unique_ptr<PDBFile> File;
+ std::unique_ptr<MsfBuilder> Msf;
+};
+}
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/Raw/PublicsStream.h b/include/llvm/DebugInfo/PDB/Raw/PublicsStream.h
new file mode 100644
index 000000000000..f5bfb0ed60a9
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Raw/PublicsStream.h
@@ -0,0 +1,74 @@
+//===- PublicsStream.h - PDB Public Symbol Stream -------- ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_PUBLICSSTREAM_H
+#define LLVM_DEBUGINFO_PDB_RAW_PUBLICSSTREAM_H
+
+#include "llvm/DebugInfo/CodeView/StreamArray.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
+
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace pdb {
+class DbiStream;
+class PDBFile;
+
+class PublicsStream {
+ struct GSIHashHeader;
+ struct HeaderInfo;
+
+public:
+ PublicsStream(PDBFile &File, std::unique_ptr<MappedBlockStream> Stream);
+ ~PublicsStream();
+ Error reload();
+
+ uint32_t getSymHash() const;
+ uint32_t getAddrMap() const;
+ uint32_t getNumBuckets() const { return NumBuckets; }
+ iterator_range<codeview::CVSymbolArray::Iterator>
+ getSymbols(bool *HadError) const;
+ codeview::FixedStreamArray<support::ulittle32_t> getHashBuckets() const {
+ return HashBuckets;
+ }
+ codeview::FixedStreamArray<support::ulittle32_t> getAddressMap() const {
+ return AddressMap;
+ }
+ codeview::FixedStreamArray<support::ulittle32_t> getThunkMap() const {
+ return ThunkMap;
+ }
+ codeview::FixedStreamArray<SectionOffset> getSectionOffsets() const {
+ return SectionOffsets;
+ }
+
+ Error commit();
+
+private:
+ PDBFile &Pdb;
+
+ std::unique_ptr<MappedBlockStream> Stream;
+ uint32_t NumBuckets = 0;
+ ArrayRef<uint8_t> Bitmap;
+ codeview::FixedStreamArray<PSHashRecord> HashRecords;
+ codeview::FixedStreamArray<support::ulittle32_t> HashBuckets;
+ codeview::FixedStreamArray<support::ulittle32_t> AddressMap;
+ codeview::FixedStreamArray<support::ulittle32_t> ThunkMap;
+ codeview::FixedStreamArray<SectionOffset> SectionOffsets;
+
+ const HeaderInfo *Header;
+ const GSIHashHeader *HashHdr;
+};
+}
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/Raw/RawConstants.h b/include/llvm/DebugInfo/PDB/Raw/RawConstants.h
new file mode 100644
index 000000000000..8daaf47882d8
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Raw/RawConstants.h
@@ -0,0 +1,94 @@
+//===- RawConstants.h -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBRAWCONSTANTS_H
+#define LLVM_DEBUGINFO_PDB_RAW_PDBRAWCONSTANTS_H
+
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+
+#include <cstdint>
+
+namespace llvm {
+namespace pdb {
+
+enum PdbRaw_ImplVer : uint32_t {
+ PdbImplVC2 = 19941610,
+ PdbImplVC4 = 19950623,
+ PdbImplVC41 = 19950814,
+ PdbImplVC50 = 19960307,
+ PdbImplVC98 = 19970604,
+ PdbImplVC70Dep = 19990604, // deprecated
+ PdbImplVC70 = 20000404,
+ PdbImplVC80 = 20030901,
+ PdbImplVC110 = 20091201,
+ PdbImplVC140 = 20140508,
+};
+
+enum PdbRaw_DbiVer : uint32_t {
+ PdbDbiVC41 = 930803,
+ PdbDbiV50 = 19960307,
+ PdbDbiV60 = 19970606,
+ PdbDbiV70 = 19990903,
+ PdbDbiV110 = 20091201
+};
+
+enum PdbRaw_TpiVer : uint32_t {
+ PdbTpiV40 = 19950410,
+ PdbTpiV41 = 19951122,
+ PdbTpiV50 = 19961031,
+ PdbTpiV70 = 19990903,
+ PdbTpiV80 = 20040203,
+};
+
+enum PdbRaw_DbiSecContribVer : uint32_t {
+ DbiSecContribVer60 = 0xeffe0000 + 19970605,
+ DbiSecContribV2 = 0xeffe0000 + 20140516
+};
+
+enum SpecialStream : uint32_t {
+ // Stream 0 contains the copy of previous version of the MSF directory.
+ // We are not currently using it, but technically if we find the main
+ // MSF is corrupted, we could fallback to it.
+ OldMSFDirectory = 0,
+
+ StreamPDB = 1,
+ StreamTPI = 2,
+ StreamDBI = 3,
+ StreamIPI = 4,
+};
+
+enum class DbgHeaderType : uint16_t {
+ FPO,
+ Exception,
+ Fixup,
+ OmapToSrc,
+ OmapFromSrc,
+ SectionHdr,
+ TokenRidMap,
+ Xdata,
+ Pdata,
+ NewFPO,
+ SectionHdrOrig,
+ Max
+};
+
+enum class OMFSegDescFlags : uint16_t {
+ Read = 1 << 0, // Segment is readable.
+ Write = 1 << 1, // Segment is writable.
+ Execute = 1 << 2, // Segment is executable.
+ AddressIs32Bit = 1 << 3, // Descriptor describes a 32-bit linear address.
+ IsSelector = 1 << 8, // Frame represents a selector.
+ IsAbsoluteAddress = 1 << 9, // Frame represents an absolute address.
+ IsGroup = 1 << 10 // If set, descriptor represents a group.
+};
+
+} // end namespace pdb
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_RAW_PDBRAWCONSTANTS_H
diff --git a/include/llvm/DebugInfo/PDB/Raw/RawError.h b/include/llvm/DebugInfo/PDB/Raw/RawError.h
new file mode 100644
index 000000000000..b0687cddbf48
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Raw/RawError.h
@@ -0,0 +1,49 @@
+//===- RawError.h - Error extensions for raw PDB implementation -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_RAWERROR_H
+#define LLVM_DEBUGINFO_PDB_RAW_RAWERROR_H
+
+#include "llvm/Support/Error.h"
+
+#include <string>
+
+namespace llvm {
+namespace pdb {
+enum class raw_error_code {
+ unspecified = 1,
+ feature_unsupported,
+ corrupt_file,
+ insufficient_buffer,
+ no_stream,
+ index_out_of_bounds,
+ invalid_block_address,
+ not_writable,
+ invalid_tpi_hash,
+};
+
+/// Base class for errors originating when parsing raw PDB files
+class RawError : public ErrorInfo<RawError> {
+public:
+ static char ID;
+ RawError(raw_error_code C);
+ RawError(const std::string &Context);
+ RawError(raw_error_code C, const std::string &Context);
+
+ void log(raw_ostream &OS) const override;
+ const std::string &getErrorMessage() const;
+ std::error_code convertToErrorCode() const override;
+
+private:
+ std::string ErrMsg;
+ raw_error_code Code;
+};
+}
+}
+#endif
diff --git a/include/llvm/DebugInfo/PDB/Raw/RawSession.h b/include/llvm/DebugInfo/PDB/Raw/RawSession.h
new file mode 100644
index 000000000000..73d281eab1a7
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Raw/RawSession.h
@@ -0,0 +1,75 @@
+//===- RawSession.h - Native implementation of IPDBSession ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_RAWSESSION_H
+#define LLVM_DEBUGINFO_PDB_RAW_RAWSESSION_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace pdb {
+class PDBFile;
+
+class RawSession : public IPDBSession {
+public:
+ explicit RawSession(std::unique_ptr<PDBFile> PdbFile);
+ ~RawSession() override;
+
+ static Error createFromPdb(StringRef Path,
+ std::unique_ptr<IPDBSession> &Session);
+ static Error createFromExe(StringRef Path,
+ std::unique_ptr<IPDBSession> &Session);
+
+ uint64_t getLoadAddress() const override;
+ void setLoadAddress(uint64_t Address) override;
+ std::unique_ptr<PDBSymbolExe> getGlobalScope() const override;
+ std::unique_ptr<PDBSymbol> getSymbolById(uint32_t SymbolId) const override;
+
+ std::unique_ptr<PDBSymbol>
+ findSymbolByAddress(uint64_t Address, PDB_SymType Type) const override;
+
+ std::unique_ptr<IPDBEnumLineNumbers>
+ findLineNumbers(const PDBSymbolCompiland &Compiland,
+ const IPDBSourceFile &File) const override;
+ std::unique_ptr<IPDBEnumLineNumbers>
+ findLineNumbersByAddress(uint64_t Address, uint32_t Length) const override;
+
+ std::unique_ptr<IPDBEnumSourceFiles>
+ findSourceFiles(const PDBSymbolCompiland *Compiland, llvm::StringRef Pattern,
+ PDB_NameSearchFlags Flags) const override;
+ std::unique_ptr<IPDBSourceFile>
+ findOneSourceFile(const PDBSymbolCompiland *Compiland,
+ llvm::StringRef Pattern,
+ PDB_NameSearchFlags Flags) const override;
+ std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>>
+ findCompilandsForSourceFile(llvm::StringRef Pattern,
+ PDB_NameSearchFlags Flags) const override;
+ std::unique_ptr<PDBSymbolCompiland>
+ findOneCompilandForSourceFile(llvm::StringRef Pattern,
+ PDB_NameSearchFlags Flags) const override;
+ std::unique_ptr<IPDBEnumSourceFiles> getAllSourceFiles() const override;
+ std::unique_ptr<IPDBEnumSourceFiles> getSourceFilesForCompiland(
+ const PDBSymbolCompiland &Compiland) const override;
+ std::unique_ptr<IPDBSourceFile>
+ getSourceFileById(uint32_t FileId) const override;
+
+ std::unique_ptr<IPDBEnumDataStreams> getDebugStreams() const override;
+
+ PDBFile &getPDBFile() { return *Pdb; }
+ const PDBFile &getPDBFile() const { return *Pdb; }
+
+private:
+ std::unique_ptr<PDBFile> Pdb;
+};
+}
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/Raw/RawTypes.h b/include/llvm/DebugInfo/PDB/Raw/RawTypes.h
new file mode 100644
index 000000000000..afcfe9405c0f
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Raw/RawTypes.h
@@ -0,0 +1,86 @@
+//===- RawTypes.h -----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_RAWTYPES_H
+#define LLVM_DEBUGINFO_PDB_RAW_RAWTYPES_H
+
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/Support/Endian.h"
+
+namespace llvm {
+namespace pdb {
+// This struct is defined as "SO" in langapi/include/pdb.h.
+struct SectionOffset {
+ support::ulittle32_t Off;
+ support::ulittle16_t Isect;
+ char Padding[2];
+};
+
+// This is HRFile.
+struct PSHashRecord {
+ support::ulittle32_t Off; // Offset in the symbol record stream
+ support::ulittle32_t CRef;
+};
+
+// This struct is defined as `SC` in include/dbicommon.h
+struct SectionContrib {
+ support::ulittle16_t ISect;
+ char Padding[2];
+ support::little32_t Off;
+ support::little32_t Size;
+ support::ulittle32_t Characteristics;
+ support::ulittle16_t Imod;
+ char Padding2[2];
+ support::ulittle32_t DataCrc;
+ support::ulittle32_t RelocCrc;
+};
+
+// This struct is defined as `SC2` in include/dbicommon.h
+struct SectionContrib2 {
+ // To guarantee SectionContrib2 is standard layout, we cannot use inheritance.
+ SectionContrib Base;
+ support::ulittle32_t ISectCoff;
+};
+
+// This corresponds to the `OMFSegMap` structure.
+struct SecMapHeader {
+ support::ulittle16_t SecCount; // Number of segment descriptors in table
+ support::ulittle16_t SecCountLog; // Number of logical segment descriptors
+};
+
+// This corresponds to the `OMFSegMapDesc` structure. The definition is not
+// present in the reference implementation, but the layout is derived from
+// code that accesses the fields.
+struct SecMapEntry {
+ support::ulittle16_t Flags; // Descriptor flags. See OMFSegDescFlags
+ support::ulittle16_t Ovl; // Logical overlay number.
+ support::ulittle16_t Group; // Group index into descriptor array.
+ support::ulittle16_t Frame;
+ support::ulittle16_t SecName; // Byte index of the segment or group name
+ // in the sstSegName table, or 0xFFFF.
+ support::ulittle16_t ClassName; // Byte index of the class name in the
+ // sstSegName table, or 0xFFFF.
+ support::ulittle32_t Offset; // Byte offset of the logical segment
+ // within the specified physical segment.
+ // If group is set in flags, offset is the
+ // offset of the group.
+ support::ulittle32_t SecByteLength; // Byte count of the segment or group.
+};
+
+// Used for serialized hash table in TPI stream.
+// In the reference, it is an array of TI and cbOff pair.
+struct TypeIndexOffset {
+ codeview::TypeIndex Type;
+ support::ulittle32_t Offset;
+};
+
+} // namespace pdb
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/Raw/SymbolStream.h b/include/llvm/DebugInfo/PDB/Raw/SymbolStream.h
new file mode 100644
index 000000000000..685a23411a3b
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Raw/SymbolStream.h
@@ -0,0 +1,41 @@
+//===- SymbolStream.cpp - PDB Symbol Stream Access --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBSYMBOLSTREAM_H
+#define LLVM_DEBUGINFO_PDB_RAW_PDBSYMBOLSTREAM_H
+
+#include "llvm/DebugInfo/CodeView/StreamArray.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
+
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace pdb {
+class PDBFile;
+
+class SymbolStream {
+public:
+ SymbolStream(std::unique_ptr<MappedBlockStream> Stream);
+ ~SymbolStream();
+ Error reload();
+
+ iterator_range<codeview::CVSymbolArray::Iterator>
+ getSymbols(bool *HadError) const;
+
+ Error commit();
+
+private:
+ codeview::CVSymbolArray SymbolRecords;
+ std::unique_ptr<MappedBlockStream> Stream;
+};
+}
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/Raw/TpiStream.h b/include/llvm/DebugInfo/PDB/Raw/TpiStream.h
new file mode 100644
index 000000000000..4f36d70aabed
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Raw/TpiStream.h
@@ -0,0 +1,72 @@
+//===- TpiStream.cpp - PDB Type Info (TPI) Stream 2 Access ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBTPISTREAM_H
+#define LLVM_DEBUGINFO_PDB_RAW_PDBTPISTREAM_H
+
+#include "llvm/DebugInfo/CodeView/StreamArray.h"
+#include "llvm/DebugInfo/CodeView/StreamRef.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace pdb {
+class PDBFile;
+
+class TpiStream {
+ struct HeaderInfo;
+
+public:
+ TpiStream(const PDBFile &File, std::unique_ptr<MappedBlockStream> Stream);
+ ~TpiStream();
+ Error reload();
+
+ PdbRaw_TpiVer getTpiVersion() const;
+
+ uint32_t TypeIndexBegin() const;
+ uint32_t TypeIndexEnd() const;
+ uint32_t NumTypeRecords() const;
+ uint16_t getTypeHashStreamIndex() const;
+ uint16_t getTypeHashStreamAuxIndex() const;
+
+ uint32_t getHashKeySize() const;
+ uint32_t NumHashBuckets() const;
+ codeview::FixedStreamArray<support::ulittle32_t> getHashValues() const;
+ codeview::FixedStreamArray<TypeIndexOffset> getTypeIndexOffsets() const;
+ codeview::FixedStreamArray<TypeIndexOffset> getHashAdjustments() const;
+
+ iterator_range<codeview::CVTypeArray::Iterator> types(bool *HadError) const;
+
+ Error commit();
+
+private:
+ Error verifyHashValues();
+
+ const PDBFile &Pdb;
+ std::unique_ptr<MappedBlockStream> Stream;
+
+ codeview::CVTypeArray TypeRecords;
+
+ std::unique_ptr<MappedBlockStream> HashStream;
+ codeview::FixedStreamArray<support::ulittle32_t> HashValues;
+ codeview::FixedStreamArray<TypeIndexOffset> TypeIndexOffsets;
+ codeview::FixedStreamArray<TypeIndexOffset> HashAdjustments;
+
+ const HeaderInfo *Header;
+};
+}
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/Symbolize/DIPrinter.h b/include/llvm/DebugInfo/Symbolize/DIPrinter.h
index 3098199bb4da..49f86eae01cf 100644
--- a/include/llvm/DebugInfo/Symbolize/DIPrinter.h
+++ b/include/llvm/DebugInfo/Symbolize/DIPrinter.h
@@ -31,7 +31,7 @@ class DIPrinter {
int PrintSourceContext;
void print(const DILineInfo &Info, bool Inlined);
- void printContext(std::string FileName, int64_t Line);
+ void printContext(const std::string &FileName, int64_t Line);
public:
DIPrinter(raw_ostream &OS, bool PrintFunctionNames = true,
diff --git a/include/llvm/DebugInfo/Symbolize/SymbolizableModule.h b/include/llvm/DebugInfo/Symbolize/SymbolizableModule.h
index ff9cc808875d..e0bec6f6cf85 100644
--- a/include/llvm/DebugInfo/Symbolize/SymbolizableModule.h
+++ b/include/llvm/DebugInfo/Symbolize/SymbolizableModule.h
@@ -14,8 +14,6 @@
#define LLVM_DEBUGINFO_SYMBOLIZE_SYMBOLIZABLEMODULE_H
#include "llvm/DebugInfo/DIContext.h"
-#include <memory>
-#include <string>
namespace llvm {
namespace object {
diff --git a/include/llvm/DebugInfo/Symbolize/Symbolize.h b/include/llvm/DebugInfo/Symbolize/Symbolize.h
index ec3ae002659c..9253adf7eedd 100644
--- a/include/llvm/DebugInfo/Symbolize/Symbolize.h
+++ b/include/llvm/DebugInfo/Symbolize/Symbolize.h
@@ -19,6 +19,7 @@
#include <map>
#include <memory>
#include <string>
+#include <utility>
namespace llvm {
namespace symbolize {
@@ -40,7 +41,7 @@ public:
bool RelativeAddresses = false, std::string DefaultArch = "")
: PrintFunctions(PrintFunctions), UseSymbolTable(UseSymbolTable),
Demangle(Demangle), RelativeAddresses(RelativeAddresses),
- DefaultArch(DefaultArch) {}
+ DefaultArch(std::move(DefaultArch)) {}
};
LLVMSymbolizer(const Options &Opts = Options()) : Opts(Opts) {}
@@ -48,12 +49,12 @@ public:
flush();
}
- ErrorOr<DILineInfo> symbolizeCode(const std::string &ModuleName,
- uint64_t ModuleOffset);
- ErrorOr<DIInliningInfo> symbolizeInlinedCode(const std::string &ModuleName,
- uint64_t ModuleOffset);
- ErrorOr<DIGlobal> symbolizeData(const std::string &ModuleName,
- uint64_t ModuleOffset);
+ Expected<DILineInfo> symbolizeCode(const std::string &ModuleName,
+ uint64_t ModuleOffset);
+ Expected<DIInliningInfo> symbolizeInlinedCode(const std::string &ModuleName,
+ uint64_t ModuleOffset);
+ Expected<DIGlobal> symbolizeData(const std::string &ModuleName,
+ uint64_t ModuleOffset);
void flush();
static std::string DemangleName(const std::string &Name,
const SymbolizableModule *ModInfo);
@@ -63,8 +64,13 @@ private:
// corresponding debug info. These objects can be the same.
typedef std::pair<ObjectFile*, ObjectFile*> ObjectPair;
- ErrorOr<SymbolizableModule *>
+ /// Returns a SymbolizableModule or an error if loading debug info failed.
+ /// Only one attempt is made to load a module, and errors during loading are
+ /// only reported once. Subsequent calls to get module info for a module that
+ /// failed to load will return nullptr.
+ Expected<SymbolizableModule *>
getOrCreateModuleInfo(const std::string &ModuleName);
+
ObjectFile *lookUpDsymFile(const std::string &Path,
const MachOObjectFile *ExeObj,
const std::string &ArchName);
@@ -73,27 +79,27 @@ private:
const std::string &ArchName);
/// \brief Returns pair of pointers to object and debug object.
- ErrorOr<ObjectPair> getOrCreateObjectPair(const std::string &Path,
+ Expected<ObjectPair> getOrCreateObjectPair(const std::string &Path,
const std::string &ArchName);
/// \brief Return a pointer to object file at specified path, for a specified
/// architecture (e.g. if path refers to a Mach-O universal binary, only one
/// object file from it will be returned).
- ErrorOr<ObjectFile *> getOrCreateObject(const std::string &Path,
+ Expected<ObjectFile *> getOrCreateObject(const std::string &Path,
const std::string &ArchName);
- std::map<std::string, ErrorOr<std::unique_ptr<SymbolizableModule>>> Modules;
+ std::map<std::string, std::unique_ptr<SymbolizableModule>> Modules;
/// \brief Contains cached results of getOrCreateObjectPair().
- std::map<std::pair<std::string, std::string>, ErrorOr<ObjectPair>>
+ std::map<std::pair<std::string, std::string>, ObjectPair>
ObjectPairForPathArch;
/// \brief Contains parsed binary for each path, or parsing error.
- std::map<std::string, ErrorOr<OwningBinary<Binary>>> BinaryForPath;
+ std::map<std::string, OwningBinary<Binary>> BinaryForPath;
/// \brief Parsed object file for path/architecture pair, where "path" refers
/// to Mach-O universal binary.
- std::map<std::pair<std::string, std::string>, ErrorOr<std::unique_ptr<ObjectFile>>>
+ std::map<std::pair<std::string, std::string>, std::unique_ptr<ObjectFile>>
ObjectForUBPathAndArch;
Options Opts;
diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h
index a7302602dcd8..ab13028b3ae0 100644
--- a/include/llvm/ExecutionEngine/ExecutionEngine.h
+++ b/include/llvm/ExecutionEngine/ExecutionEngine.h
@@ -22,7 +22,6 @@
#include "llvm/IR/Module.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/IR/ValueMap.h"
-#include "llvm/MC/MCCodeGenInfo.h"
#include "llvm/Object/Binary.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Mutex.h"
@@ -290,7 +289,8 @@ public:
/// at the specified location. This is used internally as functions are JIT'd
/// and as global variables are laid out in memory. It can and should also be
/// used by clients of the EE that want to have an LLVM global overlay
- /// existing data in memory. Mappings are automatically removed when their
+ /// existing data in memory. Values to be mapped should be named, and have
+ /// external or weak linkage. Mappings are automatically removed when their
/// GlobalValue is destroyed.
void addGlobalMapping(const GlobalValue *GV, void *Addr);
void addGlobalMapping(StringRef Name, uint64_t Addr);
@@ -477,11 +477,11 @@ public:
/// specified function pointer is invoked to create it. If it returns null,
/// the JIT will abort.
void InstallLazyFunctionCreator(FunctionCreator C) {
- LazyFunctionCreator = C;
+ LazyFunctionCreator = std::move(C);
}
protected:
- ExecutionEngine(const DataLayout DL) : DL(std::move(DL)){}
+ ExecutionEngine(DataLayout DL) : DL(std::move(DL)) {}
explicit ExecutionEngine(DataLayout DL, std::unique_ptr<Module> M);
explicit ExecutionEngine(std::unique_ptr<Module> M);
@@ -518,7 +518,7 @@ private:
std::shared_ptr<MCJITMemoryManager> MemMgr;
std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver;
TargetOptions Options;
- Reloc::Model RelocModel;
+ Optional<Reloc::Model> RelocModel;
CodeModel::Model CMModel;
std::string MArch;
std::string MCPU;
diff --git a/include/llvm/ExecutionEngine/GenericValue.h b/include/llvm/ExecutionEngine/GenericValue.h
index 0e92f79eba8f..537745519ddb 100644
--- a/include/llvm/ExecutionEngine/GenericValue.h
+++ b/include/llvm/ExecutionEngine/GenericValue.h
@@ -17,6 +17,7 @@
#include "llvm/ADT/APInt.h"
#include "llvm/Support/DataTypes.h"
+#include <vector>
namespace llvm {
diff --git a/include/llvm/ExecutionEngine/JITEventListener.h b/include/llvm/ExecutionEngine/JITEventListener.h
index c3edec868783..be7c0448bb78 100644
--- a/include/llvm/ExecutionEngine/JITEventListener.h
+++ b/include/llvm/ExecutionEngine/JITEventListener.h
@@ -81,7 +81,7 @@ public:
// Get a pointe to the GDB debugger registration listener.
static JITEventListener *createGDBRegistrationListener();
-#if LLVM_USE_INTEL_JITEVENTS
+#if defined(LLVM_USE_INTEL_JITEVENTS) && LLVM_USE_INTEL_JITEVENTS
// Construct an IntelJITEventListener
static JITEventListener *createIntelJITEventListener();
@@ -97,7 +97,7 @@ public:
}
#endif // USE_INTEL_JITEVENTS
-#if LLVM_USE_OPROFILE
+#if defined(LLVM_USE_OPROFILE) && LLVM_USE_OPROFILE
// Construct an OProfileJITEventListener
static JITEventListener *createOProfileJITEventListener();
diff --git a/include/llvm/ExecutionEngine/JITSymbolFlags.h b/include/llvm/ExecutionEngine/JITSymbolFlags.h
index 450e9481fa00..7e1d57dabc81 100644
--- a/include/llvm/ExecutionEngine/JITSymbolFlags.h
+++ b/include/llvm/ExecutionEngine/JITSymbolFlags.h
@@ -15,6 +15,7 @@
#define LLVM_EXECUTIONENGINE_JITSYMBOLFLAGS_H
#include "llvm/IR/GlobalValue.h"
+#include "llvm/Object/SymbolicFile.h"
namespace llvm {
@@ -69,7 +70,16 @@ public:
if (!GV.hasLocalLinkage() && !GV.hasHiddenVisibility())
Flags |= JITSymbolFlags::Exported;
return Flags;
+ }
+ static JITSymbolFlags
+ flagsFromObjectSymbol(const object::BasicSymbolRef &Symbol) {
+ JITSymbolFlags Flags = JITSymbolFlags::None;
+ if (Symbol.getFlags() & object::BasicSymbolRef::SF_Weak)
+ Flags |= JITSymbolFlags::Weak;
+ if (Symbol.getFlags() & object::BasicSymbolRef::SF_Exported)
+ Flags |= JITSymbolFlags::Exported;
+ return Flags;
}
private:
diff --git a/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
index 84af4728b350..ef88dd03ad4f 100644
--- a/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
+++ b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
@@ -19,12 +19,12 @@
#include "LambdaResolver.h"
#include "LogicalDylib.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include <list>
#include <memory>
#include <set>
-
-#include "llvm/Support/Debug.h"
+#include <utility>
namespace llvm {
namespace orc {
@@ -46,7 +46,7 @@ private:
class LambdaMaterializer final : public ValueMaterializer {
public:
LambdaMaterializer(MaterializerFtor M) : M(std::move(M)) {}
- Value *materializeDeclFor(Value *V) final { return M(V); }
+ Value *materialize(Value *V) final { return M(V); }
private:
MaterializerFtor M;
@@ -145,7 +145,7 @@ private:
return *this;
}
- SymbolResolverFtor ExternalSymbolResolver;
+ std::unique_ptr<RuntimeDyld::SymbolResolver> ExternalSymbolResolver;
std::unique_ptr<ResourceOwner<RuntimeDyld::MemoryManager>> MemMgr;
ModuleAdderFtor ModuleAdder;
};
@@ -173,7 +173,7 @@ public:
CompileCallbackMgrT &CallbackMgr,
IndirectStubsManagerBuilderT CreateIndirectStubsManager,
bool CloneStubsIntoPartitions = true)
- : BaseLayer(BaseLayer), Partition(Partition),
+ : BaseLayer(BaseLayer), Partition(std::move(Partition)),
CompileCallbackMgr(CallbackMgr),
CreateIndirectStubsManager(std::move(CreateIndirectStubsManager)),
CloneStubsIntoPartitions(CloneStubsIntoPartitions) {}
@@ -188,10 +188,7 @@ public:
LogicalDylibs.push_back(CODLogicalDylib(BaseLayer));
auto &LDResources = LogicalDylibs.back().getDylibResources();
- LDResources.ExternalSymbolResolver =
- [Resolver](const std::string &Name) {
- return Resolver->findSymbol(Name);
- };
+ LDResources.ExternalSymbolResolver = std::move(Resolver);
auto &MemMgrRef = *MemMgr;
LDResources.MemMgr =
@@ -256,14 +253,8 @@ private:
Module &SrcM = LMResources.SourceModule->getResource();
- // Create the GlobalValues module.
+ // Create stub functions.
const DataLayout &DL = SrcM.getDataLayout();
- auto GVsM = llvm::make_unique<Module>((SrcM.getName() + ".globals").str(),
- SrcM.getContext());
- GVsM->setDataLayout(DL);
-
- // Create function stubs.
- ValueToValueMapTy VMap;
{
typename IndirectStubsMgrT::StubInitsMap StubInits;
for (auto &F : SrcM) {
@@ -295,6 +286,19 @@ private:
assert(!EC && "Error generating stubs");
}
+ // If this module doesn't contain any globals or aliases we can bail out
+ // early and avoid the overhead of creating and managing an empty globals
+ // module.
+ if (SrcM.global_empty() && SrcM.alias_empty())
+ return;
+
+ // Create the GlobalValues module.
+ auto GVsM = llvm::make_unique<Module>((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))
@@ -356,16 +360,17 @@ private:
[&LD, LMH](const std::string &Name) {
auto &LMResources = LD.getLogicalModuleResources(LMH);
if (auto Sym = LMResources.StubsMgr->findStub(Name, false))
- return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags());
- return LD.getDylibResources().ExternalSymbolResolver(Name);
+ return Sym.toRuntimeDyldSymbol();
+ auto &LDResolver = LD.getDylibResources().ExternalSymbolResolver;
+ return LDResolver->findSymbolInLogicalDylib(Name);
},
- [](const std::string &Name) {
- return RuntimeDyld::SymbolInfo(nullptr);
+ [&LD](const std::string &Name) {
+ auto &LDResolver = LD.getDylibResources().ExternalSymbolResolver;
+ return LDResolver->findSymbol(Name);
});
- auto GVsH =
- LD.getDylibResources().ModuleAdder(BaseLayer, std::move(GVsM),
- std::move(GVsResolver));
+ auto GVsH = LD.getDylibResources().ModuleAdder(BaseLayer, std::move(GVsM),
+ std::move(GVsResolver));
LD.addToLogicalModule(LMH, GVsH);
}
@@ -481,20 +486,18 @@ private:
// Create memory manager and symbol resolver.
auto Resolver = createLambdaResolver(
[this, &LD, LMH](const std::string &Name) {
- if (auto Symbol = LD.findSymbolInternally(LMH, Name))
- return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
- Symbol.getFlags());
- return LD.getDylibResources().ExternalSymbolResolver(Name);
+ if (auto Sym = LD.findSymbolInternally(LMH, Name))
+ return Sym.toRuntimeDyldSymbol();
+ auto &LDResolver = LD.getDylibResources().ExternalSymbolResolver;
+ return LDResolver->findSymbolInLogicalDylib(Name);
},
- [this, &LD, LMH](const std::string &Name) {
- if (auto Symbol = LD.findSymbolInternally(LMH, Name))
- return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
- Symbol.getFlags());
- return RuntimeDyld::SymbolInfo(nullptr);
+ [this, &LD](const std::string &Name) {
+ auto &LDResolver = LD.getDylibResources().ExternalSymbolResolver;
+ return LDResolver->findSymbol(Name);
});
return LD.getDylibResources().ModuleAdder(BaseLayer, std::move(M),
- std::move(Resolver));
+ std::move(Resolver));
}
BaseLayerT &BaseLayer;
diff --git a/include/llvm/ExecutionEngine/Orc/CompileUtils.h b/include/llvm/ExecutionEngine/Orc/CompileUtils.h
index 1e7d211196f5..ce0864fbd9c9 100644
--- a/include/llvm/ExecutionEngine/Orc/CompileUtils.h
+++ b/include/llvm/ExecutionEngine/Orc/CompileUtils.h
@@ -42,12 +42,13 @@ public:
PM.run(M);
std::unique_ptr<MemoryBuffer> ObjBuffer(
new ObjectMemoryBuffer(std::move(ObjBufferSV)));
- ErrorOr<std::unique_ptr<object::ObjectFile>> Obj =
+ Expected<std::unique_ptr<object::ObjectFile>> Obj =
object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef());
- // TODO: Actually report errors helpfully.
typedef object::OwningBinary<object::ObjectFile> OwningObj;
if (Obj)
return OwningObj(std::move(*Obj), std::move(ObjBuffer));
+ // TODO: Actually report errors helpfully.
+ consumeError(Obj.takeError());
return OwningObj(nullptr, nullptr);
}
diff --git a/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h b/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
index e4bed95fdabf..e6ce18a42b8b 100644
--- a/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
+++ b/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
@@ -37,9 +37,6 @@ public:
private:
typedef typename BaseLayerT::ObjSetHandleT ObjSetHandleT;
- typedef std::vector<std::unique_ptr<object::ObjectFile>> OwningObjectVec;
- typedef std::vector<std::unique_ptr<MemoryBuffer>> OwningBufferVec;
-
public:
/// @brief Handle to a set of compiled modules.
typedef ObjSetHandleT ModuleSetHandleT;
@@ -62,28 +59,29 @@ public:
ModuleSetHandleT addModuleSet(ModuleSetT Ms,
MemoryManagerPtrT MemMgr,
SymbolResolverPtrT Resolver) {
- OwningObjectVec Objects;
- OwningBufferVec Buffers;
+ std::vector<std::unique_ptr<object::OwningBinary<object::ObjectFile>>>
+ Objects;
for (const auto &M : Ms) {
- std::unique_ptr<object::ObjectFile> Object;
- std::unique_ptr<MemoryBuffer> Buffer;
+ auto Object =
+ llvm::make_unique<object::OwningBinary<object::ObjectFile>>();
if (ObjCache)
- std::tie(Object, Buffer) = tryToLoadFromObjectCache(*M).takeBinary();
+ *Object = tryToLoadFromObjectCache(*M);
- if (!Object) {
- std::tie(Object, Buffer) = Compile(*M).takeBinary();
+ if (!Object->getBinary()) {
+ *Object = Compile(*M);
if (ObjCache)
- ObjCache->notifyObjectCompiled(&*M, Buffer->getMemBufferRef());
+ ObjCache->notifyObjectCompiled(&*M,
+ Object->getBinary()->getMemoryBufferRef());
}
Objects.push_back(std::move(Object));
- Buffers.push_back(std::move(Buffer));
}
ModuleSetHandleT H =
- BaseLayer.addObjectSet(Objects, std::move(MemMgr), std::move(Resolver));
+ BaseLayer.addObjectSet(std::move(Objects), std::move(MemMgr),
+ std::move(Resolver));
return H;
}
@@ -126,10 +124,13 @@ private:
if (!ObjBuffer)
return object::OwningBinary<object::ObjectFile>();
- ErrorOr<std::unique_ptr<object::ObjectFile>> Obj =
+ Expected<std::unique_ptr<object::ObjectFile>> Obj =
object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef());
- if (!Obj)
+ if (!Obj) {
+ // TODO: Actually report errors helpfully.
+ consumeError(Obj.takeError());
return object::OwningBinary<object::ObjectFile>();
+ }
return object::OwningBinary<object::ObjectFile>(std::move(*Obj),
std::move(ObjBuffer));
diff --git a/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h b/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
index e17630fa05ff..51172c51e136 100644
--- a/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
+++ b/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
@@ -16,14 +16,12 @@
#include "JITSymbol.h"
#include "LambdaResolver.h"
-#include "llvm/ADT/DenseSet.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
-#include "llvm/Transforms/Utils/ValueMapper.h"
#include "llvm/Support/Process.h"
-#include <sstream>
+#include "llvm/Transforms/Utils/ValueMapper.h"
namespace llvm {
namespace orc {
@@ -31,7 +29,6 @@ namespace orc {
/// @brief Target-independent base class for compile callback management.
class JITCompileCallbackManager {
public:
-
typedef std::function<TargetAddress()> CompileFtor;
/// @brief Handle to a newly created compile callback. Can be used to get an
@@ -40,12 +37,13 @@ public:
class CompileCallbackInfo {
public:
CompileCallbackInfo(TargetAddress Addr, CompileFtor &Compile)
- : Addr(Addr), Compile(Compile) {}
+ : Addr(Addr), Compile(Compile) {}
TargetAddress getAddress() const { return Addr; }
void setCompileAction(CompileFtor Compile) {
this->Compile = std::move(Compile);
}
+
private:
TargetAddress Addr;
CompileFtor &Compile;
@@ -55,7 +53,7 @@ public:
/// @param ErrorHandlerAddress The address of an error handler in the target
/// process to be used if a compile callback fails.
JITCompileCallbackManager(TargetAddress ErrorHandlerAddress)
- : ErrorHandlerAddress(ErrorHandlerAddress) {}
+ : ErrorHandlerAddress(ErrorHandlerAddress) {}
virtual ~JITCompileCallbackManager() {}
@@ -71,8 +69,10 @@ public:
// Found a callback handler. Yank this trampoline out of the active list and
// put it back in the available trampolines list, then try to run the
// handler's compile and update actions.
- // Moving the trampoline ID back to the available list first means there's at
- // least one available trampoline if the compile action triggers a request for
+ // Moving the trampoline ID back to the available list first means there's
+ // at
+ // least one available trampoline if the compile action triggers a request
+ // for
// a new one.
auto Compile = std::move(I->second);
ActiveTrampolines.erase(I);
@@ -118,7 +118,6 @@ protected:
std::vector<TargetAddress> AvailableTrampolines;
private:
-
TargetAddress getAvailableTrampolineAddr() {
if (this->AvailableTrampolines.empty())
grow();
@@ -139,20 +138,17 @@ private:
template <typename TargetT>
class LocalJITCompileCallbackManager : public JITCompileCallbackManager {
public:
-
/// @brief Construct a InProcessJITCompileCallbackManager.
/// @param ErrorHandlerAddress The address of an error handler in the target
/// process to be used if a compile callback fails.
LocalJITCompileCallbackManager(TargetAddress ErrorHandlerAddress)
- : JITCompileCallbackManager(ErrorHandlerAddress) {
+ : JITCompileCallbackManager(ErrorHandlerAddress) {
/// Set up the resolver block.
std::error_code EC;
- ResolverBlock =
- sys::OwningMemoryBlock(
- sys::Memory::allocateMappedMemory(TargetT::ResolverCodeSize, nullptr,
- sys::Memory::MF_READ |
- sys::Memory::MF_WRITE, EC));
+ ResolverBlock = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
+ TargetT::ResolverCodeSize, nullptr,
+ sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC));
assert(!EC && "Failed to allocate resolver block");
TargetT::writeResolverCode(static_cast<uint8_t *>(ResolverBlock.base()),
@@ -165,13 +161,11 @@ public:
}
private:
-
static TargetAddress reenter(void *CCMgr, void *TrampolineId) {
JITCompileCallbackManager *Mgr =
- static_cast<JITCompileCallbackManager*>(CCMgr);
+ static_cast<JITCompileCallbackManager *>(CCMgr);
return Mgr->executeCompileCallback(
- static_cast<TargetAddress>(
- reinterpret_cast<uintptr_t>(TrampolineId)));
+ static_cast<TargetAddress>(reinterpret_cast<uintptr_t>(TrampolineId)));
}
void grow() override {
@@ -179,18 +173,16 @@ private:
std::error_code EC;
auto TrampolineBlock =
- sys::OwningMemoryBlock(
- sys::Memory::allocateMappedMemory(sys::Process::getPageSize(), nullptr,
- sys::Memory::MF_READ |
- sys::Memory::MF_WRITE, EC));
+ sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
+ sys::Process::getPageSize(), nullptr,
+ sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC));
assert(!EC && "Failed to allocate trampoline block");
-
unsigned NumTrampolines =
- (sys::Process::getPageSize() - TargetT::PointerSize) /
+ (sys::Process::getPageSize() - TargetT::PointerSize) /
TargetT::TrampolineSize;
- uint8_t *TrampolineMem = static_cast<uint8_t*>(TrampolineBlock.base());
+ uint8_t *TrampolineMem = static_cast<uint8_t *>(TrampolineBlock.base());
TargetT::writeTrampolines(TrampolineMem, ResolverBlock.base(),
NumTrampolines);
@@ -214,19 +206,18 @@ private:
/// @brief Base class for managing collections of named indirect stubs.
class IndirectStubsManager {
public:
-
/// @brief Map type for initializing the manager. See init.
typedef StringMap<std::pair<TargetAddress, JITSymbolFlags>> StubInitsMap;
virtual ~IndirectStubsManager() {}
/// @brief Create a single stub with the given name, target address and flags.
- virtual std::error_code createStub(StringRef StubName, TargetAddress StubAddr,
- JITSymbolFlags StubFlags) = 0;
+ virtual Error createStub(StringRef StubName, TargetAddress StubAddr,
+ JITSymbolFlags StubFlags) = 0;
/// @brief Create StubInits.size() stubs with the given names, target
/// addresses, and flags.
- virtual std::error_code createStubs(const StubInitsMap &StubInits) = 0;
+ virtual Error createStubs(const StubInitsMap &StubInits) = 0;
/// @brief Find the stub with the given name. If ExportedStubsOnly is true,
/// this will only return a result if the stub's flags indicate that it
@@ -237,7 +228,8 @@ public:
virtual JITSymbol findPointer(StringRef Name) = 0;
/// @brief Change the value of the implementation pointer for the stub.
- virtual std::error_code updatePointer(StringRef Name, TargetAddress NewAddr) = 0;
+ virtual Error updatePointer(StringRef Name, TargetAddress NewAddr) = 0;
+
private:
virtual void anchor();
};
@@ -247,26 +239,25 @@ private:
template <typename TargetT>
class LocalIndirectStubsManager : public IndirectStubsManager {
public:
-
- std::error_code createStub(StringRef StubName, TargetAddress StubAddr,
- JITSymbolFlags StubFlags) override {
- if (auto EC = reserveStubs(1))
- return EC;
+ Error createStub(StringRef StubName, TargetAddress StubAddr,
+ JITSymbolFlags StubFlags) override {
+ if (auto Err = reserveStubs(1))
+ return Err;
createStubInternal(StubName, StubAddr, StubFlags);
- return std::error_code();
+ return Error::success();
}
- std::error_code createStubs(const StubInitsMap &StubInits) override {
- if (auto EC = reserveStubs(StubInits.size()))
- return EC;
+ Error createStubs(const StubInitsMap &StubInits) override {
+ if (auto Err = reserveStubs(StubInits.size()))
+ return Err;
for (auto &Entry : StubInits)
createStubInternal(Entry.first(), Entry.second.first,
Entry.second.second);
- return std::error_code();
+ return Error::success();
}
JITSymbol findStub(StringRef Name, bool ExportedStubsOnly) override {
@@ -277,7 +268,7 @@ public:
void *StubAddr = IndirectStubsInfos[Key.first].getStub(Key.second);
assert(StubAddr && "Missing stub address");
auto StubTargetAddr =
- static_cast<TargetAddress>(reinterpret_cast<uintptr_t>(StubAddr));
+ static_cast<TargetAddress>(reinterpret_cast<uintptr_t>(StubAddr));
auto StubSymbol = JITSymbol(StubTargetAddr, I->second.second);
if (ExportedStubsOnly && !StubSymbol.isExported())
return nullptr;
@@ -292,35 +283,34 @@ public:
void *PtrAddr = IndirectStubsInfos[Key.first].getPtr(Key.second);
assert(PtrAddr && "Missing pointer address");
auto PtrTargetAddr =
- static_cast<TargetAddress>(reinterpret_cast<uintptr_t>(PtrAddr));
+ static_cast<TargetAddress>(reinterpret_cast<uintptr_t>(PtrAddr));
return JITSymbol(PtrTargetAddr, I->second.second);
}
- std::error_code updatePointer(StringRef Name, TargetAddress NewAddr) override {
+ Error updatePointer(StringRef Name, TargetAddress NewAddr) override {
auto I = StubIndexes.find(Name);
assert(I != StubIndexes.end() && "No stub pointer for symbol");
auto Key = I->second.first;
*IndirectStubsInfos[Key.first].getPtr(Key.second) =
- reinterpret_cast<void*>(static_cast<uintptr_t>(NewAddr));
- return std::error_code();
+ reinterpret_cast<void *>(static_cast<uintptr_t>(NewAddr));
+ return Error::success();
}
private:
-
- std::error_code reserveStubs(unsigned NumStubs) {
+ Error reserveStubs(unsigned NumStubs) {
if (NumStubs <= FreeStubs.size())
- return std::error_code();
+ return Error::success();
unsigned NewStubsRequired = NumStubs - FreeStubs.size();
unsigned NewBlockId = IndirectStubsInfos.size();
typename TargetT::IndirectStubsInfo ISI;
- if (auto EC = TargetT::emitIndirectStubsBlock(ISI, NewStubsRequired,
- nullptr))
- return EC;
+ if (auto Err =
+ TargetT::emitIndirectStubsBlock(ISI, NewStubsRequired, nullptr))
+ return Err;
for (unsigned I = 0; I < ISI.getNumStubs(); ++I)
FreeStubs.push_back(std::make_pair(NewBlockId, I));
IndirectStubsInfos.push_back(std::move(ISI));
- return std::error_code();
+ return Error::success();
}
void createStubInternal(StringRef StubName, TargetAddress InitAddr,
@@ -328,7 +318,7 @@ private:
auto Key = FreeStubs.back();
FreeStubs.pop_back();
*IndirectStubsInfos[Key.first].getPtr(Key.second) =
- reinterpret_cast<void*>(static_cast<uintptr_t>(InitAddr));
+ reinterpret_cast<void *>(static_cast<uintptr_t>(InitAddr));
StubIndexes[StubName] = std::make_pair(Key, StubFlags);
}
@@ -338,17 +328,32 @@ private:
StringMap<std::pair<StubKey, JITSymbolFlags>> StubIndexes;
};
+/// @brief Create a local compile callback manager.
+///
+/// The given target triple will determine the ABI, and the given
+/// ErrorHandlerAddress will be used by the resulting compile callback
+/// manager if a compile callback fails.
+std::unique_ptr<JITCompileCallbackManager>
+createLocalCompileCallbackManager(const Triple &T,
+ TargetAddress ErrorHandlerAddress);
+
+/// @brief Create a local indriect stubs manager builder.
+///
+/// The given target triple will determine the ABI.
+std::function<std::unique_ptr<IndirectStubsManager>()>
+createLocalIndirectStubsManagerBuilder(const Triple &T);
+
/// @brief Build a function pointer of FunctionType with the given constant
/// address.
///
/// Usage example: Turn a trampoline address into a function pointer constant
/// for use in a stub.
-Constant* createIRTypedAddress(FunctionType &FT, TargetAddress Addr);
+Constant *createIRTypedAddress(FunctionType &FT, TargetAddress Addr);
/// @brief Create a function pointer with the given type, name, and initializer
/// in the given Module.
-GlobalVariable* createImplPointer(PointerType &PT, Module &M,
- const Twine &Name, Constant *Initializer);
+GlobalVariable *createImplPointer(PointerType &PT, Module &M, const Twine &Name,
+ Constant *Initializer);
/// @brief Turn a function declaration into a stub function that makes an
/// indirect call using the given function pointer.
@@ -373,7 +378,7 @@ void makeAllSymbolsExternallyAccessible(Module &M);
/// modules with these utilities, all decls should be cloned (and added to a
/// single VMap) before any bodies are moved. This will ensure that references
/// between functions all refer to the versions in the new module.
-Function* cloneFunctionDecl(Module &Dst, const Function &F,
+Function *cloneFunctionDecl(Module &Dst, const Function &F,
ValueToValueMapTy *VMap = nullptr);
/// @brief Move the body of function 'F' to a cloned function declaration in a
@@ -389,7 +394,7 @@ void moveFunctionBody(Function &OrigF, ValueToValueMapTy &VMap,
Function *NewF = nullptr);
/// @brief Clone a global variable declaration into a new module.
-GlobalVariable* cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV,
+GlobalVariable *cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV,
ValueToValueMapTy *VMap = nullptr);
/// @brief Move global variable GV from its parent module to cloned global
@@ -406,7 +411,7 @@ void moveGlobalVariableInitializer(GlobalVariable &OrigGV,
GlobalVariable *NewGV = nullptr);
/// @brief Clone
-GlobalAlias* cloneGlobalAliasDecl(Module &Dst, const GlobalAlias &OrigA,
+GlobalAlias *cloneGlobalAliasDecl(Module &Dst, const GlobalAlias &OrigA,
ValueToValueMapTy &VMap);
} // End namespace orc.
diff --git a/include/llvm/ExecutionEngine/Orc/JITSymbol.h b/include/llvm/ExecutionEngine/Orc/JITSymbol.h
index 422a3761837c..464417e4e6d5 100644
--- a/include/llvm/ExecutionEngine/Orc/JITSymbol.h
+++ b/include/llvm/ExecutionEngine/Orc/JITSymbol.h
@@ -15,6 +15,7 @@
#define LLVM_EXECUTIONENGINE_ORC_JITSYMBOL_H
#include "llvm/ExecutionEngine/JITSymbolFlags.h"
+#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/Support/DataTypes.h"
#include <cassert>
#include <functional>
@@ -52,6 +53,10 @@ public:
JITSymbol(GetAddressFtor GetAddress, JITSymbolFlags Flags)
: JITSymbolBase(Flags), GetAddress(std::move(GetAddress)), CachedAddr(0) {}
+ /// @brief Create a JITSymbol from a RuntimeDyld::SymbolInfo.
+ JITSymbol(const RuntimeDyld::SymbolInfo &Sym)
+ : JITSymbolBase(Sym.getFlags()), CachedAddr(Sym.getAddress()) {}
+
/// @brief Returns true if the symbol exists, false otherwise.
explicit operator bool() const { return CachedAddr || GetAddress; }
@@ -66,6 +71,11 @@ public:
return CachedAddr;
}
+ /// @brief Convert this JITSymbol to a RuntimeDyld::SymbolInfo.
+ RuntimeDyld::SymbolInfo toRuntimeDyldSymbol() {
+ return RuntimeDyld::SymbolInfo(getAddress(), getFlags());
+ }
+
private:
GetAddressFtor GetAddress;
TargetAddress CachedAddr;
diff --git a/include/llvm/ExecutionEngine/Orc/LambdaResolver.h b/include/llvm/ExecutionEngine/Orc/LambdaResolver.h
index faa23658524f..a42b9d5c29d1 100644
--- a/include/llvm/ExecutionEngine/Orc/LambdaResolver.h
+++ b/include/llvm/ExecutionEngine/Orc/LambdaResolver.h
@@ -18,42 +18,41 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include <memory>
-#include <vector>
namespace llvm {
namespace orc {
-template <typename ExternalLookupFtorT, typename DylibLookupFtorT>
+template <typename DylibLookupFtorT, typename ExternalLookupFtorT>
class LambdaResolver : public RuntimeDyld::SymbolResolver {
public:
- LambdaResolver(ExternalLookupFtorT ExternalLookupFtor,
- DylibLookupFtorT DylibLookupFtor)
- : ExternalLookupFtor(ExternalLookupFtor),
- DylibLookupFtor(DylibLookupFtor) {}
-
- RuntimeDyld::SymbolInfo findSymbol(const std::string &Name) final {
- return ExternalLookupFtor(Name);
- }
+ LambdaResolver(DylibLookupFtorT DylibLookupFtor,
+ ExternalLookupFtorT ExternalLookupFtor)
+ : DylibLookupFtor(DylibLookupFtor),
+ ExternalLookupFtor(ExternalLookupFtor) {}
RuntimeDyld::SymbolInfo
findSymbolInLogicalDylib(const std::string &Name) final {
return DylibLookupFtor(Name);
}
+ RuntimeDyld::SymbolInfo findSymbol(const std::string &Name) final {
+ return ExternalLookupFtor(Name);
+ }
+
private:
- ExternalLookupFtorT ExternalLookupFtor;
DylibLookupFtorT DylibLookupFtor;
+ ExternalLookupFtorT ExternalLookupFtor;
};
-template <typename ExternalLookupFtorT,
- typename DylibLookupFtorT>
-std::unique_ptr<LambdaResolver<ExternalLookupFtorT, DylibLookupFtorT>>
-createLambdaResolver(ExternalLookupFtorT ExternalLookupFtor,
- DylibLookupFtorT DylibLookupFtor) {
- typedef LambdaResolver<ExternalLookupFtorT, DylibLookupFtorT> LR;
- return make_unique<LR>(std::move(ExternalLookupFtor),
- std::move(DylibLookupFtor));
+template <typename DylibLookupFtorT,
+ typename ExternalLookupFtorT>
+std::unique_ptr<LambdaResolver<DylibLookupFtorT, ExternalLookupFtorT>>
+createLambdaResolver(DylibLookupFtorT DylibLookupFtor,
+ ExternalLookupFtorT ExternalLookupFtor) {
+ typedef LambdaResolver<DylibLookupFtorT, ExternalLookupFtorT> LR;
+ return make_unique<LR>(std::move(DylibLookupFtor),
+ std::move(ExternalLookupFtor));
}
} // End namespace orc.
diff --git a/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h b/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h
index a5286ff9adde..c5fb6b847b30 100644
--- a/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h
+++ b/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h
@@ -195,13 +195,8 @@ private:
for (const auto &M : Ms) {
Mangler Mang;
- for (const auto &V : M->globals())
- if (auto GV = addGlobalValue(*Symbols, V, Mang, SearchName,
- ExportedSymbolsOnly))
- return GV;
-
- for (const auto &F : *M)
- if (auto GV = addGlobalValue(*Symbols, F, Mang, SearchName,
+ for (const auto &GO : M->global_objects())
+ if (auto GV = addGlobalValue(*Symbols, GO, Mang, SearchName,
ExportedSymbolsOnly))
return GV;
}
diff --git a/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h b/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
index 4dc48f114883..a7798d8beb8d 100644
--- a/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
+++ b/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
@@ -26,7 +26,6 @@ namespace orc {
class ObjectLinkingLayerBase {
protected:
-
/// @brief Holds a set of objects to be allocated/linked as a unit in the JIT.
///
/// An instance of this class will be created for each set of objects added
@@ -38,38 +37,31 @@ protected:
LinkedObjectSet(const LinkedObjectSet&) = delete;
void operator=(const LinkedObjectSet&) = delete;
public:
- LinkedObjectSet(RuntimeDyld::MemoryManager &MemMgr,
- RuntimeDyld::SymbolResolver &Resolver,
- bool ProcessAllSections)
- : RTDyld(llvm::make_unique<RuntimeDyld>(MemMgr, Resolver)),
- State(Raw) {
- RTDyld->setProcessAllSections(ProcessAllSections);
- }
-
+ LinkedObjectSet() = default;
virtual ~LinkedObjectSet() {}
- std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
- addObject(const object::ObjectFile &Obj) {
- return RTDyld->loadObject(Obj);
- }
-
- RuntimeDyld::SymbolInfo getSymbol(StringRef Name) const {
- return RTDyld->getSymbol(Name);
- }
+ virtual void finalize() = 0;
- bool NeedsFinalization() const { return (State == Raw); }
+ virtual JITSymbol::GetAddressFtor
+ getSymbolMaterializer(std::string Name) = 0;
- virtual void Finalize() = 0;
+ virtual void mapSectionAddress(const void *LocalAddress,
+ TargetAddress TargetAddr) const = 0;
- void mapSectionAddress(const void *LocalAddress, TargetAddress TargetAddr) {
- assert((State != Finalized) &&
- "Attempting to remap sections for finalized objects.");
- RTDyld->mapSectionAddress(LocalAddress, TargetAddr);
+ JITSymbol getSymbol(StringRef Name, bool ExportedSymbolsOnly) {
+ auto SymEntry = SymbolTable.find(Name);
+ if (SymEntry == SymbolTable.end())
+ return nullptr;
+ if (!SymEntry->second.isExported() && ExportedSymbolsOnly)
+ return nullptr;
+ if (!Finalized)
+ return JITSymbol(getSymbolMaterializer(Name),
+ SymEntry->second.getFlags());
+ return JITSymbol(SymEntry->second);
}
-
protected:
- std::unique_ptr<RuntimeDyld> RTDyld;
- enum { Raw, Finalizing, Finalized } State;
+ StringMap<RuntimeDyld::SymbolInfo> SymbolTable;
+ bool Finalized = false;
};
typedef std::list<std::unique_ptr<LinkedObjectSet>> LinkedObjectSetListT;
@@ -79,6 +71,7 @@ public:
typedef LinkedObjectSetListT::iterator ObjSetHandleT;
};
+
/// @brief Default (no-op) action to perform when loading objects.
class DoNothingOnNotifyLoaded {
public:
@@ -95,34 +88,126 @@ public:
/// symbols.
template <typename NotifyLoadedFtor = DoNothingOnNotifyLoaded>
class ObjectLinkingLayer : public ObjectLinkingLayerBase {
+public:
+
+ /// @brief Functor for receiving finalization notifications.
+ typedef std::function<void(ObjSetHandleT)> NotifyFinalizedFtor;
+
private:
- template <typename MemoryManagerPtrT, typename SymbolResolverPtrT>
+ template <typename ObjSetT, typename MemoryManagerPtrT,
+ typename SymbolResolverPtrT, typename FinalizerFtor>
class ConcreteLinkedObjectSet : public LinkedObjectSet {
public:
- ConcreteLinkedObjectSet(MemoryManagerPtrT MemMgr,
+ ConcreteLinkedObjectSet(ObjSetT Objects, MemoryManagerPtrT MemMgr,
SymbolResolverPtrT Resolver,
+ FinalizerFtor Finalizer,
bool ProcessAllSections)
- : LinkedObjectSet(*MemMgr, *Resolver, ProcessAllSections),
- MemMgr(std::move(MemMgr)), Resolver(std::move(Resolver)) { }
+ : MemMgr(std::move(MemMgr)),
+ PFC(llvm::make_unique<PreFinalizeContents>(std::move(Objects),
+ std::move(Resolver),
+ std::move(Finalizer),
+ ProcessAllSections)) {
+ buildInitialSymbolTable(PFC->Objects);
+ }
+
+ void setHandle(ObjSetHandleT H) {
+ PFC->Handle = H;
+ }
+
+ void finalize() override {
+ assert(PFC && "mapSectionAddress called on finalized LinkedObjectSet");
+
+ RuntimeDyld RTDyld(*MemMgr, *PFC->Resolver);
+ RTDyld.setProcessAllSections(PFC->ProcessAllSections);
+ PFC->RTDyld = &RTDyld;
- void Finalize() override {
- State = Finalizing;
- RTDyld->finalizeWithMemoryManagerLocking();
- State = Finalized;
+ PFC->Finalizer(PFC->Handle, RTDyld, std::move(PFC->Objects),
+ [&]() {
+ this->updateSymbolTable(RTDyld);
+ this->Finalized = true;
+ });
+
+ // Release resources.
+ PFC = nullptr;
+ }
+
+ JITSymbol::GetAddressFtor getSymbolMaterializer(std::string Name) override {
+ return
+ [this, Name]() {
+ // The symbol may be materialized between the creation of this lambda
+ // and its execution, so we need to double check.
+ if (!this->Finalized)
+ this->finalize();
+ return this->getSymbol(Name, false).getAddress();
+ };
+ }
+
+ void mapSectionAddress(const void *LocalAddress,
+ TargetAddress TargetAddr) const override {
+ assert(PFC && "mapSectionAddress called on finalized LinkedObjectSet");
+ assert(PFC->RTDyld && "mapSectionAddress called on raw LinkedObjectSet");
+ PFC->RTDyld->mapSectionAddress(LocalAddress, TargetAddr);
}
private:
+
+ void buildInitialSymbolTable(const ObjSetT &Objects) {
+ for (const auto &Obj : Objects)
+ for (auto &Symbol : getObject(*Obj).symbols()) {
+ if (Symbol.getFlags() & object::SymbolRef::SF_Undefined)
+ continue;
+ Expected<StringRef> SymbolName = Symbol.getName();
+ // FIXME: Raise an error for bad symbols.
+ if (!SymbolName) {
+ consumeError(SymbolName.takeError());
+ continue;
+ }
+ auto Flags = JITSymbol::flagsFromObjectSymbol(Symbol);
+ SymbolTable.insert(
+ std::make_pair(*SymbolName, RuntimeDyld::SymbolInfo(0, Flags)));
+ }
+ }
+
+ void updateSymbolTable(const RuntimeDyld &RTDyld) {
+ for (auto &SymEntry : SymbolTable)
+ SymEntry.second = RTDyld.getSymbol(SymEntry.first());
+ }
+
+ // Contains the information needed prior to finalization: the object files,
+ // memory manager, resolver, and flags needed for RuntimeDyld.
+ struct PreFinalizeContents {
+ PreFinalizeContents(ObjSetT Objects, SymbolResolverPtrT Resolver,
+ FinalizerFtor Finalizer, bool ProcessAllSections)
+ : Objects(std::move(Objects)), Resolver(std::move(Resolver)),
+ Finalizer(std::move(Finalizer)),
+ ProcessAllSections(ProcessAllSections) {}
+
+ ObjSetT Objects;
+ SymbolResolverPtrT Resolver;
+ FinalizerFtor Finalizer;
+ bool ProcessAllSections;
+ ObjSetHandleT Handle;
+ RuntimeDyld *RTDyld;
+ };
+
MemoryManagerPtrT MemMgr;
- SymbolResolverPtrT Resolver;
+ std::unique_ptr<PreFinalizeContents> PFC;
};
- template <typename MemoryManagerPtrT, typename SymbolResolverPtrT>
- std::unique_ptr<LinkedObjectSet>
- createLinkedObjectSet(MemoryManagerPtrT MemMgr, SymbolResolverPtrT Resolver,
+ template <typename ObjSetT, typename MemoryManagerPtrT,
+ typename SymbolResolverPtrT, typename FinalizerFtor>
+ std::unique_ptr<
+ ConcreteLinkedObjectSet<ObjSetT, MemoryManagerPtrT,
+ SymbolResolverPtrT, FinalizerFtor>>
+ createLinkedObjectSet(ObjSetT Objects, MemoryManagerPtrT MemMgr,
+ SymbolResolverPtrT Resolver,
+ FinalizerFtor Finalizer,
bool ProcessAllSections) {
- typedef ConcreteLinkedObjectSet<MemoryManagerPtrT, SymbolResolverPtrT> LOS;
- return llvm::make_unique<LOS>(std::move(MemMgr), std::move(Resolver),
+ typedef ConcreteLinkedObjectSet<ObjSetT, MemoryManagerPtrT,
+ SymbolResolverPtrT, FinalizerFtor> LOS;
+ return llvm::make_unique<LOS>(std::move(Objects), std::move(MemMgr),
+ std::move(Resolver), std::move(Finalizer),
ProcessAllSections);
}
@@ -133,9 +218,6 @@ public:
typedef std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>>
LoadedObjInfoList;
- /// @brief Functor for receiving finalization notifications.
- typedef std::function<void(ObjSetHandleT)> NotifyFinalizedFtor;
-
/// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded,
/// and NotifyFinalized functors.
ObjectLinkingLayer(
@@ -158,33 +240,44 @@ public:
/// @brief Add a set of objects (or archives) that will be treated as a unit
/// for the purposes of symbol lookup and memory management.
///
- /// @return A pair containing (1) A handle that can be used to free the memory
- /// allocated for the objects, and (2) a LoadedObjInfoList containing
- /// one LoadedObjInfo instance for each object at the corresponding
- /// index in the Objects list.
- ///
- /// This version of this method allows the client to pass in an
- /// RTDyldMemoryManager instance that will be used to allocate memory and look
- /// up external symbol addresses for the given objects.
+ /// @return A handle that can be used to refer to the loaded objects (for
+ /// symbol searching, finalization, freeing memory, etc.).
template <typename ObjSetT,
typename MemoryManagerPtrT,
typename SymbolResolverPtrT>
- ObjSetHandleT addObjectSet(const ObjSetT &Objects,
+ ObjSetHandleT addObjectSet(ObjSetT Objects,
MemoryManagerPtrT MemMgr,
SymbolResolverPtrT Resolver) {
- ObjSetHandleT Handle =
- LinkedObjSetList.insert(
- LinkedObjSetList.end(),
- createLinkedObjectSet(std::move(MemMgr), std::move(Resolver),
- ProcessAllSections));
- LinkedObjectSet &LOS = **Handle;
- LoadedObjInfoList LoadedObjInfos;
+ auto Finalizer = [&](ObjSetHandleT H, RuntimeDyld &RTDyld,
+ const ObjSetT &Objs,
+ std::function<void()> LOSHandleLoad) {
+ LoadedObjInfoList LoadedObjInfos;
+
+ for (auto &Obj : Objs)
+ LoadedObjInfos.push_back(RTDyld.loadObject(this->getObject(*Obj)));
+
+ LOSHandleLoad();
- for (auto &Obj : Objects)
- LoadedObjInfos.push_back(LOS.addObject(*Obj));
+ this->NotifyLoaded(H, Objs, LoadedObjInfos);
- NotifyLoaded(Handle, Objects, LoadedObjInfos);
+ RTDyld.finalizeWithMemoryManagerLocking();
+
+ if (this->NotifyFinalized)
+ this->NotifyFinalized(H);
+ };
+
+ auto LOS =
+ createLinkedObjectSet(std::move(Objects), std::move(MemMgr),
+ std::move(Resolver), std::move(Finalizer),
+ ProcessAllSections);
+ // LOS is an owning-ptr. Keep a non-owning one so that we can set the handle
+ // below.
+ auto *LOSPtr = LOS.get();
+
+ ObjSetHandleT Handle = LinkedObjSetList.insert(LinkedObjSetList.end(),
+ std::move(LOS));
+ LOSPtr->setHandle(Handle);
return Handle;
}
@@ -224,33 +317,7 @@ public:
/// given object set.
JITSymbol findSymbolIn(ObjSetHandleT H, StringRef Name,
bool ExportedSymbolsOnly) {
- if (auto Sym = (*H)->getSymbol(Name)) {
- if (Sym.isExported() || !ExportedSymbolsOnly) {
- auto Addr = Sym.getAddress();
- auto Flags = Sym.getFlags();
- if (!(*H)->NeedsFinalization()) {
- // If this instance has already been finalized then we can just return
- // the address.
- return JITSymbol(Addr, Flags);
- } else {
- // If this instance needs finalization return a functor that will do
- // it. The functor still needs to double-check whether finalization is
- // required, in case someone else finalizes this set before the
- // functor is called.
- auto GetAddress =
- [this, Addr, H]() {
- if ((*H)->NeedsFinalization()) {
- (*H)->Finalize();
- if (NotifyFinalized)
- NotifyFinalized(H);
- }
- return Addr;
- };
- return JITSymbol(std::move(GetAddress), Flags);
- }
- }
- }
- return nullptr;
+ return (*H)->getSymbol(Name, ExportedSymbolsOnly);
}
/// @brief Map section addresses for the objects associated with the handle H.
@@ -263,12 +330,21 @@ public:
/// given handle.
/// @param H Handle for object set to emit/finalize.
void emitAndFinalize(ObjSetHandleT H) {
- (*H)->Finalize();
- if (NotifyFinalized)
- NotifyFinalized(H);
+ (*H)->finalize();
}
private:
+
+ static const object::ObjectFile& getObject(const object::ObjectFile &Obj) {
+ return Obj;
+ }
+
+ template <typename ObjT>
+ static const object::ObjectFile&
+ getObject(const object::OwningBinary<ObjT> &Obj) {
+ return *Obj.getBinary();
+ }
+
LinkedObjectSetListT LinkedObjSetList;
NotifyLoadedFtor NotifyLoaded;
NotifyFinalizedFtor NotifyFinalized;
diff --git a/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h b/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h
index f96e83ed5a1a..2ffe71c94356 100644
--- a/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h
+++ b/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h
@@ -42,13 +42,13 @@ public:
/// @return A handle for the added objects.
template <typename ObjSetT, typename MemoryManagerPtrT,
typename SymbolResolverPtrT>
- ObjSetHandleT addObjectSet(ObjSetT &Objects, MemoryManagerPtrT MemMgr,
+ ObjSetHandleT addObjectSet(ObjSetT Objects, MemoryManagerPtrT MemMgr,
SymbolResolverPtrT Resolver) {
for (auto I = Objects.begin(), E = Objects.end(); I != E; ++I)
*I = Transform(std::move(*I));
- return BaseLayer.addObjectSet(Objects, std::move(MemMgr),
+ return BaseLayer.addObjectSet(std::move(Objects), std::move(MemMgr),
std::move(Resolver));
}
diff --git a/include/llvm/ExecutionEngine/Orc/OrcABISupport.h b/include/llvm/ExecutionEngine/Orc/OrcABISupport.h
new file mode 100644
index 000000000000..4a8d0b0b801c
--- /dev/null
+++ b/include/llvm/ExecutionEngine/Orc/OrcABISupport.h
@@ -0,0 +1,232 @@
+//===-------------- OrcABISupport.h - ABI support code ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// ABI specific code for Orc, e.g. callback assembly.
+//
+// ABI classes should be part of the JIT *target* process, not the host
+// process (except where you're doing hosted JITing and the two are one and the
+// same).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_ORCABISUPPORT_H
+#define LLVM_EXECUTIONENGINE_ORC_ORCABISUPPORT_H
+
+#include "IndirectionUtils.h"
+#include "llvm/Support/Memory.h"
+#include "llvm/Support/Process.h"
+
+namespace llvm {
+namespace orc {
+
+/// Generic ORC ABI support.
+///
+/// This class can be substituted as the target architecure support class for
+/// ORC templates that require one (e.g. IndirectStubsManagers). It does not
+/// support lazy JITing however, and any attempt to use that functionality
+/// will result in execution of an llvm_unreachable.
+class OrcGenericABI {
+public:
+ static const unsigned PointerSize = sizeof(uintptr_t);
+ static const unsigned TrampolineSize = 1;
+ static const unsigned ResolverCodeSize = 1;
+
+ typedef TargetAddress (*JITReentryFn)(void *CallbackMgr, void *TrampolineId);
+
+ static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
+ void *CallbackMgr) {
+ llvm_unreachable("writeResolverCode is not supported by the generic host "
+ "support class");
+ }
+
+ static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
+ unsigned NumTrampolines) {
+ llvm_unreachable("writeTrampolines is not supported by the generic host "
+ "support class");
+ }
+
+ class IndirectStubsInfo {
+ public:
+ const static unsigned StubSize = 1;
+ unsigned getNumStubs() const { llvm_unreachable("Not supported"); }
+ void *getStub(unsigned Idx) const { llvm_unreachable("Not supported"); }
+ void **getPtr(unsigned Idx) const { llvm_unreachable("Not supported"); }
+ };
+
+ static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
+ unsigned MinStubs, void *InitialPtrVal) {
+ llvm_unreachable("emitIndirectStubsBlock is not supported by the generic "
+ "host support class");
+ }
+};
+
+/// @brief Provide information about stub blocks generated by the
+/// makeIndirectStubsBlock function.
+template <unsigned StubSizeVal> class GenericIndirectStubsInfo {
+public:
+ const static unsigned StubSize = StubSizeVal;
+
+ GenericIndirectStubsInfo() : NumStubs(0) {}
+ GenericIndirectStubsInfo(unsigned NumStubs, sys::OwningMemoryBlock StubsMem)
+ : NumStubs(NumStubs), StubsMem(std::move(StubsMem)) {}
+ GenericIndirectStubsInfo(GenericIndirectStubsInfo &&Other)
+ : NumStubs(Other.NumStubs), StubsMem(std::move(Other.StubsMem)) {
+ Other.NumStubs = 0;
+ }
+ GenericIndirectStubsInfo &operator=(GenericIndirectStubsInfo &&Other) {
+ NumStubs = Other.NumStubs;
+ Other.NumStubs = 0;
+ StubsMem = std::move(Other.StubsMem);
+ return *this;
+ }
+
+ /// @brief Number of stubs in this block.
+ unsigned getNumStubs() const { return NumStubs; }
+
+ /// @brief Get a pointer to the stub at the given index, which must be in
+ /// the range 0 .. getNumStubs() - 1.
+ void *getStub(unsigned Idx) const {
+ return static_cast<char *>(StubsMem.base()) + Idx * StubSize;
+ }
+
+ /// @brief Get a pointer to the implementation-pointer at the given index,
+ /// which must be in the range 0 .. getNumStubs() - 1.
+ void **getPtr(unsigned Idx) const {
+ char *PtrsBase = static_cast<char *>(StubsMem.base()) + NumStubs * StubSize;
+ return reinterpret_cast<void **>(PtrsBase) + Idx;
+ }
+
+private:
+ unsigned NumStubs;
+ sys::OwningMemoryBlock StubsMem;
+};
+
+class OrcAArch64 {
+public:
+ static const unsigned PointerSize = 8;
+ static const unsigned TrampolineSize = 12;
+ static const unsigned ResolverCodeSize = 0x120;
+
+ typedef GenericIndirectStubsInfo<8> IndirectStubsInfo;
+
+ typedef TargetAddress (*JITReentryFn)(void *CallbackMgr, void *TrampolineId);
+
+ /// @brief Write the resolver code into the given memory. The user is be
+ /// responsible for allocating the memory and setting permissions.
+ static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
+ void *CallbackMgr);
+
+ /// @brief Write the requsted number of trampolines into the given memory,
+ /// which must be big enough to hold 1 pointer, plus NumTrampolines
+ /// trampolines.
+ static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
+ unsigned NumTrampolines);
+
+ /// @brief Emit at least MinStubs worth of indirect call stubs, rounded out to
+ /// the nearest page size.
+ ///
+ /// E.g. Asking for 4 stubs on x86-64, where stubs are 8-bytes, with 4k
+ /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
+ /// will return a block of 1024 (2-pages worth).
+ static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
+ unsigned MinStubs, void *InitialPtrVal);
+};
+
+/// @brief X86_64 code that's common to all ABIs.
+///
+/// X86_64 supports lazy JITing.
+class OrcX86_64_Base {
+public:
+ static const unsigned PointerSize = 8;
+ static const unsigned TrampolineSize = 8;
+
+ typedef GenericIndirectStubsInfo<8> IndirectStubsInfo;
+
+ /// @brief Write the requsted number of trampolines into the given memory,
+ /// which must be big enough to hold 1 pointer, plus NumTrampolines
+ /// trampolines.
+ static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
+ unsigned NumTrampolines);
+
+ /// @brief Emit at least MinStubs worth of indirect call stubs, rounded out to
+ /// the nearest page size.
+ ///
+ /// E.g. Asking for 4 stubs on x86-64, where stubs are 8-bytes, with 4k
+ /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
+ /// will return a block of 1024 (2-pages worth).
+ static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
+ unsigned MinStubs, void *InitialPtrVal);
+};
+
+/// @brief X86_64 support for SysV ABI (Linux, MacOSX).
+///
+/// X86_64_SysV supports lazy JITing.
+class OrcX86_64_SysV : public OrcX86_64_Base {
+public:
+ static const unsigned ResolverCodeSize = 0x6C;
+ typedef TargetAddress(*JITReentryFn)(void *CallbackMgr, void *TrampolineId);
+
+ /// @brief Write the resolver code into the given memory. The user is be
+ /// responsible for allocating the memory and setting permissions.
+ static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
+ void *CallbackMgr);
+};
+
+/// @brief X86_64 support for Win32.
+///
+/// X86_64_Win32 supports lazy JITing.
+class OrcX86_64_Win32 : public OrcX86_64_Base {
+public:
+ static const unsigned ResolverCodeSize = 0x74;
+ typedef TargetAddress(*JITReentryFn)(void *CallbackMgr, void *TrampolineId);
+
+ /// @brief Write the resolver code into the given memory. The user is be
+ /// responsible for allocating the memory and setting permissions.
+ static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
+ void *CallbackMgr);
+};
+
+/// @brief I386 support.
+///
+/// I386 supports lazy JITing.
+class OrcI386 {
+public:
+ static const unsigned PointerSize = 4;
+ static const unsigned TrampolineSize = 8;
+ static const unsigned ResolverCodeSize = 0x4a;
+
+ typedef GenericIndirectStubsInfo<8> IndirectStubsInfo;
+
+ typedef TargetAddress (*JITReentryFn)(void *CallbackMgr, void *TrampolineId);
+
+ /// @brief Write the resolver code into the given memory. The user is be
+ /// responsible for allocating the memory and setting permissions.
+ static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
+ void *CallbackMgr);
+
+ /// @brief Write the requsted number of trampolines into the given memory,
+ /// which must be big enough to hold 1 pointer, plus NumTrampolines
+ /// trampolines.
+ static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
+ unsigned NumTrampolines);
+
+ /// @brief Emit at least MinStubs worth of indirect call stubs, rounded out to
+ /// the nearest page size.
+ ///
+ /// E.g. Asking for 4 stubs on i386, where stubs are 8-bytes, with 4k
+ /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
+ /// will return a block of 1024 (2-pages worth).
+ static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
+ unsigned MinStubs, void *InitialPtrVal);
+};
+
+} // End namespace orc.
+} // End namespace llvm.
+
+#endif // LLVM_EXECUTIONENGINE_ORC_ORCABISUPPORT_H
diff --git a/include/llvm/ExecutionEngine/Orc/OrcArchitectureSupport.h b/include/llvm/ExecutionEngine/Orc/OrcArchitectureSupport.h
deleted file mode 100644
index 1b0488bcf00d..000000000000
--- a/include/llvm/ExecutionEngine/Orc/OrcArchitectureSupport.h
+++ /dev/null
@@ -1,148 +0,0 @@
-//===-- OrcArchitectureSupport.h - Architecture support code ---*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Architecture specific code for Orc, e.g. callback assembly.
-//
-// Architecture classes should be part of the JIT *target* process, not the host
-// process (except where you're doing hosted JITing and the two are one and the
-// same).
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_EXECUTIONENGINE_ORC_ORCARCHITECTURESUPPORT_H
-#define LLVM_EXECUTIONENGINE_ORC_ORCARCHITECTURESUPPORT_H
-
-#include "IndirectionUtils.h"
-#include "llvm/Support/Memory.h"
-#include "llvm/Support/Process.h"
-
-namespace llvm {
-namespace orc {
-
-/// Generic ORC Architecture support.
-///
-/// This class can be substituted as the target architecure support class for
-/// ORC templates that require one (e.g. IndirectStubsManagers). It does not
-/// support lazy JITing however, and any attempt to use that functionality
-/// will result in execution of an llvm_unreachable.
-class OrcGenericArchitecture {
-public:
- static const unsigned PointerSize = sizeof(uintptr_t);
- static const unsigned TrampolineSize = 1;
- static const unsigned ResolverCodeSize = 1;
-
- typedef TargetAddress (*JITReentryFn)(void *CallbackMgr, void *TrampolineId);
-
- static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
- void *CallbackMgr) {
- llvm_unreachable("writeResolverCode is not supported by the generic host "
- "support class");
- }
-
- static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
- unsigned NumTrampolines) {
- llvm_unreachable("writeTrampolines is not supported by the generic host "
- "support class");
- }
-
- class IndirectStubsInfo {
- public:
- const static unsigned StubSize = 1;
- unsigned getNumStubs() const { llvm_unreachable("Not supported"); }
- void *getStub(unsigned Idx) const { llvm_unreachable("Not supported"); }
- void **getPtr(unsigned Idx) const { llvm_unreachable("Not supported"); }
- };
-
- static std::error_code emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
- unsigned MinStubs,
- void *InitialPtrVal) {
- llvm_unreachable("emitIndirectStubsBlock is not supported by the generic "
- "host support class");
- }
-};
-
-/// @brief X86_64 support.
-///
-/// X86_64 supports lazy JITing.
-class OrcX86_64 {
-public:
- static const unsigned PointerSize = 8;
- static const unsigned TrampolineSize = 8;
- static const unsigned ResolverCodeSize = 0x78;
-
- typedef TargetAddress (*JITReentryFn)(void *CallbackMgr, void *TrampolineId);
-
- /// @brief Write the resolver code into the given memory. The user is be
- /// responsible for allocating the memory and setting permissions.
- static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
- void *CallbackMgr);
-
- /// @brief Write the requsted number of trampolines into the given memory,
- /// which must be big enough to hold 1 pointer, plus NumTrampolines
- /// trampolines.
- static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
- unsigned NumTrampolines);
-
- /// @brief Provide information about stub blocks generated by the
- /// makeIndirectStubsBlock function.
- class IndirectStubsInfo {
- friend class OrcX86_64;
-
- public:
- const static unsigned StubSize = 8;
-
- IndirectStubsInfo() : NumStubs(0) {}
- IndirectStubsInfo(IndirectStubsInfo &&Other)
- : NumStubs(Other.NumStubs), StubsMem(std::move(Other.StubsMem)) {
- Other.NumStubs = 0;
- }
- IndirectStubsInfo &operator=(IndirectStubsInfo &&Other) {
- NumStubs = Other.NumStubs;
- Other.NumStubs = 0;
- StubsMem = std::move(Other.StubsMem);
- return *this;
- }
-
- /// @brief Number of stubs in this block.
- unsigned getNumStubs() const { return NumStubs; }
-
- /// @brief Get a pointer to the stub at the given index, which must be in
- /// the range 0 .. getNumStubs() - 1.
- void *getStub(unsigned Idx) const {
- return static_cast<uint64_t *>(StubsMem.base()) + Idx;
- }
-
- /// @brief Get a pointer to the implementation-pointer at the given index,
- /// which must be in the range 0 .. getNumStubs() - 1.
- void **getPtr(unsigned Idx) const {
- char *PtrsBase =
- static_cast<char *>(StubsMem.base()) + NumStubs * StubSize;
- return reinterpret_cast<void **>(PtrsBase) + Idx;
- }
-
- private:
- unsigned NumStubs;
- sys::OwningMemoryBlock StubsMem;
- };
-
- /// @brief Emit at least MinStubs worth of indirect call stubs, rounded out to
- /// the nearest page size.
- ///
- /// E.g. Asking for 4 stubs on x86-64, where stubs are 8-bytes, with 4k
- /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
- /// will return a block of 1024 (2-pages worth).
- static std::error_code emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
- unsigned MinStubs,
- void *InitialPtrVal);
-};
-
-} // End namespace orc.
-} // End namespace llvm.
-
-#endif // LLVM_EXECUTIONENGINE_ORC_ORCARCHITECTURESUPPORT_H
diff --git a/include/llvm/ExecutionEngine/Orc/OrcError.h b/include/llvm/ExecutionEngine/Orc/OrcError.h
index 48f35d6b39be..1b3f25fae162 100644
--- a/include/llvm/ExecutionEngine/Orc/OrcError.h
+++ b/include/llvm/ExecutionEngine/Orc/OrcError.h
@@ -14,6 +14,7 @@
#ifndef LLVM_EXECUTIONENGINE_ORC_ORCERROR_H
#define LLVM_EXECUTIONENGINE_ORC_ORCERROR_H
+#include "llvm/Support/Error.h"
#include <system_error>
namespace llvm {
@@ -26,10 +27,11 @@ enum class OrcErrorCode : int {
RemoteMProtectAddrUnrecognized,
RemoteIndirectStubsOwnerDoesNotExist,
RemoteIndirectStubsOwnerIdAlreadyInUse,
- UnexpectedRPCCall
+ UnexpectedRPCCall,
+ UnexpectedRPCResponse,
};
-std::error_code orcError(OrcErrorCode ErrCode);
+Error orcError(OrcErrorCode ErrCode);
} // End namespace orc.
} // End namespace llvm.
diff --git a/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h b/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h
index d7640b8e8b5f..5c867e7e7fd4 100644
--- a/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h
+++ b/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h
@@ -36,6 +36,23 @@ namespace remote {
template <typename ChannelT>
class OrcRemoteTargetClient : public OrcRemoteTargetRPCAPI {
public:
+ // FIXME: Remove move/copy ops once MSVC supports synthesizing move ops.
+
+ OrcRemoteTargetClient(const OrcRemoteTargetClient &) = delete;
+ OrcRemoteTargetClient &operator=(const OrcRemoteTargetClient &) = delete;
+
+ OrcRemoteTargetClient(OrcRemoteTargetClient &&Other)
+ : Channel(Other.Channel), ExistingError(std::move(Other.ExistingError)),
+ RemoteTargetTriple(std::move(Other.RemoteTargetTriple)),
+ RemotePointerSize(std::move(Other.RemotePointerSize)),
+ RemotePageSize(std::move(Other.RemotePageSize)),
+ RemoteTrampolineSize(std::move(Other.RemoteTrampolineSize)),
+ RemoteIndirectStubSize(std::move(Other.RemoteIndirectStubSize)),
+ AllocatorIds(std::move(Other.AllocatorIds)),
+ IndirectStubOwnerIds(std::move(Other.IndirectStubOwnerIds)) {}
+
+ OrcRemoteTargetClient &operator=(OrcRemoteTargetClient &&) = delete;
+
/// Remote memory manager.
class RCMemoryManager : public RuntimeDyld::MemoryManager {
public:
@@ -57,7 +74,7 @@ public:
return *this;
}
- ~RCMemoryManager() {
+ ~RCMemoryManager() override {
Client.destroyRemoteAllocator(Id);
DEBUG(dbgs() << "Destroyed remote allocator " << Id << "\n");
}
@@ -105,11 +122,13 @@ public:
DEBUG(dbgs() << "Allocator " << Id << " reserved:\n");
if (CodeSize != 0) {
- std::error_code EC = Client.reserveMem(Unmapped.back().RemoteCodeAddr,
- Id, CodeSize, CodeAlign);
- // FIXME; Add error to poll.
- assert(!EC && "Failed reserving remote memory.");
- (void)EC;
+ if (auto AddrOrErr = Client.reserveMem(Id, CodeSize, CodeAlign))
+ Unmapped.back().RemoteCodeAddr = *AddrOrErr;
+ else {
+ // FIXME; Add error to poll.
+ assert(!AddrOrErr.takeError() && "Failed reserving remote memory.");
+ }
+
DEBUG(dbgs() << " code: "
<< format("0x%016x", Unmapped.back().RemoteCodeAddr)
<< " (" << CodeSize << " bytes, alignment " << CodeAlign
@@ -117,11 +136,13 @@ public:
}
if (RODataSize != 0) {
- std::error_code EC = Client.reserveMem(Unmapped.back().RemoteRODataAddr,
- Id, RODataSize, RODataAlign);
- // FIXME; Add error to poll.
- assert(!EC && "Failed reserving remote memory.");
- (void)EC;
+ if (auto AddrOrErr = Client.reserveMem(Id, RODataSize, RODataAlign))
+ Unmapped.back().RemoteRODataAddr = *AddrOrErr;
+ else {
+ // FIXME; Add error to poll.
+ assert(!AddrOrErr.takeError() && "Failed reserving remote memory.");
+ }
+
DEBUG(dbgs() << " ro-data: "
<< format("0x%016x", Unmapped.back().RemoteRODataAddr)
<< " (" << RODataSize << " bytes, alignment "
@@ -129,11 +150,13 @@ public:
}
if (RWDataSize != 0) {
- std::error_code EC = Client.reserveMem(Unmapped.back().RemoteRWDataAddr,
- Id, RWDataSize, RWDataAlign);
- // FIXME; Add error to poll.
- assert(!EC && "Failed reserving remote memory.");
- (void)EC;
+ if (auto AddrOrErr = Client.reserveMem(Id, RWDataSize, RWDataAlign))
+ Unmapped.back().RemoteRWDataAddr = *AddrOrErr;
+ else {
+ // FIXME; Add error to poll.
+ assert(!AddrOrErr.takeError() && "Failed reserving remote memory.");
+ }
+
DEBUG(dbgs() << " rw-data: "
<< format("0x%016x", Unmapped.back().RemoteRWDataAddr)
<< " (" << RWDataSize << " bytes, alignment "
@@ -144,10 +167,18 @@ public:
bool needsToReserveAllocationSpace() override { return true; }
void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
- size_t Size) override {}
+ size_t Size) override {
+ UnfinalizedEHFrames.push_back(
+ std::make_pair(LoadAddr, static_cast<uint32_t>(Size)));
+ }
- void deregisterEHFrames(uint8_t *addr, uint64_t LoadAddr,
- size_t Size) override {}
+ void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr,
+ size_t Size) override {
+ auto Err = Client.deregisterEHFrames(LoadAddr, Size);
+ // FIXME: Add error poll.
+ assert(!Err && "Failed to register remote EH frames.");
+ (void)Err;
+ }
void notifyObjectLoaded(RuntimeDyld &Dyld,
const object::ObjectFile &Obj) override {
@@ -156,7 +187,7 @@ public:
{
TargetAddress NextCodeAddr = ObjAllocs.RemoteCodeAddr;
for (auto &Alloc : ObjAllocs.CodeAllocs) {
- NextCodeAddr = RoundUpToAlignment(NextCodeAddr, Alloc.getAlign());
+ NextCodeAddr = alignTo(NextCodeAddr, Alloc.getAlign());
Dyld.mapSectionAddress(Alloc.getLocalAddress(), NextCodeAddr);
DEBUG(dbgs() << " code: "
<< static_cast<void *>(Alloc.getLocalAddress())
@@ -168,8 +199,7 @@ public:
{
TargetAddress NextRODataAddr = ObjAllocs.RemoteRODataAddr;
for (auto &Alloc : ObjAllocs.RODataAllocs) {
- NextRODataAddr =
- RoundUpToAlignment(NextRODataAddr, Alloc.getAlign());
+ NextRODataAddr = alignTo(NextRODataAddr, Alloc.getAlign());
Dyld.mapSectionAddress(Alloc.getLocalAddress(), NextRODataAddr);
DEBUG(dbgs() << " ro-data: "
<< static_cast<void *>(Alloc.getLocalAddress())
@@ -182,8 +212,7 @@ public:
{
TargetAddress NextRWDataAddr = ObjAllocs.RemoteRWDataAddr;
for (auto &Alloc : ObjAllocs.RWDataAllocs) {
- NextRWDataAddr =
- RoundUpToAlignment(NextRWDataAddr, Alloc.getAlign());
+ NextRWDataAddr = alignTo(NextRWDataAddr, Alloc.getAlign());
Dyld.mapSectionAddress(Alloc.getLocalAddress(), NextRWDataAddr);
DEBUG(dbgs() << " rw-data: "
<< static_cast<void *>(Alloc.getLocalAddress())
@@ -208,15 +237,35 @@ public:
<< static_cast<void *>(Alloc.getLocalAddress()) << " -> "
<< format("0x%016x", Alloc.getRemoteAddress()) << " ("
<< Alloc.getSize() << " bytes)\n");
- Client.writeMem(Alloc.getRemoteAddress(), Alloc.getLocalAddress(),
- Alloc.getSize());
+ if (auto Err =
+ Client.writeMem(Alloc.getRemoteAddress(),
+ Alloc.getLocalAddress(), Alloc.getSize())) {
+ // FIXME: Replace this once finalizeMemory can return an Error.
+ handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
+ if (ErrMsg) {
+ raw_string_ostream ErrOut(*ErrMsg);
+ EIB.log(ErrOut);
+ }
+ });
+ return true;
+ }
}
if (ObjAllocs.RemoteCodeAddr) {
DEBUG(dbgs() << " setting R-X permissions on code block: "
<< format("0x%016x", ObjAllocs.RemoteCodeAddr) << "\n");
- Client.setProtections(Id, ObjAllocs.RemoteCodeAddr,
- sys::Memory::MF_READ | sys::Memory::MF_EXEC);
+ if (auto Err = Client.setProtections(Id, ObjAllocs.RemoteCodeAddr,
+ sys::Memory::MF_READ |
+ sys::Memory::MF_EXEC)) {
+ // FIXME: Replace this once finalizeMemory can return an Error.
+ handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
+ if (ErrMsg) {
+ raw_string_ostream ErrOut(*ErrMsg);
+ EIB.log(ErrOut);
+ }
+ });
+ return true;
+ }
}
for (auto &Alloc : ObjAllocs.RODataAllocs) {
@@ -224,16 +273,35 @@ public:
<< static_cast<void *>(Alloc.getLocalAddress()) << " -> "
<< format("0x%016x", Alloc.getRemoteAddress()) << " ("
<< Alloc.getSize() << " bytes)\n");
- Client.writeMem(Alloc.getRemoteAddress(), Alloc.getLocalAddress(),
- Alloc.getSize());
+ if (auto Err =
+ Client.writeMem(Alloc.getRemoteAddress(),
+ Alloc.getLocalAddress(), Alloc.getSize())) {
+ // FIXME: Replace this once finalizeMemory can return an Error.
+ handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
+ if (ErrMsg) {
+ raw_string_ostream ErrOut(*ErrMsg);
+ EIB.log(ErrOut);
+ }
+ });
+ return true;
+ }
}
if (ObjAllocs.RemoteRODataAddr) {
DEBUG(dbgs() << " setting R-- permissions on ro-data block: "
<< format("0x%016x", ObjAllocs.RemoteRODataAddr)
<< "\n");
- Client.setProtections(Id, ObjAllocs.RemoteRODataAddr,
- sys::Memory::MF_READ);
+ if (auto Err = Client.setProtections(Id, ObjAllocs.RemoteRODataAddr,
+ sys::Memory::MF_READ)) {
+ // FIXME: Replace this once finalizeMemory can return an Error.
+ handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
+ if (ErrMsg) {
+ raw_string_ostream ErrOut(*ErrMsg);
+ EIB.log(ErrOut);
+ }
+ });
+ return false;
+ }
}
for (auto &Alloc : ObjAllocs.RWDataAllocs) {
@@ -241,20 +309,54 @@ public:
<< static_cast<void *>(Alloc.getLocalAddress()) << " -> "
<< format("0x%016x", Alloc.getRemoteAddress()) << " ("
<< Alloc.getSize() << " bytes)\n");
- Client.writeMem(Alloc.getRemoteAddress(), Alloc.getLocalAddress(),
- Alloc.getSize());
+ if (auto Err =
+ Client.writeMem(Alloc.getRemoteAddress(),
+ Alloc.getLocalAddress(), Alloc.getSize())) {
+ // FIXME: Replace this once finalizeMemory can return an Error.
+ handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
+ if (ErrMsg) {
+ raw_string_ostream ErrOut(*ErrMsg);
+ EIB.log(ErrOut);
+ }
+ });
+ return false;
+ }
}
if (ObjAllocs.RemoteRWDataAddr) {
DEBUG(dbgs() << " setting RW- permissions on rw-data block: "
<< format("0x%016x", ObjAllocs.RemoteRWDataAddr)
<< "\n");
- Client.setProtections(Id, ObjAllocs.RemoteRWDataAddr,
- sys::Memory::MF_READ | sys::Memory::MF_WRITE);
+ if (auto Err = Client.setProtections(Id, ObjAllocs.RemoteRWDataAddr,
+ sys::Memory::MF_READ |
+ sys::Memory::MF_WRITE)) {
+ // FIXME: Replace this once finalizeMemory can return an Error.
+ handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
+ if (ErrMsg) {
+ raw_string_ostream ErrOut(*ErrMsg);
+ EIB.log(ErrOut);
+ }
+ });
+ return false;
+ }
}
}
Unfinalized.clear();
+ for (auto &EHFrame : UnfinalizedEHFrames) {
+ if (auto Err = Client.registerEHFrames(EHFrame.first, EHFrame.second)) {
+ // FIXME: Replace this once finalizeMemory can return an Error.
+ handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
+ if (ErrMsg) {
+ raw_string_ostream ErrOut(*ErrMsg);
+ EIB.log(ErrOut);
+ }
+ });
+ return false;
+ }
+ }
+ UnfinalizedEHFrames.clear();
+
return false;
}
@@ -262,8 +364,7 @@ public:
class Alloc {
public:
Alloc(uint64_t Size, unsigned Align)
- : Size(Size), Align(Align), Contents(new char[Size + Align - 1]),
- RemoteAddr(0) {}
+ : Size(Size), Align(Align), Contents(new char[Size + Align - 1]) {}
Alloc(Alloc &&Other)
: Size(std::move(Other.Size)), Align(std::move(Other.Align)),
@@ -284,7 +385,7 @@ public:
char *getLocalAddress() const {
uintptr_t LocalAddr = reinterpret_cast<uintptr_t>(Contents.get());
- LocalAddr = RoundUpToAlignment(LocalAddr, Align);
+ LocalAddr = alignTo(LocalAddr, Align);
return reinterpret_cast<char *>(LocalAddr);
}
@@ -298,12 +399,11 @@ public:
uint64_t Size;
unsigned Align;
std::unique_ptr<char[]> Contents;
- TargetAddress RemoteAddr;
+ TargetAddress RemoteAddr = 0;
};
struct ObjectAllocs {
- ObjectAllocs()
- : RemoteCodeAddr(0), RemoteRODataAddr(0), RemoteRWDataAddr(0) {}
+ ObjectAllocs() = default;
ObjectAllocs(ObjectAllocs &&Other)
: RemoteCodeAddr(std::move(Other.RemoteCodeAddr)),
@@ -323,9 +423,9 @@ public:
return *this;
}
- TargetAddress RemoteCodeAddr;
- TargetAddress RemoteRODataAddr;
- TargetAddress RemoteRWDataAddr;
+ TargetAddress RemoteCodeAddr = 0;
+ TargetAddress RemoteRODataAddr = 0;
+ TargetAddress RemoteRWDataAddr = 0;
std::vector<Alloc> CodeAllocs, RODataAllocs, RWDataAllocs;
};
@@ -333,6 +433,7 @@ public:
ResourceIdMgr::ResourceId Id;
std::vector<ObjectAllocs> Unmapped;
std::vector<ObjectAllocs> Unfinalized;
+ std::vector<std::pair<uint64_t, uint32_t>> UnfinalizedEHFrames;
};
/// Remote indirect stubs manager.
@@ -342,26 +443,31 @@ public:
ResourceIdMgr::ResourceId Id)
: Remote(Remote), Id(Id) {}
- ~RCIndirectStubsManager() { Remote.destroyIndirectStubsManager(Id); }
+ ~RCIndirectStubsManager() override {
+ if (auto Err = Remote.destroyIndirectStubsManager(Id)) {
+ // FIXME: Thread this error back to clients.
+ consumeError(std::move(Err));
+ }
+ }
- std::error_code createStub(StringRef StubName, TargetAddress StubAddr,
- JITSymbolFlags StubFlags) override {
- if (auto EC = reserveStubs(1))
- return EC;
+ Error createStub(StringRef StubName, TargetAddress StubAddr,
+ JITSymbolFlags StubFlags) override {
+ if (auto Err = reserveStubs(1))
+ return Err;
return createStubInternal(StubName, StubAddr, StubFlags);
}
- std::error_code createStubs(const StubInitsMap &StubInits) override {
- if (auto EC = reserveStubs(StubInits.size()))
- return EC;
+ Error createStubs(const StubInitsMap &StubInits) override {
+ if (auto Err = reserveStubs(StubInits.size()))
+ return Err;
for (auto &Entry : StubInits)
- if (auto EC = createStubInternal(Entry.first(), Entry.second.first,
- Entry.second.second))
- return EC;
+ if (auto Err = createStubInternal(Entry.first(), Entry.second.first,
+ Entry.second.second))
+ return Err;
- return std::error_code();
+ return Error::success();
}
JITSymbol findStub(StringRef Name, bool ExportedStubsOnly) override {
@@ -385,8 +491,7 @@ public:
return JITSymbol(getPtrAddr(Key), Flags);
}
- std::error_code updatePointer(StringRef Name,
- TargetAddress NewAddr) override {
+ Error updatePointer(StringRef Name, TargetAddress NewAddr) override {
auto I = StubIndexes.find(Name);
assert(I != StubIndexes.end() && "No stub pointer for symbol");
auto Key = I->second.first;
@@ -395,9 +500,6 @@ public:
private:
struct RemoteIndirectStubsInfo {
- RemoteIndirectStubsInfo(TargetAddress StubBase, TargetAddress PtrBase,
- unsigned NumStubs)
- : StubBase(StubBase), PtrBase(PtrBase), NumStubs(NumStubs) {}
TargetAddress StubBase;
TargetAddress PtrBase;
unsigned NumStubs;
@@ -410,31 +512,31 @@ public:
std::vector<StubKey> FreeStubs;
StringMap<std::pair<StubKey, JITSymbolFlags>> StubIndexes;
- std::error_code reserveStubs(unsigned NumStubs) {
+ Error reserveStubs(unsigned NumStubs) {
if (NumStubs <= FreeStubs.size())
- return std::error_code();
+ return Error::success();
unsigned NewStubsRequired = NumStubs - FreeStubs.size();
TargetAddress StubBase;
TargetAddress PtrBase;
unsigned NumStubsEmitted;
- Remote.emitIndirectStubs(StubBase, PtrBase, NumStubsEmitted, Id,
- NewStubsRequired);
+ if (auto StubInfoOrErr = Remote.emitIndirectStubs(Id, NewStubsRequired))
+ std::tie(StubBase, PtrBase, NumStubsEmitted) = *StubInfoOrErr;
+ else
+ return StubInfoOrErr.takeError();
unsigned NewBlockId = RemoteIndirectStubsInfos.size();
- RemoteIndirectStubsInfos.push_back(
- RemoteIndirectStubsInfo(StubBase, PtrBase, NumStubsEmitted));
+ RemoteIndirectStubsInfos.push_back({StubBase, PtrBase, NumStubsEmitted});
for (unsigned I = 0; I < NumStubsEmitted; ++I)
FreeStubs.push_back(std::make_pair(NewBlockId, I));
- return std::error_code();
+ return Error::success();
}
- std::error_code createStubInternal(StringRef StubName,
- TargetAddress InitAddr,
- JITSymbolFlags StubFlags) {
+ Error createStubInternal(StringRef StubName, TargetAddress InitAddr,
+ JITSymbolFlags StubFlags) {
auto Key = FreeStubs.back();
FreeStubs.pop_back();
StubIndexes[StubName] = std::make_pair(Key, StubFlags);
@@ -461,20 +563,18 @@ public:
public:
RCCompileCallbackManager(TargetAddress ErrorHandlerAddress,
OrcRemoteTargetClient &Remote)
- : JITCompileCallbackManager(ErrorHandlerAddress), Remote(Remote) {
- assert(!Remote.CompileCallback && "Compile callback already set");
- Remote.CompileCallback = [this](TargetAddress TrampolineAddr) {
- return executeCompileCallback(TrampolineAddr);
- };
- Remote.emitResolverBlock();
- }
+ : JITCompileCallbackManager(ErrorHandlerAddress), Remote(Remote) {}
private:
- void grow() {
+ void grow() override {
TargetAddress BlockAddr = 0;
uint32_t NumTrampolines = 0;
- auto EC = Remote.emitTrampolineBlock(BlockAddr, NumTrampolines);
- assert(!EC && "Failed to create trampolines");
+ if (auto TrampolineInfoOrErr = Remote.emitTrampolineBlock())
+ std::tie(BlockAddr, NumTrampolines) = *TrampolineInfoOrErr;
+ else {
+ // FIXME: Return error.
+ llvm_unreachable("Failed to create trampolines");
+ }
uint32_t TrampolineSize = Remote.getTrampolineSize();
for (unsigned I = 0; I < NumTrampolines; ++I)
@@ -487,143 +587,123 @@ public:
/// Create an OrcRemoteTargetClient.
/// Channel is the ChannelT instance to communicate on. It is assumed that
/// the channel is ready to be read from and written to.
- static ErrorOr<OrcRemoteTargetClient> Create(ChannelT &Channel) {
- std::error_code EC;
- OrcRemoteTargetClient H(Channel, EC);
- if (EC)
- return EC;
- return H;
+ static Expected<OrcRemoteTargetClient> Create(ChannelT &Channel) {
+ Error Err;
+ OrcRemoteTargetClient H(Channel, Err);
+ if (Err)
+ return std::move(Err);
+ return Expected<OrcRemoteTargetClient>(std::move(H));
}
/// Call the int(void) function at the given address in the target and return
/// its result.
- std::error_code callIntVoid(int &Result, TargetAddress Addr) {
+ Expected<int> callIntVoid(TargetAddress Addr) {
DEBUG(dbgs() << "Calling int(*)(void) " << format("0x%016x", Addr) << "\n");
- if (auto EC = call<CallIntVoid>(Channel, Addr))
- return EC;
-
- unsigned NextProcId;
- if (auto EC = listenForCompileRequests(NextProcId))
- return EC;
-
- if (NextProcId != CallIntVoidResponseId)
- return orcError(OrcErrorCode::UnexpectedRPCCall);
-
- return handle<CallIntVoidResponse>(Channel, [&](int R) {
- Result = R;
- DEBUG(dbgs() << "Result: " << R << "\n");
- return std::error_code();
- });
+ auto Listen = [&](RPCChannel &C, uint32_t Id) {
+ return listenForCompileRequests(C, Id);
+ };
+ return callSTHandling<CallIntVoid>(Channel, Listen, Addr);
}
/// Call the int(int, char*[]) function at the given address in the target and
/// return its result.
- std::error_code callMain(int &Result, TargetAddress Addr,
- const std::vector<std::string> &Args) {
+ Expected<int> callMain(TargetAddress Addr,
+ const std::vector<std::string> &Args) {
DEBUG(dbgs() << "Calling int(*)(int, char*[]) " << format("0x%016x", Addr)
<< "\n");
- if (auto EC = call<CallMain>(Channel, Addr, Args))
- return EC;
-
- unsigned NextProcId;
- if (auto EC = listenForCompileRequests(NextProcId))
- return EC;
-
- if (NextProcId != CallMainResponseId)
- return orcError(OrcErrorCode::UnexpectedRPCCall);
-
- return handle<CallMainResponse>(Channel, [&](int R) {
- Result = R;
- DEBUG(dbgs() << "Result: " << R << "\n");
- return std::error_code();
- });
+ auto Listen = [&](RPCChannel &C, uint32_t Id) {
+ return listenForCompileRequests(C, Id);
+ };
+ return callSTHandling<CallMain>(Channel, Listen, Addr, Args);
}
/// Call the void() function at the given address in the target and wait for
/// it to finish.
- std::error_code callVoidVoid(TargetAddress Addr) {
+ Error callVoidVoid(TargetAddress Addr) {
DEBUG(dbgs() << "Calling void(*)(void) " << format("0x%016x", Addr)
<< "\n");
- if (auto EC = call<CallVoidVoid>(Channel, Addr))
- return EC;
-
- unsigned NextProcId;
- if (auto EC = listenForCompileRequests(NextProcId))
- return EC;
-
- if (NextProcId != CallVoidVoidResponseId)
- return orcError(OrcErrorCode::UnexpectedRPCCall);
-
- return handle<CallVoidVoidResponse>(Channel, doNothing);
+ auto Listen = [&](RPCChannel &C, uint32_t Id) {
+ return listenForCompileRequests(C, Id);
+ };
+ return callSTHandling<CallVoidVoid>(Channel, Listen, Addr);
}
/// Create an RCMemoryManager which will allocate its memory on the remote
/// target.
- std::error_code
- createRemoteMemoryManager(std::unique_ptr<RCMemoryManager> &MM) {
+ Error createRemoteMemoryManager(std::unique_ptr<RCMemoryManager> &MM) {
assert(!MM && "MemoryManager should be null before creation.");
auto Id = AllocatorIds.getNext();
- if (auto EC = call<CreateRemoteAllocator>(Channel, Id))
- return EC;
+ if (auto Err = callST<CreateRemoteAllocator>(Channel, Id))
+ return Err;
MM = llvm::make_unique<RCMemoryManager>(*this, Id);
- return std::error_code();
+ return Error::success();
}
/// Create an RCIndirectStubsManager that will allocate stubs on the remote
/// target.
- std::error_code
- createIndirectStubsManager(std::unique_ptr<RCIndirectStubsManager> &I) {
+ Error createIndirectStubsManager(std::unique_ptr<RCIndirectStubsManager> &I) {
assert(!I && "Indirect stubs manager should be null before creation.");
auto Id = IndirectStubOwnerIds.getNext();
- if (auto EC = call<CreateIndirectStubsOwner>(Channel, Id))
- return EC;
+ if (auto Err = callST<CreateIndirectStubsOwner>(Channel, Id))
+ return Err;
I = llvm::make_unique<RCIndirectStubsManager>(*this, Id);
- return std::error_code();
+ return Error::success();
+ }
+
+ Expected<RCCompileCallbackManager &>
+ enableCompileCallbacks(TargetAddress ErrorHandlerAddress) {
+ // Check for an 'out-of-band' error, e.g. from an MM destructor.
+ if (ExistingError)
+ return std::move(ExistingError);
+
+ // Emit the resolver block on the JIT server.
+ if (auto Err = callST<EmitResolverBlock>(Channel))
+ return std::move(Err);
+
+ // Create the callback manager.
+ CallbackManager.emplace(ErrorHandlerAddress, *this);
+ RCCompileCallbackManager &Mgr = *CallbackManager;
+ return Mgr;
}
/// Search for symbols in the remote process. Note: This should be used by
/// symbol resolvers *after* they've searched the local symbol table in the
/// JIT stack.
- std::error_code getSymbolAddress(TargetAddress &Addr, StringRef Name) {
+ Expected<TargetAddress> getSymbolAddress(StringRef Name) {
// Check for an 'out-of-band' error, e.g. from an MM destructor.
if (ExistingError)
- return ExistingError;
-
- // Request remote symbol address.
- if (auto EC = call<GetSymbolAddress>(Channel, Name))
- return EC;
-
- return expect<GetSymbolAddressResponse>(Channel, [&](TargetAddress &A) {
- Addr = A;
- DEBUG(dbgs() << "Remote address lookup " << Name << " = "
- << format("0x%016x", Addr) << "\n");
- return std::error_code();
- });
+ return std::move(ExistingError);
+
+ return callST<GetSymbolAddress>(Channel, Name);
}
/// Get the triple for the remote target.
const std::string &getTargetTriple() const { return RemoteTargetTriple; }
- std::error_code terminateSession() { return call<TerminateSession>(Channel); }
+ Error terminateSession() { return callST<TerminateSession>(Channel); }
private:
- OrcRemoteTargetClient(ChannelT &Channel, std::error_code &EC)
- : Channel(Channel), RemotePointerSize(0), RemotePageSize(0),
- RemoteTrampolineSize(0), RemoteIndirectStubSize(0) {
- if ((EC = call<GetRemoteInfo>(Channel)))
- return;
-
- EC = expect<GetRemoteInfoResponse>(
- Channel, readArgs(RemoteTargetTriple, RemotePointerSize, RemotePageSize,
- RemoteTrampolineSize, RemoteIndirectStubSize));
+ OrcRemoteTargetClient(ChannelT &Channel, Error &Err) : Channel(Channel) {
+ ErrorAsOutParameter EAO(Err);
+ if (auto RIOrErr = callST<GetRemoteInfo>(Channel)) {
+ std::tie(RemoteTargetTriple, RemotePointerSize, RemotePageSize,
+ RemoteTrampolineSize, RemoteIndirectStubSize) = *RIOrErr;
+ Err = Error::success();
+ } else {
+ Err = joinErrors(RIOrErr.takeError(), std::move(ExistingError));
+ }
+ }
+
+ Error deregisterEHFrames(TargetAddress Addr, uint32_t Size) {
+ return callST<RegisterEHFrames>(Channel, Addr, Size);
}
void destroyRemoteAllocator(ResourceIdMgr::ResourceId Id) {
- if (auto EC = call<DestroyRemoteAllocator>(Channel, Id)) {
+ if (auto Err = callST<DestroyRemoteAllocator>(Channel, Id)) {
// FIXME: This will be triggered by a removeModuleSet call: Propagate
// error return up through that.
llvm_unreachable("Failed to destroy remote allocator.");
@@ -631,46 +711,22 @@ private:
}
}
- std::error_code destroyIndirectStubsManager(ResourceIdMgr::ResourceId Id) {
+ Error destroyIndirectStubsManager(ResourceIdMgr::ResourceId Id) {
IndirectStubOwnerIds.release(Id);
- return call<DestroyIndirectStubsOwner>(Channel, Id);
+ return callST<DestroyIndirectStubsOwner>(Channel, Id);
}
- std::error_code emitIndirectStubs(TargetAddress &StubBase,
- TargetAddress &PtrBase,
- uint32_t &NumStubsEmitted,
- ResourceIdMgr::ResourceId Id,
- uint32_t NumStubsRequired) {
- if (auto EC = call<EmitIndirectStubs>(Channel, Id, NumStubsRequired))
- return EC;
-
- return expect<EmitIndirectStubsResponse>(
- Channel, readArgs(StubBase, PtrBase, NumStubsEmitted));
+ Expected<std::tuple<TargetAddress, TargetAddress, uint32_t>>
+ emitIndirectStubs(ResourceIdMgr::ResourceId Id, uint32_t NumStubsRequired) {
+ return callST<EmitIndirectStubs>(Channel, Id, NumStubsRequired);
}
- std::error_code emitResolverBlock() {
+ Expected<std::tuple<TargetAddress, uint32_t>> emitTrampolineBlock() {
// Check for an 'out-of-band' error, e.g. from an MM destructor.
if (ExistingError)
- return ExistingError;
+ return std::move(ExistingError);
- return call<EmitResolverBlock>(Channel);
- }
-
- std::error_code emitTrampolineBlock(TargetAddress &BlockAddr,
- uint32_t &NumTrampolines) {
- // Check for an 'out-of-band' error, e.g. from an MM destructor.
- if (ExistingError)
- return ExistingError;
-
- if (auto EC = call<EmitTrampolineBlock>(Channel))
- return EC;
-
- return expect<EmitTrampolineBlockResponse>(
- Channel, [&](TargetAddress BAddr, uint32_t NTrampolines) {
- BlockAddr = BAddr;
- NumTrampolines = NTrampolines;
- return std::error_code();
- });
+ return callST<EmitTrampolineBlock>(Channel);
}
uint32_t getIndirectStubSize() const { return RemoteIndirectStubSize; }
@@ -679,100 +735,86 @@ private:
uint32_t getTrampolineSize() const { return RemoteTrampolineSize; }
- std::error_code listenForCompileRequests(uint32_t &NextId) {
+ Error listenForCompileRequests(RPCChannel &C, uint32_t &Id) {
+ assert(CallbackManager &&
+ "No calback manager. enableCompileCallbacks must be called first");
+
// Check for an 'out-of-band' error, e.g. from an MM destructor.
if (ExistingError)
- return ExistingError;
-
- if (auto EC = getNextProcId(Channel, NextId))
- return EC;
-
- while (NextId == RequestCompileId) {
- TargetAddress TrampolineAddr = 0;
- if (auto EC = handle<RequestCompile>(Channel, readArgs(TrampolineAddr)))
- return EC;
-
- TargetAddress ImplAddr = CompileCallback(TrampolineAddr);
- if (auto EC = call<RequestCompileResponse>(Channel, ImplAddr))
- return EC;
+ return std::move(ExistingError);
+
+ // FIXME: CompileCallback could be an anonymous lambda defined at the use
+ // site below, but that triggers a GCC 4.7 ICE. When we move off
+ // GCC 4.7, tidy this up.
+ auto CompileCallback =
+ [this](TargetAddress Addr) -> Expected<TargetAddress> {
+ return this->CallbackManager->executeCompileCallback(Addr);
+ };
- if (auto EC = getNextProcId(Channel, NextId))
- return EC;
+ if (Id == RequestCompileId) {
+ if (auto Err = handle<RequestCompile>(C, CompileCallback))
+ return Err;
+ return Error::success();
}
-
- return std::error_code();
+ // else
+ return orcError(OrcErrorCode::UnexpectedRPCCall);
}
- std::error_code readMem(char *Dst, TargetAddress Src, uint64_t Size) {
+ Expected<std::vector<char>> readMem(char *Dst, TargetAddress Src,
+ uint64_t Size) {
// Check for an 'out-of-band' error, e.g. from an MM destructor.
if (ExistingError)
- return ExistingError;
-
- if (auto EC = call<ReadMem>(Channel, Src, Size))
- return EC;
+ return std::move(ExistingError);
- if (auto EC = expect<ReadMemResponse>(
- Channel, [&]() { return Channel.readBytes(Dst, Size); }))
- return EC;
+ return callST<ReadMem>(Channel, Src, Size);
+ }
- return std::error_code();
+ Error registerEHFrames(TargetAddress &RAddr, uint32_t Size) {
+ return callST<RegisterEHFrames>(Channel, RAddr, Size);
}
- std::error_code reserveMem(TargetAddress &RemoteAddr,
- ResourceIdMgr::ResourceId Id, uint64_t Size,
- uint32_t Align) {
+ Expected<TargetAddress> reserveMem(ResourceIdMgr::ResourceId Id,
+ uint64_t Size, uint32_t Align) {
// Check for an 'out-of-band' error, e.g. from an MM destructor.
if (ExistingError)
- return ExistingError;
-
- if (std::error_code EC = call<ReserveMem>(Channel, Id, Size, Align))
- return EC;
+ return std::move(ExistingError);
- return expect<ReserveMemResponse>(Channel, readArgs(RemoteAddr));
+ return callST<ReserveMem>(Channel, Id, Size, Align);
}
- std::error_code setProtections(ResourceIdMgr::ResourceId Id,
- TargetAddress RemoteSegAddr,
- unsigned ProtFlags) {
- return call<SetProtections>(Channel, Id, RemoteSegAddr, ProtFlags);
+ Error setProtections(ResourceIdMgr::ResourceId Id,
+ TargetAddress RemoteSegAddr, unsigned ProtFlags) {
+ return callST<SetProtections>(Channel, Id, RemoteSegAddr, ProtFlags);
}
- std::error_code writeMem(TargetAddress Addr, const char *Src, uint64_t Size) {
+ Error writeMem(TargetAddress Addr, const char *Src, uint64_t Size) {
// Check for an 'out-of-band' error, e.g. from an MM destructor.
if (ExistingError)
- return ExistingError;
-
- // Make the send call.
- if (auto EC = call<WriteMem>(Channel, Addr, Size))
- return EC;
-
- // Follow this up with the section contents.
- if (auto EC = Channel.appendBytes(Src, Size))
- return EC;
+ return std::move(ExistingError);
- return Channel.send();
+ return callST<WriteMem>(Channel, DirectBufferWriter(Src, Addr, Size));
}
- std::error_code writePointer(TargetAddress Addr, TargetAddress PtrVal) {
+ Error writePointer(TargetAddress Addr, TargetAddress PtrVal) {
// Check for an 'out-of-band' error, e.g. from an MM destructor.
if (ExistingError)
- return ExistingError;
+ return std::move(ExistingError);
- return call<WritePtr>(Channel, Addr, PtrVal);
+ return callST<WritePtr>(Channel, Addr, PtrVal);
}
- static std::error_code doNothing() { return std::error_code(); }
+ static Error doNothing() { return Error::success(); }
ChannelT &Channel;
- std::error_code ExistingError;
+ Error ExistingError;
std::string RemoteTargetTriple;
- uint32_t RemotePointerSize;
- uint32_t RemotePageSize;
- uint32_t RemoteTrampolineSize;
- uint32_t RemoteIndirectStubSize;
+ uint32_t RemotePointerSize = 0;
+ uint32_t RemotePageSize = 0;
+ uint32_t RemoteTrampolineSize = 0;
+ uint32_t RemoteIndirectStubSize = 0;
ResourceIdMgr AllocatorIds, IndirectStubOwnerIds;
- std::function<TargetAddress(TargetAddress)> CompileCallback;
+ Optional<RCCompileCallbackManager> CallbackManager;
};
} // end namespace remote
@@ -781,4 +823,4 @@ private:
#undef DEBUG_TYPE
-#endif
+#endif // LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H
diff --git a/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h b/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h
index 96dc24251026..74d851522f79 100644
--- a/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h
+++ b/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h
@@ -24,12 +24,51 @@ namespace llvm {
namespace orc {
namespace remote {
+class DirectBufferWriter {
+public:
+ DirectBufferWriter() = default;
+ DirectBufferWriter(const char *Src, TargetAddress Dst, uint64_t Size)
+ : Src(Src), Dst(Dst), Size(Size) {}
+
+ const char *getSrc() const { return Src; }
+ TargetAddress getDst() const { return Dst; }
+ uint64_t getSize() const { return Size; }
+
+private:
+ const char *Src;
+ TargetAddress Dst;
+ uint64_t Size;
+};
+
+inline Error serialize(RPCChannel &C, const DirectBufferWriter &DBW) {
+ if (auto EC = serialize(C, DBW.getDst()))
+ return EC;
+ if (auto EC = serialize(C, DBW.getSize()))
+ return EC;
+ return C.appendBytes(DBW.getSrc(), DBW.getSize());
+}
+
+inline Error deserialize(RPCChannel &C, DirectBufferWriter &DBW) {
+ TargetAddress Dst;
+ if (auto EC = deserialize(C, Dst))
+ return EC;
+ uint64_t Size;
+ if (auto EC = deserialize(C, Size))
+ return EC;
+ char *Addr = reinterpret_cast<char *>(static_cast<uintptr_t>(Dst));
+
+ DBW = DirectBufferWriter(0, Dst, Size);
+
+ return C.readBytes(Addr, Size);
+}
+
class OrcRemoteTargetRPCAPI : public RPC<RPCChannel> {
protected:
class ResourceIdMgr {
public:
typedef uint64_t ResourceId;
- ResourceIdMgr() : NextId(0) {}
+ static const ResourceId InvalidId = ~0U;
+
ResourceId getNext() {
if (!FreeIds.empty()) {
ResourceId I = FreeIds.back();
@@ -41,140 +80,122 @@ protected:
void release(ResourceId I) { FreeIds.push_back(I); }
private:
- ResourceId NextId;
+ ResourceId NextId = 0;
std::vector<ResourceId> FreeIds;
};
public:
- enum JITProcId : uint32_t {
- InvalidId = 0,
- CallIntVoidId,
- CallIntVoidResponseId,
+ // FIXME: Remove constructors once MSVC supports synthesizing move-ops.
+ OrcRemoteTargetRPCAPI() = default;
+ OrcRemoteTargetRPCAPI(const OrcRemoteTargetRPCAPI &) = delete;
+ OrcRemoteTargetRPCAPI &operator=(const OrcRemoteTargetRPCAPI &) = delete;
+
+ OrcRemoteTargetRPCAPI(OrcRemoteTargetRPCAPI &&) {}
+ OrcRemoteTargetRPCAPI &operator=(OrcRemoteTargetRPCAPI &&) { return *this; }
+
+ enum JITFuncId : uint32_t {
+ InvalidId = RPCFunctionIdTraits<JITFuncId>::InvalidId,
+ CallIntVoidId = RPCFunctionIdTraits<JITFuncId>::FirstValidId,
CallMainId,
- CallMainResponseId,
CallVoidVoidId,
- CallVoidVoidResponseId,
CreateRemoteAllocatorId,
CreateIndirectStubsOwnerId,
+ DeregisterEHFramesId,
DestroyRemoteAllocatorId,
DestroyIndirectStubsOwnerId,
EmitIndirectStubsId,
- EmitIndirectStubsResponseId,
EmitResolverBlockId,
EmitTrampolineBlockId,
- EmitTrampolineBlockResponseId,
GetSymbolAddressId,
- GetSymbolAddressResponseId,
GetRemoteInfoId,
- GetRemoteInfoResponseId,
ReadMemId,
- ReadMemResponseId,
+ RegisterEHFramesId,
ReserveMemId,
- ReserveMemResponseId,
RequestCompileId,
- RequestCompileResponseId,
SetProtectionsId,
TerminateSessionId,
WriteMemId,
WritePtrId
};
- static const char *getJITProcIdName(JITProcId Id);
+ static const char *getJITFuncIdName(JITFuncId Id);
- typedef Procedure<CallIntVoidId, TargetAddress /* FnAddr */> CallIntVoid;
+ typedef Function<CallIntVoidId, int32_t(TargetAddress Addr)> CallIntVoid;
- typedef Procedure<CallIntVoidResponseId, int /* Result */>
- CallIntVoidResponse;
-
- typedef Procedure<CallMainId, TargetAddress /* FnAddr */,
- std::vector<std::string> /* Args */>
+ typedef Function<CallMainId,
+ int32_t(TargetAddress Addr, std::vector<std::string> Args)>
CallMain;
- typedef Procedure<CallMainResponseId, int /* Result */> CallMainResponse;
-
- typedef Procedure<CallVoidVoidId, TargetAddress /* FnAddr */> CallVoidVoid;
-
- typedef Procedure<CallVoidVoidResponseId> CallVoidVoidResponse;
+ typedef Function<CallVoidVoidId, void(TargetAddress FnAddr)> CallVoidVoid;
- typedef Procedure<CreateRemoteAllocatorId,
- ResourceIdMgr::ResourceId /* Allocator ID */>
+ typedef Function<CreateRemoteAllocatorId,
+ void(ResourceIdMgr::ResourceId AllocatorID)>
CreateRemoteAllocator;
- typedef Procedure<CreateIndirectStubsOwnerId,
- ResourceIdMgr::ResourceId /* StubsOwner ID */>
+ typedef Function<CreateIndirectStubsOwnerId,
+ void(ResourceIdMgr::ResourceId StubOwnerID)>
CreateIndirectStubsOwner;
- typedef Procedure<DestroyRemoteAllocatorId,
- ResourceIdMgr::ResourceId /* Allocator ID */>
+ typedef Function<DeregisterEHFramesId,
+ void(TargetAddress Addr, uint32_t Size)>
+ DeregisterEHFrames;
+
+ typedef Function<DestroyRemoteAllocatorId,
+ void(ResourceIdMgr::ResourceId AllocatorID)>
DestroyRemoteAllocator;
- typedef Procedure<DestroyIndirectStubsOwnerId,
- ResourceIdMgr::ResourceId /* StubsOwner ID */>
+ typedef Function<DestroyIndirectStubsOwnerId,
+ void(ResourceIdMgr::ResourceId StubsOwnerID)>
DestroyIndirectStubsOwner;
- typedef Procedure<EmitIndirectStubsId,
- ResourceIdMgr::ResourceId /* StubsOwner ID */,
- uint32_t /* NumStubsRequired */>
+ /// EmitIndirectStubs result is (StubsBase, PtrsBase, NumStubsEmitted).
+ typedef Function<EmitIndirectStubsId,
+ std::tuple<TargetAddress, TargetAddress, uint32_t>(
+ ResourceIdMgr::ResourceId StubsOwnerID,
+ uint32_t NumStubsRequired)>
EmitIndirectStubs;
- typedef Procedure<
- EmitIndirectStubsResponseId, TargetAddress /* StubsBaseAddr */,
- TargetAddress /* PtrsBaseAddr */, uint32_t /* NumStubsEmitted */>
- EmitIndirectStubsResponse;
-
- typedef Procedure<EmitResolverBlockId> EmitResolverBlock;
+ typedef Function<EmitResolverBlockId, void()> EmitResolverBlock;
- typedef Procedure<EmitTrampolineBlockId> EmitTrampolineBlock;
+ /// EmitTrampolineBlock result is (BlockAddr, NumTrampolines).
+ typedef Function<EmitTrampolineBlockId, std::tuple<TargetAddress, uint32_t>()>
+ EmitTrampolineBlock;
- typedef Procedure<EmitTrampolineBlockResponseId,
- TargetAddress /* BlockAddr */,
- uint32_t /* NumTrampolines */>
- EmitTrampolineBlockResponse;
-
- typedef Procedure<GetSymbolAddressId, std::string /*SymbolName*/>
+ typedef Function<GetSymbolAddressId, TargetAddress(std::string SymbolName)>
GetSymbolAddress;
- typedef Procedure<GetSymbolAddressResponseId, uint64_t /* SymbolAddr */>
- GetSymbolAddressResponse;
-
- typedef Procedure<GetRemoteInfoId> GetRemoteInfo;
-
- typedef Procedure<GetRemoteInfoResponseId, std::string /* Triple */,
- uint32_t /* PointerSize */, uint32_t /* PageSize */,
- uint32_t /* TrampolineSize */,
- uint32_t /* IndirectStubSize */>
- GetRemoteInfoResponse;
+ /// GetRemoteInfo result is (Triple, PointerSize, PageSize, TrampolineSize,
+ /// IndirectStubsSize).
+ typedef Function<GetRemoteInfoId, std::tuple<std::string, uint32_t, uint32_t,
+ uint32_t, uint32_t>()>
+ GetRemoteInfo;
- typedef Procedure<ReadMemId, TargetAddress /* Src */, uint64_t /* Size */>
+ typedef Function<ReadMemId,
+ std::vector<char>(TargetAddress Src, uint64_t Size)>
ReadMem;
- typedef Procedure<ReadMemResponseId> ReadMemResponse;
+ typedef Function<RegisterEHFramesId, void(TargetAddress Addr, uint32_t Size)>
+ RegisterEHFrames;
- typedef Procedure<ReserveMemId, ResourceIdMgr::ResourceId /* Id */,
- uint64_t /* Size */, uint32_t /* Align */>
+ typedef Function<ReserveMemId,
+ TargetAddress(ResourceIdMgr::ResourceId AllocID,
+ uint64_t Size, uint32_t Align)>
ReserveMem;
- typedef Procedure<ReserveMemResponseId, TargetAddress /* Addr */>
- ReserveMemResponse;
-
- typedef Procedure<RequestCompileId, TargetAddress /* TrampolineAddr */>
+ typedef Function<RequestCompileId,
+ TargetAddress(TargetAddress TrampolineAddr)>
RequestCompile;
- typedef Procedure<RequestCompileResponseId, TargetAddress /* ImplAddr */>
- RequestCompileResponse;
-
- typedef Procedure<SetProtectionsId, ResourceIdMgr::ResourceId /* Id */,
- TargetAddress /* Dst */, uint32_t /* ProtFlags */>
+ typedef Function<SetProtectionsId,
+ void(ResourceIdMgr::ResourceId AllocID, TargetAddress Dst,
+ uint32_t ProtFlags)>
SetProtections;
- typedef Procedure<TerminateSessionId> TerminateSession;
+ typedef Function<TerminateSessionId, void()> TerminateSession;
- typedef Procedure<WriteMemId, TargetAddress /* Dst */, uint64_t /* Size */
- /* Data should follow */>
- WriteMem;
+ typedef Function<WriteMemId, void(DirectBufferWriter DB)> WriteMem;
- typedef Procedure<WritePtrId, TargetAddress /* Dst */,
- TargetAddress /* Val */>
+ typedef Function<WritePtrId, void(TargetAddress Dst, TargetAddress Val)>
WritePtr;
};
diff --git a/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h b/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h
index 5247661e49ce..bf4299c69b24 100644
--- a/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h
+++ b/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h
@@ -35,17 +35,31 @@ public:
typedef std::function<TargetAddress(const std::string &Name)>
SymbolLookupFtor;
- OrcRemoteTargetServer(ChannelT &Channel, SymbolLookupFtor SymbolLookup)
- : Channel(Channel), SymbolLookup(std::move(SymbolLookup)) {}
+ typedef std::function<void(uint8_t *Addr, uint32_t Size)>
+ EHFrameRegistrationFtor;
- std::error_code getNextProcId(JITProcId &Id) {
- return deserialize(Channel, Id);
- }
+ OrcRemoteTargetServer(ChannelT &Channel, SymbolLookupFtor SymbolLookup,
+ EHFrameRegistrationFtor EHFramesRegister,
+ EHFrameRegistrationFtor EHFramesDeregister)
+ : Channel(Channel), SymbolLookup(std::move(SymbolLookup)),
+ EHFramesRegister(std::move(EHFramesRegister)),
+ EHFramesDeregister(std::move(EHFramesDeregister)) {}
+
+ // FIXME: Remove move/copy ops once MSVC supports synthesizing move ops.
+ OrcRemoteTargetServer(const OrcRemoteTargetServer &) = delete;
+ OrcRemoteTargetServer &operator=(const OrcRemoteTargetServer &) = delete;
+
+ OrcRemoteTargetServer(OrcRemoteTargetServer &&Other)
+ : Channel(Other.Channel), SymbolLookup(std::move(Other.SymbolLookup)),
+ EHFramesRegister(std::move(Other.EHFramesRegister)),
+ EHFramesDeregister(std::move(Other.EHFramesDeregister)) {}
+
+ OrcRemoteTargetServer &operator=(OrcRemoteTargetServer &&) = delete;
- std::error_code handleKnownProcedure(JITProcId Id) {
+ Error handleKnownFunction(JITFuncId Id) {
typedef OrcRemoteTargetServer ThisT;
- DEBUG(dbgs() << "Handling known proc: " << getJITProcIdName(Id) << "\n");
+ DEBUG(dbgs() << "Handling known proc: " << getJITFuncIdName(Id) << "\n");
switch (Id) {
case CallIntVoidId:
@@ -60,6 +74,9 @@ public:
case CreateIndirectStubsOwnerId:
return handle<CreateIndirectStubsOwner>(
Channel, *this, &ThisT::handleCreateIndirectStubsOwner);
+ case DeregisterEHFramesId:
+ return handle<DeregisterEHFrames>(Channel, *this,
+ &ThisT::handleDeregisterEHFrames);
case DestroyRemoteAllocatorId:
return handle<DestroyRemoteAllocator>(
Channel, *this, &ThisT::handleDestroyRemoteAllocator);
@@ -82,6 +99,9 @@ public:
return handle<GetRemoteInfo>(Channel, *this, &ThisT::handleGetRemoteInfo);
case ReadMemId:
return handle<ReadMem>(Channel, *this, &ThisT::handleReadMem);
+ case RegisterEHFramesId:
+ return handle<RegisterEHFrames>(Channel, *this,
+ &ThisT::handleRegisterEHFrames);
case ReserveMemId:
return handle<ReserveMem>(Channel, *this, &ThisT::handleReserveMem);
case SetProtectionsId:
@@ -98,27 +118,16 @@ public:
llvm_unreachable("Unhandled JIT RPC procedure Id.");
}
- std::error_code requestCompile(TargetAddress &CompiledFnAddr,
- TargetAddress TrampolineAddr) {
- if (auto EC = call<RequestCompile>(Channel, TrampolineAddr))
- return EC;
-
- while (1) {
- JITProcId Id = InvalidId;
- if (auto EC = getNextProcId(Id))
- return EC;
-
- switch (Id) {
- case RequestCompileResponseId:
- return handle<RequestCompileResponse>(Channel,
- readArgs(CompiledFnAddr));
- default:
- if (auto EC = handleKnownProcedure(Id))
- return EC;
- }
- }
+ Expected<TargetAddress> requestCompile(TargetAddress TrampolineAddr) {
+ auto Listen = [&](RPCChannel &C, uint32_t Id) {
+ return handleKnownFunction(static_cast<JITFuncId>(Id));
+ };
+
+ return callSTHandling<RequestCompile>(Channel, Listen, TrampolineAddr);
+ }
- llvm_unreachable("Fell through request-compile command loop.");
+ Error handleTerminateSession() {
+ return handle<TerminateSession>(Channel, []() { return Error::success(); });
}
private:
@@ -135,60 +144,56 @@ private:
sys::Memory::releaseMappedMemory(Alloc.second);
}
- std::error_code allocate(void *&Addr, size_t Size, uint32_t Align) {
+ Error allocate(void *&Addr, size_t Size, uint32_t Align) {
std::error_code EC;
sys::MemoryBlock MB = sys::Memory::allocateMappedMemory(
Size, nullptr, sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC);
if (EC)
- return EC;
+ return errorCodeToError(EC);
Addr = MB.base();
assert(Allocs.find(MB.base()) == Allocs.end() && "Duplicate alloc");
Allocs[MB.base()] = std::move(MB);
- return std::error_code();
+ return Error::success();
}
- std::error_code setProtections(void *block, unsigned Flags) {
+ Error setProtections(void *block, unsigned Flags) {
auto I = Allocs.find(block);
if (I == Allocs.end())
return orcError(OrcErrorCode::RemoteMProtectAddrUnrecognized);
- return sys::Memory::protectMappedMemory(I->second, Flags);
+ return errorCodeToError(
+ sys::Memory::protectMappedMemory(I->second, Flags));
}
private:
std::map<void *, sys::MemoryBlock> Allocs;
};
- static std::error_code doNothing() { return std::error_code(); }
+ static Error doNothing() { return Error::success(); }
static TargetAddress reenter(void *JITTargetAddr, void *TrampolineAddr) {
- TargetAddress CompiledFnAddr = 0;
-
auto T = static_cast<OrcRemoteTargetServer *>(JITTargetAddr);
- auto EC = T->requestCompile(
- CompiledFnAddr, static_cast<TargetAddress>(
- reinterpret_cast<uintptr_t>(TrampolineAddr)));
- assert(!EC && "Compile request failed");
- (void)EC;
- return CompiledFnAddr;
+ auto AddrOrErr = T->requestCompile(static_cast<TargetAddress>(
+ reinterpret_cast<uintptr_t>(TrampolineAddr)));
+ // FIXME: Allow customizable failure substitution functions.
+ assert(AddrOrErr && "Compile request failed");
+ return *AddrOrErr;
}
- std::error_code handleCallIntVoid(TargetAddress Addr) {
+ Expected<int32_t> handleCallIntVoid(TargetAddress Addr) {
typedef int (*IntVoidFnTy)();
IntVoidFnTy Fn =
reinterpret_cast<IntVoidFnTy>(static_cast<uintptr_t>(Addr));
- DEBUG(dbgs() << " Calling "
- << reinterpret_cast<void *>(reinterpret_cast<intptr_t>(Fn))
- << "\n");
+ DEBUG(dbgs() << " Calling " << format("0x%016x", Addr) << "\n");
int Result = Fn();
DEBUG(dbgs() << " Result = " << Result << "\n");
- return call<CallIntVoidResponse>(Channel, Result);
+ return Result;
}
- std::error_code handleCallMain(TargetAddress Addr,
- std::vector<std::string> Args) {
+ Expected<int32_t> handleCallMain(TargetAddress Addr,
+ std::vector<std::string> Args) {
typedef int (*MainFnTy)(int, const char *[]);
MainFnTy Fn = reinterpret_cast<MainFnTy>(static_cast<uintptr_t>(Addr));
@@ -199,63 +204,71 @@ private:
for (auto &Arg : Args)
ArgV[Idx++] = Arg.c_str();
- DEBUG(dbgs() << " Calling " << reinterpret_cast<void *>(Fn) << "\n");
+ DEBUG(dbgs() << " Calling " << format("0x%016x", Addr) << "\n");
int Result = Fn(ArgC, ArgV.get());
DEBUG(dbgs() << " Result = " << Result << "\n");
- return call<CallMainResponse>(Channel, Result);
+ return Result;
}
- std::error_code handleCallVoidVoid(TargetAddress Addr) {
+ Error handleCallVoidVoid(TargetAddress Addr) {
typedef void (*VoidVoidFnTy)();
VoidVoidFnTy Fn =
reinterpret_cast<VoidVoidFnTy>(static_cast<uintptr_t>(Addr));
- DEBUG(dbgs() << " Calling " << reinterpret_cast<void *>(Fn) << "\n");
+ DEBUG(dbgs() << " Calling " << format("0x%016x", Addr) << "\n");
Fn();
DEBUG(dbgs() << " Complete.\n");
- return call<CallVoidVoidResponse>(Channel);
+ return Error::success();
}
- std::error_code handleCreateRemoteAllocator(ResourceIdMgr::ResourceId Id) {
+ Error handleCreateRemoteAllocator(ResourceIdMgr::ResourceId Id) {
auto I = Allocators.find(Id);
if (I != Allocators.end())
return orcError(OrcErrorCode::RemoteAllocatorIdAlreadyInUse);
DEBUG(dbgs() << " Created allocator " << Id << "\n");
Allocators[Id] = Allocator();
- return std::error_code();
+ return Error::success();
}
- std::error_code handleCreateIndirectStubsOwner(ResourceIdMgr::ResourceId Id) {
+ Error handleCreateIndirectStubsOwner(ResourceIdMgr::ResourceId Id) {
auto I = IndirectStubsOwners.find(Id);
if (I != IndirectStubsOwners.end())
return orcError(OrcErrorCode::RemoteIndirectStubsOwnerIdAlreadyInUse);
DEBUG(dbgs() << " Create indirect stubs owner " << Id << "\n");
IndirectStubsOwners[Id] = ISBlockOwnerList();
- return std::error_code();
+ return Error::success();
+ }
+
+ Error handleDeregisterEHFrames(TargetAddress TAddr, uint32_t Size) {
+ uint8_t *Addr = reinterpret_cast<uint8_t *>(static_cast<uintptr_t>(TAddr));
+ DEBUG(dbgs() << " Registering EH frames at " << format("0x%016x", TAddr)
+ << ", Size = " << Size << " bytes\n");
+ EHFramesDeregister(Addr, Size);
+ return Error::success();
}
- std::error_code handleDestroyRemoteAllocator(ResourceIdMgr::ResourceId Id) {
+ Error handleDestroyRemoteAllocator(ResourceIdMgr::ResourceId Id) {
auto I = Allocators.find(Id);
if (I == Allocators.end())
return orcError(OrcErrorCode::RemoteAllocatorDoesNotExist);
Allocators.erase(I);
DEBUG(dbgs() << " Destroyed allocator " << Id << "\n");
- return std::error_code();
+ return Error::success();
}
- std::error_code
- handleDestroyIndirectStubsOwner(ResourceIdMgr::ResourceId Id) {
+ Error handleDestroyIndirectStubsOwner(ResourceIdMgr::ResourceId Id) {
auto I = IndirectStubsOwners.find(Id);
if (I == IndirectStubsOwners.end())
return orcError(OrcErrorCode::RemoteIndirectStubsOwnerDoesNotExist);
IndirectStubsOwners.erase(I);
- return std::error_code();
+ return Error::success();
}
- std::error_code handleEmitIndirectStubs(ResourceIdMgr::ResourceId Id,
- uint32_t NumStubsRequired) {
+ Expected<std::tuple<TargetAddress, TargetAddress, uint32_t>>
+ handleEmitIndirectStubs(ResourceIdMgr::ResourceId Id,
+ uint32_t NumStubsRequired) {
DEBUG(dbgs() << " ISMgr " << Id << " request " << NumStubsRequired
<< " stubs.\n");
@@ -264,9 +277,9 @@ private:
return orcError(OrcErrorCode::RemoteIndirectStubsOwnerDoesNotExist);
typename TargetT::IndirectStubsInfo IS;
- if (auto EC =
+ if (auto Err =
TargetT::emitIndirectStubsBlock(IS, NumStubsRequired, nullptr))
- return EC;
+ return std::move(Err);
TargetAddress StubsBase =
static_cast<TargetAddress>(reinterpret_cast<uintptr_t>(IS.getStub(0)));
@@ -277,36 +290,35 @@ private:
auto &BlockList = StubOwnerItr->second;
BlockList.push_back(std::move(IS));
- return call<EmitIndirectStubsResponse>(Channel, StubsBase, PtrsBase,
- NumStubsEmitted);
+ return std::make_tuple(StubsBase, PtrsBase, NumStubsEmitted);
}
- std::error_code handleEmitResolverBlock() {
+ Error handleEmitResolverBlock() {
std::error_code EC;
ResolverBlock = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
TargetT::ResolverCodeSize, nullptr,
sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC));
if (EC)
- return EC;
+ return errorCodeToError(EC);
TargetT::writeResolverCode(static_cast<uint8_t *>(ResolverBlock.base()),
&reenter, this);
- return sys::Memory::protectMappedMemory(ResolverBlock.getMemoryBlock(),
- sys::Memory::MF_READ |
- sys::Memory::MF_EXEC);
+ return errorCodeToError(sys::Memory::protectMappedMemory(
+ ResolverBlock.getMemoryBlock(),
+ sys::Memory::MF_READ | sys::Memory::MF_EXEC));
}
- std::error_code handleEmitTrampolineBlock() {
+ Expected<std::tuple<TargetAddress, uint32_t>> handleEmitTrampolineBlock() {
std::error_code EC;
auto TrampolineBlock =
sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
sys::Process::getPageSize(), nullptr,
sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC));
if (EC)
- return EC;
+ return errorCodeToError(EC);
- unsigned NumTrampolines =
+ uint32_t NumTrampolines =
(sys::Process::getPageSize() - TargetT::PointerSize) /
TargetT::TrampolineSize;
@@ -320,20 +332,21 @@ private:
TrampolineBlocks.push_back(std::move(TrampolineBlock));
- return call<EmitTrampolineBlockResponse>(
- Channel,
- static_cast<TargetAddress>(reinterpret_cast<uintptr_t>(TrampolineMem)),
- NumTrampolines);
+ auto TrampolineBaseAddr =
+ static_cast<TargetAddress>(reinterpret_cast<uintptr_t>(TrampolineMem));
+
+ return std::make_tuple(TrampolineBaseAddr, NumTrampolines);
}
- std::error_code handleGetSymbolAddress(const std::string &Name) {
+ Expected<TargetAddress> handleGetSymbolAddress(const std::string &Name) {
TargetAddress Addr = SymbolLookup(Name);
DEBUG(dbgs() << " Symbol '" << Name << "' = " << format("0x%016x", Addr)
<< "\n");
- return call<GetSymbolAddressResponse>(Channel, Addr);
+ return Addr;
}
- std::error_code handleGetRemoteInfo() {
+ Expected<std::tuple<std::string, uint32_t, uint32_t, uint32_t, uint32_t>>
+ handleGetRemoteInfo() {
std::string ProcessTriple = sys::getProcessTriple();
uint32_t PointerSize = TargetT::PointerSize;
uint32_t PageSize = sys::Process::getPageSize();
@@ -345,35 +358,41 @@ private:
<< " page size = " << PageSize << "\n"
<< " trampoline size = " << TrampolineSize << "\n"
<< " indirect stub size = " << IndirectStubSize << "\n");
- return call<GetRemoteInfoResponse>(Channel, ProcessTriple, PointerSize,
- PageSize, TrampolineSize,
- IndirectStubSize);
+ return std::make_tuple(ProcessTriple, PointerSize, PageSize, TrampolineSize,
+ IndirectStubSize);
}
- std::error_code handleReadMem(TargetAddress RSrc, uint64_t Size) {
+ Expected<std::vector<char>> handleReadMem(TargetAddress RSrc, uint64_t Size) {
char *Src = reinterpret_cast<char *>(static_cast<uintptr_t>(RSrc));
DEBUG(dbgs() << " Reading " << Size << " bytes from "
- << static_cast<void *>(Src) << "\n");
+ << format("0x%016x", RSrc) << "\n");
- if (auto EC = call<ReadMemResponse>(Channel))
- return EC;
+ std::vector<char> Buffer;
+ Buffer.resize(Size);
+ for (char *P = Src; Size != 0; --Size)
+ Buffer.push_back(*P++);
- if (auto EC = Channel.appendBytes(Src, Size))
- return EC;
+ return Buffer;
+ }
- return Channel.send();
+ Error handleRegisterEHFrames(TargetAddress TAddr, uint32_t Size) {
+ uint8_t *Addr = reinterpret_cast<uint8_t *>(static_cast<uintptr_t>(TAddr));
+ DEBUG(dbgs() << " Registering EH frames at " << format("0x%016x", TAddr)
+ << ", Size = " << Size << " bytes\n");
+ EHFramesRegister(Addr, Size);
+ return Error::success();
}
- std::error_code handleReserveMem(ResourceIdMgr::ResourceId Id, uint64_t Size,
- uint32_t Align) {
+ Expected<TargetAddress> handleReserveMem(ResourceIdMgr::ResourceId Id,
+ uint64_t Size, uint32_t Align) {
auto I = Allocators.find(Id);
if (I == Allocators.end())
return orcError(OrcErrorCode::RemoteAllocatorDoesNotExist);
auto &Allocator = I->second;
void *LocalAllocAddr = nullptr;
- if (auto EC = Allocator.allocate(LocalAllocAddr, Size, Align))
- return EC;
+ if (auto Err = Allocator.allocate(LocalAllocAddr, Size, Align))
+ return std::move(Err);
DEBUG(dbgs() << " Allocator " << Id << " reserved " << LocalAllocAddr
<< " (" << Size << " bytes, alignment " << Align << ")\n");
@@ -381,11 +400,11 @@ private:
TargetAddress AllocAddr =
static_cast<TargetAddress>(reinterpret_cast<uintptr_t>(LocalAllocAddr));
- return call<ReserveMemResponse>(Channel, AllocAddr);
+ return AllocAddr;
}
- std::error_code handleSetProtections(ResourceIdMgr::ResourceId Id,
- TargetAddress Addr, uint32_t Flags) {
+ Error handleSetProtections(ResourceIdMgr::ResourceId Id, TargetAddress Addr,
+ uint32_t Flags) {
auto I = Allocators.find(Id);
if (I == Allocators.end())
return orcError(OrcErrorCode::RemoteAllocatorDoesNotExist);
@@ -398,24 +417,24 @@ private:
return Allocator.setProtections(LocalAddr, Flags);
}
- std::error_code handleWriteMem(TargetAddress RDst, uint64_t Size) {
- char *Dst = reinterpret_cast<char *>(static_cast<uintptr_t>(RDst));
- DEBUG(dbgs() << " Writing " << Size << " bytes to "
- << format("0x%016x", RDst) << "\n");
- return Channel.readBytes(Dst, Size);
+ Error handleWriteMem(DirectBufferWriter DBW) {
+ DEBUG(dbgs() << " Writing " << DBW.getSize() << " bytes to "
+ << format("0x%016x", DBW.getDst()) << "\n");
+ return Error::success();
}
- std::error_code handleWritePtr(TargetAddress Addr, TargetAddress PtrVal) {
+ Error handleWritePtr(TargetAddress Addr, TargetAddress PtrVal) {
DEBUG(dbgs() << " Writing pointer *" << format("0x%016x", Addr) << " = "
<< format("0x%016x", PtrVal) << "\n");
uintptr_t *Ptr =
reinterpret_cast<uintptr_t *>(static_cast<uintptr_t>(Addr));
*Ptr = static_cast<uintptr_t>(PtrVal);
- return std::error_code();
+ return Error::success();
}
ChannelT &Channel;
SymbolLookupFtor SymbolLookup;
+ EHFrameRegistrationFtor EHFramesRegister, EHFramesDeregister;
std::map<ResourceIdMgr::ResourceId, Allocator> Allocators;
typedef std::vector<typename TargetT::IndirectStubsInfo> ISBlockOwnerList;
std::map<ResourceIdMgr::ResourceId, ISBlockOwnerList> IndirectStubsOwners;
diff --git a/include/llvm/ExecutionEngine/Orc/RPCChannel.h b/include/llvm/ExecutionEngine/Orc/RPCChannel.h
index b97b6daf5864..c569e3cf05b4 100644
--- a/include/llvm/ExecutionEngine/Orc/RPCChannel.h
+++ b/include/llvm/ExecutionEngine/Orc/RPCChannel.h
@@ -1,13 +1,27 @@
-// -*- c++ -*-
+//===- llvm/ExecutionEngine/Orc/RPCChannel.h --------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
#ifndef LLVM_EXECUTIONENGINE_ORC_RPCCHANNEL_H
#define LLVM_EXECUTIONENGINE_ORC_RPCCHANNEL_H
#include "OrcError.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Endian.h"
-
-#include <system_error>
+#include "llvm/Support/Error.h"
+#include <cstddef>
+#include <cstdint>
+#include <mutex>
+#include <string>
+#include <tuple>
+#include <vector>
namespace llvm {
namespace orc {
@@ -19,40 +33,73 @@ public:
virtual ~RPCChannel() {}
/// Read Size bytes from the stream into *Dst.
- virtual std::error_code readBytes(char *Dst, unsigned Size) = 0;
+ virtual Error readBytes(char *Dst, unsigned Size) = 0;
/// Read size bytes from *Src and append them to the stream.
- virtual std::error_code appendBytes(const char *Src, unsigned Size) = 0;
+ virtual Error appendBytes(const char *Src, unsigned Size) = 0;
/// Flush the stream if possible.
- virtual std::error_code send() = 0;
+ virtual Error send() = 0;
+
+ /// Get the lock for stream reading.
+ std::mutex &getReadLock() { return readLock; }
+
+ /// Get the lock for stream writing.
+ std::mutex &getWriteLock() { return writeLock; }
+
+private:
+ std::mutex readLock, writeLock;
};
+/// Notify the channel that we're starting a message send.
+/// Locks the channel for writing.
+inline Error startSendMessage(RPCChannel &C) {
+ C.getWriteLock().lock();
+ return Error::success();
+}
+
+/// Notify the channel that we're ending a message send.
+/// Unlocks the channel for writing.
+inline Error endSendMessage(RPCChannel &C) {
+ C.getWriteLock().unlock();
+ return Error::success();
+}
+
+/// Notify the channel that we're starting a message receive.
+/// Locks the channel for reading.
+inline Error startReceiveMessage(RPCChannel &C) {
+ C.getReadLock().lock();
+ return Error::success();
+}
+
+/// Notify the channel that we're ending a message receive.
+/// Unlocks the channel for reading.
+inline Error endReceiveMessage(RPCChannel &C) {
+ C.getReadLock().unlock();
+ return Error::success();
+}
+
/// RPC channel serialization for a variadic list of arguments.
template <typename T, typename... Ts>
-std::error_code serialize_seq(RPCChannel &C, const T &Arg, const Ts &... Args) {
- if (auto EC = serialize(C, Arg))
- return EC;
- return serialize_seq(C, Args...);
+Error serializeSeq(RPCChannel &C, const T &Arg, const Ts &... Args) {
+ if (auto Err = serialize(C, Arg))
+ return Err;
+ return serializeSeq(C, Args...);
}
/// RPC channel serialization for an (empty) variadic list of arguments.
-inline std::error_code serialize_seq(RPCChannel &C) {
- return std::error_code();
-}
+inline Error serializeSeq(RPCChannel &C) { return Error::success(); }
/// RPC channel deserialization for a variadic list of arguments.
template <typename T, typename... Ts>
-std::error_code deserialize_seq(RPCChannel &C, T &Arg, Ts &... Args) {
- if (auto EC = deserialize(C, Arg))
- return EC;
- return deserialize_seq(C, Args...);
+Error deserializeSeq(RPCChannel &C, T &Arg, Ts &... Args) {
+ if (auto Err = deserialize(C, Arg))
+ return Err;
+ return deserializeSeq(C, Args...);
}
/// RPC channel serialization for an (empty) variadic list of arguments.
-inline std::error_code deserialize_seq(RPCChannel &C) {
- return std::error_code();
-}
+inline Error deserializeSeq(RPCChannel &C) { return Error::success(); }
/// RPC channel serialization for integer primitives.
template <typename T>
@@ -61,7 +108,7 @@ typename std::enable_if<
std::is_same<T, uint32_t>::value || std::is_same<T, int32_t>::value ||
std::is_same<T, uint16_t>::value || std::is_same<T, int16_t>::value ||
std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value,
- std::error_code>::type
+ Error>::type
serialize(RPCChannel &C, T V) {
support::endian::byte_swap<T, support::big>(V);
return C.appendBytes(reinterpret_cast<const char *>(&V), sizeof(T));
@@ -74,106 +121,129 @@ typename std::enable_if<
std::is_same<T, uint32_t>::value || std::is_same<T, int32_t>::value ||
std::is_same<T, uint16_t>::value || std::is_same<T, int16_t>::value ||
std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value,
- std::error_code>::type
+ Error>::type
deserialize(RPCChannel &C, T &V) {
- if (auto EC = C.readBytes(reinterpret_cast<char *>(&V), sizeof(T)))
- return EC;
+ if (auto Err = C.readBytes(reinterpret_cast<char *>(&V), sizeof(T)))
+ return Err;
support::endian::byte_swap<T, support::big>(V);
- return std::error_code();
+ return Error::success();
}
/// RPC channel serialization for enums.
template <typename T>
-typename std::enable_if<std::is_enum<T>::value, std::error_code>::type
+typename std::enable_if<std::is_enum<T>::value, Error>::type
serialize(RPCChannel &C, T V) {
return serialize(C, static_cast<typename std::underlying_type<T>::type>(V));
}
/// RPC channel deserialization for enums.
template <typename T>
-typename std::enable_if<std::is_enum<T>::value, std::error_code>::type
+typename std::enable_if<std::is_enum<T>::value, Error>::type
deserialize(RPCChannel &C, T &V) {
typename std::underlying_type<T>::type Tmp;
- std::error_code EC = deserialize(C, Tmp);
+ Error Err = deserialize(C, Tmp);
V = static_cast<T>(Tmp);
- return EC;
+ return Err;
}
/// RPC channel serialization for bools.
-inline std::error_code serialize(RPCChannel &C, bool V) {
+inline Error serialize(RPCChannel &C, bool V) {
uint8_t VN = V ? 1 : 0;
return C.appendBytes(reinterpret_cast<const char *>(&VN), 1);
}
/// RPC channel deserialization for bools.
-inline std::error_code deserialize(RPCChannel &C, bool &V) {
+inline Error deserialize(RPCChannel &C, bool &V) {
uint8_t VN = 0;
- if (auto EC = C.readBytes(reinterpret_cast<char *>(&VN), 1))
- return EC;
+ if (auto Err = C.readBytes(reinterpret_cast<char *>(&VN), 1))
+ return Err;
- V = (VN != 0) ? true : false;
- return std::error_code();
+ V = (VN != 0);
+ return Error::success();
}
/// RPC channel serialization for StringRefs.
/// Note: There is no corresponding deseralization for this, as StringRef
/// doesn't own its memory and so can't hold the deserialized data.
-inline std::error_code serialize(RPCChannel &C, StringRef S) {
- if (auto EC = serialize(C, static_cast<uint64_t>(S.size())))
- return EC;
+inline Error serialize(RPCChannel &C, StringRef S) {
+ if (auto Err = serialize(C, static_cast<uint64_t>(S.size())))
+ return Err;
return C.appendBytes((const char *)S.bytes_begin(), S.size());
}
/// RPC channel serialization for std::strings.
-inline std::error_code serialize(RPCChannel &C, const std::string &S) {
+inline Error serialize(RPCChannel &C, const std::string &S) {
return serialize(C, StringRef(S));
}
/// RPC channel deserialization for std::strings.
-inline std::error_code deserialize(RPCChannel &C, std::string &S) {
+inline Error deserialize(RPCChannel &C, std::string &S) {
uint64_t Count;
- if (auto EC = deserialize(C, Count))
- return EC;
+ if (auto Err = deserialize(C, Count))
+ return Err;
S.resize(Count);
return C.readBytes(&S[0], Count);
}
+// Serialization helper for std::tuple.
+template <typename TupleT, size_t... Is>
+inline Error serializeTupleHelper(RPCChannel &C, const TupleT &V,
+ llvm::index_sequence<Is...> _) {
+ return serializeSeq(C, std::get<Is>(V)...);
+}
+
+/// RPC channel serialization for std::tuple.
+template <typename... ArgTs>
+inline Error serialize(RPCChannel &C, const std::tuple<ArgTs...> &V) {
+ return serializeTupleHelper(C, V, llvm::index_sequence_for<ArgTs...>());
+}
+
+// Serialization helper for std::tuple.
+template <typename TupleT, size_t... Is>
+inline Error deserializeTupleHelper(RPCChannel &C, TupleT &V,
+ llvm::index_sequence<Is...> _) {
+ return deserializeSeq(C, std::get<Is>(V)...);
+}
+
+/// RPC channel deserialization for std::tuple.
+template <typename... ArgTs>
+inline Error deserialize(RPCChannel &C, std::tuple<ArgTs...> &V) {
+ return deserializeTupleHelper(C, V, llvm::index_sequence_for<ArgTs...>());
+}
+
/// RPC channel serialization for ArrayRef<T>.
-template <typename T>
-std::error_code serialize(RPCChannel &C, const ArrayRef<T> &A) {
- if (auto EC = serialize(C, static_cast<uint64_t>(A.size())))
- return EC;
+template <typename T> Error serialize(RPCChannel &C, const ArrayRef<T> &A) {
+ if (auto Err = serialize(C, static_cast<uint64_t>(A.size())))
+ return Err;
for (const auto &E : A)
- if (auto EC = serialize(C, E))
- return EC;
+ if (auto Err = serialize(C, E))
+ return Err;
- return std::error_code();
+ return Error::success();
}
/// RPC channel serialization for std::array<T>.
-template <typename T>
-std::error_code serialize(RPCChannel &C, const std::vector<T> &V) {
+template <typename T> Error serialize(RPCChannel &C, const std::vector<T> &V) {
return serialize(C, ArrayRef<T>(V));
}
/// RPC channel deserialization for std::array<T>.
-template <typename T>
-std::error_code deserialize(RPCChannel &C, std::vector<T> &V) {
+template <typename T> Error deserialize(RPCChannel &C, std::vector<T> &V) {
uint64_t Count = 0;
- if (auto EC = deserialize(C, Count))
- return EC;
+ if (auto Err = deserialize(C, Count))
+ return Err;
V.resize(Count);
for (auto &E : V)
- if (auto EC = deserialize(C, E))
- return EC;
+ if (auto Err = deserialize(C, E))
+ return Err;
- return std::error_code();
+ return Error::success();
}
} // end namespace remote
} // end namespace orc
} // end namespace llvm
-#endif
+#endif // LLVM_EXECUTIONENGINE_ORC_RPCCHANNEL_H
diff --git a/include/llvm/ExecutionEngine/Orc/RPCUtils.h b/include/llvm/ExecutionEngine/Orc/RPCUtils.h
index 0bd5cbc0cdde..966a49684348 100644
--- a/include/llvm/ExecutionEngine/Orc/RPCUtils.h
+++ b/include/llvm/ExecutionEngine/Orc/RPCUtils.h
@@ -14,78 +14,256 @@
#ifndef LLVM_EXECUTIONENGINE_ORC_RPCUTILS_H
#define LLVM_EXECUTIONENGINE_ORC_RPCUTILS_H
+#include <map>
+#include <vector>
+
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ExecutionEngine/Orc/OrcError.h"
+
+#ifdef _MSC_VER
+// concrt.h depends on eh.h for __uncaught_exception declaration
+// even if we disable exceptions.
+#include <eh.h>
+
+// Disable warnings from ppltasks.h transitively included by <future>.
+#pragma warning(push)
+#pragma warning(disable : 4530)
+#pragma warning(disable : 4062)
+#endif
+
+#include <future>
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
namespace llvm {
namespace orc {
namespace remote {
+/// Describes reserved RPC Function Ids.
+///
+/// The default implementation will serve for integer and enum function id
+/// types. If you want to use a custom type as your FunctionId you can
+/// specialize this class and provide unique values for InvalidId,
+/// ResponseId and FirstValidId.
+
+template <typename T> class RPCFunctionIdTraits {
+public:
+ static const T InvalidId = static_cast<T>(0);
+ static const T ResponseId = static_cast<T>(1);
+ static const T FirstValidId = static_cast<T>(2);
+};
+
// Base class containing utilities that require partial specialization.
// These cannot be included in RPC, as template class members cannot be
// partially specialized.
class RPCBase {
protected:
- template <typename ProcedureIdT, ProcedureIdT ProcId, typename... Ts>
- class ProcedureHelper {
+ // RPC Function description type.
+ //
+ // This class provides the information and operations needed to support the
+ // RPC primitive operations (call, expect, etc) for a given function. It
+ // is specialized for void and non-void functions to deal with the differences
+ // betwen the two. Both specializations have the same interface:
+ //
+ // Id - The function's unique identifier.
+ // OptionalReturn - The return type for asyncronous calls.
+ // ErrorReturn - The return type for synchronous calls.
+ // optionalToErrorReturn - Conversion from a valid OptionalReturn to an
+ // ErrorReturn.
+ // readResult - Deserialize a result from a channel.
+ // abandon - Abandon a promised (asynchronous) result.
+ // respond - Retun a result on the channel.
+ template <typename FunctionIdT, FunctionIdT FuncId, typename FnT>
+ class FunctionHelper {};
+
+ // RPC Function description specialization for non-void functions.
+ template <typename FunctionIdT, FunctionIdT FuncId, typename RetT,
+ typename... ArgTs>
+ class FunctionHelper<FunctionIdT, FuncId, RetT(ArgTs...)> {
public:
- static const ProcedureIdT Id = ProcId;
+ static_assert(FuncId != RPCFunctionIdTraits<FunctionIdT>::InvalidId &&
+ FuncId != RPCFunctionIdTraits<FunctionIdT>::ResponseId,
+ "Cannot define custom function with InvalidId or ResponseId. "
+ "Please use RPCFunctionTraits<FunctionIdT>::FirstValidId.");
+
+ static const FunctionIdT Id = FuncId;
+
+ typedef Optional<RetT> OptionalReturn;
+
+ typedef Expected<RetT> ErrorReturn;
+
+ static ErrorReturn optionalToErrorReturn(OptionalReturn &&V) {
+ assert(V && "Return value not available");
+ return std::move(*V);
+ }
+
+ template <typename ChannelT>
+ static Error readResult(ChannelT &C, std::promise<OptionalReturn> &P) {
+ RetT Val;
+ auto Err = deserialize(C, Val);
+ auto Err2 = endReceiveMessage(C);
+ Err = joinErrors(std::move(Err), std::move(Err2));
+
+ if (Err) {
+ P.set_value(OptionalReturn());
+ return Err;
+ }
+ P.set_value(std::move(Val));
+ return Error::success();
+ }
+
+ static void abandon(std::promise<OptionalReturn> &P) {
+ P.set_value(OptionalReturn());
+ }
+
+ template <typename ChannelT, typename SequenceNumberT>
+ static Error respond(ChannelT &C, SequenceNumberT SeqNo,
+ ErrorReturn &Result) {
+ FunctionIdT ResponseId = RPCFunctionIdTraits<FunctionIdT>::ResponseId;
+
+ // If the handler returned an error then bail out with that.
+ if (!Result)
+ return Result.takeError();
+
+ // Otherwise open a new message on the channel and send the result.
+ if (auto Err = startSendMessage(C))
+ return Err;
+ if (auto Err = serializeSeq(C, ResponseId, SeqNo, *Result))
+ return Err;
+ return endSendMessage(C);
+ }
};
- template <typename ChannelT, typename Proc> class CallHelper;
+ // RPC Function description specialization for void functions.
+ template <typename FunctionIdT, FunctionIdT FuncId, typename... ArgTs>
+ class FunctionHelper<FunctionIdT, FuncId, void(ArgTs...)> {
+ public:
+ static_assert(FuncId != RPCFunctionIdTraits<FunctionIdT>::InvalidId &&
+ FuncId != RPCFunctionIdTraits<FunctionIdT>::ResponseId,
+ "Cannot define custom function with InvalidId or ResponseId. "
+ "Please use RPCFunctionTraits<FunctionIdT>::FirstValidId.");
- template <typename ChannelT, typename ProcedureIdT, ProcedureIdT ProcId,
- typename... ArgTs>
- class CallHelper<ChannelT, ProcedureHelper<ProcedureIdT, ProcId, ArgTs...>> {
+ static const FunctionIdT Id = FuncId;
+
+ typedef bool OptionalReturn;
+ typedef Error ErrorReturn;
+
+ static ErrorReturn optionalToErrorReturn(OptionalReturn &&V) {
+ assert(V && "Return value not available");
+ return Error::success();
+ }
+
+ template <typename ChannelT>
+ static Error readResult(ChannelT &C, std::promise<OptionalReturn> &P) {
+ // Void functions don't have anything to deserialize, so we're good.
+ P.set_value(true);
+ return endReceiveMessage(C);
+ }
+
+ static void abandon(std::promise<OptionalReturn> &P) { P.set_value(false); }
+
+ template <typename ChannelT, typename SequenceNumberT>
+ static Error respond(ChannelT &C, SequenceNumberT SeqNo,
+ ErrorReturn &Result) {
+ const FunctionIdT ResponseId =
+ RPCFunctionIdTraits<FunctionIdT>::ResponseId;
+
+ // If the handler returned an error then bail out with that.
+ if (Result)
+ return std::move(Result);
+
+ // Otherwise open a new message on the channel and send the result.
+ if (auto Err = startSendMessage(C))
+ return Err;
+ if (auto Err = serializeSeq(C, ResponseId, SeqNo))
+ return Err;
+ return endSendMessage(C);
+ }
+ };
+
+ // Helper for the call primitive.
+ template <typename ChannelT, typename SequenceNumberT, typename Func>
+ class CallHelper;
+
+ template <typename ChannelT, typename SequenceNumberT, typename FunctionIdT,
+ FunctionIdT FuncId, typename RetT, typename... ArgTs>
+ class CallHelper<ChannelT, SequenceNumberT,
+ FunctionHelper<FunctionIdT, FuncId, RetT(ArgTs...)>> {
public:
- static std::error_code call(ChannelT &C, const ArgTs &... Args) {
- if (auto EC = serialize(C, ProcId))
- return EC;
- // If you see a compile-error on this line you're probably calling a
- // function with the wrong signature.
- return serialize_seq(C, Args...);
+ static Error call(ChannelT &C, SequenceNumberT SeqNo,
+ const ArgTs &... Args) {
+ if (auto Err = startSendMessage(C))
+ return Err;
+ if (auto Err = serializeSeq(C, FuncId, SeqNo, Args...))
+ return Err;
+ return endSendMessage(C);
}
};
- template <typename ChannelT, typename Proc> class HandlerHelper;
+ // Helper for handle primitive.
+ template <typename ChannelT, typename SequenceNumberT, typename Func>
+ class HandlerHelper;
- template <typename ChannelT, typename ProcedureIdT, ProcedureIdT ProcId,
- typename... ArgTs>
- class HandlerHelper<ChannelT,
- ProcedureHelper<ProcedureIdT, ProcId, ArgTs...>> {
+ template <typename ChannelT, typename SequenceNumberT, typename FunctionIdT,
+ FunctionIdT FuncId, typename RetT, typename... ArgTs>
+ class HandlerHelper<ChannelT, SequenceNumberT,
+ FunctionHelper<FunctionIdT, FuncId, RetT(ArgTs...)>> {
public:
template <typename HandlerT>
- static std::error_code handle(ChannelT &C, HandlerT Handler) {
+ static Error handle(ChannelT &C, HandlerT Handler) {
return readAndHandle(C, Handler, llvm::index_sequence_for<ArgTs...>());
}
private:
+ typedef FunctionHelper<FunctionIdT, FuncId, RetT(ArgTs...)> Func;
+
template <typename HandlerT, size_t... Is>
- static std::error_code readAndHandle(ChannelT &C, HandlerT Handler,
- llvm::index_sequence<Is...> _) {
+ static Error readAndHandle(ChannelT &C, HandlerT Handler,
+ llvm::index_sequence<Is...> _) {
std::tuple<ArgTs...> RPCArgs;
- if (auto EC = deserialize_seq(C, std::get<Is>(RPCArgs)...))
- return EC;
- return Handler(std::get<Is>(RPCArgs)...);
+ SequenceNumberT SeqNo;
+ // GCC 4.7 and 4.8 incorrectly issue a -Wunused-but-set-variable warning
+ // for RPCArgs. Void cast RPCArgs to work around this for now.
+ // FIXME: Remove this workaround once we can assume a working GCC version.
+ (void)RPCArgs;
+ if (auto Err = deserializeSeq(C, SeqNo, std::get<Is>(RPCArgs)...))
+ return Err;
+
+ // We've deserialized the arguments, so unlock the channel for reading
+ // before we call the handler. This allows recursive RPC calls.
+ if (auto Err = endReceiveMessage(C))
+ return Err;
+
+ // Run the handler and get the result.
+ auto Result = Handler(std::get<Is>(RPCArgs)...);
+
+ // Return the result to the client.
+ return Func::template respond<ChannelT, SequenceNumberT>(C, SeqNo,
+ Result);
}
};
- template <typename ClassT, typename... ArgTs> class MemberFnWrapper {
+ // Helper for wrapping member functions up as functors.
+ template <typename ClassT, typename RetT, typename... ArgTs>
+ class MemberFnWrapper {
public:
- typedef std::error_code (ClassT::*MethodT)(ArgTs...);
+ typedef RetT (ClassT::*MethodT)(ArgTs...);
MemberFnWrapper(ClassT &Instance, MethodT Method)
: Instance(Instance), Method(Method) {}
- std::error_code operator()(ArgTs &... Args) {
- return (Instance.*Method)(Args...);
- }
+ RetT operator()(ArgTs &... Args) { return (Instance.*Method)(Args...); }
private:
ClassT &Instance;
MethodT Method;
};
+ // Helper that provides a Functor for deserializing arguments.
template <typename... ArgTs> class ReadArgs {
public:
- std::error_code operator()() { return std::error_code(); }
+ Error operator()() { return Error::success(); }
};
template <typename ArgT, typename... ArgTs>
@@ -94,7 +272,7 @@ protected:
ReadArgs(ArgT &Arg, ArgTs &... Args)
: ReadArgs<ArgTs...>(Args...), Arg(Arg) {}
- std::error_code operator()(ArgT &ArgVal, ArgTs &... ArgVals) {
+ Error operator()(ArgT &ArgVal, ArgTs &... ArgVals) {
this->Arg = std::move(ArgVal);
return ReadArgs<ArgTs...>::operator()(ArgVals...);
}
@@ -106,7 +284,7 @@ protected:
/// Contains primitive utilities for defining, calling and handling calls to
/// remote procedures. ChannelT is a bidirectional stream conforming to the
-/// RPCChannel interface (see RPCChannel.h), and ProcedureIdT is a procedure
+/// RPCChannel interface (see RPCChannel.h), and FunctionIdT is a procedure
/// identifier type that must be serializable on ChannelT.
///
/// These utilities support the construction of very primitive RPC utilities.
@@ -123,120 +301,223 @@ protected:
///
/// Overview (see comments individual types/methods for details):
///
-/// Procedure<Id, Args...> :
+/// Function<Id, Args...> :
///
/// associates a unique serializable id with an argument list.
///
///
-/// call<Proc>(Channel, Args...) :
+/// call<Func>(Channel, Args...) :
///
-/// Calls the remote procedure 'Proc' by serializing Proc's id followed by its
+/// Calls the remote procedure 'Func' by serializing Func's id followed by its
/// arguments and sending the resulting bytes to 'Channel'.
///
///
-/// handle<Proc>(Channel, <functor matching std::error_code(Args...)> :
+/// handle<Func>(Channel, <functor matching Error(Args...)> :
///
-/// Handles a call to 'Proc' by deserializing its arguments and calling the
-/// given functor. This assumes that the id for 'Proc' has already been
+/// Handles a call to 'Func' by deserializing its arguments and calling the
+/// given functor. This assumes that the id for 'Func' has already been
/// deserialized.
///
-/// expect<Proc>(Channel, <functor matching std::error_code(Args...)> :
+/// expect<Func>(Channel, <functor matching Error(Args...)> :
///
/// The same as 'handle', except that the procedure id should not have been
-/// read yet. Expect will deserialize the id and assert that it matches Proc's
+/// read yet. Expect will deserialize the id and assert that it matches Func's
/// id. If it does not, and unexpected RPC call error is returned.
-
-template <typename ChannelT, typename ProcedureIdT = uint32_t>
+template <typename ChannelT, typename FunctionIdT = uint32_t,
+ typename SequenceNumberT = uint16_t>
class RPC : public RPCBase {
public:
+ /// RPC default constructor.
+ RPC() = default;
+
+ /// RPC instances cannot be copied.
+ RPC(const RPC &) = delete;
+
+ /// RPC instances cannot be copied.
+ RPC &operator=(const RPC &) = delete;
+
+ /// RPC move constructor.
+ // FIXME: Remove once MSVC can synthesize move ops.
+ RPC(RPC &&Other)
+ : SequenceNumberMgr(std::move(Other.SequenceNumberMgr)),
+ OutstandingResults(std::move(Other.OutstandingResults)) {}
+
+ /// RPC move assignment.
+ // FIXME: Remove once MSVC can synthesize move ops.
+ RPC &operator=(RPC &&Other) {
+ SequenceNumberMgr = std::move(Other.SequenceNumberMgr);
+ OutstandingResults = std::move(Other.OutstandingResults);
+ return *this;
+ }
+
/// Utility class for defining/referring to RPC procedures.
///
/// Typedefs of this utility are used when calling/handling remote procedures.
///
- /// ProcId should be a unique value of ProcedureIdT (i.e. not used with any
- /// other Procedure typedef in the RPC API being defined.
+ /// FuncId should be a unique value of FunctionIdT (i.e. not used with any
+ /// other Function typedef in the RPC API being defined.
///
/// the template argument Ts... gives the argument list for the remote
/// procedure.
///
/// E.g.
///
- /// typedef Procedure<0, bool> Proc1;
- /// typedef Procedure<1, std::string, std::vector<int>> Proc2;
+ /// typedef Function<0, bool> Func1;
+ /// typedef Function<1, std::string, std::vector<int>> Func2;
///
- /// if (auto EC = call<Proc1>(Channel, true))
- /// /* handle EC */;
+ /// if (auto Err = call<Func1>(Channel, true))
+ /// /* handle Err */;
///
- /// if (auto EC = expect<Proc2>(Channel,
+ /// if (auto Err = expect<Func2>(Channel,
/// [](std::string &S, std::vector<int> &V) {
/// // Stuff.
- /// return std::error_code();
+ /// return Error::success();
/// })
- /// /* handle EC */;
+ /// /* handle Err */;
///
- template <ProcedureIdT ProcId, typename... Ts>
- using Procedure = ProcedureHelper<ProcedureIdT, ProcId, Ts...>;
+ template <FunctionIdT FuncId, typename FnT>
+ using Function = FunctionHelper<FunctionIdT, FuncId, FnT>;
+
+ /// Return type for asynchronous call primitives.
+ template <typename Func>
+ using AsyncCallResult = std::future<typename Func::OptionalReturn>;
+
+ /// Return type for asynchronous call-with-seq primitives.
+ template <typename Func>
+ using AsyncCallWithSeqResult =
+ std::pair<std::future<typename Func::OptionalReturn>, SequenceNumberT>;
/// Serialize Args... to channel C, but do not call C.send().
///
- /// For buffered channels, this can be used to queue up several calls before
- /// flushing the channel.
- template <typename Proc, typename... ArgTs>
- static std::error_code appendCall(ChannelT &C, const ArgTs &... Args) {
- return CallHelper<ChannelT, Proc>::call(C, Args...);
+ /// Returns an error (on serialization failure) or a pair of:
+ /// (1) A future Optional<T> (or future<bool> for void functions), and
+ /// (2) A sequence number.
+ ///
+ /// This utility function is primarily used for single-threaded mode support,
+ /// where the sequence number can be used to wait for the corresponding
+ /// result. In multi-threaded mode the appendCallAsync method, which does not
+ /// return the sequence numeber, should be preferred.
+ template <typename Func, typename... ArgTs>
+ Expected<AsyncCallWithSeqResult<Func>>
+ appendCallAsyncWithSeq(ChannelT &C, const ArgTs &... Args) {
+ auto SeqNo = SequenceNumberMgr.getSequenceNumber();
+ std::promise<typename Func::OptionalReturn> Promise;
+ auto Result = Promise.get_future();
+ OutstandingResults[SeqNo] =
+ createOutstandingResult<Func>(std::move(Promise));
+
+ if (auto Err = CallHelper<ChannelT, SequenceNumberT, Func>::call(C, SeqNo,
+ Args...)) {
+ abandonOutstandingResults();
+ return std::move(Err);
+ } else
+ return AsyncCallWithSeqResult<Func>(std::move(Result), SeqNo);
}
- /// Serialize Args... to channel C and call C.send().
- template <typename Proc, typename... ArgTs>
- static std::error_code call(ChannelT &C, const ArgTs &... Args) {
- if (auto EC = appendCall<Proc>(C, Args...))
- return EC;
- return C.send();
+ /// The same as appendCallAsyncWithSeq, except that it calls C.send() to
+ /// flush the channel after serializing the call.
+ template <typename Func, typename... ArgTs>
+ Expected<AsyncCallWithSeqResult<Func>>
+ callAsyncWithSeq(ChannelT &C, const ArgTs &... Args) {
+ auto Result = appendCallAsyncWithSeq<Func>(C, Args...);
+ if (!Result)
+ return Result;
+ if (auto Err = C.send()) {
+ abandonOutstandingResults();
+ return std::move(Err);
+ }
+ return Result;
+ }
+
+ /// Serialize Args... to channel C, but do not call send.
+ /// Returns an error if serialization fails, otherwise returns a
+ /// std::future<Optional<T>> (or a future<bool> for void functions).
+ template <typename Func, typename... ArgTs>
+ Expected<AsyncCallResult<Func>> appendCallAsync(ChannelT &C,
+ const ArgTs &... Args) {
+ auto ResAndSeqOrErr = appendCallAsyncWithSeq<Func>(C, Args...);
+ if (ResAndSeqOrErr)
+ return std::move(ResAndSeqOrErr->first);
+ return ResAndSeqOrErr.getError();
+ }
+
+ /// The same as appendCallAsync, except that it calls C.send to flush the
+ /// channel after serializing the call.
+ template <typename Func, typename... ArgTs>
+ Expected<AsyncCallResult<Func>> callAsync(ChannelT &C,
+ const ArgTs &... Args) {
+ auto ResAndSeqOrErr = callAsyncWithSeq<Func>(C, Args...);
+ if (ResAndSeqOrErr)
+ return std::move(ResAndSeqOrErr->first);
+ return ResAndSeqOrErr.getError();
+ }
+
+ /// This can be used in single-threaded mode.
+ template <typename Func, typename HandleFtor, typename... ArgTs>
+ typename Func::ErrorReturn
+ callSTHandling(ChannelT &C, HandleFtor &HandleOther, const ArgTs &... Args) {
+ if (auto ResultAndSeqNoOrErr = callAsyncWithSeq<Func>(C, Args...)) {
+ auto &ResultAndSeqNo = *ResultAndSeqNoOrErr;
+ if (auto Err = waitForResult(C, ResultAndSeqNo.second, HandleOther))
+ return std::move(Err);
+ return Func::optionalToErrorReturn(ResultAndSeqNo.first.get());
+ } else
+ return ResultAndSeqNoOrErr.takeError();
}
- /// Deserialize and return an enum whose underlying type is ProcedureIdT.
- static std::error_code getNextProcId(ChannelT &C, ProcedureIdT &Id) {
+ // This can be used in single-threaded mode.
+ template <typename Func, typename... ArgTs>
+ typename Func::ErrorReturn callST(ChannelT &C, const ArgTs &... Args) {
+ return callSTHandling<Func>(C, handleNone, Args...);
+ }
+
+ /// Start receiving a new function call.
+ ///
+ /// Calls startReceiveMessage on the channel, then deserializes a FunctionId
+ /// into Id.
+ Error startReceivingFunction(ChannelT &C, FunctionIdT &Id) {
+ if (auto Err = startReceiveMessage(C))
+ return Err;
+
return deserialize(C, Id);
}
- /// Deserialize args for Proc from C and call Handler. The signature of
- /// handler must conform to 'std::error_code(Args...)' where Args... matches
- /// the arguments used in the Proc typedef.
- template <typename Proc, typename HandlerT>
- static std::error_code handle(ChannelT &C, HandlerT Handler) {
- return HandlerHelper<ChannelT, Proc>::handle(C, Handler);
+ /// Deserialize args for Func from C and call Handler. The signature of
+ /// handler must conform to 'Error(Args...)' where Args... matches
+ /// the arguments used in the Func typedef.
+ template <typename Func, typename HandlerT>
+ static Error handle(ChannelT &C, HandlerT Handler) {
+ return HandlerHelper<ChannelT, SequenceNumberT, Func>::handle(C, Handler);
}
/// Helper version of 'handle' for calling member functions.
- template <typename Proc, typename ClassT, typename... ArgTs>
- static std::error_code
- handle(ChannelT &C, ClassT &Instance,
- std::error_code (ClassT::*HandlerMethod)(ArgTs...)) {
- return handle<Proc>(
- C, MemberFnWrapper<ClassT, ArgTs...>(Instance, HandlerMethod));
+ template <typename Func, typename ClassT, typename RetT, typename... ArgTs>
+ static Error handle(ChannelT &C, ClassT &Instance,
+ RetT (ClassT::*HandlerMethod)(ArgTs...)) {
+ return handle<Func>(
+ C, MemberFnWrapper<ClassT, RetT, ArgTs...>(Instance, HandlerMethod));
}
- /// Deserialize a ProcedureIdT from C and verify it matches the id for Proc.
+ /// Deserialize a FunctionIdT from C and verify it matches the id for Func.
/// If the id does match, deserialize the arguments and call the handler
/// (similarly to handle).
/// If the id does not match, return an unexpect RPC call error and do not
/// deserialize any further bytes.
- template <typename Proc, typename HandlerT>
- static std::error_code expect(ChannelT &C, HandlerT Handler) {
- ProcedureIdT ProcId;
- if (auto EC = getNextProcId(C, ProcId))
- return EC;
- if (ProcId != Proc::Id)
+ template <typename Func, typename HandlerT>
+ Error expect(ChannelT &C, HandlerT Handler) {
+ FunctionIdT FuncId;
+ if (auto Err = startReceivingFunction(C, FuncId))
+ return std::move(Err);
+ if (FuncId != Func::Id)
return orcError(OrcErrorCode::UnexpectedRPCCall);
- return handle<Proc>(C, Handler);
+ return handle<Func>(C, Handler);
}
/// Helper version of expect for calling member functions.
- template <typename Proc, typename ClassT, typename... ArgTs>
- static std::error_code
- expect(ChannelT &C, ClassT &Instance,
- std::error_code (ClassT::*HandlerMethod)(ArgTs...)) {
- return expect<Proc>(
+ template <typename Func, typename ClassT, typename... ArgTs>
+ static Error expect(ChannelT &C, ClassT &Instance,
+ Error (ClassT::*HandlerMethod)(ArgTs...)) {
+ return expect<Func>(
C, MemberFnWrapper<ClassT, ArgTs...>(Instance, HandlerMethod));
}
@@ -245,18 +526,165 @@ public:
/// channel.
/// E.g.
///
- /// typedef Procedure<0, bool, int> Proc1;
+ /// typedef Function<0, bool, int> Func1;
///
/// ...
/// bool B;
/// int I;
- /// if (auto EC = expect<Proc1>(Channel, readArgs(B, I)))
+ /// if (auto Err = expect<Func1>(Channel, readArgs(B, I)))
/// /* Handle Args */ ;
///
template <typename... ArgTs>
static ReadArgs<ArgTs...> readArgs(ArgTs &... Args) {
return ReadArgs<ArgTs...>(Args...);
}
+
+ /// Read a response from Channel.
+ /// This should be called from the receive loop to retrieve results.
+ Error handleResponse(ChannelT &C, SequenceNumberT *SeqNoRet = nullptr) {
+ SequenceNumberT SeqNo;
+ if (auto Err = deserialize(C, SeqNo)) {
+ abandonOutstandingResults();
+ return Err;
+ }
+
+ if (SeqNoRet)
+ *SeqNoRet = SeqNo;
+
+ auto I = OutstandingResults.find(SeqNo);
+ if (I == OutstandingResults.end()) {
+ abandonOutstandingResults();
+ return orcError(OrcErrorCode::UnexpectedRPCResponse);
+ }
+
+ if (auto Err = I->second->readResult(C)) {
+ abandonOutstandingResults();
+ // FIXME: Release sequence numbers?
+ return Err;
+ }
+
+ OutstandingResults.erase(I);
+ SequenceNumberMgr.releaseSequenceNumber(SeqNo);
+
+ return Error::success();
+ }
+
+ // Loop waiting for a result with the given sequence number.
+ // This can be used as a receive loop if the user doesn't have a default.
+ template <typename HandleOtherFtor>
+ Error waitForResult(ChannelT &C, SequenceNumberT TgtSeqNo,
+ HandleOtherFtor &HandleOther = handleNone) {
+ bool GotTgtResult = false;
+
+ while (!GotTgtResult) {
+ FunctionIdT Id = RPCFunctionIdTraits<FunctionIdT>::InvalidId;
+ if (auto Err = startReceivingFunction(C, Id))
+ return Err;
+ if (Id == RPCFunctionIdTraits<FunctionIdT>::ResponseId) {
+ SequenceNumberT SeqNo;
+ if (auto Err = handleResponse(C, &SeqNo))
+ return Err;
+ GotTgtResult = (SeqNo == TgtSeqNo);
+ } else if (auto Err = HandleOther(C, Id))
+ return Err;
+ }
+
+ return Error::success();
+ }
+
+ // Default handler for 'other' (non-response) functions when waiting for a
+ // result from the channel.
+ static Error handleNone(ChannelT &, FunctionIdT) {
+ return orcError(OrcErrorCode::UnexpectedRPCCall);
+ };
+
+private:
+ // Manage sequence numbers.
+ class SequenceNumberManager {
+ public:
+ SequenceNumberManager() = default;
+
+ SequenceNumberManager(const SequenceNumberManager &) = delete;
+ SequenceNumberManager &operator=(const SequenceNumberManager &) = delete;
+
+ SequenceNumberManager(SequenceNumberManager &&Other)
+ : NextSequenceNumber(std::move(Other.NextSequenceNumber)),
+ FreeSequenceNumbers(std::move(Other.FreeSequenceNumbers)) {}
+
+ SequenceNumberManager &operator=(SequenceNumberManager &&Other) {
+ NextSequenceNumber = std::move(Other.NextSequenceNumber);
+ FreeSequenceNumbers = std::move(Other.FreeSequenceNumbers);
+ }
+
+ void reset() {
+ std::lock_guard<std::mutex> Lock(SeqNoLock);
+ NextSequenceNumber = 0;
+ FreeSequenceNumbers.clear();
+ }
+
+ SequenceNumberT getSequenceNumber() {
+ std::lock_guard<std::mutex> Lock(SeqNoLock);
+ if (FreeSequenceNumbers.empty())
+ return NextSequenceNumber++;
+ auto SequenceNumber = FreeSequenceNumbers.back();
+ FreeSequenceNumbers.pop_back();
+ return SequenceNumber;
+ }
+
+ void releaseSequenceNumber(SequenceNumberT SequenceNumber) {
+ std::lock_guard<std::mutex> Lock(SeqNoLock);
+ FreeSequenceNumbers.push_back(SequenceNumber);
+ }
+
+ private:
+ std::mutex SeqNoLock;
+ SequenceNumberT NextSequenceNumber = 0;
+ std::vector<SequenceNumberT> FreeSequenceNumbers;
+ };
+
+ // Base class for results that haven't been returned from the other end of the
+ // RPC connection yet.
+ class OutstandingResult {
+ public:
+ virtual ~OutstandingResult() {}
+ virtual Error readResult(ChannelT &C) = 0;
+ virtual void abandon() = 0;
+ };
+
+ // Outstanding results for a specific function.
+ template <typename Func>
+ class OutstandingResultImpl : public OutstandingResult {
+ private:
+ public:
+ OutstandingResultImpl(std::promise<typename Func::OptionalReturn> &&P)
+ : P(std::move(P)) {}
+
+ Error readResult(ChannelT &C) override { return Func::readResult(C, P); }
+
+ void abandon() override { Func::abandon(P); }
+
+ private:
+ std::promise<typename Func::OptionalReturn> P;
+ };
+
+ // Create an outstanding result for the given function.
+ template <typename Func>
+ std::unique_ptr<OutstandingResult>
+ createOutstandingResult(std::promise<typename Func::OptionalReturn> &&P) {
+ return llvm::make_unique<OutstandingResultImpl<Func>>(std::move(P));
+ }
+
+ // Abandon all outstanding results.
+ void abandonOutstandingResults() {
+ for (auto &KV : OutstandingResults)
+ KV.second->abandon();
+ OutstandingResults.clear();
+ SequenceNumberMgr.reset();
+ }
+
+ SequenceNumberManager SequenceNumberMgr;
+ std::map<SequenceNumberT, std::unique_ptr<OutstandingResult>>
+ OutstandingResults;
};
} // end namespace remote
diff --git a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h
index c5006962550e..adcb063f4544 100644
--- a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h
+++ b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h
@@ -16,7 +16,6 @@
#include "RuntimeDyld.h"
#include "llvm-c/ExecutionEngine.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/Support/CBindingWrapping.h"
#include "llvm/Support/Memory.h"
@@ -62,8 +61,19 @@ public:
RTDyldMemoryManager() {}
~RTDyldMemoryManager() override;
- void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override;
- void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override;
+ /// Register EH frames in the current process.
+ static void registerEHFramesInProcess(uint8_t *Addr, size_t Size);
+
+ /// Deregister EH frames in the current proces.
+ static void deregisterEHFramesInProcess(uint8_t *Addr, size_t Size);
+
+ void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override {
+ registerEHFramesInProcess(Addr, Size);
+ }
+
+ void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override {
+ registerEHFramesInProcess(Addr, Size);
+ }
/// This method returns the address of the specified function or variable in
/// the current process.
diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h
index 100e97b8b3d9..bd485de91bd4 100644
--- a/include/llvm/ExecutionEngine/RuntimeDyld.h
+++ b/include/llvm/ExecutionEngine/RuntimeDyld.h
@@ -16,20 +16,35 @@
#include "JITSymbolFlags.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/DIContext.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Memory.h"
-#include "llvm/DebugInfo/DIContext.h"
#include <map>
#include <memory>
+#include <utility>
namespace llvm {
+class StringRef;
+
namespace object {
class ObjectFile;
template <typename T> class OwningBinary;
}
+/// Base class for errors originating in RuntimeDyld, e.g. missing relocation
+/// support.
+class RuntimeDyldError : public ErrorInfo<RuntimeDyldError> {
+public:
+ static char ID;
+ RuntimeDyldError(std::string ErrMsg) : ErrMsg(std::move(ErrMsg)) {}
+ void log(raw_ostream &OS) const override;
+ const std::string &getErrorMessage() const { return ErrMsg; }
+ std::error_code convertToErrorCode() const override;
+private:
+ std::string ErrMsg;
+};
+
class RuntimeDyldImpl;
class RuntimeDyldCheckerImpl;
@@ -64,7 +79,7 @@ public:
typedef std::map<object::SectionRef, unsigned> ObjSectionToIDMap;
LoadedObjectInfo(RuntimeDyldImpl &RTDyld, ObjSectionToIDMap ObjSecToIDMap)
- : RTDyld(RTDyld), ObjSecToIDMap(ObjSecToIDMap) { }
+ : RTDyld(RTDyld), ObjSecToIDMap(std::move(ObjSecToIDMap)) {}
virtual object::OwningBinary<object::ObjectFile>
getObjectForDebug(const object::ObjectFile &Obj) const = 0;
@@ -179,17 +194,9 @@ public:
public:
virtual ~SymbolResolver() {}
- /// This method returns the address of the specified function or variable.
- /// It is used to resolve symbols during module linking.
- ///
- /// If the returned symbol's address is equal to ~0ULL then RuntimeDyld will
- /// skip all relocations for that symbol, and the client will be responsible
- /// for handling them manually.
- virtual SymbolInfo findSymbol(const std::string &Name) = 0;
-
/// This method returns the address of the specified symbol if it exists
/// within the logical dynamic library represented by this
- /// RTDyldMemoryManager. Unlike getSymbolAddress, queries through this
+ /// RTDyldMemoryManager. Unlike findSymbol, queries through this
/// interface should return addresses for hidden symbols.
///
/// This is of particular importance for the Orc JIT APIs, which support lazy
@@ -198,13 +205,17 @@ public:
/// writing memory managers for MCJIT can usually ignore this method.
///
/// This method will be queried by RuntimeDyld when checking for previous
- /// definitions of common symbols. It will *not* be queried by default when
- /// resolving external symbols (this minimises the link-time overhead for
- /// MCJIT clients who don't care about Orc features). If you are writing a
- /// RTDyldMemoryManager for Orc and want "external" symbol resolution to
- /// search the logical dylib, you should override your getSymbolAddress
- /// method call this method directly.
+ /// definitions of common symbols.
virtual SymbolInfo findSymbolInLogicalDylib(const std::string &Name) = 0;
+
+ /// This method returns the address of the specified function or variable.
+ /// It is used to resolve symbols during module linking.
+ ///
+ /// If the returned symbol's address is equal to ~0ULL then RuntimeDyld will
+ /// skip all relocations for that symbol, and the client will be responsible
+ /// for handling them manually.
+ virtual SymbolInfo findSymbol(const std::string &Name) = 0;
+
private:
virtual void anchor();
};
diff --git a/include/llvm/ExecutionEngine/RuntimeDyldChecker.h b/include/llvm/ExecutionEngine/RuntimeDyldChecker.h
index 31ce151c56a3..f5f52b5d2f92 100644
--- a/include/llvm/ExecutionEngine/RuntimeDyldChecker.h
+++ b/include/llvm/ExecutionEngine/RuntimeDyldChecker.h
@@ -10,10 +10,14 @@
#ifndef LLVM_EXECUTIONENGINE_RUNTIMEDYLDCHECKER_H
#define LLVM_EXECUTIONENGINE_RUNTIMEDYLDCHECKER_H
-#include "llvm/ADT/StringRef.h"
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <utility>
namespace llvm {
+class StringRef;
class MCDisassembler;
class MemoryBuffer;
class MCInstPrinter;
diff --git a/include/llvm/IR/Argument.h b/include/llvm/IR/Argument.h
index 0092f49e49ad..d8b280a66f18 100644
--- a/include/llvm/IR/Argument.h
+++ b/include/llvm/IR/Argument.h
@@ -73,6 +73,12 @@ public:
/// containing function.
bool hasByValAttr() const;
+ /// \brief Return true if this argument has the swiftself attribute.
+ bool hasSwiftSelfAttr() const;
+
+ /// \brief Return true if this argument has the swifterror attribute.
+ bool hasSwiftErrorAttr() const;
+
/// \brief Return true if this argument has the byval attribute or inalloca
/// attribute on it in its containing function. These attributes both
/// represent arguments being passed by value.
@@ -120,9 +126,20 @@ public:
/// \brief Add a Attribute to an argument.
void addAttr(AttributeSet AS);
+ void addAttr(Attribute::AttrKind Kind) {
+ addAttr(AttributeSet::get(getContext(), getArgNo() + 1, Kind));
+ }
+
/// \brief Remove a Attribute from an argument.
void removeAttr(AttributeSet AS);
+ void removeAttr(Attribute::AttrKind Kind) {
+ removeAttr(AttributeSet::get(getContext(), getArgNo() + 1, Kind));
+ }
+
+ /// \brief Checks if an argument has a given attribute.
+ bool hasAttribute(Attribute::AttrKind Kind) const;
+
/// \brief Method for support type inquiry through isa, cast, and
/// dyn_cast.
static inline bool classof(const Value *V) {
diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h
index 0e3373165407..af1bf0a354ec 100644
--- a/include/llvm/IR/Attributes.h
+++ b/include/llvm/IR/Attributes.h
@@ -18,8 +18,10 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
+#include "llvm-c/Types.h"
#include <bitset>
#include <cassert>
#include <map>
@@ -94,6 +96,9 @@ public:
uint64_t Bytes);
static Attribute getWithDereferenceableOrNullBytes(LLVMContext &Context,
uint64_t Bytes);
+ static Attribute getWithAllocSizeArgs(LLVMContext &Context,
+ unsigned ElemSizeArg,
+ const Optional<unsigned> &NumElemsArg);
//===--------------------------------------------------------------------===//
// Attribute Accessors
@@ -116,11 +121,11 @@ public:
bool hasAttribute(StringRef Val) const;
/// \brief Return the attribute's kind as an enum (Attribute::AttrKind). This
- /// requires the attribute to be an enum or alignment attribute.
+ /// requires the attribute to be an enum or integer attribute.
Attribute::AttrKind getKindAsEnum() const;
/// \brief Return the attribute's value as an integer. This requires that the
- /// attribute be an alignment attribute.
+ /// attribute be an integer attribute.
uint64_t getValueAsInt() const;
/// \brief Return the attribute's kind as a string. This requires the
@@ -147,6 +152,10 @@ public:
/// dereferenceable_or_null attribute.
uint64_t getDereferenceableOrNullBytes() const;
+ /// Returns the argument numbers for the allocsize attribute (or pair(0, 0)
+ /// if not known).
+ std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;
+
/// \brief The Attribute is converted to a string of equivalent mnemonic. This
/// is, presumably, for writing out the mnemonics for the assembly writer.
std::string getAsString(bool InAttrGrp = false) const;
@@ -161,8 +170,28 @@ public:
void Profile(FoldingSetNodeID &ID) const {
ID.AddPointer(pImpl);
}
+
+ /// \brief Return a raw pointer that uniquely identifies this attribute.
+ void *getRawPointer() const {
+ return pImpl;
+ }
+
+ /// \brief Get an attribute from a raw pointer created by getRawPointer.
+ static Attribute fromRawPointer(void *RawPtr) {
+ return Attribute(reinterpret_cast<AttributeImpl*>(RawPtr));
+ }
};
+// Specialized opaque value conversions.
+inline LLVMAttributeRef wrap(Attribute Attr) {
+ return reinterpret_cast<LLVMAttributeRef>(Attr.getRawPointer());
+}
+
+// Specialized opaque value conversions.
+inline Attribute unwrap(LLVMAttributeRef Attr) {
+ return Attribute::fromRawPointer(Attr);
+}
+
//===----------------------------------------------------------------------===//
/// \class
/// \brief This class holds the attributes for a function, its return value, and
@@ -213,20 +242,20 @@ public:
/// \brief Return an AttributeSet with the specified parameters in it.
static AttributeSet get(LLVMContext &C, ArrayRef<AttributeSet> Attrs);
static AttributeSet get(LLVMContext &C, unsigned Index,
- ArrayRef<Attribute::AttrKind> Kind);
+ ArrayRef<Attribute::AttrKind> Kinds);
+ static AttributeSet get(LLVMContext &C, unsigned Index,
+ ArrayRef<StringRef> Kind);
static AttributeSet get(LLVMContext &C, unsigned Index, const AttrBuilder &B);
/// \brief Add an attribute to the attribute set at the given index. Because
/// attribute sets are immutable, this returns a new set.
AttributeSet addAttribute(LLVMContext &C, unsigned Index,
- Attribute::AttrKind Attr) const;
+ Attribute::AttrKind Kind) const;
/// \brief Add an attribute to the attribute set at the given index. Because
/// attribute sets are immutable, this returns a new set.
- AttributeSet addAttribute(LLVMContext &C, unsigned Index,
- StringRef Kind) const;
- AttributeSet addAttribute(LLVMContext &C, unsigned Index,
- StringRef Kind, StringRef Value) const;
+ AttributeSet addAttribute(LLVMContext &C, unsigned Index, StringRef Kind,
+ StringRef Value = StringRef()) const;
/// Add an attribute to the attribute set at the given indices. Because
/// attribute sets are immutable, this returns a new set.
@@ -242,7 +271,13 @@ public:
/// attribute list. Because attribute lists are immutable, this returns the
/// new list.
AttributeSet removeAttribute(LLVMContext &C, unsigned Index,
- Attribute::AttrKind Attr) const;
+ Attribute::AttrKind Kind) const;
+
+ /// \brief Remove the specified attribute at the specified index from this
+ /// attribute list. Because attribute lists are immutable, this returns the
+ /// new list.
+ AttributeSet removeAttribute(LLVMContext &C, unsigned Index,
+ StringRef Kind) const;
/// \brief Remove the specified attributes at the specified index from this
/// attribute list. Because attribute lists are immutable, this returns the
@@ -267,6 +302,12 @@ public:
AttributeSet addDereferenceableOrNullAttr(LLVMContext &C, unsigned Index,
uint64_t Bytes) const;
+ /// Add the allocsize attribute to the attribute set at the given index.
+ /// Because attribute sets are immutable, this returns a new set.
+ AttributeSet addAllocSizeAttr(LLVMContext &C, unsigned Index,
+ unsigned ElemSizeArg,
+ const Optional<unsigned> &NumElemsArg);
+
//===--------------------------------------------------------------------===//
// AttributeSet Accessors
//===--------------------------------------------------------------------===//
@@ -292,9 +333,15 @@ public:
/// \brief Return true if attribute exists at the given index.
bool hasAttributes(unsigned Index) const;
+ /// \brief Equivalent to hasAttribute(AttributeSet::FunctionIndex, Kind) but
+ /// may be faster.
+ bool hasFnAttribute(Attribute::AttrKind Kind) const;
+
/// \brief Return true if the specified attribute is set for at least one
- /// parameter or for the return value.
- bool hasAttrSomewhere(Attribute::AttrKind Attr) const;
+ /// parameter or for the return value. If Index is not nullptr, the index
+ /// of a parameter with the specified attribute is provided.
+ bool hasAttrSomewhere(Attribute::AttrKind Kind,
+ unsigned *Index = nullptr) const;
/// \brief Return the attribute object that exists at the given index.
Attribute getAttribute(unsigned Index, Attribute::AttrKind Kind) const;
@@ -315,6 +362,10 @@ public:
/// unknown).
uint64_t getDereferenceableOrNullBytes(unsigned Index) const;
+ /// Get the allocsize argument numbers (or pair(0, 0) if unknown).
+ std::pair<unsigned, Optional<unsigned>>
+ getAllocSizeArgs(unsigned Index) const;
+
/// \brief Return the attributes at the index as a string.
std::string getAsString(unsigned Index, bool InAttrGrp = false) const;
@@ -396,19 +447,20 @@ class AttrBuilder {
uint64_t StackAlignment;
uint64_t DerefBytes;
uint64_t DerefOrNullBytes;
+ uint64_t AllocSizeArgs;
public:
AttrBuilder()
: Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0),
- DerefOrNullBytes(0) {}
+ DerefOrNullBytes(0), AllocSizeArgs(0) {}
explicit AttrBuilder(uint64_t Val)
: Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0),
- DerefOrNullBytes(0) {
+ DerefOrNullBytes(0), AllocSizeArgs(0) {
addRawValue(Val);
}
AttrBuilder(const Attribute &A)
: Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0),
- DerefOrNullBytes(0) {
+ DerefOrNullBytes(0), AllocSizeArgs(0) {
addAttribute(A);
}
AttrBuilder(AttributeSet AS, unsigned Idx);
@@ -477,6 +529,10 @@ public:
/// dereferenceable_or_null attribute exists (zero is returned otherwise).
uint64_t getDereferenceableOrNullBytes() const { return DerefOrNullBytes; }
+ /// Retrieve the allocsize args, if the allocsize attribute exists. If it
+ /// doesn't exist, pair(0, 0) is returned.
+ std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;
+
/// \brief This turns an int alignment (which must be a power of 2) into the
/// form used internally in Attribute.
AttrBuilder &addAlignmentAttr(unsigned Align);
@@ -493,6 +549,14 @@ public:
/// form used internally in Attribute.
AttrBuilder &addDereferenceableOrNullAttr(uint64_t Bytes);
+ /// This turns one (or two) ints into the form used internally in Attribute.
+ AttrBuilder &addAllocSizeAttr(unsigned ElemSizeArg,
+ const Optional<unsigned> &NumElemsArg);
+
+ /// Add an allocsize attribute, using the representation returned by
+ /// Attribute.getIntValue().
+ AttrBuilder &addAllocSizeAttrFromRawRepr(uint64_t RawAllocSizeRepr);
+
/// \brief Return true if the builder contains no target-independent
/// attributes.
bool empty() const { return Attrs.none(); }
diff --git a/include/llvm/IR/Attributes.td b/include/llvm/IR/Attributes.td
index 30249bbd8fab..7b63638a3f6a 100644
--- a/include/llvm/IR/Attributes.td
+++ b/include/llvm/IR/Attributes.td
@@ -16,6 +16,10 @@ class StrBoolAttr<string S> : Attr<S>;
/// 0 means unaligned (different from align(1)).
def Alignment : EnumAttr<"align">;
+/// The result of the function is guaranteed to point to a number of bytes that
+/// we can determine if we know the value of the function's arguments.
+def AllocSize : EnumAttr<"allocsize">;
+
/// inline=always.
def AlwaysInline : EnumAttr<"alwaysinline">;
@@ -154,9 +158,18 @@ def SanitizeThread : EnumAttr<"sanitize_thread">;
/// MemorySanitizer is on.
def SanitizeMemory : EnumAttr<"sanitize_memory">;
+/// Argument is swift error.
+def SwiftError : EnumAttr<"swifterror">;
+
+/// Argument is swift self/context.
+def SwiftSelf : EnumAttr<"swiftself">;
+
/// Function must be in a unwind table.
def UWTable : EnumAttr<"uwtable">;
+/// Function only writes to memory.
+def WriteOnly : EnumAttr<"writeonly">;
+
/// Zero extended before/after call.
def ZExt : EnumAttr<"zeroext">;
@@ -165,6 +178,7 @@ def LessPreciseFPMAD : StrBoolAttr<"less-precise-fpmad">;
def NoInfsFPMath : StrBoolAttr<"no-infs-fp-math">;
def NoNansFPMath : StrBoolAttr<"no-nans-fp-math">;
def UnsafeFPMath : StrBoolAttr<"unsafe-fp-math">;
+def NoJumpTables : StrBoolAttr<"no-jump-tables">;
class CompatRule<string F> {
// The name of the function called to check the attribute of the caller and
@@ -179,6 +193,7 @@ class CompatRule<string F> {
def : CompatRule<"isEqual<SanitizeAddressAttr>">;
def : CompatRule<"isEqual<SanitizeThreadAttr>">;
def : CompatRule<"isEqual<SanitizeMemoryAttr>">;
+def : CompatRule<"isEqual<SafeStackAttr>">;
class MergeRule<string F> {
// The name of the function called to merge the attributes of the caller and
@@ -194,4 +209,5 @@ def : MergeRule<"setAND<NoInfsFPMathAttr>">;
def : MergeRule<"setAND<NoNansFPMathAttr>">;
def : MergeRule<"setAND<UnsafeFPMathAttr>">;
def : MergeRule<"setOR<NoImplicitFloatAttr>">;
+def : MergeRule<"setOR<NoJumpTablesAttr>">;
def : MergeRule<"adjustCallerSSPLevel">;
diff --git a/include/llvm/IR/AutoUpgrade.h b/include/llvm/IR/AutoUpgrade.h
index a4b3c410c4f6..9eb358682c65 100644
--- a/include/llvm/IR/AutoUpgrade.h
+++ b/include/llvm/IR/AutoUpgrade.h
@@ -14,13 +14,14 @@
#ifndef LLVM_IR_AUTOUPGRADE_H
#define LLVM_IR_AUTOUPGRADE_H
-#include <string>
+#include "llvm/ADT/StringRef.h"
namespace llvm {
class CallInst;
class Constant;
class Function;
class Instruction;
+ class MDNode;
class Module;
class GlobalVariable;
class Type;
@@ -46,6 +47,10 @@ namespace llvm {
/// if it requires upgrading.
bool UpgradeGlobalVariable(GlobalVariable *GV);
+ /// This checks for module flags which should be upgraded. It returns true if
+ /// module is modified.
+ bool UpgradeModuleFlags(Module &M);
+
/// If the TBAA tag for the given instruction uses the scalar TBAA format,
/// we upgrade it to the struct-path aware TBAA format.
void UpgradeInstWithTBAATag(Instruction *I);
@@ -64,8 +69,14 @@ namespace llvm {
/// info. Return true if module is modified.
bool UpgradeDebugInfo(Module &M);
- /// Upgrade a metadata string constant in place.
- void UpgradeMDStringConstant(std::string &String);
+ /// Check whether a string looks like an old loop attachment tag.
+ inline bool mayBeOldLoopAttachmentTag(StringRef Name) {
+ return Name.startswith("llvm.vectorizer.");
+ }
+
+ /// Upgrade the loop attachment metadata node.
+ MDNode *upgradeInstructionLoopAttachment(MDNode &N);
+
} // End llvm namespace
#endif
diff --git a/include/llvm/IR/BasicBlock.h b/include/llvm/IR/BasicBlock.h
index c6b54d308ce6..e7daf6ee238e 100644
--- a/include/llvm/IR/BasicBlock.h
+++ b/include/llvm/IR/BasicBlock.h
@@ -111,6 +111,14 @@ public:
TerminatorInst *getTerminator();
const TerminatorInst *getTerminator() const;
+ /// \brief Returns the call instruction calling @llvm.experimental.deoptimize
+ /// prior to the terminating return instruction of this basic block, if such a
+ /// call is present. Otherwise, returns null.
+ CallInst *getTerminatingDeoptimizeCall();
+ const CallInst *getTerminatingDeoptimizeCall() const {
+ return const_cast<BasicBlock *>(this)->getTerminatingDeoptimizeCall();
+ }
+
/// \brief Returns the call instruction marked 'musttail' prior to the
/// terminating return instruction of this basic block, if such a call is
/// present. Otherwise, returns null.
diff --git a/include/llvm/IR/CallSite.h b/include/llvm/IR/CallSite.h
index f7bfb47a5b44..9c977aef941a 100644
--- a/include/llvm/IR/CallSite.h
+++ b/include/llvm/IR/CallSite.h
@@ -273,6 +273,10 @@ public:
CALLSITE_DELEGATE_GETTER(getArgOperand(i));
}
+ ValTy *getReturnedArgOperand() const {
+ CALLSITE_DELEGATE_GETTER(getReturnedArgOperand());
+ }
+
bool isInlineAsm() const {
if (isCall())
return cast<CallInst>(getInstruction())->isInlineAsm();
@@ -305,19 +309,51 @@ public:
CALLSITE_DELEGATE_SETTER(setAttributes(PAL));
}
+ void addAttribute(unsigned i, Attribute::AttrKind Kind) {
+ CALLSITE_DELEGATE_SETTER(addAttribute(i, Kind));
+ }
+
+ void addAttribute(unsigned i, StringRef Kind, StringRef Value) {
+ CALLSITE_DELEGATE_SETTER(addAttribute(i, Kind, Value));
+ }
+
+ void addAttribute(unsigned i, Attribute Attr) {
+ CALLSITE_DELEGATE_SETTER(addAttribute(i, Attr));
+ }
+
+ void removeAttribute(unsigned i, Attribute::AttrKind Kind) {
+ CALLSITE_DELEGATE_SETTER(removeAttribute(i, Kind));
+ }
+
+ void removeAttribute(unsigned i, StringRef Kind) {
+ CALLSITE_DELEGATE_SETTER(removeAttribute(i, Kind));
+ }
+
+ void removeAttribute(unsigned i, Attribute Attr) {
+ CALLSITE_DELEGATE_SETTER(removeAttribute(i, Attr));
+ }
+
/// \brief Return true if this function has the given attribute.
- bool hasFnAttr(Attribute::AttrKind A) const {
- CALLSITE_DELEGATE_GETTER(hasFnAttr(A));
+ bool hasFnAttr(Attribute::AttrKind Kind) const {
+ CALLSITE_DELEGATE_GETTER(hasFnAttr(Kind));
}
/// \brief Return true if this function has the given attribute.
- bool hasFnAttr(StringRef A) const {
- CALLSITE_DELEGATE_GETTER(hasFnAttr(A));
+ bool hasFnAttr(StringRef Kind) const {
+ CALLSITE_DELEGATE_GETTER(hasFnAttr(Kind));
}
/// \brief Return true if the call or the callee has the given attribute.
- bool paramHasAttr(unsigned i, Attribute::AttrKind A) const {
- CALLSITE_DELEGATE_GETTER(paramHasAttr(i, A));
+ bool paramHasAttr(unsigned i, Attribute::AttrKind Kind) const {
+ CALLSITE_DELEGATE_GETTER(paramHasAttr(i, Kind));
+ }
+
+ Attribute getAttribute(unsigned i, Attribute::AttrKind Kind) const {
+ CALLSITE_DELEGATE_GETTER(getAttribute(i, Kind));
+ }
+
+ Attribute getAttribute(unsigned i, StringRef Kind) const {
+ CALLSITE_DELEGATE_GETTER(getAttribute(i, Kind));
}
/// \brief Return true if the data operand at index \p i directly or
@@ -327,8 +363,8 @@ public:
/// in the attribute set attached to this instruction, while operand bundle
/// operands may have some attributes implied by the type of its containing
/// operand bundle.
- bool dataOperandHasImpliedAttr(unsigned i, Attribute::AttrKind A) const {
- CALLSITE_DELEGATE_GETTER(dataOperandHasImpliedAttr(i, A));
+ bool dataOperandHasImpliedAttr(unsigned i, Attribute::AttrKind Kind) const {
+ CALLSITE_DELEGATE_GETTER(dataOperandHasImpliedAttr(i, Kind));
}
/// @brief Extract the alignment for a call or parameter (0=unknown).
@@ -385,6 +421,14 @@ public:
CALLSITE_DELEGATE_SETTER(setOnlyReadsMemory());
}
+ /// @brief Determine if the call does not access or only writes memory.
+ bool doesNotReadMemory() const {
+ CALLSITE_DELEGATE_GETTER(doesNotReadMemory());
+ }
+ void setDoesNotReadMemory() {
+ CALLSITE_DELEGATE_SETTER(setDoesNotReadMemory());
+ }
+
/// @brief Determine if the call can access memmory only using pointers based
/// on its arguments.
bool onlyAccessesArgMemory() const {
@@ -410,6 +454,25 @@ public:
CALLSITE_DELEGATE_SETTER(setDoesNotThrow());
}
+ /// @brief Determine if the call can be duplicated.
+ bool cannotDuplicate() const {
+ CALLSITE_DELEGATE_GETTER(cannotDuplicate());
+ }
+ void setCannotDuplicate() {
+ CALLSITE_DELEGATE_GETTER(setCannotDuplicate());
+ }
+
+ /// @brief Determine if the call is convergent.
+ bool isConvergent() const {
+ CALLSITE_DELEGATE_GETTER(isConvergent());
+ }
+ void setConvergent() {
+ CALLSITE_DELEGATE_SETTER(setConvergent());
+ }
+ void setNotConvergent() {
+ CALLSITE_DELEGATE_SETTER(setNotConvergent());
+ }
+
unsigned getNumOperandBundles() const {
CALLSITE_DELEGATE_GETTER(getNumOperandBundles());
}
@@ -442,6 +505,10 @@ public:
CALLSITE_DELEGATE_GETTER(getOperandBundle(ID));
}
+ unsigned countOperandBundlesOfType(uint32_t ID) const {
+ CALLSITE_DELEGATE_GETTER(countOperandBundlesOfType(ID));
+ }
+
IterTy arg_begin() const {
CALLSITE_DELEGATE_GETTER(arg_begin());
}
diff --git a/include/llvm/IR/CallingConv.h b/include/llvm/IR/CallingConv.h
index bc050928266e..4987b7e943f2 100644
--- a/include/llvm/IR/CallingConv.h
+++ b/include/llvm/IR/CallingConv.h
@@ -168,6 +168,31 @@ namespace CallingConv {
/// subtargets.
X86_INTR = 83,
+ /// Used for AVR interrupt routines.
+ AVR_INTR = 84,
+
+ /// Calling convention used for AVR signal routines.
+ AVR_SIGNAL = 85,
+
+ /// Calling convention used for special AVR rtlib functions
+ /// which have an "optimized" convention to preserve registers.
+ AVR_BUILTIN = 86,
+
+ /// Calling convention used for Mesa vertex shaders.
+ AMDGPU_VS = 87,
+
+ /// Calling convention used for Mesa geometry shaders.
+ AMDGPU_GS = 88,
+
+ /// Calling convention used for Mesa pixel shaders.
+ AMDGPU_PS = 89,
+
+ /// Calling convention used for Mesa compute shaders.
+ AMDGPU_CS = 90,
+
+ /// Calling convention for AMDGPU code object kernels.
+ AMDGPU_KERNEL = 91,
+
/// The highest possible calling convention ID. Must be some 2^k - 1.
MaxID = 1023
};
diff --git a/include/llvm/IR/Comdat.h b/include/llvm/IR/Comdat.h
index fb79e13af3a5..577247f27e20 100644
--- a/include/llvm/IR/Comdat.h
+++ b/include/llvm/IR/Comdat.h
@@ -16,12 +16,10 @@
#ifndef LLVM_IR_COMDAT_H
#define LLVM_IR_COMDAT_H
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Compiler.h"
-
namespace llvm {
class raw_ostream;
+class StringRef;
template <typename ValueTy> class StringMapEntry;
// This is a Name X SelectionKind pair. The reason for having this be an
@@ -48,7 +46,6 @@ public:
private:
friend class Module;
Comdat();
- Comdat(SelectionKind SK, StringMapEntry<Comdat> *Name);
Comdat(const Comdat &) = delete;
// Points to the map in Module.
diff --git a/include/llvm/IR/Constant.h b/include/llvm/IR/Constant.h
index bb88905aa57a..3c5fe556d50f 100644
--- a/include/llvm/IR/Constant.h
+++ b/include/llvm/IR/Constant.h
@@ -48,42 +48,41 @@ protected:
: User(ty, vty, Ops, NumOps) {}
public:
- /// isNullValue - Return true if this is the value that would be returned by
- /// getNullValue.
+ /// Return true if this is the value that would be returned by getNullValue.
bool isNullValue() const;
- /// \brief Returns true if the value is one.
+ /// Returns true if the value is one.
bool isOneValue() const;
- /// isAllOnesValue - Return true if this is the value that would be returned by
+ /// Return true if this is the value that would be returned by
/// getAllOnesValue.
bool isAllOnesValue() const;
- /// isNegativeZeroValue - Return true if the value is what would be returned
- /// by getZeroValueForNegation.
+ /// Return true if the value is what would be returned by
+ /// getZeroValueForNegation.
bool isNegativeZeroValue() const;
/// Return true if the value is negative zero or null value.
bool isZeroValue() const;
- /// \brief Return true if the value is not the smallest signed value.
+ /// Return true if the value is not the smallest signed value.
bool isNotMinSignedValue() const;
- /// \brief Return true if the value is the smallest signed value.
+ /// Return true if the value is the smallest signed value.
bool isMinSignedValue() const;
- /// canTrap - Return true if evaluation of this constant could trap. This is
- /// true for things like constant expressions that could divide by zero.
+ /// Return true if evaluation of this constant could trap. This is true for
+ /// things like constant expressions that could divide by zero.
bool canTrap() const;
- /// isThreadDependent - Return true if the value can vary between threads.
+ /// Return true if the value can vary between threads.
bool isThreadDependent() const;
/// Return true if the value is dependent on a dllimport variable.
bool isDLLImportDependent() const;
- /// isConstantUsed - Return true if the constant has users other than constant
- /// exprs and other dangling things.
+ /// Return true if the constant has users other than constant expressions and
+ /// other dangling things.
bool isConstantUsed() const;
/// This method classifies the entry according to whether or not it may
@@ -93,15 +92,14 @@ public:
/// FIXME: This really should not be in IR.
bool needsRelocation() const;
- /// getAggregateElement - For aggregates (struct/array/vector) return the
- /// constant that corresponds to the specified element if possible, or null if
- /// not. This can return null if the element index is a ConstantExpr, or if
- /// 'this' is a constant expr.
+ /// For aggregates (struct/array/vector) return the constant that corresponds
+ /// to the specified element if possible, or null if not. This can return null
+ /// if the element index is a ConstantExpr, or if 'this' is a constant expr.
Constant *getAggregateElement(unsigned Elt) const;
Constant *getAggregateElement(Constant *Elt) const;
- /// getSplatValue - If this is a splat vector constant, meaning that all of
- /// the elements have the same value, return that value. Otherwise return 0.
+ /// If this is a splat vector constant, meaning that all of the elements have
+ /// the same value, return that value. Otherwise return 0.
Constant *getSplatValue() const;
/// If C is a constant integer then return its value, otherwise C must be a
@@ -133,7 +131,7 @@ public:
/// use Value::replaceAllUsesWith, which automatically dispatches to this
/// method as needed.
///
- void handleOperandChange(Value *, Value *, Use *);
+ void handleOperandChange(Value *, Value *);
static Constant *getNullValue(Type* Ty);
@@ -142,14 +140,14 @@ public:
/// @brief Get the all ones value
static Constant *getAllOnesValue(Type* Ty);
- /// getIntegerValue - Return the value for an integer or pointer constant,
- /// or a vector thereof, with the given scalar value.
+ /// Return the value for an integer or pointer constant, or a vector thereof,
+ /// with the given scalar value.
static Constant *getIntegerValue(Type *Ty, const APInt &V);
- /// removeDeadConstantUsers - If there are any dead constant users dangling
- /// off of this constant, remove them. This method is useful for clients
- /// that want to check to see if a global is unused, but don't want to deal
- /// with potentially dead constants hanging off of the globals.
+ /// If there are any dead constant users dangling off of this constant, remove
+ /// them. This method is useful for clients that want to check to see if a
+ /// global is unused, but don't want to deal with potentially dead constants
+ /// hanging off of the globals.
void removeDeadConstantUsers() const;
Constant *stripPointerCasts() {
diff --git a/include/llvm/IR/ConstantRange.h b/include/llvm/IR/ConstantRange.h
index fb596a3bf16e..9458fa9f5c86 100644
--- a/include/llvm/IR/ConstantRange.h
+++ b/include/llvm/IR/ConstantRange.h
@@ -82,16 +82,42 @@ public:
static ConstantRange makeSatisfyingICmpRegion(CmpInst::Predicate Pred,
const ConstantRange &Other);
- /// Return the largest range containing all X such that "X BinOpC C" does not
- /// wrap (overflow).
+ /// Produce the exact range such that all values in the returned range satisfy
+ /// the given predicate with any value contained within Other. Formally, this
+ /// returns the exact answer when the superset of 'union over all y in Other
+ /// is exactly same as the subset of intersection over all y in Other.
+ /// { x : icmp op x y is true}'.
///
- /// Example:
+ /// Example: Pred = ult and Other = i8 3 returns [0, 3)
+ static ConstantRange makeExactICmpRegion(CmpInst::Predicate Pred,
+ const APInt &Other);
+
+ /// Return the largest range containing all X such that "X BinOpC Y" is
+ /// guaranteed not to wrap (overflow) for all Y in Other.
+ ///
+ /// NB! The returned set does *not* contain **all** possible values of X for
+ /// which "X BinOpC Y" does not wrap -- some viable values of X may be
+ /// missing, so you cannot use this to contrain X's range. E.g. in the last
+ /// example, "(-2) + 1" is both nsw and nuw (so the "X" could be -2), but (-2)
+ /// is not in the set returned.
+ ///
+ /// Examples:
/// typedef OverflowingBinaryOperator OBO;
- /// makeNoWrapRegion(Add, i8 1, OBO::NoSignedWrap) == [-128, 127)
- /// makeNoWrapRegion(Add, i8 1, OBO::NoUnsignedWrap) == [0, -1)
- /// makeNoWrapRegion(Add, i8 0, OBO::NoUnsignedWrap) == Full Set
- static ConstantRange makeNoWrapRegion(Instruction::BinaryOps BinOp,
- const APInt &C, unsigned NoWrapKind);
+ /// #define MGNR makeGuaranteedNoWrapRegion
+ /// MGNR(Add, [i8 1, 2), OBO::NoSignedWrap) == [-128, 127)
+ /// MGNR(Add, [i8 1, 2), OBO::NoUnsignedWrap) == [0, -1)
+ /// MGNR(Add, [i8 0, 1), OBO::NoUnsignedWrap) == Full Set
+ /// MGNR(Add, [i8 1, 2), OBO::NoUnsignedWrap | OBO::NoSignedWrap)
+ /// == [0,INT_MAX)
+ /// MGNR(Add, [i8 -1, 6), OBO::NoSignedWrap) == [INT_MIN+1, INT_MAX-4)
+ static ConstantRange makeGuaranteedNoWrapRegion(Instruction::BinaryOps BinOp,
+ const ConstantRange &Other,
+ unsigned NoWrapKind);
+
+ /// Set up \p Pred and \p RHS such that
+ /// ConstantRange::makeExactICmpRegion(Pred, RHS) == *this. Return true if
+ /// successful.
+ bool getEquivalentICmp(CmpInst::Predicate &Pred, APInt &RHS) const;
/// Return the lower value for this range.
///
@@ -245,6 +271,14 @@ public:
ConstantRange umax(const ConstantRange &Other) const;
/// Return a new range representing the possible values resulting
+ /// from a signed minimum of a value in this range and a value in \p Other.
+ ConstantRange smin(const ConstantRange &Other) const;
+
+ /// Return a new range representing the possible values resulting
+ /// from an unsigned minimum of a value in this range and a value in \p Other.
+ ConstantRange umin(const ConstantRange &Other) const;
+
+ /// Return a new range representing the possible values resulting
/// from an unsigned division of a value in this range and a value in
/// \p Other.
ConstantRange udiv(const ConstantRange &Other) const;
diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h
index a5a20c9c5701..2a5d14d94646 100644
--- a/include/llvm/IR/Constants.h
+++ b/include/llvm/IR/Constants.h
@@ -40,26 +40,47 @@ class SequentialType;
struct ConstantExprKeyType;
template <class ConstantClass> struct ConstantAggrKeyType;
+/// Base class for constants with no operands.
+///
+/// These constants have no operands; they represent their data directly.
+/// Since they can be in use by unrelated modules (and are never based on
+/// GlobalValues), it never makes sense to RAUW them.
+class ConstantData : public Constant {
+ void anchor() override;
+ void *operator new(size_t, unsigned) = delete;
+ ConstantData() = delete;
+ ConstantData(const ConstantData &) = delete;
+
+ friend class Constant;
+ Value *handleOperandChangeImpl(Value *From, Value *To) {
+ llvm_unreachable("Constant data does not have operands!");
+ }
+
+protected:
+ explicit ConstantData(Type *Ty, ValueTy VT) : Constant(Ty, VT, nullptr, 0) {}
+ void *operator new(size_t s) { return User::operator new(s, 0); }
+
+public:
+ /// Methods to support type inquiry through isa, cast, and dyn_cast.
+ static bool classof(const Value *V) {
+ return V->getValueID() >= ConstantDataFirstVal &&
+ V->getValueID() <= ConstantDataLastVal;
+ }
+};
+
//===----------------------------------------------------------------------===//
/// This is the shared class of boolean and integer constants. This class
/// represents both boolean and integral constants.
/// @brief Class for constant integers.
-class ConstantInt : public Constant {
+class ConstantInt final : public ConstantData {
void anchor() override;
- void *operator new(size_t, unsigned) = delete;
ConstantInt(const ConstantInt &) = delete;
ConstantInt(IntegerType *Ty, const APInt& V);
APInt Val;
friend class Constant;
void destroyConstantImpl();
- Value *handleOperandChangeImpl(Value *From, Value *To, Use *U);
-protected:
- // allocate space for exactly zero operands
- void *operator new(size_t s) {
- return User::operator new(s, 0);
- }
public:
static ConstantInt *getTrue(LLVMContext &Context);
static ConstantInt *getFalse(LLVMContext &Context);
@@ -230,34 +251,26 @@ public:
//===----------------------------------------------------------------------===//
/// ConstantFP - Floating Point Values [float, double]
///
-class ConstantFP : public Constant {
+class ConstantFP final : public ConstantData {
APFloat Val;
void anchor() override;
- void *operator new(size_t, unsigned) = delete;
ConstantFP(const ConstantFP &) = delete;
- friend class LLVMContextImpl;
friend class Constant;
void destroyConstantImpl();
- Value *handleOperandChangeImpl(Value *From, Value *To, Use *U);
-protected:
ConstantFP(Type *Ty, const APFloat& V);
-protected:
- // allocate space for exactly zero operands
- void *operator new(size_t s) {
- return User::operator new(s, 0);
- }
+
public:
/// Floating point negation must be implemented with f(x) = -0.0 - x. This
/// method returns the negative zero constant for floating point or vector
/// floating point types; for all other types, it returns the null value.
static Constant *getZeroValueForNegation(Type *Ty);
- /// get() - This returns a ConstantFP, or a vector containing a splat of a
- /// ConstantFP, for the specified value in the specified type. This should
- /// only be used for simple constant values like 2.0/1.0 etc, that are
- /// known-valid both as host double and as the target format.
+ /// This returns a ConstantFP, or a vector containing a splat of a ConstantFP,
+ /// for the specified value in the specified type. This should only be used
+ /// for simple constant values like 2.0/1.0 etc, that are known-valid both as
+ /// host double and as the target format.
static Constant *get(Type* Ty, double V);
static Constant *get(Type* Ty, StringRef Str);
static ConstantFP *get(LLVMContext &Context, const APFloat &V);
@@ -265,24 +278,24 @@ public:
static Constant *getNegativeZero(Type *Ty);
static Constant *getInfinity(Type *Ty, bool Negative = false);
- /// isValueValidForType - return true if Ty is big enough to represent V.
+ /// Return true if Ty is big enough to represent V.
static bool isValueValidForType(Type *Ty, const APFloat &V);
inline const APFloat &getValueAPF() const { return Val; }
- /// isZero - Return true if the value is positive or negative zero.
+ /// Return true if the value is positive or negative zero.
bool isZero() const { return Val.isZero(); }
- /// isNegative - Return true if the sign bit is set.
+ /// Return true if the sign bit is set.
bool isNegative() const { return Val.isNegative(); }
- /// isInfinity - Return true if the value is infinity
+ /// Return true if the value is infinity
bool isInfinity() const { return Val.isInfinity(); }
- /// isNaN - Return true if the value is a NaN.
+ /// Return true if the value is a NaN.
bool isNaN() const { return Val.isNaN(); }
- /// isExactlyValue - We don't rely on operator== working on double values, as
- /// it returns true for things that are clearly not equal, like -0.0 and 0.0.
+ /// We don't rely on operator== working on double values, as it returns true
+ /// for things that are clearly not equal, like -0.0 and 0.0.
/// As such, this method can be used to do an exact bit-for-bit comparison of
/// two floating point values. The version with a double operand is retained
/// because it's so convenient to write isExactlyValue(2.0), but please use
@@ -302,44 +315,36 @@ public:
};
//===----------------------------------------------------------------------===//
-/// ConstantAggregateZero - All zero aggregate value
+/// All zero aggregate value
///
-class ConstantAggregateZero : public Constant {
- void *operator new(size_t, unsigned) = delete;
+class ConstantAggregateZero final : public ConstantData {
ConstantAggregateZero(const ConstantAggregateZero &) = delete;
friend class Constant;
void destroyConstantImpl();
- Value *handleOperandChangeImpl(Value *From, Value *To, Use *U);
-protected:
- explicit ConstantAggregateZero(Type *ty)
- : Constant(ty, ConstantAggregateZeroVal, nullptr, 0) {}
-protected:
- // allocate space for exactly zero operands
- void *operator new(size_t s) {
- return User::operator new(s, 0);
- }
+ explicit ConstantAggregateZero(Type *Ty)
+ : ConstantData(Ty, ConstantAggregateZeroVal) {}
+
public:
static ConstantAggregateZero *get(Type *Ty);
- /// getSequentialElement - If this CAZ has array or vector type, return a zero
- /// with the right element type.
+ /// If this CAZ has array or vector type, return a zero with the right element
+ /// type.
Constant *getSequentialElement() const;
- /// getStructElement - If this CAZ has struct type, return a zero with the
- /// right element type for the specified element.
+ /// If this CAZ has struct type, return a zero with the right element type for
+ /// the specified element.
Constant *getStructElement(unsigned Elt) const;
- /// getElementValue - Return a zero of the right value for the specified GEP
- /// index.
+ /// Return a zero of the right value for the specified GEP index if we can,
+ /// otherwise return null (e.g. if C is a ConstantExpr).
Constant *getElementValue(Constant *C) const;
- /// getElementValue - Return a zero of the right value for the specified GEP
- /// index.
+ /// Return a zero of the right value for the specified GEP index.
Constant *getElementValue(unsigned Idx) const;
- /// \brief Return the number of elements in the array, vector, or struct.
+ /// Return the number of elements in the array, vector, or struct.
unsigned getNumElements() const;
/// Methods for support type inquiry through isa, cast, and dyn_cast:
@@ -349,20 +354,49 @@ public:
}
};
+/// Base class for aggregate constants (with operands).
+///
+/// These constants are aggregates of other constants, which are stored as
+/// operands.
+///
+/// Subclasses are \a ConstantStruct, \a ConstantArray, and \a
+/// ConstantVector.
+///
+/// \note Some subclasses of \a ConstantData are semantically aggregates --
+/// such as \a ConstantDataArray -- but are not subclasses of this because they
+/// use operands.
+class ConstantAggregate : public Constant {
+protected:
+ ConstantAggregate(CompositeType *T, ValueTy VT, ArrayRef<Constant *> V);
+
+public:
+ /// Transparently provide more efficient getOperand methods.
+ DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
+
+ /// Methods for support type inquiry through isa, cast, and dyn_cast:
+ static bool classof(const Value *V) {
+ return V->getValueID() >= ConstantAggregateFirstVal &&
+ V->getValueID() <= ConstantAggregateLastVal;
+ }
+};
+
+template <>
+struct OperandTraits<ConstantAggregate>
+ : public VariadicOperandTraits<ConstantAggregate> {};
+
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantAggregate, Constant)
//===----------------------------------------------------------------------===//
/// ConstantArray - Constant Array Declarations
///
-class ConstantArray : public Constant {
+class ConstantArray final : public ConstantAggregate {
friend struct ConstantAggrKeyType<ConstantArray>;
- ConstantArray(const ConstantArray &) = delete;
-
friend class Constant;
void destroyConstantImpl();
- Value *handleOperandChangeImpl(Value *From, Value *To, Use *U);
+ Value *handleOperandChangeImpl(Value *From, Value *To);
-protected:
ConstantArray(ArrayType *T, ArrayRef<Constant *> Val);
+
public:
// ConstantArray accessors
static Constant *get(ArrayType *T, ArrayRef<Constant*> V);
@@ -371,12 +405,8 @@ private:
static Constant *getImpl(ArrayType *T, ArrayRef<Constant *> V);
public:
- /// Transparently provide more efficient getOperand methods.
- DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
-
- /// getType - Specialize the getType() method to always return an ArrayType,
+ /// Specialize the getType() method to always return an ArrayType,
/// which reduces the amount of casting needed in parts of the compiler.
- ///
inline ArrayType *getType() const {
return cast<ArrayType>(Value::getType());
}
@@ -387,34 +417,24 @@ public:
}
};
-template <>
-struct OperandTraits<ConstantArray> :
- public VariadicOperandTraits<ConstantArray> {
-};
-
-DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantArray, Constant)
-
//===----------------------------------------------------------------------===//
-// ConstantStruct - Constant Struct Declarations
+// Constant Struct Declarations
//
-class ConstantStruct : public Constant {
+class ConstantStruct final : public ConstantAggregate {
friend struct ConstantAggrKeyType<ConstantStruct>;
- ConstantStruct(const ConstantStruct &) = delete;
-
friend class Constant;
void destroyConstantImpl();
- Value *handleOperandChangeImpl(Value *From, Value *To, Use *U);
+ Value *handleOperandChangeImpl(Value *From, Value *To);
-protected:
ConstantStruct(StructType *T, ArrayRef<Constant *> Val);
+
public:
// ConstantStruct accessors
static Constant *get(StructType *T, ArrayRef<Constant*> V);
static Constant *get(StructType *T, ...) LLVM_END_WITH_NULL;
- /// getAnon - Return an anonymous struct that has the specified
- /// elements. If the struct is possibly empty, then you must specify a
- /// context.
+ /// Return an anonymous struct that has the specified elements.
+ /// If the struct is possibly empty, then you must specify a context.
static Constant *getAnon(ArrayRef<Constant*> V, bool Packed = false) {
return get(getTypeForElements(V, Packed), V);
}
@@ -423,20 +443,16 @@ public:
return get(getTypeForElements(Ctx, V, Packed), V);
}
- /// getTypeForElements - Return an anonymous struct type to use for a constant
- /// with the specified set of elements. The list must not be empty.
+ /// Return an anonymous struct type to use for a constant with the specified
+ /// set of elements. The list must not be empty.
static StructType *getTypeForElements(ArrayRef<Constant*> V,
bool Packed = false);
- /// getTypeForElements - This version of the method allows an empty list.
+ /// This version of the method allows an empty list.
static StructType *getTypeForElements(LLVMContext &Ctx,
ArrayRef<Constant*> V,
bool Packed = false);
- /// Transparently provide more efficient getOperand methods.
- DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
-
- /// getType() specialization - Reduce amount of casting...
- ///
+ /// Specialization - reduce amount of casting.
inline StructType *getType() const {
return cast<StructType>(Value::getType());
}
@@ -447,27 +463,18 @@ public:
}
};
-template <>
-struct OperandTraits<ConstantStruct> :
- public VariadicOperandTraits<ConstantStruct> {
-};
-
-DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantStruct, Constant)
-
//===----------------------------------------------------------------------===//
-/// ConstantVector - Constant Vector Declarations
+/// Constant Vector Declarations
///
-class ConstantVector : public Constant {
+class ConstantVector final : public ConstantAggregate {
friend struct ConstantAggrKeyType<ConstantVector>;
- ConstantVector(const ConstantVector &) = delete;
-
friend class Constant;
void destroyConstantImpl();
- Value *handleOperandChangeImpl(Value *From, Value *To, Use *U);
+ Value *handleOperandChangeImpl(Value *From, Value *To);
-protected:
ConstantVector(VectorType *T, ArrayRef<Constant *> Val);
+
public:
// ConstantVector accessors
static Constant *get(ArrayRef<Constant*> V);
@@ -476,22 +483,17 @@ private:
static Constant *getImpl(ArrayRef<Constant *> V);
public:
- /// getSplat - Return a ConstantVector with the specified constant in each
- /// element.
+ /// Return a ConstantVector with the specified constant in each element.
static Constant *getSplat(unsigned NumElts, Constant *Elt);
- /// Transparently provide more efficient getOperand methods.
- DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
-
- /// getType - Specialize the getType() method to always return a VectorType,
+ /// Specialize the getType() method to always return a VectorType,
/// which reduces the amount of casting needed in parts of the compiler.
- ///
inline VectorType *getType() const {
return cast<VectorType>(Value::getType());
}
- /// getSplatValue - If this is a splat constant, meaning that all of the
- /// elements have the same value, return that value. Otherwise return NULL.
+ /// If this is a splat constant, meaning that all of the elements have the
+ /// same value, return that value. Otherwise return NULL.
Constant *getSplatValue() const;
/// Methods for support type inquiry through isa, cast, and dyn_cast:
@@ -500,41 +502,24 @@ public:
}
};
-template <>
-struct OperandTraits<ConstantVector> :
- public VariadicOperandTraits<ConstantVector> {
-};
-
-DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantVector, Constant)
-
//===----------------------------------------------------------------------===//
-/// ConstantPointerNull - a constant pointer value that points to null
+/// A constant pointer value that points to null
///
-class ConstantPointerNull : public Constant {
- void *operator new(size_t, unsigned) = delete;
+class ConstantPointerNull final : public ConstantData {
ConstantPointerNull(const ConstantPointerNull &) = delete;
friend class Constant;
void destroyConstantImpl();
- Value *handleOperandChangeImpl(Value *From, Value *To, Use *U);
-protected:
explicit ConstantPointerNull(PointerType *T)
- : Constant(T,
- Value::ConstantPointerNullVal, nullptr, 0) {}
+ : ConstantData(T, Value::ConstantPointerNullVal) {}
-protected:
- // allocate space for exactly zero operands
- void *operator new(size_t s) {
- return User::operator new(s, 0);
- }
public:
- /// get() - Static factory methods - Return objects of the specified value
+ /// Static factory methods - Return objects of the specified value
static ConstantPointerNull *get(PointerType *T);
- /// getType - Specialize the getType() method to always return an PointerType,
+ /// Specialize the getType() method to always return an PointerType,
/// which reduces the amount of casting needed in parts of the compiler.
- ///
inline PointerType *getType() const {
return cast<PointerType>(Value::getType());
}
@@ -554,116 +539,101 @@ public:
///
/// This is the common base class of ConstantDataArray and ConstantDataVector.
///
-class ConstantDataSequential : public Constant {
+class ConstantDataSequential : public ConstantData {
friend class LLVMContextImpl;
- /// DataElements - A pointer to the bytes underlying this constant (which is
- /// owned by the uniquing StringMap).
+ /// A pointer to the bytes underlying this constant (which is owned by the
+ /// uniquing StringMap).
const char *DataElements;
- /// Next - This forms a link list of ConstantDataSequential nodes that have
+ /// This forms a link list of ConstantDataSequential nodes that have
/// the same value but different type. For example, 0,0,0,1 could be a 4
/// element array of i8, or a 1-element array of i32. They'll both end up in
/// the same StringMap bucket, linked up.
ConstantDataSequential *Next;
- void *operator new(size_t, unsigned) = delete;
ConstantDataSequential(const ConstantDataSequential &) = delete;
friend class Constant;
void destroyConstantImpl();
- Value *handleOperandChangeImpl(Value *From, Value *To, Use *U);
protected:
explicit ConstantDataSequential(Type *ty, ValueTy VT, const char *Data)
- : Constant(ty, VT, nullptr, 0), DataElements(Data), Next(nullptr) {}
+ : ConstantData(ty, VT), DataElements(Data), Next(nullptr) {}
~ConstantDataSequential() override { delete Next; }
static Constant *getImpl(StringRef Bytes, Type *Ty);
-protected:
- // allocate space for exactly zero operands.
- void *operator new(size_t s) {
- return User::operator new(s, 0);
- }
public:
-
- /// isElementTypeCompatible - Return true if a ConstantDataSequential can be
- /// formed with a vector or array of the specified element type.
+ /// Return true if a ConstantDataSequential can be formed with a vector or
+ /// array of the specified element type.
/// ConstantDataArray only works with normal float and int types that are
/// stored densely in memory, not with things like i42 or x86_f80.
static bool isElementTypeCompatible(Type *Ty);
- /// getElementAsInteger - If this is a sequential container of integers (of
- /// any size), return the specified element in the low bits of a uint64_t.
+ /// If this is a sequential container of integers (of any size), return the
+ /// specified element in the low bits of a uint64_t.
uint64_t getElementAsInteger(unsigned i) const;
- /// getElementAsAPFloat - If this is a sequential container of floating point
- /// type, return the specified element as an APFloat.
+ /// If this is a sequential container of floating point type, return the
+ /// specified element as an APFloat.
APFloat getElementAsAPFloat(unsigned i) const;
- /// getElementAsFloat - If this is an sequential container of floats, return
- /// the specified element as a float.
+ /// If this is an sequential container of floats, return the specified element
+ /// as a float.
float getElementAsFloat(unsigned i) const;
- /// getElementAsDouble - If this is an sequential container of doubles, return
- /// the specified element as a double.
+ /// If this is an sequential container of doubles, return the specified
+ /// element as a double.
double getElementAsDouble(unsigned i) const;
- /// getElementAsConstant - Return a Constant for a specified index's element.
+ /// Return a Constant for a specified index's element.
/// Note that this has to compute a new constant to return, so it isn't as
/// efficient as getElementAsInteger/Float/Double.
Constant *getElementAsConstant(unsigned i) const;
- /// getType - Specialize the getType() method to always return a
- /// SequentialType, which reduces the amount of casting needed in parts of the
- /// compiler.
+ /// Specialize the getType() method to always return a SequentialType, which
+ /// reduces the amount of casting needed in parts of the compiler.
inline SequentialType *getType() const {
return cast<SequentialType>(Value::getType());
}
- /// getElementType - Return the element type of the array/vector.
+ /// Return the element type of the array/vector.
Type *getElementType() const;
- /// getNumElements - Return the number of elements in the array or vector.
+ /// Return the number of elements in the array or vector.
unsigned getNumElements() const;
- /// getElementByteSize - Return the size (in bytes) of each element in the
- /// array/vector. The size of the elements is known to be a multiple of one
- /// byte.
+ /// Return the size (in bytes) of each element in the array/vector.
+ /// The size of the elements is known to be a multiple of one byte.
uint64_t getElementByteSize() const;
-
- /// isString - This method returns true if this is an array of i8.
+ /// This method returns true if this is an array of i8.
bool isString() const;
- /// isCString - This method returns true if the array "isString", ends with a
- /// nul byte, and does not contains any other nul bytes.
+ /// This method returns true if the array "isString", ends with a null byte,
+ /// and does not contains any other null bytes.
bool isCString() const;
- /// getAsString - If this array is isString(), then this method returns the
- /// array as a StringRef. Otherwise, it asserts out.
- ///
+ /// If this array is isString(), then this method returns the array as a
+ /// StringRef. Otherwise, it asserts out.
StringRef getAsString() const {
assert(isString() && "Not a string");
return getRawDataValues();
}
- /// getAsCString - If this array is isCString(), then this method returns the
- /// array (without the trailing null byte) as a StringRef. Otherwise, it
- /// asserts out.
- ///
+ /// If this array is isCString(), then this method returns the array (without
+ /// the trailing null byte) as a StringRef. Otherwise, it asserts out.
StringRef getAsCString() const {
assert(isCString() && "Isn't a C string");
StringRef Str = getAsString();
return Str.substr(0, Str.size()-1);
}
- /// getRawDataValues - Return the raw, underlying, bytes of this data. Note
- /// that this is an extremely tricky thing to work with, as it exposes the
- /// host endianness of the data elements.
+ /// Return the raw, underlying, bytes of this data. Note that this is an
+ /// extremely tricky thing to work with, as it exposes the host endianness of
+ /// the data elements.
StringRef getRawDataValues() const;
/// Methods for support type inquiry through isa, cast, and dyn_cast:
- ///
static bool classof(const Value *V) {
return V->getValueID() == ConstantDataArrayVal ||
V->getValueID() == ConstantDataVectorVal;
@@ -673,25 +643,24 @@ private:
};
//===----------------------------------------------------------------------===//
-/// ConstantDataArray - An array constant whose element type is a simple
-/// 1/2/4/8-byte integer or float/double, and whose elements are just simple
-/// data values (i.e. ConstantInt/ConstantFP). This Constant node has no
-/// operands because it stores all of the elements of the constant as densely
-/// packed data, instead of as Value*'s.
-class ConstantDataArray : public ConstantDataSequential {
+/// An array constant whose element type is a simple 1/2/4/8-byte integer or
+/// float/double, and whose elements are just simple data values
+/// (i.e. ConstantInt/ConstantFP). This Constant node has no operands because it
+/// stores all of the elements of the constant as densely packed data, instead
+/// of as Value*'s.
+class ConstantDataArray final : public ConstantDataSequential {
void *operator new(size_t, unsigned) = delete;
ConstantDataArray(const ConstantDataArray &) = delete;
void anchor() override;
friend class ConstantDataSequential;
explicit ConstantDataArray(Type *ty, const char *Data)
- : ConstantDataSequential(ty, ConstantDataArrayVal, Data) {}
-protected:
- // allocate space for exactly zero operands.
+ : ConstantDataSequential(ty, ConstantDataArrayVal, Data) {}
+ /// Allocate space for exactly zero operands.
void *operator new(size_t s) {
return User::operator new(s, 0);
}
-public:
+public:
/// get() constructors - Return a constant with array type with an element
/// count and element type matching the ArrayRef passed in. Note that this
/// can return a ConstantAggregateZero object.
@@ -711,48 +680,45 @@ public:
static Constant *getFP(LLVMContext &Context, ArrayRef<uint32_t> Elts);
static Constant *getFP(LLVMContext &Context, ArrayRef<uint64_t> Elts);
- /// getString - This method constructs a CDS and initializes it with a text
- /// string. The default behavior (AddNull==true) causes a null terminator to
+ /// This method constructs a CDS and initializes it with a text string.
+ /// The default behavior (AddNull==true) causes a null terminator to
/// be placed at the end of the array (increasing the length of the string by
/// one more than the StringRef would normally indicate. Pass AddNull=false
/// to disable this behavior.
static Constant *getString(LLVMContext &Context, StringRef Initializer,
bool AddNull = true);
- /// getType - Specialize the getType() method to always return an ArrayType,
+ /// Specialize the getType() method to always return an ArrayType,
/// which reduces the amount of casting needed in parts of the compiler.
- ///
inline ArrayType *getType() const {
return cast<ArrayType>(Value::getType());
}
/// Methods for support type inquiry through isa, cast, and dyn_cast:
- ///
static bool classof(const Value *V) {
return V->getValueID() == ConstantDataArrayVal;
}
};
//===----------------------------------------------------------------------===//
-/// ConstantDataVector - A vector constant whose element type is a simple
-/// 1/2/4/8-byte integer or float/double, and whose elements are just simple
-/// data values (i.e. ConstantInt/ConstantFP). This Constant node has no
-/// operands because it stores all of the elements of the constant as densely
-/// packed data, instead of as Value*'s.
-class ConstantDataVector : public ConstantDataSequential {
+/// A vector constant whose element type is a simple 1/2/4/8-byte integer or
+/// float/double, and whose elements are just simple data values
+/// (i.e. ConstantInt/ConstantFP). This Constant node has no operands because it
+/// stores all of the elements of the constant as densely packed data, instead
+/// of as Value*'s.
+class ConstantDataVector final : public ConstantDataSequential {
void *operator new(size_t, unsigned) = delete;
ConstantDataVector(const ConstantDataVector &) = delete;
void anchor() override;
friend class ConstantDataSequential;
explicit ConstantDataVector(Type *ty, const char *Data)
- : ConstantDataSequential(ty, ConstantDataVectorVal, Data) {}
-protected:
+ : ConstantDataSequential(ty, ConstantDataVectorVal, Data) {}
// allocate space for exactly zero operands.
void *operator new(size_t s) {
return User::operator new(s, 0);
}
-public:
+public:
/// get() constructors - Return a constant with vector type with an element
/// count and element type matching the ArrayRef passed in. Note that this
/// can return a ConstantAggregateZero object.
@@ -772,45 +738,38 @@ public:
static Constant *getFP(LLVMContext &Context, ArrayRef<uint32_t> Elts);
static Constant *getFP(LLVMContext &Context, ArrayRef<uint64_t> Elts);
- /// getSplat - Return a ConstantVector with the specified constant in each
- /// element. The specified constant has to be a of a compatible type (i8/i16/
+ /// Return a ConstantVector with the specified constant in each element.
+ /// The specified constant has to be a of a compatible type (i8/i16/
/// i32/i64/float/double) and must be a ConstantFP or ConstantInt.
static Constant *getSplat(unsigned NumElts, Constant *Elt);
- /// getSplatValue - If this is a splat constant, meaning that all of the
- /// elements have the same value, return that value. Otherwise return NULL.
+ /// If this is a splat constant, meaning that all of the elements have the
+ /// same value, return that value. Otherwise return NULL.
Constant *getSplatValue() const;
- /// getType - Specialize the getType() method to always return a VectorType,
+ /// Specialize the getType() method to always return a VectorType,
/// which reduces the amount of casting needed in parts of the compiler.
- ///
inline VectorType *getType() const {
return cast<VectorType>(Value::getType());
}
/// Methods for support type inquiry through isa, cast, and dyn_cast:
- ///
static bool classof(const Value *V) {
return V->getValueID() == ConstantDataVectorVal;
}
};
//===----------------------------------------------------------------------===//
-/// ConstantTokenNone - a constant token which is empty
+/// A constant token which is empty
///
-class ConstantTokenNone : public Constant {
- void *operator new(size_t, unsigned) = delete;
+class ConstantTokenNone final : public ConstantData {
ConstantTokenNone(const ConstantTokenNone &) = delete;
friend class Constant;
void destroyConstantImpl();
- Value *handleOperandChangeImpl(Value *From, Value *To, Use *U);
-protected:
explicit ConstantTokenNone(LLVMContext &Context)
- : Constant(Type::getTokenTy(Context), ConstantTokenNoneVal, nullptr, 0) {}
- // allocate space for exactly zero operands
- void *operator new(size_t s) { return User::operator new(s, 0); }
+ : ConstantData(Type::getTokenTy(Context), ConstantTokenNoneVal) {}
public:
/// Return the ConstantTokenNone.
@@ -822,27 +781,26 @@ public:
}
};
-/// BlockAddress - The address of a basic block.
+/// The address of a basic block.
///
-class BlockAddress : public Constant {
+class BlockAddress final : public Constant {
void *operator new(size_t, unsigned) = delete;
void *operator new(size_t s) { return User::operator new(s, 2); }
BlockAddress(Function *F, BasicBlock *BB);
friend class Constant;
void destroyConstantImpl();
- Value *handleOperandChangeImpl(Value *From, Value *To, Use *U);
+ Value *handleOperandChangeImpl(Value *From, Value *To);
public:
- /// get - Return a BlockAddress for the specified function and basic block.
+ /// Return a BlockAddress for the specified function and basic block.
static BlockAddress *get(Function *F, BasicBlock *BB);
- /// get - Return a BlockAddress for the specified basic block. The basic
+ /// Return a BlockAddress for the specified basic block. The basic
/// block must be embedded into a function.
static BlockAddress *get(BasicBlock *BB);
- /// \brief Lookup an existing \c BlockAddress constant for the given
- /// BasicBlock.
+ /// Lookup an existing \c BlockAddress constant for the given BasicBlock.
///
/// \returns 0 if \c !BB->hasAddressTaken(), otherwise the \c BlockAddress.
static BlockAddress *lookup(const BasicBlock *BB);
@@ -868,7 +826,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BlockAddress, Value)
//===----------------------------------------------------------------------===//
-/// ConstantExpr - a constant value that is initialized with an expression using
+/// A constant value that is initialized with an expression using
/// other constant values.
///
/// This class uses the standard Instruction opcodes to define the various
@@ -879,11 +837,11 @@ class ConstantExpr : public Constant {
friend class Constant;
void destroyConstantImpl();
- Value *handleOperandChangeImpl(Value *From, Value *To, Use *U);
+ Value *handleOperandChangeImpl(Value *From, Value *To);
protected:
ConstantExpr(Type *ty, unsigned Opcode, Use *Ops, unsigned NumOps)
- : Constant(ty, ConstantExprVal, Ops, NumOps) {
+ : Constant(ty, ConstantExprVal, Ops, NumOps) {
// Operation type (an Instruction opcode) is stored as the SubclassData.
setValueSubclassData(Opcode);
}
@@ -998,12 +956,12 @@ public:
return getLShr(C1, C2, true);
}
- /// getBinOpIdentity - Return the identity for the given binary operation,
+ /// Return the identity for the given binary operation,
/// i.e. a constant C such that X op C = X and C op X = X for every X. It
/// returns null if the operator doesn't have an identity.
static Constant *getBinOpIdentity(unsigned Opcode, Type *Ty);
- /// getBinOpAbsorber - Return the absorbing element for the given binary
+ /// Return the absorbing element for the given binary
/// operation, i.e. a constant C such that X op C = C and C op X = C for
/// every X. For example, this returns zero for integer multiplication.
/// It returns null if the operator doesn't have an absorbing element.
@@ -1165,32 +1123,32 @@ public:
ArrayRef<unsigned> Idxs,
Type *OnlyIfReducedTy = nullptr);
- /// getOpcode - Return the opcode at the root of this constant expression
+ /// Return the opcode at the root of this constant expression
unsigned getOpcode() const { return getSubclassDataFromValue(); }
- /// getPredicate - Return the ICMP or FCMP predicate value. Assert if this is
- /// not an ICMP or FCMP constant expression.
+ /// Return the ICMP or FCMP predicate value. Assert if this is not an ICMP or
+ /// FCMP constant expression.
unsigned getPredicate() const;
- /// getIndices - Assert that this is an insertvalue or exactvalue
+ /// Assert that this is an insertvalue or exactvalue
/// expression and return the list of indices.
ArrayRef<unsigned> getIndices() const;
- /// getOpcodeName - Return a string representation for an opcode.
+ /// Return a string representation for an opcode.
const char *getOpcodeName() const;
- /// getWithOperandReplaced - Return a constant expression identical to this
- /// one, but with the specified operand set to the specified value.
+ /// Return a constant expression identical to this one, but with the specified
+ /// operand set to the specified value.
Constant *getWithOperandReplaced(unsigned OpNo, Constant *Op) const;
- /// getWithOperands - This returns the current constant expression with the
- /// operands replaced with the specified values. The specified array must
- /// have the same number of operands as our current one.
+ /// This returns the current constant expression with the operands replaced
+ /// with the specified values. The specified array must have the same number
+ /// of operands as our current one.
Constant *getWithOperands(ArrayRef<Constant*> Ops) const {
return getWithOperands(Ops, getType());
}
- /// \brief Get the current expression with the operands replaced.
+ /// Get the current expression with the operands replaced.
///
/// Return the current constant expression with the operands replaced with \c
/// Ops and the type with \c Ty. The new operands must have the same number
@@ -1203,9 +1161,8 @@ public:
bool OnlyIfReduced = false,
Type *SrcTy = nullptr) const;
- /// getAsInstruction - Returns an Instruction which implements the same
- /// operation as this ConstantExpr. The instruction is not linked to any basic
- /// block.
+ /// Returns an Instruction which implements the same operation as this
+ /// ConstantExpr. The instruction is not linked to any basic block.
///
/// A better approach to this could be to have a constructor for Instruction
/// which would take a ConstantExpr parameter, but that would have spread
@@ -1234,7 +1191,7 @@ struct OperandTraits<ConstantExpr> :
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantExpr, Constant)
//===----------------------------------------------------------------------===//
-/// UndefValue - 'undef' values are things that do not have specified contents.
+/// 'undef' values are things that do not have specified contents.
/// These are used for a variety of purposes, including global variable
/// initializers and operands to instructions. 'undef' values can occur with
/// any first-class type.
@@ -1243,44 +1200,34 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantExpr, Constant)
/// can appear to have different bit patterns at each use. See
/// LangRef.html#undefvalues for details.
///
-class UndefValue : public Constant {
- void *operator new(size_t, unsigned) = delete;
+class UndefValue final : public ConstantData {
UndefValue(const UndefValue &) = delete;
friend class Constant;
void destroyConstantImpl();
- Value *handleOperandChangeImpl(Value *From, Value *To, Use *U);
-protected:
- explicit UndefValue(Type *T) : Constant(T, UndefValueVal, nullptr, 0) {}
-protected:
- // allocate space for exactly zero operands
- void *operator new(size_t s) {
- return User::operator new(s, 0);
- }
+ explicit UndefValue(Type *T) : ConstantData(T, UndefValueVal) {}
+
public:
- /// get() - Static factory methods - Return an 'undef' object of the specified
- /// type.
- ///
+ /// Static factory methods - Return an 'undef' object of the specified type.
static UndefValue *get(Type *T);
- /// getSequentialElement - If this Undef has array or vector type, return a
- /// undef with the right element type.
+ /// If this Undef has array or vector type, return a undef with the right
+ /// element type.
UndefValue *getSequentialElement() const;
- /// getStructElement - If this undef has struct type, return a undef with the
- /// right element type for the specified element.
+ /// If this undef has struct type, return a undef with the right element type
+ /// for the specified element.
UndefValue *getStructElement(unsigned Elt) const;
- /// getElementValue - Return an undef of the right value for the specified GEP
- /// index.
+ /// Return an undef of the right value for the specified GEP index if we can,
+ /// otherwise return null (e.g. if C is a ConstantExpr).
UndefValue *getElementValue(Constant *C) const;
- /// getElementValue - Return an undef of the right value for the specified GEP
- /// index.
+ /// Return an undef of the right value for the specified GEP index.
UndefValue *getElementValue(unsigned Idx) const;
- /// \brief Return the number of elements in the array, vector, or struct.
+ /// Return the number of elements in the array, vector, or struct.
unsigned getNumElements() const;
/// Methods for support type inquiry through isa, cast, and dyn_cast:
diff --git a/include/llvm/IR/DIBuilder.h b/include/llvm/IR/DIBuilder.h
index aeec39541154..0f2f67f5feaf 100644
--- a/include/llvm/IR/DIBuilder.h
+++ b/include/llvm/IR/DIBuilder.h
@@ -15,8 +15,6 @@
#ifndef LLVM_IR_DIBUILDER_H
#define LLVM_IR_DIBUILDER_H
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/TrackingMDRef.h"
#include "llvm/IR/ValueHandle.h"
@@ -31,6 +29,7 @@ namespace llvm {
class Constant;
class LLVMContext;
class StringRef;
+ template <typename T> class ArrayRef;
class DIBuilder {
Module &M;
@@ -52,7 +51,11 @@ namespace llvm {
bool AllowUnresolvedNodes;
/// Each subprogram's preserved local variables.
- DenseMap<MDNode *, std::vector<TrackingMDNodeRef>> PreservedVariables;
+ ///
+ /// Do not use a std::vector. Some versions of libc++ apparently copy
+ /// instead of move on grow operations, and TrackingMDRef is expensive to
+ /// copy.
+ DenseMap<MDNode *, SmallVector<TrackingMDNodeRef, 1>> PreservedVariables;
DIBuilder(const DIBuilder &) = delete;
void operator=(const DIBuilder &) = delete;
@@ -68,7 +71,6 @@ namespace llvm {
/// If \c AllowUnresolved, collect unresolved nodes attached to the module
/// in order to resolve cycles during \a finalize().
explicit DIBuilder(Module &M, bool AllowUnresolved = true);
- enum DebugEmissionKind { FullDebug=1, LineTablesOnly };
/// Construct any deferred debug info descriptors.
void finalize();
@@ -93,22 +95,13 @@ namespace llvm {
/// out into.
/// \param Kind The kind of debug information to generate.
/// \param DWOId The DWOId if this is a split skeleton compile unit.
- /// \param EmitDebugInfo A boolean flag which indicates whether
- /// debug information should be written to
- /// the final output or not. When this is
- /// false, debug information annotations will
- /// be present in the IL but they are not
- /// written to the final assembly or object
- /// file. This supports tracking source
- /// location information in the back end
- /// without actually changing the output
- /// (e.g., when using optimization remarks).
DICompileUnit *
createCompileUnit(unsigned Lang, StringRef File, StringRef Dir,
StringRef Producer, bool isOptimized, StringRef Flags,
unsigned RV, StringRef SplitName = StringRef(),
- DebugEmissionKind Kind = FullDebug, uint64_t DWOId = 0,
- bool EmitDebugInfo = true);
+ DICompileUnit::DebugEmissionKind Kind =
+ DICompileUnit::DebugEmissionKind::FullDebug,
+ uint64_t DWOId = 0);
/// Create a file descriptor to hold debugging information
/// for a file.
@@ -154,7 +147,8 @@ namespace llvm {
/// \param Class Type for which this pointer points to members of.
DIDerivedType *createMemberPointerType(DIType *PointeeTy, DIType *Class,
uint64_t SizeInBits,
- uint64_t AlignInBits = 0);
+ uint64_t AlignInBits = 0,
+ unsigned Flags = 0);
/// Create debugging information entry for a c++
/// style reference or rvalue reference type.
@@ -200,6 +194,22 @@ namespace llvm {
uint64_t OffsetInBits, unsigned Flags,
DIType *Ty);
+ /// Create debugging information entry for a bit field member.
+ /// \param Scope Member scope.
+ /// \param Name Member name.
+ /// \param File File where this member is defined.
+ /// \param LineNo Line number.
+ /// \param SizeInBits Member size.
+ /// \param AlignInBits Member alignment.
+ /// \param OffsetInBits Member offset.
+ /// \param StorageOffsetInBits Member storage offset.
+ /// \param Flags Flags to encode member attribute.
+ /// \param Ty Parent type.
+ DIDerivedType *createBitFieldMemberType(
+ DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNo,
+ uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits,
+ uint64_t StorageOffsetInBits, unsigned Flags, DIType *Ty);
+
/// Create debugging information entry for a
/// C++ static data member.
/// \param Scope Member scope.
@@ -381,8 +391,9 @@ namespace llvm {
/// includes return type at 0th index.
/// \param Flags E.g.: LValueReference.
/// These flags are used to emit dwarf attributes.
+ /// \param CC Calling convention, e.g. dwarf::DW_CC_normal
DISubroutineType *createSubroutineType(DITypeRefArray ParameterTypes,
- unsigned Flags = 0);
+ unsigned Flags = 0, unsigned CC = 0);
/// Create an external type reference.
/// \param Tag Dwarf TAG.
@@ -413,9 +424,9 @@ namespace llvm {
uint64_t AlignInBits = 0, unsigned Flags = DINode::FlagFwdDecl,
StringRef UniqueIdentifier = "");
- /// Retain DIType* in a module even if it is not referenced
+ /// Retain DIScope* in a module even if it is not referenced
/// through debug info anchors.
- void retainType(DIType *T);
+ void retainType(DIScope *T);
/// Create unspecified parameter type
/// for a subroutine type.
@@ -535,17 +546,6 @@ namespace llvm {
bool isOptimized = false, DITemplateParameterArray TParams = nullptr,
DISubprogram *Decl = nullptr);
- /// FIXME: this is added for dragonegg. Once we update dragonegg
- /// to call resolve function, this will be removed.
- DISubprogram *createFunction(DIScopeRef Scope, StringRef Name,
- StringRef LinkageName, DIFile *File,
- unsigned LineNo, DISubroutineType *Ty,
- bool isLocalToUnit, bool isDefinition,
- unsigned ScopeLine, unsigned Flags = 0,
- bool isOptimized = false,
- DITemplateParameterArray TParams = nullptr,
- DISubprogram *Decl = nullptr);
-
/// Create a new descriptor for the specified C++ method.
/// See comments in \a DISubprogram* for descriptions of these fields.
/// \param Scope Function scope.
@@ -558,7 +558,11 @@ namespace llvm {
/// \param isDefinition True if this is a function definition.
/// \param Virtuality Attributes describing virtualness. e.g. pure
/// virtual function.
- /// \param VTableIndex Index no of this method in virtual table.
+ /// \param VTableIndex Index no of this method in virtual table, or -1u if
+ /// unrepresentable.
+ /// \param ThisAdjustment
+ /// MS ABI-specific adjustment of 'this' that occurs
+ /// in the prologue.
/// \param VTableHolder Type that holds vtable.
/// \param Flags e.g. is this function prototyped or not.
/// This flags are used to emit dwarf attributes.
@@ -568,8 +572,9 @@ namespace llvm {
createMethod(DIScope *Scope, StringRef Name, StringRef LinkageName,
DIFile *File, unsigned LineNo, DISubroutineType *Ty,
bool isLocalToUnit, bool isDefinition, unsigned Virtuality = 0,
- unsigned VTableIndex = 0, DIType *VTableHolder = nullptr,
- unsigned Flags = 0, bool isOptimized = false,
+ unsigned VTableIndex = 0, int ThisAdjustment = 0,
+ DIType *VTableHolder = nullptr, unsigned Flags = 0,
+ bool isOptimized = false,
DITemplateParameterArray TParams = nullptr);
/// This creates new descriptor for a namespace with the specified
diff --git a/include/llvm/IR/DataLayout.h b/include/llvm/IR/DataLayout.h
index 19a3a6661feb..173121b72ffd 100644
--- a/include/llvm/IR/DataLayout.h
+++ b/include/llvm/IR/DataLayout.h
@@ -20,7 +20,6 @@
#ifndef LLVM_IR_DATALAYOUT_H
#define LLVM_IR_DATALAYOUT_H
-#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Type.h"
@@ -34,8 +33,6 @@ typedef struct LLVMOpaqueTargetData *LLVMTargetDataRef;
namespace llvm {
class Value;
-class Type;
-class IntegerType;
class StructType;
class StructLayout;
class Triple;
@@ -236,14 +233,14 @@ public:
/// on any known one. This returns false if the integer width is not legal.
///
/// The width is specified in bits.
- bool isLegalInteger(unsigned Width) const {
+ bool isLegalInteger(uint64_t Width) const {
for (unsigned LegalIntWidth : LegalIntWidths)
if (LegalIntWidth == Width)
return true;
return false;
}
- bool isIllegalInteger(unsigned Width) const { return !isLegalInteger(Width); }
+ bool isIllegalInteger(uint64_t Width) const { return !isLegalInteger(Width); }
/// Returns true if the given alignment exceeds the natural stack alignment.
bool exceedsNaturalStackAlignment(unsigned Align) const {
@@ -387,7 +384,7 @@ public:
/// returns 12 or 16 for x86_fp80, depending on alignment.
uint64_t getTypeAllocSize(Type *Ty) const {
// Round up to the next alignment boundary.
- return RoundUpToAlignment(getTypeStoreSize(Ty), getABITypeAlignment(Ty));
+ return alignTo(getTypeStoreSize(Ty), getABITypeAlignment(Ty));
}
/// \brief Returns the offset in bits between successive objects of the
@@ -430,19 +427,20 @@ public:
/// \brief Returns the largest legal integer type, or null if none are set.
Type *getLargestLegalIntType(LLVMContext &C) const {
- unsigned LargestSize = getLargestLegalIntTypeSize();
+ unsigned LargestSize = getLargestLegalIntTypeSizeInBits();
return (LargestSize == 0) ? nullptr : Type::getIntNTy(C, LargestSize);
}
/// \brief Returns the size of largest legal integer type size, or 0 if none
/// are set.
- unsigned getLargestLegalIntTypeSize() const;
+ unsigned getLargestLegalIntTypeSizeInBits() const;
/// \brief Returns the offset from the beginning of the type for the specified
/// indices.
///
+ /// Note that this takes the element type, not the pointer type.
/// This is used to implement getelementptr.
- uint64_t getIndexedOffset(Type *Ty, ArrayRef<Value *> Indices) const;
+ int64_t getIndexedOffsetInType(Type *ElemTy, ArrayRef<Value *> Indices) const;
/// \brief Returns a StructLayout object, indicating the alignment of the
/// struct, its size, and the offsets of its fields.
@@ -475,7 +473,7 @@ inline LLVMTargetDataRef wrap(const DataLayout *P) {
class StructLayout {
uint64_t StructSize;
unsigned StructAlignment;
- bool IsPadded : 1;
+ unsigned IsPadded : 1;
unsigned NumElements : 31;
uint64_t MemberOffsets[1]; // variable sized array!
public:
diff --git a/include/llvm/IR/DebugInfo.h b/include/llvm/IR/DebugInfo.h
index 4caceacbb58e..972042432b7b 100644
--- a/include/llvm/IR/DebugInfo.h
+++ b/include/llvm/IR/DebugInfo.h
@@ -17,10 +17,8 @@
#ifndef LLVM_IR_DEBUGINFO_H
#define LLVM_IR_DEBUGINFO_H
-#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/Support/Casting.h"
@@ -32,21 +30,12 @@ namespace llvm {
class Module;
class DbgDeclareInst;
class DbgValueInst;
-
-/// \brief Maps from type identifier to the actual MDNode.
-typedef DenseMap<const MDString *, DIType *> DITypeIdentifierMap;
+template <typename K, typename V, typename KeyInfoT, typename BucketT>
+class DenseMap;
/// \brief Find subprogram that is enclosing this scope.
DISubprogram *getDISubprogram(const MDNode *Scope);
-/// \brief Find debug info for a given function.
-///
-/// \returns a valid subprogram, if found. Otherwise, return \c nullptr.
-DISubprogram *getDISubprogram(const Function *F);
-
-/// \brief Generate map by visiting all retained types.
-DITypeIdentifierMap generateDITypeIdentifierMap(const NamedMDNode *CU_Nodes);
-
/// \brief Strip debug info in the module if it exists.
///
/// To do this, we remove all calls to the debugger intrinsics and any named
@@ -68,8 +57,6 @@ unsigned getDebugMetadataVersionFromModule(const Module &M);
/// used by the CUs.
class DebugInfoFinder {
public:
- DebugInfoFinder() : TypeMapInitialized(false) {}
-
/// \brief Process entire module and collect debug info anchors.
void processModule(const Module &M);
@@ -136,11 +123,7 @@ private:
SmallVector<DIGlobalVariable *, 8> GVs;
SmallVector<DIType *, 8> TYs;
SmallVector<DIScope *, 8> Scopes;
- SmallPtrSet<const MDNode *, 64> NodesSeen;
- DITypeIdentifierMap TypeIdentifierMap;
-
- /// \brief Specify if TypeIdentifierMap is initialized.
- bool TypeMapInitialized;
+ SmallPtrSet<const MDNode *, 32> NodesSeen;
};
} // end namespace llvm
diff --git a/include/llvm/IR/DebugInfoFlags.def b/include/llvm/IR/DebugInfoFlags.def
index 9756c12264b4..26238c349e7e 100644
--- a/include/llvm/IR/DebugInfoFlags.def
+++ b/include/llvm/IR/DebugInfoFlags.def
@@ -33,5 +33,10 @@ HANDLE_DI_FLAG((1 << 12), StaticMember)
HANDLE_DI_FLAG((1 << 13), LValueReference)
HANDLE_DI_FLAG((1 << 14), RValueReference)
HANDLE_DI_FLAG((1 << 15), ExternalTypeRef)
+HANDLE_DI_FLAG((1 << 16), SingleInheritance)
+HANDLE_DI_FLAG((2 << 16), MultipleInheritance)
+HANDLE_DI_FLAG((3 << 16), VirtualInheritance)
+HANDLE_DI_FLAG((1 << 18), IntroducedVirtual)
+HANDLE_DI_FLAG((1 << 19), BitField)
#undef HANDLE_DI_FLAG
diff --git a/include/llvm/IR/DebugInfoMetadata.h b/include/llvm/IR/DebugInfoMetadata.h
index 456313a70e83..853a94afd9d9 100644
--- a/include/llvm/IR/DebugInfoMetadata.h
+++ b/include/llvm/IR/DebugInfoMetadata.h
@@ -43,21 +43,25 @@
namespace llvm {
-/// \brief Pointer union between a subclass of DINode and MDString.
+template <typename T> class Optional;
+
+/// Holds a subclass of DINode.
///
-/// \a DICompositeType can be referenced via an \a MDString unique identifier.
-/// This class allows some type safety in the face of that, requiring either a
-/// node of a particular type or an \a MDString.
+/// FIXME: This class doesn't currently make much sense. Previously it was a
+/// union beteen MDString (for ODR-uniqued types) and things like DIType. To
+/// support CodeView work, it wasn't deleted outright when MDString-based type
+/// references were deleted; we'll soon need a similar concept for CodeView
+/// DITypeIndex.
template <class T> class TypedDINodeRef {
const Metadata *MD = nullptr;
public:
TypedDINodeRef() = default;
TypedDINodeRef(std::nullptr_t) {}
+ TypedDINodeRef(const T *MD) : MD(MD) {}
- /// \brief Construct from a raw pointer.
explicit TypedDINodeRef(const Metadata *MD) : MD(MD) {
- assert((!MD || isa<MDString>(MD) || isa<T>(MD)) && "Expected valid ref");
+ assert((!MD || isa<T>(MD)) && "Expected valid type ref");
}
template <class U>
@@ -69,26 +73,10 @@ public:
operator Metadata *() const { return const_cast<Metadata *>(MD); }
+ T *resolve() const { return const_cast<T *>(cast_or_null<T>(MD)); }
+
bool operator==(const TypedDINodeRef<T> &X) const { return MD == X.MD; }
bool operator!=(const TypedDINodeRef<T> &X) const { return MD != X.MD; }
-
- /// \brief Create a reference.
- ///
- /// Get a reference to \c N, using an \a MDString reference if available.
- static TypedDINodeRef get(const T *N);
-
- template <class MapTy> T *resolve(const MapTy &Map) const {
- if (!MD)
- return nullptr;
-
- if (auto *Typed = dyn_cast<T>(MD))
- return const_cast<T *>(Typed);
-
- auto *S = cast<MDString>(MD);
- auto I = Map.find(S);
- assert(I != Map.end() && "Missing identifier in type map");
- return cast<T>(I->second);
- }
};
typedef TypedDINodeRef<DINode> DINodeRef;
@@ -173,6 +161,9 @@ protected:
return MDString::get(Context, S);
}
+ /// Allow subclasses to mutate the tag.
+ void setTag(unsigned Tag) { SubclassData16 = Tag; }
+
public:
unsigned getTag() const { return SubclassData16; }
@@ -183,7 +174,9 @@ public:
enum DIFlags {
#define HANDLE_DI_FLAG(ID, NAME) Flag##NAME = ID,
#include "llvm/IR/DebugInfoFlags.def"
- FlagAccessibility = FlagPrivate | FlagProtected | FlagPublic
+ FlagAccessibility = FlagPrivate | FlagProtected | FlagPublic,
+ FlagPtrToMemberRep = FlagSingleInheritance | FlagMultipleInheritance |
+ FlagVirtualInheritance,
};
static unsigned getFlag(StringRef Flag);
@@ -196,8 +189,6 @@ public:
static unsigned splitFlags(unsigned Flags,
SmallVectorImpl<unsigned> &SplitFlags);
- DINodeRef getRef() const { return DINodeRef::get(this); }
-
static bool classof(const Metadata *MD) {
switch (MD->getMetadataID()) {
default:
@@ -291,6 +282,7 @@ public:
unsigned getTag() const { return SubclassData16; }
StringRef getHeader() const { return getStringOperand(0); }
+ MDString *getRawHeader() const { return getOperandAs<MDString>(0); }
op_iterator dwarf_op_begin() const { return op_begin() + 1; }
op_iterator dwarf_op_end() const { return op_end(); }
@@ -431,8 +423,6 @@ public:
: static_cast<Metadata *>(getOperand(0));
}
- DIScopeRef getRef() const { return DIScopeRef::get(this); }
-
static bool classof(const Metadata *MD) {
switch (MD->getMetadataID()) {
default:
@@ -527,11 +517,28 @@ protected:
DIType(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag,
unsigned Line, uint64_t SizeInBits, uint64_t AlignInBits,
uint64_t OffsetInBits, unsigned Flags, ArrayRef<Metadata *> Ops)
- : DIScope(C, ID, Storage, Tag, Ops), Line(Line), Flags(Flags),
- SizeInBits(SizeInBits), AlignInBits(AlignInBits),
- OffsetInBits(OffsetInBits) {}
+ : DIScope(C, ID, Storage, Tag, Ops) {
+ init(Line, SizeInBits, AlignInBits, OffsetInBits, Flags);
+ }
~DIType() = default;
+ void init(unsigned Line, uint64_t SizeInBits, uint64_t AlignInBits,
+ uint64_t OffsetInBits, unsigned Flags) {
+ this->Line = Line;
+ this->Flags = Flags;
+ this->SizeInBits = SizeInBits;
+ this->AlignInBits = AlignInBits;
+ this->OffsetInBits = OffsetInBits;
+ }
+
+ /// Change fields in place.
+ void mutate(unsigned Tag, unsigned Line, uint64_t SizeInBits,
+ uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags) {
+ assert(isDistinct() && "Only distinct nodes can mutate");
+ setTag(Tag);
+ init(Line, SizeInBits, AlignInBits, OffsetInBits, Flags);
+ }
+
public:
TempDIType clone() const {
return TempDIType(cast<DIType>(MDNode::clone().release()));
@@ -574,13 +581,12 @@ public:
return getFlags() & FlagObjcClassComplete;
}
bool isVector() const { return getFlags() & FlagVector; }
+ bool isBitField() const { return getFlags() & FlagBitField; }
bool isStaticMember() const { return getFlags() & FlagStaticMember; }
bool isLValueReference() const { return getFlags() & FlagLValueReference; }
bool isRValueReference() const { return getFlags() & FlagRValueReference; }
bool isExternalTypeRef() const { return getFlags() & FlagExternalTypeRef; }
- DITypeRef getRef() const { return DITypeRef::get(this); }
-
static bool classof(const Metadata *MD) {
switch (MD->getMetadataID()) {
default:
@@ -735,6 +741,12 @@ public:
DIObjCProperty *getObjCProperty() const {
return dyn_cast_or_null<DIObjCProperty>(getExtraData());
}
+ Constant *getStorageOffsetInBits() const {
+ assert(getTag() == dwarf::DW_TAG_member && isBitField());
+ if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData()))
+ return C->getValue();
+ return nullptr;
+ }
Constant *getConstant() const {
assert(getTag() == dwarf::DW_TAG_member && isStaticMember());
if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData()))
@@ -767,6 +779,16 @@ class DICompositeType : public DIType {
RuntimeLang(RuntimeLang) {}
~DICompositeType() = default;
+ /// Change fields in place.
+ void mutate(unsigned Tag, unsigned Line, unsigned RuntimeLang,
+ uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits,
+ unsigned Flags) {
+ assert(isDistinct() && "Only distinct nodes can mutate");
+ assert(getRawIdentifier() && "Only ODR-uniqued nodes should mutate");
+ this->RuntimeLang = RuntimeLang;
+ DIType::mutate(Tag, Line, SizeInBits, AlignInBits, OffsetInBits, Flags);
+ }
+
static DICompositeType *
getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, Metadata *File,
unsigned Line, DIScopeRef Scope, DITypeRef BaseType,
@@ -822,6 +844,40 @@ public:
TempDICompositeType clone() const { return cloneImpl(); }
+ /// Get a DICompositeType with the given ODR identifier.
+ ///
+ /// If \a LLVMContext::isODRUniquingDebugTypes(), gets the mapped
+ /// DICompositeType for the given ODR \c Identifier. If none exists, creates
+ /// a new node.
+ ///
+ /// Else, returns \c nullptr.
+ static DICompositeType *
+ getODRType(LLVMContext &Context, MDString &Identifier, unsigned Tag,
+ MDString *Name, Metadata *File, unsigned Line, Metadata *Scope,
+ Metadata *BaseType, uint64_t SizeInBits, uint64_t AlignInBits,
+ uint64_t OffsetInBits, unsigned Flags, Metadata *Elements,
+ unsigned RuntimeLang, Metadata *VTableHolder,
+ Metadata *TemplateParams);
+ static DICompositeType *getODRTypeIfExists(LLVMContext &Context,
+ MDString &Identifier);
+
+ /// Build a DICompositeType with the given ODR identifier.
+ ///
+ /// Looks up the mapped DICompositeType for the given ODR \c Identifier. If
+ /// it doesn't exist, creates a new one. If it does exist and \a
+ /// isForwardDecl(), and the new arguments would be a definition, mutates the
+ /// the type in place. In either case, returns the type.
+ ///
+ /// If not \a LLVMContext::isODRUniquingDebugTypes(), this function returns
+ /// nullptr.
+ static DICompositeType *
+ buildODRType(LLVMContext &Context, MDString &Identifier, unsigned Tag,
+ MDString *Name, Metadata *File, unsigned Line, Metadata *Scope,
+ Metadata *BaseType, uint64_t SizeInBits, uint64_t AlignInBits,
+ uint64_t OffsetInBits, unsigned Flags, Metadata *Elements,
+ unsigned RuntimeLang, Metadata *VTableHolder,
+ Metadata *TemplateParams);
+
DITypeRef getBaseType() const { return DITypeRef(getRawBaseType()); }
DINodeArray getElements() const {
return cast_or_null<MDTuple>(getRawElements());
@@ -866,14 +922,6 @@ public:
}
};
-template <class T> TypedDINodeRef<T> TypedDINodeRef<T>::get(const T *N) {
- if (N)
- if (auto *Composite = dyn_cast<DICompositeType>(N))
- if (auto *S = Composite->getRawIdentifier())
- return TypedDINodeRef<T>(S);
- return TypedDINodeRef<T>(N);
-}
-
/// \brief Type array for a subprogram.
///
/// TODO: Fold the array of types in directly as operands.
@@ -881,35 +929,44 @@ class DISubroutineType : public DIType {
friend class LLVMContextImpl;
friend class MDNode;
+ /// The calling convention used with DW_AT_calling_convention. Actually of
+ /// type dwarf::CallingConvention.
+ uint8_t CC;
+
DISubroutineType(LLVMContext &C, StorageType Storage, unsigned Flags,
- ArrayRef<Metadata *> Ops)
+ uint8_t CC, ArrayRef<Metadata *> Ops)
: DIType(C, DISubroutineTypeKind, Storage, dwarf::DW_TAG_subroutine_type,
- 0, 0, 0, 0, Flags, Ops) {}
+ 0, 0, 0, 0, Flags, Ops),
+ CC(CC) {}
~DISubroutineType() = default;
static DISubroutineType *getImpl(LLVMContext &Context, unsigned Flags,
- DITypeRefArray TypeArray,
+ uint8_t CC, DITypeRefArray TypeArray,
StorageType Storage,
bool ShouldCreate = true) {
- return getImpl(Context, Flags, TypeArray.get(), Storage, ShouldCreate);
+ return getImpl(Context, Flags, CC, TypeArray.get(), Storage, ShouldCreate);
}
static DISubroutineType *getImpl(LLVMContext &Context, unsigned Flags,
- Metadata *TypeArray, StorageType Storage,
+ uint8_t CC, Metadata *TypeArray,
+ StorageType Storage,
bool ShouldCreate = true);
TempDISubroutineType cloneImpl() const {
- return getTemporary(getContext(), getFlags(), getTypeArray());
+ return getTemporary(getContext(), getFlags(), getCC(), getTypeArray());
}
public:
DEFINE_MDNODE_GET(DISubroutineType,
- (unsigned Flags, DITypeRefArray TypeArray),
- (Flags, TypeArray))
- DEFINE_MDNODE_GET(DISubroutineType, (unsigned Flags, Metadata *TypeArray),
- (Flags, TypeArray))
+ (unsigned Flags, uint8_t CC, DITypeRefArray TypeArray),
+ (Flags, CC, TypeArray))
+ DEFINE_MDNODE_GET(DISubroutineType,
+ (unsigned Flags, uint8_t CC, Metadata *TypeArray),
+ (Flags, CC, TypeArray))
TempDISubroutineType clone() const { return cloneImpl(); }
+ uint8_t getCC() const { return CC; }
+
DITypeRefArray getTypeArray() const {
return cast_or_null<MDTuple>(getRawTypeArray());
}
@@ -924,7 +981,17 @@ public:
class DICompileUnit : public DIScope {
friend class LLVMContextImpl;
friend class MDNode;
+public:
+ enum DebugEmissionKind : unsigned {
+ NoDebug = 0,
+ FullDebug,
+ LineTablesOnly,
+ LastEmissionKind = LineTablesOnly
+ };
+ static Optional<DebugEmissionKind> getEmissionKind(StringRef Str);
+ static const char *EmissionKindString(DebugEmissionKind EK);
+private:
unsigned SourceLanguage;
bool IsOptimized;
unsigned RuntimeVersion;
@@ -947,33 +1014,30 @@ class DICompileUnit : public DIScope {
StringRef Producer, bool IsOptimized, StringRef Flags,
unsigned RuntimeVersion, StringRef SplitDebugFilename,
unsigned EmissionKind, DICompositeTypeArray EnumTypes,
- DITypeArray RetainedTypes, DISubprogramArray Subprograms,
- DIGlobalVariableArray GlobalVariables,
+ DIScopeArray RetainedTypes, DIGlobalVariableArray GlobalVariables,
DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros,
uint64_t DWOId, StorageType Storage, bool ShouldCreate = true) {
- return getImpl(Context, SourceLanguage, File,
- getCanonicalMDString(Context, Producer), IsOptimized,
- getCanonicalMDString(Context, Flags), RuntimeVersion,
- getCanonicalMDString(Context, SplitDebugFilename),
- EmissionKind, EnumTypes.get(), RetainedTypes.get(),
- Subprograms.get(), GlobalVariables.get(),
- ImportedEntities.get(), Macros.get(), DWOId, Storage,
- ShouldCreate);
+ return getImpl(
+ Context, SourceLanguage, File, getCanonicalMDString(Context, Producer),
+ IsOptimized, getCanonicalMDString(Context, Flags), RuntimeVersion,
+ getCanonicalMDString(Context, SplitDebugFilename), EmissionKind,
+ EnumTypes.get(), RetainedTypes.get(), GlobalVariables.get(),
+ ImportedEntities.get(), Macros.get(), DWOId, Storage, ShouldCreate);
}
static DICompileUnit *
getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File,
MDString *Producer, bool IsOptimized, MDString *Flags,
unsigned RuntimeVersion, MDString *SplitDebugFilename,
unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes,
- Metadata *Subprograms, Metadata *GlobalVariables,
- Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId,
- StorageType Storage, bool ShouldCreate = true);
+ Metadata *GlobalVariables, Metadata *ImportedEntities,
+ Metadata *Macros, uint64_t DWOId, StorageType Storage,
+ bool ShouldCreate = true);
TempDICompileUnit cloneImpl() const {
return getTemporary(
getContext(), getSourceLanguage(), getFile(), getProducer(),
isOptimized(), getFlags(), getRuntimeVersion(), getSplitDebugFilename(),
- getEmissionKind(), getEnumTypes(), getRetainedTypes(), getSubprograms(),
+ getEmissionKind(), getEnumTypes(), getRetainedTypes(),
getGlobalVariables(), getImportedEntities(), getMacros(), DWOId);
}
@@ -985,24 +1049,23 @@ public:
DICompileUnit,
(unsigned SourceLanguage, DIFile *File, StringRef Producer,
bool IsOptimized, StringRef Flags, unsigned RuntimeVersion,
- StringRef SplitDebugFilename, unsigned EmissionKind,
- DICompositeTypeArray EnumTypes, DITypeArray RetainedTypes,
- DISubprogramArray Subprograms, DIGlobalVariableArray GlobalVariables,
+ StringRef SplitDebugFilename, DebugEmissionKind EmissionKind,
+ DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes,
+ DIGlobalVariableArray GlobalVariables,
DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros,
uint64_t DWOId),
(SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion,
- SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, Subprograms,
+ SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes,
GlobalVariables, ImportedEntities, Macros, DWOId))
DEFINE_MDNODE_GET_DISTINCT_TEMPORARY(
DICompileUnit,
(unsigned SourceLanguage, Metadata *File, MDString *Producer,
bool IsOptimized, MDString *Flags, unsigned RuntimeVersion,
MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes,
- Metadata *RetainedTypes, Metadata *Subprograms,
- Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros,
- uint64_t DWOId),
+ Metadata *RetainedTypes, Metadata *GlobalVariables,
+ Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId),
(SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion,
- SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, Subprograms,
+ SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes,
GlobalVariables, ImportedEntities, Macros, DWOId))
TempDICompileUnit clone() const { return cloneImpl(); }
@@ -1010,19 +1073,18 @@ public:
unsigned getSourceLanguage() const { return SourceLanguage; }
bool isOptimized() const { return IsOptimized; }
unsigned getRuntimeVersion() const { return RuntimeVersion; }
- unsigned getEmissionKind() const { return EmissionKind; }
+ DebugEmissionKind getEmissionKind() const {
+ return (DebugEmissionKind)EmissionKind;
+ }
StringRef getProducer() const { return getStringOperand(1); }
StringRef getFlags() const { return getStringOperand(2); }
StringRef getSplitDebugFilename() const { return getStringOperand(3); }
DICompositeTypeArray getEnumTypes() const {
return cast_or_null<MDTuple>(getRawEnumTypes());
}
- DITypeArray getRetainedTypes() const {
+ DIScopeArray getRetainedTypes() const {
return cast_or_null<MDTuple>(getRawRetainedTypes());
}
- DISubprogramArray getSubprograms() const {
- return cast_or_null<MDTuple>(getRawSubprograms());
- }
DIGlobalVariableArray getGlobalVariables() const {
return cast_or_null<MDTuple>(getRawGlobalVariables());
}
@@ -1042,10 +1104,9 @@ public:
}
Metadata *getRawEnumTypes() const { return getOperand(4); }
Metadata *getRawRetainedTypes() const { return getOperand(5); }
- Metadata *getRawSubprograms() const { return getOperand(6); }
- Metadata *getRawGlobalVariables() const { return getOperand(7); }
- Metadata *getRawImportedEntities() const { return getOperand(8); }
- Metadata *getRawMacros() const { return getOperand(9); }
+ Metadata *getRawGlobalVariables() const { return getOperand(6); }
+ Metadata *getRawImportedEntities() const { return getOperand(7); }
+ Metadata *getRawMacros() const { return getOperand(8); }
/// \brief Replace arrays.
///
@@ -1059,16 +1120,13 @@ public:
void replaceRetainedTypes(DITypeArray N) {
replaceOperandWith(5, N.get());
}
- void replaceSubprograms(DISubprogramArray N) {
- replaceOperandWith(6, N.get());
- }
void replaceGlobalVariables(DIGlobalVariableArray N) {
- replaceOperandWith(7, N.get());
+ replaceOperandWith(6, N.get());
}
void replaceImportedEntities(DIImportedEntityArray N) {
- replaceOperandWith(8, N.get());
+ replaceOperandWith(7, N.get());
}
- void replaceMacros(DIMacroNodeArray N) { replaceOperandWith(9, N.get()); }
+ void replaceMacros(DIMacroNodeArray N) { replaceOperandWith(8, N.get()); }
/// @}
static bool classof(const Metadata *MD) {
@@ -1095,6 +1153,12 @@ public:
/// chain.
DISubprogram *getSubprogram() const;
+ /// Get the first non DILexicalBlockFile scope of this scope.
+ ///
+ /// Return this if it's not a \a DILexicalBlockFIle; otherwise, look up the
+ /// scope chain.
+ DILocalScope *getNonLexicalBlockFileScope() const;
+
static bool classof(const Metadata *MD) {
return MD->getMetadataID() == DISubprogramKind ||
MD->getMetadataID() == DILexicalBlockKind ||
@@ -1192,15 +1256,6 @@ public:
/// instructions that are on different basic blocks.
inline unsigned getDiscriminator() const;
- /// \brief Compute new discriminator in the given context.
- ///
- /// This modifies the \a LLVMContext that \c this is in to increment the next
- /// discriminator for \c this's line/filename combination.
- ///
- /// FIXME: Delete this. See comments in implementation and at the only call
- /// site in \a AddDiscriminators::runOnFunction().
- unsigned computeNewDiscriminator() const;
-
Metadata *getRawScope() const { return getOperand(0); }
Metadata *getRawInlinedAt() const {
if (getNumOperands() == 2)
@@ -1223,22 +1278,41 @@ class DISubprogram : public DILocalScope {
unsigned Line;
unsigned ScopeLine;
- unsigned Virtuality;
unsigned VirtualIndex;
- unsigned Flags;
- bool IsLocalToUnit;
- bool IsDefinition;
- bool IsOptimized;
+
+ /// In the MS ABI, the implicit 'this' parameter is adjusted in the prologue
+ /// of method overrides from secondary bases by this amount. It may be
+ /// negative.
+ int ThisAdjustment;
+
+ // Virtuality can only assume three values, so we can pack
+ // in 2 bits (none/pure/pure_virtual).
+ unsigned Virtuality : 2;
+
+ unsigned Flags : 27;
+
+ // These are boolean flags so one bit is enough.
+ // MSVC starts a new container field every time the base
+ // type changes so we can't use 'bool' to ensure these bits
+ // are packed.
+ unsigned IsLocalToUnit : 1;
+ unsigned IsDefinition : 1;
+ unsigned IsOptimized : 1;
DISubprogram(LLVMContext &C, StorageType Storage, unsigned Line,
unsigned ScopeLine, unsigned Virtuality, unsigned VirtualIndex,
- unsigned Flags, bool IsLocalToUnit, bool IsDefinition,
- bool IsOptimized, ArrayRef<Metadata *> Ops)
+ int ThisAdjustment, unsigned Flags, bool IsLocalToUnit,
+ bool IsDefinition, bool IsOptimized, ArrayRef<Metadata *> Ops)
: DILocalScope(C, DISubprogramKind, Storage, dwarf::DW_TAG_subprogram,
Ops),
- Line(Line), ScopeLine(ScopeLine), Virtuality(Virtuality),
- VirtualIndex(VirtualIndex), Flags(Flags), IsLocalToUnit(IsLocalToUnit),
- IsDefinition(IsDefinition), IsOptimized(IsOptimized) {}
+ Line(Line), ScopeLine(ScopeLine), VirtualIndex(VirtualIndex),
+ ThisAdjustment(ThisAdjustment), Virtuality(Virtuality), Flags(Flags),
+ IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition),
+ IsOptimized(IsOptimized) {
+ static_assert(dwarf::DW_VIRTUALITY_max < 4, "Virtuality out of range");
+ assert(Virtuality < 4 && "Virtuality out of range");
+ assert((Flags < (1 << 27)) && "Flags out of range");
+ }
~DISubprogram() = default;
static DISubprogram *
@@ -1246,32 +1320,34 @@ class DISubprogram : public DILocalScope {
StringRef LinkageName, DIFile *File, unsigned Line,
DISubroutineType *Type, bool IsLocalToUnit, bool IsDefinition,
unsigned ScopeLine, DITypeRef ContainingType, unsigned Virtuality,
- unsigned VirtualIndex, unsigned Flags, bool IsOptimized,
+ unsigned VirtualIndex, int ThisAdjustment, unsigned Flags,
+ bool IsOptimized, DICompileUnit *Unit,
DITemplateParameterArray TemplateParams, DISubprogram *Declaration,
DILocalVariableArray Variables, StorageType Storage,
bool ShouldCreate = true) {
return getImpl(Context, Scope, getCanonicalMDString(Context, Name),
getCanonicalMDString(Context, LinkageName), File, Line, Type,
IsLocalToUnit, IsDefinition, ScopeLine, ContainingType,
- Virtuality, VirtualIndex, Flags, IsOptimized,
- TemplateParams.get(), Declaration, Variables.get(), Storage,
- ShouldCreate);
+ Virtuality, VirtualIndex, ThisAdjustment, Flags, IsOptimized,
+ Unit, TemplateParams.get(), Declaration, Variables.get(),
+ Storage, ShouldCreate);
}
static DISubprogram *
getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name,
MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type,
bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine,
Metadata *ContainingType, unsigned Virtuality, unsigned VirtualIndex,
- unsigned Flags, bool IsOptimized, Metadata *TemplateParams,
- Metadata *Declaration, Metadata *Variables, StorageType Storage,
- bool ShouldCreate = true);
+ int ThisAdjustment, unsigned Flags, bool IsOptimized, Metadata *Unit,
+ Metadata *TemplateParams, Metadata *Declaration, Metadata *Variables,
+ StorageType Storage, bool ShouldCreate = true);
TempDISubprogram cloneImpl() const {
return getTemporary(
getContext(), getScope(), getName(), getLinkageName(), getFile(),
getLine(), getType(), isLocalToUnit(), isDefinition(), getScopeLine(),
- getContainingType(), getVirtuality(), getVirtualIndex(), getFlags(),
- isOptimized(), getTemplateParams(), getDeclaration(), getVariables());
+ getContainingType(), getVirtuality(), getVirtualIndex(),
+ getThisAdjustment(), getFlags(), isOptimized(), getUnit(),
+ getTemplateParams(), getDeclaration(), getVariables());
}
public:
@@ -1280,25 +1356,26 @@ public:
DIFile *File, unsigned Line, DISubroutineType *Type,
bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine,
DITypeRef ContainingType, unsigned Virtuality,
- unsigned VirtualIndex, unsigned Flags, bool IsOptimized,
+ unsigned VirtualIndex, int ThisAdjustment, unsigned Flags,
+ bool IsOptimized, DICompileUnit *Unit,
DITemplateParameterArray TemplateParams = nullptr,
DISubprogram *Declaration = nullptr,
DILocalVariableArray Variables = nullptr),
(Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit,
IsDefinition, ScopeLine, ContainingType, Virtuality,
- VirtualIndex, Flags, IsOptimized, TemplateParams,
- Declaration, Variables))
+ VirtualIndex, ThisAdjustment, Flags, IsOptimized, Unit,
+ TemplateParams, Declaration, Variables))
DEFINE_MDNODE_GET(
DISubprogram,
(Metadata * Scope, MDString *Name, MDString *LinkageName, Metadata *File,
unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition,
unsigned ScopeLine, Metadata *ContainingType, unsigned Virtuality,
- unsigned VirtualIndex, unsigned Flags, bool IsOptimized,
- Metadata *TemplateParams = nullptr, Metadata *Declaration = nullptr,
- Metadata *Variables = nullptr),
+ unsigned VirtualIndex, int ThisAdjustment, unsigned Flags,
+ bool IsOptimized, Metadata *Unit, Metadata *TemplateParams = nullptr,
+ Metadata *Declaration = nullptr, Metadata *Variables = nullptr),
(Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition,
- ScopeLine, ContainingType, Virtuality, VirtualIndex, Flags, IsOptimized,
- TemplateParams, Declaration, Variables))
+ ScopeLine, ContainingType, Virtuality, VirtualIndex, ThisAdjustment,
+ Flags, IsOptimized, Unit, TemplateParams, Declaration, Variables))
TempDISubprogram clone() const { return cloneImpl(); }
@@ -1306,6 +1383,7 @@ public:
unsigned getLine() const { return Line; }
unsigned getVirtuality() const { return Virtuality; }
unsigned getVirtualIndex() const { return VirtualIndex; }
+ int getThisAdjustment() const { return ThisAdjustment; }
unsigned getScopeLine() const { return ScopeLine; }
unsigned getFlags() const { return Flags; }
bool isLocalToUnit() const { return IsLocalToUnit; }
@@ -1357,6 +1435,12 @@ public:
return DITypeRef(getRawContainingType());
}
+ DICompileUnit *getUnit() const {
+ return cast_or_null<DICompileUnit>(getRawUnit());
+ }
+ void replaceUnit(DICompileUnit *CU) {
+ replaceOperandWith(7, CU);
+ }
DITemplateParameterArray getTemplateParams() const {
return cast_or_null<MDTuple>(getRawTemplateParams());
}
@@ -1370,9 +1454,10 @@ public:
Metadata *getRawScope() const { return getOperand(1); }
Metadata *getRawType() const { return getOperand(5); }
Metadata *getRawContainingType() const { return getOperand(6); }
- Metadata *getRawTemplateParams() const { return getOperand(7); }
- Metadata *getRawDeclaration() const { return getOperand(8); }
- Metadata *getRawVariables() const { return getOperand(9); }
+ Metadata *getRawUnit() const { return getOperand(7); }
+ Metadata *getRawTemplateParams() const { return getOperand(8); }
+ Metadata *getRawDeclaration() const { return getOperand(9); }
+ Metadata *getRawVariables() const { return getOperand(10); }
/// \brief Check if this subprogram describes the given function.
///
@@ -1852,13 +1937,16 @@ class DILocalVariable : public DIVariable {
friend class LLVMContextImpl;
friend class MDNode;
- unsigned Arg;
- unsigned Flags;
+ unsigned Arg : 16;
+ unsigned Flags : 16;
DILocalVariable(LLVMContext &C, StorageType Storage, unsigned Line,
unsigned Arg, unsigned Flags, ArrayRef<Metadata *> Ops)
: DIVariable(C, DILocalVariableKind, Storage, Line, Ops), Arg(Arg),
- Flags(Flags) {}
+ Flags(Flags) {
+ assert(Flags < (1 << 16) && "DILocalVariable: Flags out of range");
+ assert(Arg < (1 << 16) && "DILocalVariable: Arg out of range");
+ }
~DILocalVariable() = default;
static DILocalVariable *getImpl(LLVMContext &Context, DIScope *Scope,
diff --git a/include/llvm/IR/DerivedTypes.h b/include/llvm/IR/DerivedTypes.h
index 071e69b1e808..efd0d07366ee 100644
--- a/include/llvm/IR/DerivedTypes.h
+++ b/include/llvm/IR/DerivedTypes.h
@@ -61,15 +61,14 @@ public:
/// @brief Get the number of bits in this IntegerType
unsigned getBitWidth() const { return getSubclassData(); }
- /// getBitMask - Return a bitmask with ones set for all of the bits
- /// that can be set by an unsigned version of this type. This is 0xFF for
- /// i8, 0xFFFF for i16, etc.
+ /// Return a bitmask with ones set for all of the bits that can be set by an
+ /// unsigned version of this type. This is 0xFF for i8, 0xFFFF for i16, etc.
uint64_t getBitMask() const {
return ~uint64_t(0UL) >> (64-getBitWidth());
}
- /// getSignBit - Return a uint64_t with just the most significant bit set (the
- /// sign bit, if the value is treated as a signed number).
+ /// Return a uint64_t with just the most significant bit set (the sign bit, if
+ /// the value is treated as a signed number).
uint64_t getSignBit() const {
return 1ULL << (getBitWidth()-1);
}
@@ -95,7 +94,7 @@ unsigned Type::getIntegerBitWidth() const {
return cast<IntegerType>(this)->getBitWidth();
}
-/// FunctionType - Class to represent function types
+/// Class to represent function types
///
class FunctionType : public Type {
FunctionType(const FunctionType &) = delete;
@@ -103,22 +102,17 @@ class FunctionType : public Type {
FunctionType(Type *Result, ArrayRef<Type*> Params, bool IsVarArgs);
public:
- /// FunctionType::get - This static method is the primary way of constructing
- /// a FunctionType.
- ///
+ /// This static method is the primary way of constructing a FunctionType.
static FunctionType *get(Type *Result,
ArrayRef<Type*> Params, bool isVarArg);
- /// FunctionType::get - Create a FunctionType taking no parameters.
- ///
+ /// Create a FunctionType taking no parameters.
static FunctionType *get(Type *Result, bool isVarArg);
- /// isValidReturnType - Return true if the specified type is valid as a return
- /// type.
+ /// Return true if the specified type is valid as a return type.
static bool isValidReturnType(Type *RetTy);
- /// isValidArgumentType - Return true if the specified type is valid as an
- /// argument type.
+ /// Return true if the specified type is valid as an argument type.
static bool isValidArgumentType(Type *ArgTy);
bool isVarArg() const { return getSubclassData()!=0; }
@@ -134,9 +128,8 @@ public:
/// Parameter type accessors.
Type *getParamType(unsigned i) const { return ContainedTys[i+1]; }
- /// getNumParams - Return the number of fixed parameters this function type
- /// requires. This does not consider varargs.
- ///
+ /// Return the number of fixed parameters this function type requires.
+ /// This does not consider varargs.
unsigned getNumParams() const { return NumContainedTys - 1; }
/// Methods for support type inquiry through isa, cast, and dyn_cast.
@@ -159,16 +152,13 @@ unsigned Type::getFunctionNumParams() const {
return cast<FunctionType>(this)->getNumParams();
}
-/// CompositeType - Common super class of ArrayType, StructType, PointerType
-/// and VectorType.
+/// Common super class of ArrayType, StructType, PointerType and VectorType.
class CompositeType : public Type {
protected:
explicit CompositeType(LLVMContext &C, TypeID tid) : Type(C, tid) {}
public:
- /// getTypeAtIndex - Given an index value into the type, return the type of
- /// the element.
- ///
+ /// Given an index value into the type, return the type of the element.
Type *getTypeAtIndex(const Value *V) const;
Type *getTypeAtIndex(unsigned Idx) const;
bool indexValid(const Value *V) const;
@@ -183,8 +173,8 @@ public:
}
};
-/// StructType - Class to represent struct types. There are two different kinds
-/// of struct types: Literal structs and Identified structs.
+/// Class to represent struct types. There are two different kinds of struct
+/// types: Literal structs and Identified structs.
///
/// Literal struct types (e.g. { i32, i32 }) are uniqued structurally, and must
/// always have a body when created. You can get one of these by using one of
@@ -216,15 +206,14 @@ class StructType : public CompositeType {
SCDB_IsSized = 8
};
- /// SymbolTableEntry - For a named struct that actually has a name, this is a
- /// pointer to the symbol table entry (maintained by LLVMContext) for the
- /// struct. This is null if the type is an literal struct or if it is
- /// a identified type that has an empty name.
- ///
+ /// For a named struct that actually has a name, this is a pointer to the
+ /// symbol table entry (maintained by LLVMContext) for the struct.
+ /// This is null if the type is an literal struct or if it is a identified
+ /// type that has an empty name.
void *SymbolTableEntry;
public:
- /// StructType::create - This creates an identified struct.
+ /// This creates an identified struct.
static StructType *create(LLVMContext &Context, StringRef Name);
static StructType *create(LLVMContext &Context);
@@ -236,53 +225,48 @@ public:
static StructType *create(LLVMContext &Context, ArrayRef<Type *> Elements);
static StructType *create(StringRef Name, Type *elt1, ...) LLVM_END_WITH_NULL;
- /// StructType::get - This static method is the primary way to create a
- /// literal StructType.
+ /// This static method is the primary way to create a literal StructType.
static StructType *get(LLVMContext &Context, ArrayRef<Type*> Elements,
bool isPacked = false);
- /// StructType::get - Create an empty structure type.
- ///
+ /// Create an empty structure type.
static StructType *get(LLVMContext &Context, bool isPacked = false);
- /// StructType::get - This static method is a convenience method for creating
- /// structure types by specifying the elements as arguments. Note that this
- /// method always returns a non-packed struct, and requires at least one
- /// element type.
+ /// This static method is a convenience method for creating structure types by
+ /// specifying the elements as arguments. Note that this method always returns
+ /// a non-packed struct, and requires at least one element type.
static StructType *get(Type *elt1, ...) LLVM_END_WITH_NULL;
bool isPacked() const { return (getSubclassData() & SCDB_Packed) != 0; }
- /// isLiteral - Return true if this type is uniqued by structural
- /// equivalence, false if it is a struct definition.
+ /// Return true if this type is uniqued by structural equivalence, false if it
+ /// is a struct definition.
bool isLiteral() const { return (getSubclassData() & SCDB_IsLiteral) != 0; }
- /// isOpaque - Return true if this is a type with an identity that has no body
- /// specified yet. These prints as 'opaque' in .ll files.
+ /// Return true if this is a type with an identity that has no body specified
+ /// yet. These prints as 'opaque' in .ll files.
bool isOpaque() const { return (getSubclassData() & SCDB_HasBody) == 0; }
/// isSized - Return true if this is a sized type.
bool isSized(SmallPtrSetImpl<Type *> *Visited = nullptr) const;
- /// hasName - Return true if this is a named struct that has a non-empty name.
+ /// Return true if this is a named struct that has a non-empty name.
bool hasName() const { return SymbolTableEntry != nullptr; }
- /// getName - Return the name for this struct type if it has an identity.
+ /// Return the name for this struct type if it has an identity.
/// This may return an empty string for an unnamed struct type. Do not call
/// this on an literal type.
StringRef getName() const;
- /// setName - Change the name of this type to the specified name, or to a name
- /// with a suffix if there is a collision. Do not call this on an literal
- /// type.
+ /// Change the name of this type to the specified name, or to a name with a
+ /// suffix if there is a collision. Do not call this on an literal type.
void setName(StringRef Name);
- /// setBody - Specify a body for an opaque identified type.
+ /// Specify a body for an opaque identified type.
void setBody(ArrayRef<Type*> Elements, bool isPacked = false);
void setBody(Type *elt1, ...) LLVM_END_WITH_NULL;
- /// isValidElementType - Return true if the specified type is valid as a
- /// element type.
+ /// Return true if the specified type is valid as a element type.
static bool isValidElementType(Type *ElemTy);
// Iterator access to the elements.
@@ -293,8 +277,7 @@ public:
return makeArrayRef(element_begin(), element_end());
}
- /// isLayoutIdentical - Return true if this is layout identical to the
- /// specified struct.
+ /// Return true if this is layout identical to the specified struct.
bool isLayoutIdentical(StructType *Other) const;
/// Random access to the elements
@@ -322,14 +305,12 @@ Type *Type::getStructElementType(unsigned N) const {
return cast<StructType>(this)->getElementType(N);
}
-/// SequentialType - This is the superclass of the array, pointer and vector
-/// type classes. All of these represent "arrays" in memory. The array type
-/// represents a specifically sized array, pointer types are unsized/unknown
-/// size arrays, vector types represent specifically sized arrays that
-/// allow for use of SIMD instructions. SequentialType holds the common
-/// features of all, which stem from the fact that all three lay their
-/// components out in memory identically.
-///
+/// This is the superclass of the array, pointer and vector type classes.
+/// All of these represent "arrays" in memory. The array type represents a
+/// specifically sized array, pointer types are unsized/unknown size arrays,
+/// vector types represent specifically sized arrays that allow for use of SIMD
+/// instructions. SequentialType holds the common features of all, which stem
+/// from the fact that all three lay their components out in memory identically.
class SequentialType : public CompositeType {
Type *ContainedType; ///< Storage for the single contained type.
SequentialType(const SequentialType &) = delete;
@@ -343,7 +324,7 @@ protected:
}
public:
- Type *getElementType() const { return ContainedTys[0]; }
+ Type *getElementType() const { return getSequentialElementType(); }
/// Methods for support type inquiry through isa, cast, and dyn_cast.
static inline bool classof(const Type *T) {
@@ -353,12 +334,7 @@ public:
}
};
-Type *Type::getSequentialElementType() const {
- return cast<SequentialType>(this)->getElementType();
-}
-
-/// ArrayType - Class to represent array types.
-///
+/// Class to represent array types.
class ArrayType : public SequentialType {
uint64_t NumElements;
@@ -367,13 +343,10 @@ class ArrayType : public SequentialType {
ArrayType(Type *ElType, uint64_t NumEl);
public:
- /// ArrayType::get - This static method is the primary way to construct an
- /// ArrayType
- ///
+ /// This static method is the primary way to construct an ArrayType
static ArrayType *get(Type *ElementType, uint64_t NumElements);
- /// isValidElementType - Return true if the specified type is valid as a
- /// element type.
+ /// Return true if the specified type is valid as a element type.
static bool isValidElementType(Type *ElemTy);
uint64_t getNumElements() const { return NumElements; }
@@ -388,8 +361,7 @@ uint64_t Type::getArrayNumElements() const {
return cast<ArrayType>(this)->getNumElements();
}
-/// VectorType - Class to represent vector types.
-///
+/// Class to represent vector types.
class VectorType : public SequentialType {
unsigned NumElements;
@@ -398,15 +370,12 @@ class VectorType : public SequentialType {
VectorType(Type *ElType, unsigned NumEl);
public:
- /// VectorType::get - This static method is the primary way to construct an
- /// VectorType.
- ///
+ /// This static method is the primary way to construct an VectorType.
static VectorType *get(Type *ElementType, unsigned NumElements);
- /// VectorType::getInteger - This static method gets a VectorType with the
- /// same number of elements as the input type, and the element type is an
- /// integer type of the same width as the input element type.
- ///
+ /// This static method gets a VectorType with the same number of elements as
+ /// the input type, and the element type is an integer type of the same width
+ /// as the input element type.
static VectorType *getInteger(VectorType *VTy) {
unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits();
assert(EltBits && "Element size must be of a non-zero size");
@@ -414,20 +383,16 @@ public:
return VectorType::get(EltTy, VTy->getNumElements());
}
- /// VectorType::getExtendedElementVectorType - This static method is like
- /// getInteger except that the element types are twice as wide as the
- /// elements in the input type.
- ///
+ /// This static method is like getInteger except that the element types are
+ /// twice as wide as the elements in the input type.
static VectorType *getExtendedElementVectorType(VectorType *VTy) {
unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits();
Type *EltTy = IntegerType::get(VTy->getContext(), EltBits * 2);
return VectorType::get(EltTy, VTy->getNumElements());
}
- /// VectorType::getTruncatedElementVectorType - This static method is like
- /// getInteger except that the element types are half as wide as the
- /// elements in the input type.
- ///
+ /// This static method is like getInteger except that the element types are
+ /// half as wide as the elements in the input type.
static VectorType *getTruncatedElementVectorType(VectorType *VTy) {
unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits();
assert((EltBits & 1) == 0 &&
@@ -436,10 +401,8 @@ public:
return VectorType::get(EltTy, VTy->getNumElements());
}
- /// VectorType::getHalfElementsVectorType - This static method returns
- /// a VectorType with half as many elements as the input type and the
- /// same element type.
- ///
+ /// This static method returns a VectorType with half as many elements as the
+ /// input type and the same element type.
static VectorType *getHalfElementsVectorType(VectorType *VTy) {
unsigned NumElts = VTy->getNumElements();
assert ((NumElts & 1) == 0 &&
@@ -447,23 +410,20 @@ public:
return VectorType::get(VTy->getElementType(), NumElts/2);
}
- /// VectorType::getDoubleElementsVectorType - This static method returns
- /// a VectorType with twice as many elements as the input type and the
- /// same element type.
- ///
+ /// This static method returns a VectorType with twice as many elements as the
+ /// input type and the same element type.
static VectorType *getDoubleElementsVectorType(VectorType *VTy) {
unsigned NumElts = VTy->getNumElements();
return VectorType::get(VTy->getElementType(), NumElts*2);
}
- /// isValidElementType - Return true if the specified type is valid as a
- /// element type.
+ /// Return true if the specified type is valid as a element type.
static bool isValidElementType(Type *ElemTy);
- /// @brief Return the number of elements in the Vector type.
+ /// Return the number of elements in the Vector type.
unsigned getNumElements() const { return NumElements; }
- /// @brief Return the number of bits in the Vector type.
+ /// Return the number of bits in the Vector type.
/// Returns zero when the vector is a vector of pointers.
unsigned getBitWidth() const {
return NumElements * getElementType()->getPrimitiveSizeInBits();
@@ -479,32 +439,30 @@ unsigned Type::getVectorNumElements() const {
return cast<VectorType>(this)->getNumElements();
}
-/// PointerType - Class to represent pointers.
-///
+/// Class to represent pointers.
class PointerType : public SequentialType {
PointerType(const PointerType &) = delete;
const PointerType &operator=(const PointerType &) = delete;
explicit PointerType(Type *ElType, unsigned AddrSpace);
public:
- /// PointerType::get - This constructs a pointer to an object of the specified
- /// type in a numbered address space.
+ /// This constructs a pointer to an object of the specified type in a numbered
+ /// address space.
static PointerType *get(Type *ElementType, unsigned AddressSpace);
- /// PointerType::getUnqual - This constructs a pointer to an object of the
- /// specified type in the generic address space (address space zero).
+ /// This constructs a pointer to an object of the specified type in the
+ /// generic address space (address space zero).
static PointerType *getUnqual(Type *ElementType) {
return PointerType::get(ElementType, 0);
}
- /// isValidElementType - Return true if the specified type is valid as a
- /// element type.
+ /// Return true if the specified type is valid as a element type.
static bool isValidElementType(Type *ElemTy);
/// Return true if we can load or store from a pointer to this type.
static bool isLoadableOrStorableType(Type *ElemTy);
- /// @brief Return the address space of the Pointer type.
+ /// Return the address space of the Pointer type.
inline unsigned getAddressSpace() const { return getSubclassData(); }
/// Implement support type inquiry through isa, cast, and dyn_cast.
diff --git a/include/llvm/IR/DiagnosticInfo.h b/include/llvm/IR/DiagnosticInfo.h
index f69955e5ed48..1c78684da64d 100644
--- a/include/llvm/IR/DiagnosticInfo.h
+++ b/include/llvm/IR/DiagnosticInfo.h
@@ -1,4 +1,4 @@
-//===- llvm/Support/DiagnosticInfo.h - Diagnostic Declaration ---*- C++ -*-===//
+//===- llvm/IR/DiagnosticInfo.h - Diagnostic Declaration --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,11 +15,14 @@
#ifndef LLVM_IR_DIAGNOSTICINFO_H
#define LLVM_IR_DIAGNOSTICINFO_H
-#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/IR/DebugLoc.h"
-#include "llvm/IR/Module.h"
-#include "llvm/Support/Casting.h"
+#include "llvm/Support/CBindingWrapping.h"
+#include "llvm-c/Types.h"
#include <functional>
+#include <string>
namespace llvm {
@@ -27,14 +30,12 @@ namespace llvm {
class DiagnosticPrinter;
class Function;
class Instruction;
-class LLVMContextImpl;
-class Twine;
-class Value;
-class DebugLoc;
+class LLVMContext;
+class Module;
class SMDiagnostic;
/// \brief Defines the different supported severity of a diagnostic.
-enum DiagnosticSeverity {
+enum DiagnosticSeverity : char {
DS_Error,
DS_Warning,
DS_Remark,
@@ -48,9 +49,11 @@ enum DiagnosticSeverity {
enum DiagnosticKind {
DK_Bitcode,
DK_InlineAsm,
+ DK_ResourceLimit,
DK_StackSize,
DK_Linker,
DK_DebugMetadataVersion,
+ DK_DebugMetadataInvalid,
DK_SampleProfile,
DK_OptimizationRemark,
DK_OptimizationRemarkMissed,
@@ -58,8 +61,11 @@ enum DiagnosticKind {
DK_OptimizationRemarkAnalysisFPCommute,
DK_OptimizationRemarkAnalysisAliasing,
DK_OptimizationFailure,
+ DK_FirstRemark = DK_OptimizationRemark,
+ DK_LastRemark = DK_OptimizationFailure,
DK_MIRParser,
DK_PGOProfile,
+ DK_Unsupported,
DK_FirstPluginKind
};
@@ -101,8 +107,6 @@ public:
/// The printed message must not end with '.' nor start with a severity
/// keyword.
virtual void print(DiagnosticPrinter &DP) const = 0;
-
- static const char *AlwaysPrint;
};
typedef std::function<void(const DiagnosticInfo &)> DiagnosticHandlerFunction;
@@ -156,29 +160,64 @@ public:
}
};
-/// Diagnostic information for stack size reporting.
+/// Diagnostic information for stack size etc. reporting.
/// This is basically a function and a size.
-class DiagnosticInfoStackSize : public DiagnosticInfo {
+class DiagnosticInfoResourceLimit : public DiagnosticInfo {
private:
- /// The function that is concerned by this stack size diagnostic.
+ /// The function that is concerned by this resource limit diagnostic.
const Function &Fn;
- /// The computed stack size.
- unsigned StackSize;
+
+ /// Description of the resource type (e.g. stack size)
+ const char *ResourceName;
+
+ /// The computed size usage
+ uint64_t ResourceSize;
+
+ // Threshould passed
+ uint64_t ResourceLimit;
public:
/// \p The function that is concerned by this stack size diagnostic.
/// \p The computed stack size.
- DiagnosticInfoStackSize(const Function &Fn, unsigned StackSize,
- DiagnosticSeverity Severity = DS_Warning)
- : DiagnosticInfo(DK_StackSize, Severity), Fn(Fn), StackSize(StackSize) {}
+ DiagnosticInfoResourceLimit(const Function &Fn,
+ const char *ResourceName,
+ uint64_t ResourceSize,
+ DiagnosticSeverity Severity = DS_Warning,
+ DiagnosticKind Kind = DK_ResourceLimit,
+ uint64_t ResourceLimit = 0)
+ : DiagnosticInfo(Kind, Severity),
+ Fn(Fn),
+ ResourceName(ResourceName),
+ ResourceSize(ResourceSize),
+ ResourceLimit(ResourceLimit) {}
const Function &getFunction() const { return Fn; }
- unsigned getStackSize() const { return StackSize; }
+ const char *getResourceName() const { return ResourceName; }
+ uint64_t getResourceSize() const { return ResourceSize; }
+ uint64_t getResourceLimit() const { return ResourceLimit; }
/// \see DiagnosticInfo::print.
void print(DiagnosticPrinter &DP) const override;
static bool classof(const DiagnosticInfo *DI) {
+ return DI->getKind() == DK_ResourceLimit ||
+ DI->getKind() == DK_StackSize;
+ }
+};
+
+class DiagnosticInfoStackSize : public DiagnosticInfoResourceLimit {
+public:
+ DiagnosticInfoStackSize(const Function &Fn,
+ uint64_t StackSize,
+ DiagnosticSeverity Severity = DS_Warning,
+ uint64_t StackLimit = 0)
+ : DiagnosticInfoResourceLimit(Fn, "stack size", StackSize,
+ Severity, DK_StackSize, StackLimit) {}
+
+ uint64_t getStackSize() const { return getResourceSize(); }
+ uint64_t getStackLimit() const { return getResourceLimit(); }
+
+ static bool classof(const DiagnosticInfo *DI) {
return DI->getKind() == DK_StackSize;
}
};
@@ -211,6 +250,29 @@ public:
}
};
+/// Diagnostic information for stripping invalid debug metadata.
+class DiagnosticInfoIgnoringInvalidDebugMetadata : public DiagnosticInfo {
+private:
+ /// The module that is concerned by this debug metadata version diagnostic.
+ const Module &M;
+
+public:
+ /// \p The module that is concerned by this debug metadata version diagnostic.
+ DiagnosticInfoIgnoringInvalidDebugMetadata(
+ const Module &M, DiagnosticSeverity Severity = DS_Warning)
+ : DiagnosticInfo(DK_DebugMetadataVersion, Severity), M(M) {}
+
+ const Module &getModule() const { return M; }
+
+ /// \see DiagnosticInfo::print.
+ void print(DiagnosticPrinter &DP) const override;
+
+ static bool classof(const DiagnosticInfo *DI) {
+ return DI->getKind() == DK_DebugMetadataInvalid;
+ }
+};
+
+
/// Diagnostic information for the sample profiler.
class DiagnosticInfoSampleProfile : public DiagnosticInfo {
public:
@@ -275,8 +337,42 @@ private:
const Twine &Msg;
};
+/// Common features for diagnostics with an associated DebugLoc
+class DiagnosticInfoWithDebugLocBase : public DiagnosticInfo {
+public:
+ /// \p Fn is the function where the diagnostic is being emitted. \p DLoc is
+ /// the location information to use in the diagnostic.
+ DiagnosticInfoWithDebugLocBase(enum DiagnosticKind Kind,
+ enum DiagnosticSeverity Severity,
+ const Function &Fn,
+ const DebugLoc &DLoc)
+ : DiagnosticInfo(Kind, Severity), Fn(Fn), DLoc(DLoc) {}
+
+ /// Return true if location information is available for this diagnostic.
+ bool isLocationAvailable() const;
+
+ /// Return a string with the location information for this diagnostic
+ /// in the format "file:line:col". If location information is not available,
+ /// it returns "<unknown>:0:0".
+ const std::string getLocationStr() const;
+
+ /// Return location information for this diagnostic in three parts:
+ /// the source file name, line number and column.
+ void getLocation(StringRef *Filename, unsigned *Line, unsigned *Column) const;
+
+ const Function &getFunction() const { return Fn; }
+ const DebugLoc &getDebugLoc() const { return DLoc; }
+
+private:
+ /// Function where this diagnostic is triggered.
+ const Function &Fn;
+
+ /// Debug location where this diagnostic is triggered.
+ DebugLoc DLoc;
+};
+
/// Common features for diagnostics dealing with optimization remarks.
-class DiagnosticInfoOptimizationBase : public DiagnosticInfo {
+class DiagnosticInfoOptimizationBase : public DiagnosticInfoWithDebugLocBase {
public:
/// \p PassName is the name of the pass emitting this diagnostic.
/// \p Fn is the function where the diagnostic is being emitted. \p DLoc is
@@ -288,9 +384,10 @@ public:
DiagnosticInfoOptimizationBase(enum DiagnosticKind Kind,
enum DiagnosticSeverity Severity,
const char *PassName, const Function &Fn,
- const DebugLoc &DLoc, const Twine &Msg)
- : DiagnosticInfo(Kind, Severity), PassName(PassName), Fn(Fn), DLoc(DLoc),
- Msg(Msg) {}
+ const DebugLoc &DLoc, const Twine &Msg,
+ Optional<uint64_t> Hotness = None)
+ : DiagnosticInfoWithDebugLocBase(Kind, Severity, Fn, DLoc),
+ PassName(PassName), Msg(Msg), Hotness(Hotness) {}
/// \see DiagnosticInfo::print.
void print(DiagnosticPrinter &DP) const override;
@@ -302,37 +399,26 @@ public:
/// in BackendConsumer::OptimizationRemarkHandler).
virtual bool isEnabled() const = 0;
- /// Return true if location information is available for this diagnostic.
- bool isLocationAvailable() const;
-
- /// Return a string with the location information for this diagnostic
- /// in the format "file:line:col". If location information is not available,
- /// it returns "<unknown>:0:0".
- const std::string getLocationStr() const;
-
- /// Return location information for this diagnostic in three parts:
- /// the source file name, line number and column.
- void getLocation(StringRef *Filename, unsigned *Line, unsigned *Column) const;
-
const char *getPassName() const { return PassName; }
- const Function &getFunction() const { return Fn; }
- const DebugLoc &getDebugLoc() const { return DLoc; }
const Twine &getMsg() const { return Msg; }
+ static bool classof(const DiagnosticInfo *DI) {
+ return DI->getKind() >= DK_FirstRemark &&
+ DI->getKind() <= DK_LastRemark;
+ }
+
private:
/// Name of the pass that triggers this report. If this matches the
/// regular expression given in -Rpass=regexp, then the remark will
/// be emitted.
const char *PassName;
- /// Function where this diagnostic is triggered.
- const Function &Fn;
-
- /// Debug location where this diagnostic is triggered.
- DebugLoc DLoc;
-
/// Message to report.
const Twine &Msg;
+
+ /// If profile information is available, this is the number of times the
+ /// corresponding code was executed in a profile instrumentation run.
+ Optional<uint64_t> Hotness;
};
/// Diagnostic information for applied optimization remarks.
@@ -373,9 +459,10 @@ public:
/// must be valid for the whole life time of the diagnostic.
DiagnosticInfoOptimizationRemarkMissed(const char *PassName,
const Function &Fn,
- const DebugLoc &DLoc, const Twine &Msg)
+ const DebugLoc &DLoc, const Twine &Msg,
+ Optional<uint64_t> Hotness = None)
: DiagnosticInfoOptimizationBase(DK_OptimizationRemarkMissed, DS_Remark,
- PassName, Fn, DLoc, Msg) {}
+ PassName, Fn, DLoc, Msg, Hotness) {}
static bool classof(const DiagnosticInfo *DI) {
return DI->getKind() == DK_OptimizationRemarkMissed;
@@ -411,6 +498,10 @@ public:
/// \see DiagnosticInfoOptimizationBase::isEnabled.
bool isEnabled() const override;
+ static const char *AlwaysPrint;
+
+ bool shouldAlwaysPrint() const { return getPassName() == AlwaysPrint; }
+
protected:
DiagnosticInfoOptimizationRemarkAnalysis(enum DiagnosticKind Kind,
const char *PassName,
@@ -572,6 +663,34 @@ public:
bool isEnabled() const override;
};
+/// Diagnostic information for unsupported feature in backend.
+class DiagnosticInfoUnsupported
+ : public DiagnosticInfoWithDebugLocBase {
+private:
+ Twine Msg;
+
+public:
+ /// \p Fn is the function where the diagnostic is being emitted. \p DLoc is
+ /// the location information to use in the diagnostic. If line table
+ /// information is available, the diagnostic will include the source code
+ /// location. \p Msg is the message to show. Note that this class does not
+ /// copy this message, so this reference must be valid for the whole life time
+ /// of the diagnostic.
+ DiagnosticInfoUnsupported(const Function &Fn, const Twine &Msg,
+ DebugLoc DLoc = DebugLoc(),
+ DiagnosticSeverity Severity = DS_Error)
+ : DiagnosticInfoWithDebugLocBase(DK_Unsupported, Severity, Fn, DLoc),
+ Msg(Msg) {}
+
+ static bool classof(const DiagnosticInfo *DI) {
+ return DI->getKind() == DK_Unsupported;
+ }
+
+ const Twine &getMessage() const { return Msg; }
+
+ void print(DiagnosticPrinter &DP) const override;
+};
+
/// Emit a warning when loop vectorization is specified but fails. \p Fn is the
/// function triggering the warning, \p DLoc is the debug location where the
/// diagnostic is generated. \p Msg is the message string to use.
@@ -584,6 +703,6 @@ void emitLoopVectorizeWarning(LLVMContext &Ctx, const Function &Fn,
void emitLoopInterleaveWarning(LLVMContext &Ctx, const Function &Fn,
const DebugLoc &DLoc, const Twine &Msg);
-} // End namespace llvm
+} // end namespace llvm
-#endif
+#endif // LLVM_IR_DIAGNOSTICINFO_H
diff --git a/include/llvm/IR/Dominators.h b/include/llvm/IR/Dominators.h
index 37447c353b19..f445a49b67b8 100644
--- a/include/llvm/IR/Dominators.h
+++ b/include/llvm/IR/Dominators.h
@@ -15,26 +15,19 @@
#ifndef LLVM_IR_DOMINATORS_H
#define LLVM_IR_DOMINATORS_H
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/DepthFirstIterator.h"
+#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CFG.h"
-#include "llvm/IR/Function.h"
+#include "llvm/IR/PassManager.h"
#include "llvm/Pass.h"
-#include "llvm/Support/Compiler.h"
#include "llvm/Support/GenericDomTree.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
namespace llvm {
-// FIXME: Replace this brittle forward declaration with the include of the new
-// PassManager.h when doing so doesn't break the PassManagerBuilder.
-template <typename IRUnitT> class AnalysisManager;
-class PreservedAnalyses;
+class Function;
+class BasicBlock;
+class raw_ostream;
extern template class DomTreeNodeBase<BasicBlock>;
extern template class DominatorTreeBase<BasicBlock>;
@@ -62,6 +55,26 @@ public:
bool isSingleEdge() const;
};
+template <> struct DenseMapInfo<BasicBlockEdge> {
+ static unsigned getHashValue(const BasicBlockEdge *V);
+ typedef DenseMapInfo<const BasicBlock *> BBInfo;
+ static inline BasicBlockEdge getEmptyKey() {
+ return BasicBlockEdge(BBInfo::getEmptyKey(), BBInfo::getEmptyKey());
+ }
+ static inline BasicBlockEdge getTombstoneKey() {
+ return BasicBlockEdge(BBInfo::getTombstoneKey(), BBInfo::getTombstoneKey());
+ }
+
+ static unsigned getHashValue(const BasicBlockEdge &Edge) {
+ return hash_combine(BBInfo::getHashValue(Edge.getStart()),
+ BBInfo::getHashValue(Edge.getEnd()));
+ }
+ static bool isEqual(const BasicBlockEdge &LHS, const BasicBlockEdge &RHS) {
+ return BBInfo::isEqual(LHS.getStart(), RHS.getStart()) &&
+ BBInfo::isEqual(LHS.getEnd(), RHS.getEnd());
+ }
+};
+
/// \brief Concrete subclass of DominatorTreeBase that is used to compute a
/// normal dominator tree.
///
@@ -186,40 +199,31 @@ template <> struct GraphTraits<DominatorTree*>
};
/// \brief Analysis pass which computes a \c DominatorTree.
-class DominatorTreeAnalysis {
+class DominatorTreeAnalysis : public AnalysisInfoMixin<DominatorTreeAnalysis> {
+ friend AnalysisInfoMixin<DominatorTreeAnalysis>;
+ static char PassID;
+
public:
/// \brief Provide the result typedef for this analysis pass.
typedef DominatorTree Result;
- /// \brief Opaque, unique identifier for this analysis pass.
- static void *ID() { return (void *)&PassID; }
-
/// \brief Run the analysis pass over a function and produce a dominator tree.
- DominatorTree run(Function &F);
-
- /// \brief Provide access to a name for this pass for debugging purposes.
- static StringRef name() { return "DominatorTreeAnalysis"; }
-
-private:
- static char PassID;
+ DominatorTree run(Function &F, AnalysisManager<Function> &);
};
/// \brief Printer pass for the \c DominatorTree.
-class DominatorTreePrinterPass {
+class DominatorTreePrinterPass
+ : public PassInfoMixin<DominatorTreePrinterPass> {
raw_ostream &OS;
public:
explicit DominatorTreePrinterPass(raw_ostream &OS);
- PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM);
-
- static StringRef name() { return "DominatorTreePrinterPass"; }
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
};
/// \brief Verifier pass for the \c DominatorTree.
-struct DominatorTreeVerifierPass {
- PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM);
-
- static StringRef name() { return "DominatorTreeVerifierPass"; }
+struct DominatorTreeVerifierPass : PassInfoMixin<DominatorTreeVerifierPass> {
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
};
/// \brief Legacy analysis pass which computes a \c DominatorTree.
diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h
index 4f64caeade20..d7d27e7585c1 100644
--- a/include/llvm/IR/Function.h
+++ b/include/llvm/IR/Function.h
@@ -19,7 +19,6 @@
#define LLVM_IR_FUNCTION_H
#include "llvm/ADT/iterator_range.h"
-#include "llvm/ADT/Optional.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/BasicBlock.h"
@@ -30,6 +29,7 @@
namespace llvm {
+template <typename T> class Optional;
class FunctionType;
class LLVMContext;
class DISubprogram;
@@ -56,7 +56,6 @@ private:
mutable ArgumentListType ArgumentList; ///< The formal arguments
ValueSymbolTable *SymTab; ///< Symbol table of args/instructions
AttributeSet AttributeSets; ///< Parameter attributes
- FunctionType *Ty;
/*
* Value::SubclassData
@@ -73,13 +72,8 @@ private:
/// Bits from GlobalObject::GlobalObjectSubclassData.
enum {
/// Whether this function is materializable.
- IsMaterializableBit = 1 << 0,
- HasMetadataHashEntryBit = 1 << 1
+ IsMaterializableBit = 0,
};
- void setGlobalObjectBit(unsigned Mask, bool Value) {
- setGlobalObjectSubClassData((~Mask & getGlobalObjectSubClassData()) |
- (Value ? Mask : 0u));
- }
friend class SymbolTableListTraits<Function>;
@@ -89,9 +83,12 @@ private:
/// built on demand, so that the list isn't allocated until the first client
/// needs it. The hasLazyArguments predicate returns true if the arg list
/// hasn't been set up yet.
+public:
bool hasLazyArguments() const {
return getSubclassDataFromValue() & (1<<0);
}
+
+private:
void CheckLazyArguments() const {
if (hasLazyArguments())
BuildLazyArguments();
@@ -166,7 +163,7 @@ public:
AttributeSet getAttributes() const { return AttributeSets; }
/// @brief Set the attribute list for this Function.
- void setAttributes(AttributeSet attrs) { AttributeSets = attrs; }
+ void setAttributes(AttributeSet Attrs) { AttributeSets = Attrs; }
/// @brief Add function attributes to this function.
void addFnAttr(Attribute::AttrKind N) {
@@ -175,9 +172,9 @@ public:
}
/// @brief Remove function attributes from this function.
- void removeFnAttr(Attribute::AttrKind N) {
+ void removeFnAttr(Attribute::AttrKind Kind) {
setAttributes(AttributeSets.removeAttribute(
- getContext(), AttributeSet::FunctionIndex, N));
+ getContext(), AttributeSet::FunctionIndex, Kind));
}
/// @brief Add function attributes to this function.
@@ -200,7 +197,7 @@ public:
/// @brief Return true if the function has the attribute.
bool hasFnAttribute(Attribute::AttrKind Kind) const {
- return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Kind);
+ return AttributeSets.hasFnAttribute(Kind);
}
bool hasFnAttribute(StringRef Kind) const {
return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Kind);
@@ -208,14 +205,16 @@ public:
/// @brief Return the attribute for the given attribute kind.
Attribute getFnAttribute(Attribute::AttrKind Kind) const {
- return AttributeSets.getAttribute(AttributeSet::FunctionIndex, Kind);
+ return getAttribute(AttributeSet::FunctionIndex, Kind);
}
Attribute getFnAttribute(StringRef Kind) const {
- return AttributeSets.getAttribute(AttributeSet::FunctionIndex, Kind);
+ return getAttribute(AttributeSet::FunctionIndex, Kind);
}
/// \brief Return the stack alignment for the function.
unsigned getFnStackAlignment() const {
+ if (!hasFnAttribute(Attribute::StackAlignment))
+ return 0;
return AttributeSets.getStackAlignment(AttributeSet::FunctionIndex);
}
@@ -225,17 +224,39 @@ public:
return getSubclassDataFromValue() & (1<<14);
}
const std::string &getGC() const;
- void setGC(const std::string Str);
+ void setGC(std::string Str);
void clearGC();
/// @brief adds the attribute to the list of attributes.
- void addAttribute(unsigned i, Attribute::AttrKind attr);
+ void addAttribute(unsigned i, Attribute::AttrKind Kind);
+
+ /// @brief adds the attribute to the list of attributes.
+ void addAttribute(unsigned i, Attribute Attr);
/// @brief adds the attributes to the list of attributes.
- void addAttributes(unsigned i, AttributeSet attrs);
+ void addAttributes(unsigned i, AttributeSet Attrs);
+
+ /// @brief removes the attribute from the list of attributes.
+ void removeAttribute(unsigned i, Attribute::AttrKind Kind);
+
+ /// @brief removes the attribute from the list of attributes.
+ void removeAttribute(unsigned i, StringRef Kind);
/// @brief removes the attributes from the list of attributes.
- void removeAttributes(unsigned i, AttributeSet attr);
+ void removeAttributes(unsigned i, AttributeSet Attrs);
+
+ /// @brief check if an attributes is in the list of attributes.
+ bool hasAttribute(unsigned i, Attribute::AttrKind Kind) const {
+ return getAttributes().hasAttribute(i, Kind);
+ }
+
+ Attribute getAttribute(unsigned i, Attribute::AttrKind Kind) const {
+ return AttributeSets.getAttribute(i, Kind);
+ }
+
+ Attribute getAttribute(unsigned i, StringRef Kind) const {
+ return AttributeSets.getAttribute(i, Kind);
+ }
/// @brief adds the dereferenceable attribute to the list of attributes.
void addDereferenceableAttr(unsigned i, uint64_t Bytes);
@@ -263,8 +284,7 @@ public:
/// @brief Determine if the function does not access memory.
bool doesNotAccessMemory() const {
- return AttributeSets.hasAttribute(AttributeSet::FunctionIndex,
- Attribute::ReadNone);
+ return hasFnAttribute(Attribute::ReadNone);
}
void setDoesNotAccessMemory() {
addFnAttr(Attribute::ReadNone);
@@ -272,27 +292,31 @@ public:
/// @brief Determine if the function does not access or only reads memory.
bool onlyReadsMemory() const {
- return doesNotAccessMemory() ||
- AttributeSets.hasAttribute(AttributeSet::FunctionIndex,
- Attribute::ReadOnly);
+ return doesNotAccessMemory() || hasFnAttribute(Attribute::ReadOnly);
}
void setOnlyReadsMemory() {
addFnAttr(Attribute::ReadOnly);
}
+ /// @brief Determine if the function does not access or only writes memory.
+ bool doesNotReadMemory() const {
+ return doesNotAccessMemory() || hasFnAttribute(Attribute::WriteOnly);
+ }
+ void setDoesNotReadMemory() {
+ addFnAttr(Attribute::WriteOnly);
+ }
+
/// @brief Determine if the call can access memmory only using pointers based
/// on its arguments.
bool onlyAccessesArgMemory() const {
- return AttributeSets.hasAttribute(AttributeSet::FunctionIndex,
- Attribute::ArgMemOnly);
+ return hasFnAttribute(Attribute::ArgMemOnly);
}
void setOnlyAccessesArgMemory() { addFnAttr(Attribute::ArgMemOnly); }
/// @brief Determine if the function may only access memory that is
/// inaccessible from the IR.
bool onlyAccessesInaccessibleMemory() const {
- return AttributeSets.hasAttribute(AttributeSet::FunctionIndex,
- Attribute::InaccessibleMemOnly);
+ return hasFnAttribute(Attribute::InaccessibleMemOnly);
}
void setOnlyAccessesInaccessibleMemory() {
addFnAttr(Attribute::InaccessibleMemOnly);
@@ -301,8 +325,7 @@ public:
/// @brief Determine if the function may only access memory that is
// either inaccessible from the IR or pointed to by its arguments.
bool onlyAccessesInaccessibleMemOrArgMem() const {
- return AttributeSets.hasAttribute(AttributeSet::FunctionIndex,
- Attribute::InaccessibleMemOrArgMemOnly);
+ return hasFnAttribute(Attribute::InaccessibleMemOrArgMemOnly);
}
void setOnlyAccessesInaccessibleMemOrArgMem() {
addFnAttr(Attribute::InaccessibleMemOrArgMemOnly);
@@ -310,8 +333,7 @@ public:
/// @brief Determine if the function cannot return.
bool doesNotReturn() const {
- return AttributeSets.hasAttribute(AttributeSet::FunctionIndex,
- Attribute::NoReturn);
+ return hasFnAttribute(Attribute::NoReturn);
}
void setDoesNotReturn() {
addFnAttr(Attribute::NoReturn);
@@ -319,8 +341,7 @@ public:
/// @brief Determine if the function cannot unwind.
bool doesNotThrow() const {
- return AttributeSets.hasAttribute(AttributeSet::FunctionIndex,
- Attribute::NoUnwind);
+ return hasFnAttribute(Attribute::NoUnwind);
}
void setDoesNotThrow() {
addFnAttr(Attribute::NoUnwind);
@@ -328,8 +349,7 @@ public:
/// @brief Determine if the call cannot be duplicated.
bool cannotDuplicate() const {
- return AttributeSets.hasAttribute(AttributeSet::FunctionIndex,
- Attribute::NoDuplicate);
+ return hasFnAttribute(Attribute::NoDuplicate);
}
void setCannotDuplicate() {
addFnAttr(Attribute::NoDuplicate);
@@ -337,18 +357,19 @@ public:
/// @brief Determine if the call is convergent.
bool isConvergent() const {
- return AttributeSets.hasAttribute(AttributeSet::FunctionIndex,
- Attribute::Convergent);
+ return hasFnAttribute(Attribute::Convergent);
}
void setConvergent() {
addFnAttr(Attribute::Convergent);
}
+ void setNotConvergent() {
+ removeFnAttr(Attribute::Convergent);
+ }
/// Determine if the function is known not to recurse, directly or
/// indirectly.
bool doesNotRecurse() const {
- return AttributeSets.hasAttribute(AttributeSet::FunctionIndex,
- Attribute::NoRecurse);
+ return hasFnAttribute(Attribute::NoRecurse);
}
void setDoesNotRecurse() {
addFnAttr(Attribute::NoRecurse);
@@ -357,8 +378,7 @@ public:
/// @brief True if the ABI mandates (or the user requested) that this
/// function be in a unwind table.
bool hasUWTable() const {
- return AttributeSets.hasAttribute(AttributeSet::FunctionIndex,
- Attribute::UWTable);
+ return hasFnAttribute(Attribute::UWTable);
}
void setHasUWTable() {
addFnAttr(Attribute::UWTable);
@@ -440,6 +460,12 @@ public:
///
void eraseFromParent() override;
+ /// Steal arguments from another function.
+ ///
+ /// Drop this function's arguments and splice in the ones from \c Src.
+ /// Requires that this has no function body.
+ void stealArgumentListFrom(Function &Src);
+
/// Get the underlying elements of the Function... the basic block list is
/// empty for external functions.
///
@@ -547,6 +573,12 @@ public:
Constant *getPrologueData() const;
void setPrologueData(Constant *PrologueData);
+ /// Print the function to an output stream with an optional
+ /// AssemblyAnnotationWriter.
+ void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW = nullptr,
+ bool ShouldPreserveUseListOrder = false,
+ bool IsForDebug = false) const;
+
/// viewCFG - This function is meant for use from the debugger. You can just
/// say 'call F->viewCFG()' and a ghostview window should pop up from the
/// program, displaying the CFG of the current function with the code for each
@@ -597,35 +629,6 @@ public:
/// setjmp or other function that gcc recognizes as "returning twice".
bool callsFunctionThatReturnsTwice() const;
- /// \brief Check if this has any metadata.
- bool hasMetadata() const { return hasMetadataHashEntry(); }
-
- /// \brief Get the current metadata attachment, if any.
- ///
- /// Returns \c nullptr if such an attachment is missing.
- /// @{
- MDNode *getMetadata(unsigned KindID) const;
- MDNode *getMetadata(StringRef Kind) const;
- /// @}
-
- /// \brief Set a particular kind of metadata attachment.
- ///
- /// Sets the given attachment to \c MD, erasing it if \c MD is \c nullptr or
- /// replacing it if it already exists.
- /// @{
- void setMetadata(unsigned KindID, MDNode *MD);
- void setMetadata(StringRef Kind, MDNode *MD);
- /// @}
-
- /// \brief Get all current metadata attachments.
- void
- getAllMetadata(SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const;
-
- /// \brief Drop metadata not in the given list.
- ///
- /// Drop all metadata from \c this not included in \c KnownIDs.
- void dropUnknownMetadata(ArrayRef<unsigned> KnownIDs);
-
/// \brief Set the attached subprogram.
///
/// Calls \a setMetadata() with \a LLVMContext::MD_dbg.
@@ -647,15 +650,6 @@ private:
Value::setValueSubclassData(D);
}
void setValueSubclassDataBit(unsigned Bit, bool On);
-
- bool hasMetadataHashEntry() const {
- return getGlobalObjectSubClassData() & HasMetadataHashEntryBit;
- }
- void setHasMetadataHashEntry(bool HasEntry) {
- setGlobalObjectBit(HasMetadataHashEntryBit, HasEntry);
- }
-
- void clearMetadata();
};
template <>
diff --git a/include/llvm/IR/FunctionInfo.h b/include/llvm/IR/FunctionInfo.h
deleted file mode 100644
index eba088a61bc0..000000000000
--- a/include/llvm/IR/FunctionInfo.h
+++ /dev/null
@@ -1,241 +0,0 @@
-//===-- llvm/FunctionInfo.h - Function Info Index ---------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-/// @file
-/// FunctionInfo.h This file contains the declarations the classes that hold
-/// the function info index and summary.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_IR_FUNCTIONINFO_H
-#define LLVM_IR_FUNCTIONINFO_H
-
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/IR/Module.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
-
-namespace llvm {
-
-/// \brief Function summary information to aid decisions and implementation of
-/// importing.
-///
-/// This is a separate class from FunctionInfo to enable lazy reading of this
-/// function summary information from the combined index file during imporing.
-class FunctionSummary {
-private:
- /// \brief Path of module containing function IR, used to locate module when
- /// importing this function.
- ///
- /// This is only used during parsing of the combined function index, or when
- /// parsing the per-module index for creation of the combined function index,
- /// not during writing of the per-module index which doesn't contain a
- /// module path string table.
- StringRef ModulePath;
-
- /// \brief Used to flag functions that have local linkage types and need to
- /// have module identifier appended before placing into the combined
- /// index, to disambiguate from other functions with the same name.
- ///
- /// This is only used in the per-module function index, as it is consumed
- /// while creating the combined index.
- bool IsLocalFunction;
-
- // The rest of the information is used to help decide whether importing
- // is likely to be profitable.
- // Other information will be added as the importing is tuned, such
- // as hotness (when profile available), and other function characteristics.
-
- /// Number of instructions (ignoring debug instructions, e.g.) computed
- /// during the initial compile step when the function index is first built.
- unsigned InstCount;
-
-public:
- /// Construct a summary object from summary data expected for all
- /// summary records.
- FunctionSummary(unsigned NumInsts) : InstCount(NumInsts) {}
-
- /// Set the path to the module containing this function, for use in
- /// the combined index.
- void setModulePath(StringRef ModPath) { ModulePath = ModPath; }
-
- /// Get the path to the module containing this function.
- StringRef modulePath() const { return ModulePath; }
-
- /// Record whether this is a local function in the per-module index.
- void setLocalFunction(bool IsLocal) { IsLocalFunction = IsLocal; }
-
- /// Check whether this was a local function, for use in creating
- /// the combined index.
- bool isLocalFunction() const { return IsLocalFunction; }
-
- /// Get the instruction count recorded for this function.
- unsigned instCount() const { return InstCount; }
-};
-
-/// \brief Class to hold pointer to function summary and information required
-/// for parsing it.
-///
-/// For the per-module index, this holds the bitcode offset
-/// of the corresponding function block. For the combined index,
-/// after parsing of the \a ValueSymbolTable, this initially
-/// holds the offset of the corresponding function summary bitcode
-/// record. After parsing the associated summary information from the summary
-/// block the \a FunctionSummary is populated and stored here.
-class FunctionInfo {
-private:
- /// Function summary information used to help make ThinLTO importing
- /// decisions.
- std::unique_ptr<FunctionSummary> Summary;
-
- /// \brief The bitcode offset corresponding to either the associated
- /// function's function body record, or its function summary record,
- /// depending on whether this is a per-module or combined index.
- ///
- /// This bitcode offset is written to or read from the associated
- /// \a ValueSymbolTable entry for the function.
- /// For the per-module index this holds the bitcode offset of the
- /// function's body record within bitcode module block in its module,
- /// which is used during lazy function parsing or ThinLTO importing.
- /// For the combined index this holds the offset of the corresponding
- /// function summary record, to enable associating the combined index
- /// VST records with the summary records.
- uint64_t BitcodeIndex;
-
-public:
- /// Constructor used during parsing of VST entries.
- FunctionInfo(uint64_t FuncOffset)
- : Summary(nullptr), BitcodeIndex(FuncOffset) {}
-
- /// Constructor used for per-module index bitcode writing.
- FunctionInfo(uint64_t FuncOffset,
- std::unique_ptr<FunctionSummary> FuncSummary)
- : Summary(std::move(FuncSummary)), BitcodeIndex(FuncOffset) {}
-
- /// Record the function summary information parsed out of the function
- /// summary block during parsing or combined index creation.
- void setFunctionSummary(std::unique_ptr<FunctionSummary> FuncSummary) {
- Summary = std::move(FuncSummary);
- }
-
- /// Get the function summary recorded for this function.
- FunctionSummary *functionSummary() const { return Summary.get(); }
-
- /// Get the bitcode index recorded for this function, depending on
- /// the index type.
- uint64_t bitcodeIndex() const { return BitcodeIndex; }
-
- /// Record the bitcode index for this function, depending on
- /// the index type.
- void setBitcodeIndex(uint64_t FuncOffset) { BitcodeIndex = FuncOffset; }
-};
-
-/// List of function info structures for a particular function name held
-/// in the FunctionMap. Requires a vector in the case of multiple
-/// COMDAT functions of the same name.
-typedef std::vector<std::unique_ptr<FunctionInfo>> FunctionInfoList;
-
-/// Map from function name to corresponding function info structures.
-typedef StringMap<FunctionInfoList> FunctionInfoMapTy;
-
-/// Type used for iterating through the function info map.
-typedef FunctionInfoMapTy::const_iterator const_funcinfo_iterator;
-typedef FunctionInfoMapTy::iterator funcinfo_iterator;
-
-/// String table to hold/own module path strings, which additionally holds the
-/// module ID assigned to each module during the plugin step. The StringMap
-/// makes a copy of and owns inserted strings.
-typedef StringMap<uint64_t> ModulePathStringTableTy;
-
-/// Class to hold module path string table and function map,
-/// and encapsulate methods for operating on them.
-class FunctionInfoIndex {
-private:
- /// Map from function name to list of function information instances
- /// for functions of that name (may be duplicates in the COMDAT case, e.g.).
- FunctionInfoMapTy FunctionMap;
-
- /// Holds strings for combined index, mapping to the corresponding module ID.
- ModulePathStringTableTy ModulePathStringTable;
-
-public:
- FunctionInfoIndex() = default;
-
- // Disable the copy constructor and assignment operators, so
- // no unexpected copying/moving occurs.
- FunctionInfoIndex(const FunctionInfoIndex &) = delete;
- void operator=(const FunctionInfoIndex &) = delete;
-
- funcinfo_iterator begin() { return FunctionMap.begin(); }
- const_funcinfo_iterator begin() const { return FunctionMap.begin(); }
- funcinfo_iterator end() { return FunctionMap.end(); }
- const_funcinfo_iterator end() const { return FunctionMap.end(); }
-
- /// Get the list of function info objects for a given function.
- const FunctionInfoList &getFunctionInfoList(StringRef FuncName) {
- return FunctionMap[FuncName];
- }
-
- /// Get the list of function info objects for a given function.
- const const_funcinfo_iterator findFunctionInfoList(StringRef FuncName) const {
- return FunctionMap.find(FuncName);
- }
-
- /// Add a function info for a function of the given name.
- void addFunctionInfo(StringRef FuncName, std::unique_ptr<FunctionInfo> Info) {
- FunctionMap[FuncName].push_back(std::move(Info));
- }
-
- /// Iterator to allow writer to walk through table during emission.
- iterator_range<StringMap<uint64_t>::const_iterator>
- modPathStringEntries() const {
- return llvm::make_range(ModulePathStringTable.begin(),
- ModulePathStringTable.end());
- }
-
- /// Get the module ID recorded for the given module path.
- uint64_t getModuleId(const StringRef ModPath) const {
- return ModulePathStringTable.lookup(ModPath);
- }
-
- /// Add the given per-module index into this function index/summary,
- /// assigning it the given module ID. Each module merged in should have
- /// a unique ID, necessary for consistent renaming of promoted
- /// static (local) variables.
- void mergeFrom(std::unique_ptr<FunctionInfoIndex> Other,
- uint64_t NextModuleId);
-
- /// Convenience method for creating a promoted global name
- /// for the given value name of a local, and its original module's ID.
- static std::string getGlobalNameForLocal(StringRef Name, uint64_t ModId) {
- SmallString<256> NewName(Name);
- NewName += ".llvm.";
- raw_svector_ostream(NewName) << ModId;
- return NewName.str();
- }
-
- /// Add a new module path, mapped to the given module Id, and return StringRef
- /// owned by string table map.
- StringRef addModulePath(StringRef ModPath, uint64_t ModId) {
- return ModulePathStringTable.insert(std::make_pair(ModPath, ModId))
- .first->first();
- }
-
- /// Check if the given Module has any functions available for exporting
- /// in the index. We consider any module present in the ModulePathStringTable
- /// to have exported functions.
- bool hasExportedFunctions(const Module &M) const {
- return ModulePathStringTable.count(M.getModuleIdentifier());
- }
-};
-
-} // End llvm namespace
-
-#endif
diff --git a/include/llvm/IR/GVMaterializer.h b/include/llvm/IR/GVMaterializer.h
index 6cb593c7a3da..9e47722c892b 100644
--- a/include/llvm/IR/GVMaterializer.h
+++ b/include/llvm/IR/GVMaterializer.h
@@ -18,14 +18,12 @@
#ifndef LLVM_IR_GVMATERIALIZER_H
#define LLVM_IR_GVMATERIALIZER_H
-#include "llvm/ADT/DenseMap.h"
#include <system_error>
#include <vector>
namespace llvm {
class Function;
class GlobalValue;
-class Metadata;
class Module;
class StructType;
@@ -47,14 +45,6 @@ public:
virtual std::error_code materializeMetadata() = 0;
virtual void setStripDebugInfo() = 0;
- /// Client should define this interface if the mapping between metadata
- /// values and value ids needs to be preserved, e.g. across materializer
- /// instantiations. If OnlyTempMD is true, only those that have remained
- /// temporary metadata are recorded in the map.
- virtual void
- saveMetadataList(DenseMap<const Metadata *, unsigned> &MetadataToIDs,
- bool OnlyTempMD) {}
-
virtual std::vector<StructType *> getIdentifiedStructTypes() const = 0;
};
diff --git a/include/llvm/IR/GetElementPtrTypeIterator.h b/include/llvm/IR/GetElementPtrTypeIterator.h
index 7cb13fa33aa6..4953aebbe8aa 100644
--- a/include/llvm/IR/GetElementPtrTypeIterator.h
+++ b/include/llvm/IR/GetElementPtrTypeIterator.h
@@ -33,12 +33,6 @@ namespace llvm {
generic_gep_type_iterator() {}
public:
- static generic_gep_type_iterator begin(Type *Ty, ItTy It) {
- generic_gep_type_iterator I;
- I.CurTy.setPointer(Ty);
- I.OpIt = It;
- return I;
- }
static generic_gep_type_iterator begin(Type *Ty, unsigned AddrSpace,
ItTy It) {
generic_gep_type_iterator I;
@@ -125,13 +119,13 @@ namespace llvm {
template<typename T>
inline generic_gep_type_iterator<const T *>
- gep_type_begin(Type *Op0, ArrayRef<T> A) {
- return generic_gep_type_iterator<const T *>::begin(Op0, A.begin());
+ gep_type_begin(Type *Op0, unsigned AS, ArrayRef<T> A) {
+ return generic_gep_type_iterator<const T *>::begin(Op0, AS, A.begin());
}
template<typename T>
inline generic_gep_type_iterator<const T *>
- gep_type_end(Type * /*Op0*/, ArrayRef<T> A) {
+ gep_type_end(Type * /*Op0*/, unsigned /*AS*/, ArrayRef<T> A) {
return generic_gep_type_iterator<const T *>::end(A.end());
}
} // end namespace llvm
diff --git a/include/llvm/IR/GlobalAlias.h b/include/llvm/IR/GlobalAlias.h
index b0772143309f..3ae3e4a001e1 100644
--- a/include/llvm/IR/GlobalAlias.h
+++ b/include/llvm/IR/GlobalAlias.h
@@ -15,17 +15,17 @@
#ifndef LLVM_IR_GLOBALALIAS_H
#define LLVM_IR_GLOBALALIAS_H
-#include "llvm/ADT/Twine.h"
#include "llvm/ADT/ilist_node.h"
-#include "llvm/IR/GlobalValue.h"
-#include "llvm/IR/OperandTraits.h"
+#include "llvm/IR/GlobalIndirectSymbol.h"
namespace llvm {
+class Twine;
class Module;
template <typename ValueSubClass> class SymbolTableListTraits;
-class GlobalAlias : public GlobalValue, public ilist_node<GlobalAlias> {
+class GlobalAlias : public GlobalIndirectSymbol,
+ public ilist_node<GlobalAlias> {
friend class SymbolTableListTraits<GlobalAlias>;
void operator=(const GlobalAlias &) = delete;
GlobalAlias(const GlobalAlias &) = delete;
@@ -36,11 +36,6 @@ class GlobalAlias : public GlobalValue, public ilist_node<GlobalAlias> {
const Twine &Name, Constant *Aliasee, Module *Parent);
public:
- // allocate space for exactly one operand
- void *operator new(size_t s) {
- return User::operator new(s, 1);
- }
-
/// If a parent module is specified, the alias is automatically inserted into
/// the end of the specified module's alias list.
static GlobalAlias *create(Type *Ty, unsigned AddressSpace,
@@ -64,9 +59,6 @@ public:
// Linkage, Type, Parent and AddressSpace taken from the Aliasee.
static GlobalAlias *create(const Twine &Name, GlobalValue *Aliasee);
- /// Provide fast operand accessors
- DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
-
/// removeFromParent - This method unlinks 'this' from the containing module,
/// but does not delete it.
///
@@ -77,28 +69,13 @@ public:
///
void eraseFromParent() override;
- /// These methods retrive and set alias target.
+ /// These methods retrieve and set alias target.
void setAliasee(Constant *Aliasee);
const Constant *getAliasee() const {
- return const_cast<GlobalAlias *>(this)->getAliasee();
+ return getIndirectSymbol();
}
Constant *getAliasee() {
- return getOperand(0);
- }
-
- const GlobalObject *getBaseObject() const {
- return const_cast<GlobalAlias *>(this)->getBaseObject();
- }
- GlobalObject *getBaseObject() {
- return dyn_cast<GlobalObject>(getAliasee()->stripInBoundsOffsets());
- }
-
- const GlobalObject *getBaseObject(const DataLayout &DL, APInt &Offset) const {
- return const_cast<GlobalAlias *>(this)->getBaseObject(DL, Offset);
- }
- GlobalObject *getBaseObject(const DataLayout &DL, APInt &Offset) {
- return dyn_cast<GlobalObject>(
- getAliasee()->stripAndAccumulateInBoundsConstantOffsets(DL, Offset));
+ return getIndirectSymbol();
}
static bool isValidLinkage(LinkageTypes L) {
@@ -112,13 +89,6 @@ public:
}
};
-template <>
-struct OperandTraits<GlobalAlias> :
- public FixedNumOperandTraits<GlobalAlias, 1> {
-};
-
-DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GlobalAlias, Constant)
-
} // End llvm namespace
#endif
diff --git a/include/llvm/IR/GlobalIFunc.h b/include/llvm/IR/GlobalIFunc.h
new file mode 100644
index 000000000000..0cbe882c58d8
--- /dev/null
+++ b/include/llvm/IR/GlobalIFunc.h
@@ -0,0 +1,76 @@
+//===-------- llvm/GlobalIFunc.h - GlobalIFunc class ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \brief
+/// This file contains the declaration of the GlobalIFunc class, which
+/// represents a single indirect function in the IR. Indirect function uses
+/// ELF symbol type extension to mark that the address of a declaration should
+/// be resolved at runtime by calling a resolver function.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_GLOBALIFUNC_H
+#define LLVM_IR_GLOBALIFUNC_H
+
+#include "llvm/ADT/ilist_node.h"
+#include "llvm/IR/GlobalIndirectSymbol.h"
+
+namespace llvm {
+
+class Twine;
+class Module;
+
+// Traits class for using GlobalIFunc in symbol table in Module.
+template <typename ValueSubClass> class SymbolTableListTraits;
+
+class GlobalIFunc final : public GlobalIndirectSymbol,
+ public ilist_node<GlobalIFunc> {
+ friend class SymbolTableListTraits<GlobalIFunc>;
+ void operator=(const GlobalIFunc &) = delete;
+ GlobalIFunc(const GlobalIFunc &) = delete;
+
+ void setParent(Module *parent);
+
+ GlobalIFunc(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage,
+ const Twine &Name, Constant *Resolver, Module *Parent);
+
+public:
+ /// If a parent module is specified, the ifunc is automatically inserted into
+ /// the end of the specified module's ifunc list.
+ static GlobalIFunc *create(Type *Ty, unsigned AddressSpace,
+ LinkageTypes Linkage, const Twine &Name,
+ Constant *Resolver, Module *Parent);
+
+ /// This method unlinks 'this' from the containing module, but does not
+ /// delete it.
+ void removeFromParent() final;
+
+ /// This method unlinks 'this' from the containing module and deletes it.
+ void eraseFromParent() final;
+
+ /// These methods retrieve and set ifunc resolver function.
+ void setResolver(Constant *Resolver) {
+ setIndirectSymbol(Resolver);
+ }
+ const Constant *getResolver() const {
+ return getIndirectSymbol();
+ }
+ Constant *getResolver() {
+ return getIndirectSymbol();
+ }
+
+ // Methods for support type inquiry through isa, cast, and dyn_cast:
+ static inline bool classof(const Value *V) {
+ return V->getValueID() == Value::GlobalIFuncVal;
+ }
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/include/llvm/IR/GlobalIndirectSymbol.h b/include/llvm/IR/GlobalIndirectSymbol.h
new file mode 100644
index 000000000000..8edb3d1dbf4b
--- /dev/null
+++ b/include/llvm/IR/GlobalIndirectSymbol.h
@@ -0,0 +1,84 @@
+//===- llvm/GlobalIndirectSymbol.h - GlobalIndirectSymbol class -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the declaration of the GlobalIndirectSymbol class, which
+// is a base class for GlobalAlias and GlobalIFunc. It contains all common code
+// for aliases and ifuncs.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_GLOBALINDIRECTSYMBOL_H
+#define LLVM_IR_GLOBALINDIRECTSYMBOL_H
+
+#include "llvm/IR/GlobalValue.h"
+#include "llvm/IR/OperandTraits.h"
+
+namespace llvm {
+
+class GlobalIndirectSymbol : public GlobalValue {
+ void operator=(const GlobalIndirectSymbol &) = delete;
+ GlobalIndirectSymbol(const GlobalIndirectSymbol &) = delete;
+
+protected:
+ GlobalIndirectSymbol(Type *Ty, ValueTy VTy, unsigned AddressSpace,
+ LinkageTypes Linkage, const Twine &Name, Constant *Symbol);
+
+public:
+ // allocate space for exactly one operand
+ void *operator new(size_t s) {
+ return User::operator new(s, 1);
+ }
+
+ /// Provide fast operand accessors
+ DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
+
+ /// These methods set and retrieve indirect symbol.
+ void setIndirectSymbol(Constant *Symbol) {
+ setOperand(0, Symbol);
+ }
+ const Constant *getIndirectSymbol() const {
+ return const_cast<GlobalIndirectSymbol *>(this)->getIndirectSymbol();
+ }
+ Constant *getIndirectSymbol() {
+ return getOperand(0);
+ }
+
+ const GlobalObject *getBaseObject() const {
+ return const_cast<GlobalIndirectSymbol *>(this)->getBaseObject();
+ }
+ GlobalObject *getBaseObject() {
+ return dyn_cast<GlobalObject>(getIndirectSymbol()->stripInBoundsOffsets());
+ }
+
+ const GlobalObject *getBaseObject(const DataLayout &DL, APInt &Offset) const {
+ return const_cast<GlobalIndirectSymbol *>(this)->getBaseObject(DL, Offset);
+ }
+ GlobalObject *getBaseObject(const DataLayout &DL, APInt &Offset) {
+ return dyn_cast<GlobalObject>(
+ getIndirectSymbol()->stripAndAccumulateInBoundsConstantOffsets(DL,
+ Offset));
+ }
+
+ // Methods for support type inquiry through isa, cast, and dyn_cast:
+ static inline bool classof(const Value *V) {
+ return V->getValueID() == Value::GlobalAliasVal ||
+ V->getValueID() == Value::GlobalIFuncVal;
+ }
+};
+
+template <>
+struct OperandTraits<GlobalIndirectSymbol> :
+ public FixedNumOperandTraits<GlobalIndirectSymbol, 1> {
+};
+
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GlobalIndirectSymbol, Constant)
+
+} // End llvm namespace
+
+#endif
diff --git a/include/llvm/IR/GlobalObject.h b/include/llvm/IR/GlobalObject.h
index ee111a046d73..04737a045ae5 100644
--- a/include/llvm/IR/GlobalObject.h
+++ b/include/llvm/IR/GlobalObject.h
@@ -15,12 +15,13 @@
#ifndef LLVM_IR_GLOBALOBJECT_H
#define LLVM_IR_GLOBALOBJECT_H
-#include "llvm/IR/Constant.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/GlobalValue.h"
namespace llvm {
class Comdat;
+class MDNode;
+class Metadata;
class Module;
class GlobalObject : public GlobalValue {
@@ -37,12 +38,19 @@ protected:
std::string Section; // Section to emit this into, empty means default
Comdat *ObjComdat;
- static const unsigned AlignmentBits = 5;
+ enum {
+ LastAlignmentBit = 4,
+ HasMetadataHashEntryBit,
+
+ GlobalObjectBits,
+ };
static const unsigned GlobalObjectSubClassDataBits =
- GlobalValueSubClassDataBits - AlignmentBits;
+ GlobalValueSubClassDataBits - GlobalObjectBits;
private:
+ static const unsigned AlignmentBits = LastAlignmentBit + 1;
static const unsigned AlignmentMask = (1 << AlignmentBits) - 1;
+ static const unsigned GlobalObjectMask = (1 << GlobalObjectBits) - 1;
public:
unsigned getAlignment() const {
@@ -55,8 +63,8 @@ public:
unsigned getGlobalObjectSubClassData() const;
void setGlobalObjectSubClassData(unsigned Val);
- bool hasSection() const { return !StringRef(getSection()).empty(); }
- const char *getSection() const { return Section.c_str(); }
+ bool hasSection() const { return !getSection().empty(); }
+ StringRef getSection() const { return Section; }
void setSection(StringRef S);
bool hasComdat() const { return getComdat() != nullptr; }
@@ -64,6 +72,54 @@ public:
Comdat *getComdat() { return ObjComdat; }
void setComdat(Comdat *C) { ObjComdat = C; }
+ /// Check if this has any metadata.
+ bool hasMetadata() const { return hasMetadataHashEntry(); }
+
+ /// Get the current metadata attachments for the given kind, if any.
+ ///
+ /// These functions require that the function have at most a single attachment
+ /// of the given kind, and return \c nullptr if such an attachment is missing.
+ /// @{
+ MDNode *getMetadata(unsigned KindID) const;
+ MDNode *getMetadata(StringRef Kind) const;
+ /// @}
+
+ /// Appends all attachments with the given ID to \c MDs in insertion order.
+ /// If the global has no attachments with the given ID, or if ID is invalid,
+ /// leaves MDs unchanged.
+ /// @{
+ void getMetadata(unsigned KindID, SmallVectorImpl<MDNode *> &MDs) const;
+ void getMetadata(StringRef Kind, SmallVectorImpl<MDNode *> &MDs) const;
+ /// @}
+
+ /// Set a particular kind of metadata attachment.
+ ///
+ /// Sets the given attachment to \c MD, erasing it if \c MD is \c nullptr or
+ /// replacing it if it already exists.
+ /// @{
+ void setMetadata(unsigned KindID, MDNode *MD);
+ void setMetadata(StringRef Kind, MDNode *MD);
+ /// @}
+
+ /// Add a metadata attachment.
+ /// @{
+ void addMetadata(unsigned KindID, MDNode &MD);
+ void addMetadata(StringRef Kind, MDNode &MD);
+ /// @}
+
+ /// Appends all attachments for the global to \c MDs, sorting by attachment
+ /// ID. Attachments with the same ID appear in insertion order.
+ void
+ getAllMetadata(SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const;
+
+ /// Erase all metadata attachments with the given kind.
+ void eraseMetadata(unsigned KindID);
+
+ /// Copy metadata from Src, adjusting offsets by Offset.
+ void copyMetadata(const GlobalObject *Src, unsigned Offset);
+
+ void addTypeMetadata(unsigned Offset, Metadata *TypeID);
+
void copyAttributesFrom(const GlobalValue *Src) override;
// Methods for support type inquiry through isa, cast, and dyn_cast:
@@ -71,6 +127,18 @@ public:
return V->getValueID() == Value::FunctionVal ||
V->getValueID() == Value::GlobalVariableVal;
}
+
+ void clearMetadata();
+
+private:
+ bool hasMetadataHashEntry() const {
+ return getGlobalValueSubClassData() & (1 << HasMetadataHashEntryBit);
+ }
+ void setHasMetadataHashEntry(bool HasEntry) {
+ unsigned Mask = 1 << HasMetadataHashEntryBit;
+ setGlobalValueSubClassData((~Mask & getGlobalValueSubClassData()) |
+ (HasEntry ? Mask : 0u));
+ }
};
} // End llvm namespace
diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h
index fa6469aa0ade..09682f7aa349 100644
--- a/include/llvm/IR/GlobalValue.h
+++ b/include/llvm/IR/GlobalValue.h
@@ -20,6 +20,7 @@
#include "llvm/IR/Constant.h"
#include "llvm/IR/DerivedTypes.h"
+#include "llvm/Support/MD5.h"
#include <system_error>
namespace llvm {
@@ -69,17 +70,18 @@ protected:
LinkageTypes Linkage, const Twine &Name, unsigned AddressSpace)
: Constant(PointerType::get(Ty, AddressSpace), VTy, Ops, NumOps),
ValueType(Ty), Linkage(Linkage), Visibility(DefaultVisibility),
- UnnamedAddr(0), DllStorageClass(DefaultStorageClass),
- ThreadLocal(NotThreadLocal), IntID((Intrinsic::ID)0U), Parent(nullptr) {
+ UnnamedAddrVal(unsigned(UnnamedAddr::None)),
+ DllStorageClass(DefaultStorageClass), ThreadLocal(NotThreadLocal),
+ IntID((Intrinsic::ID)0U), Parent(nullptr) {
setName(Name);
}
Type *ValueType;
- // Note: VC++ treats enums as signed, so an extra bit is required to prevent
- // Linkage and Visibility from turning into negative values.
- LinkageTypes Linkage : 5; // The linkage of this global
+ // All bitfields use unsigned as the underlying type so that MSVC will pack
+ // them.
+ unsigned Linkage : 4; // The linkage of this global
unsigned Visibility : 2; // The visibility style of this global
- unsigned UnnamedAddr : 1; // This value's address is not significant
+ unsigned UnnamedAddrVal : 2; // This value's address is not significant
unsigned DllStorageClass : 2; // DLL storage class
unsigned ThreadLocal : 3; // Is this symbol "Thread Local", if so, what is
@@ -88,12 +90,36 @@ protected:
private:
// Give subclasses access to what otherwise would be wasted padding.
- // (19 + 3 + 2 + 1 + 2 + 5) == 32.
+ // (19 + 4 + 2 + 2 + 2 + 3) == 32.
unsigned SubClassData : GlobalValueSubClassDataBits;
friend class Constant;
void destroyConstantImpl();
- Value *handleOperandChangeImpl(Value *From, Value *To, Use *U);
+ Value *handleOperandChangeImpl(Value *From, Value *To);
+
+ /// Returns true if the definition of this global may be replaced by a
+ /// differently optimized variant of the same source level function at link
+ /// time.
+ bool mayBeDerefined() const {
+ switch (getLinkage()) {
+ case WeakODRLinkage:
+ case LinkOnceODRLinkage:
+ case AvailableExternallyLinkage:
+ return true;
+
+ case WeakAnyLinkage:
+ case LinkOnceAnyLinkage:
+ case CommonLinkage:
+ case ExternalWeakLinkage:
+ case ExternalLinkage:
+ case AppendingLinkage:
+ case InternalLinkage:
+ case PrivateLinkage:
+ return isInterposable();
+ }
+
+ llvm_unreachable("Fully covered switch above!");
+ }
protected:
/// \brief The intrinsic ID for this subclass (which must be a Function).
@@ -128,8 +154,37 @@ public:
unsigned getAlignment() const;
- bool hasUnnamedAddr() const { return UnnamedAddr; }
- void setUnnamedAddr(bool Val) { UnnamedAddr = Val; }
+ enum class UnnamedAddr {
+ None,
+ Local,
+ Global,
+ };
+
+ bool hasGlobalUnnamedAddr() const {
+ return getUnnamedAddr() == UnnamedAddr::Global;
+ }
+
+ /// Returns true if this value's address is not significant in this module.
+ /// This attribute is intended to be used only by the code generator and LTO
+ /// to allow the linker to decide whether the global needs to be in the symbol
+ /// table. It should probably not be used in optimizations, as the value may
+ /// have uses outside the module; use hasGlobalUnnamedAddr() instead.
+ bool hasAtLeastLocalUnnamedAddr() const {
+ return getUnnamedAddr() != UnnamedAddr::None;
+ }
+
+ UnnamedAddr getUnnamedAddr() const {
+ return UnnamedAddr(UnnamedAddrVal);
+ }
+ void setUnnamedAddr(UnnamedAddr Val) { UnnamedAddrVal = unsigned(Val); }
+
+ static UnnamedAddr getMinUnnamedAddr(UnnamedAddr A, UnnamedAddr B) {
+ if (A == UnnamedAddr::None || B == UnnamedAddr::None)
+ return UnnamedAddr::None;
+ if (A == UnnamedAddr::Local || B == UnnamedAddr::Local)
+ return UnnamedAddr::Local;
+ return UnnamedAddr::Global;
+ }
bool hasComdat() const { return getComdat() != nullptr; }
Comdat *getComdat();
@@ -173,14 +228,8 @@ public:
}
void setDLLStorageClass(DLLStorageClassTypes C) { DllStorageClass = C; }
- bool hasSection() const { return !StringRef(getSection()).empty(); }
- // It is unfortunate that we have to use "char *" in here since this is
- // always non NULL, but:
- // * The C API expects a null terminated string, so we cannot use StringRef.
- // * The C API expects us to own it, so we cannot use a std:string.
- // * For GlobalAliases we can fail to find the section and we have to
- // return "", so we cannot use a "const std::string &".
- const char *getSection() const;
+ bool hasSection() const { return !getSection().empty(); }
+ StringRef getSection() const;
/// Global values are always pointers.
PointerType *getType() const { return cast<PointerType>(User::getType()); }
@@ -233,6 +282,34 @@ public:
static bool isCommonLinkage(LinkageTypes Linkage) {
return Linkage == CommonLinkage;
}
+ static bool isValidDeclarationLinkage(LinkageTypes Linkage) {
+ return isExternalWeakLinkage(Linkage) || isExternalLinkage(Linkage);
+ }
+
+ /// Whether the definition of this global may be replaced by something
+ /// non-equivalent at link time. For example, if a function has weak linkage
+ /// then the code defining it may be replaced by different code.
+ static bool isInterposableLinkage(LinkageTypes Linkage) {
+ switch (Linkage) {
+ case WeakAnyLinkage:
+ case LinkOnceAnyLinkage:
+ case CommonLinkage:
+ case ExternalWeakLinkage:
+ return true;
+
+ case AvailableExternallyLinkage:
+ case LinkOnceODRLinkage:
+ case WeakODRLinkage:
+ // The above three cannot be overridden but can be de-refined.
+
+ case ExternalLinkage:
+ case AppendingLinkage:
+ case InternalLinkage:
+ case PrivateLinkage:
+ return false;
+ }
+ llvm_unreachable("Fully covered switch above!");
+ }
/// Whether the definition of this global may be discarded if it is not used
/// in its compilation unit.
@@ -241,17 +318,9 @@ public:
isAvailableExternallyLinkage(Linkage);
}
- /// Whether the definition of this global may be replaced by something
- /// non-equivalent at link time. For example, if a function has weak linkage
- /// then the code defining it may be replaced by different code.
- static bool mayBeOverridden(LinkageTypes Linkage) {
- return Linkage == WeakAnyLinkage || Linkage == LinkOnceAnyLinkage ||
- Linkage == CommonLinkage || Linkage == ExternalWeakLinkage;
- }
-
/// Whether the definition of this global may be replaced at link time. NB:
/// Using this method outside of the code generators is almost always a
- /// mistake: when working at the IR level use mayBeOverridden instead as it
+ /// mistake: when working at the IR level use isInterposable instead as it
/// knows about ODR semantics.
static bool isWeakForLinker(LinkageTypes Linkage) {
return Linkage == WeakAnyLinkage || Linkage == WeakODRLinkage ||
@@ -259,44 +328,87 @@ public:
Linkage == CommonLinkage || Linkage == ExternalWeakLinkage;
}
- bool hasExternalLinkage() const { return isExternalLinkage(Linkage); }
+ /// Return true if the currently visible definition of this global (if any) is
+ /// exactly the definition we will see at runtime.
+ ///
+ /// Non-exact linkage types inhibits most non-inlining IPO, since a
+ /// differently optimized variant of the same function can have different
+ /// observable or undefined behavior than in the variant currently visible.
+ /// For instance, we could have started with
+ ///
+ /// void foo(int *v) {
+ /// int t = 5 / v[0];
+ /// (void) t;
+ /// }
+ ///
+ /// and "refined" it to
+ ///
+ /// void foo(int *v) { }
+ ///
+ /// However, we cannot infer readnone for `foo`, since that would justify
+ /// DSE'ing a store to `v[0]` across a call to `foo`, which can cause
+ /// undefined behavior if the linker replaces the actual call destination with
+ /// the unoptimized `foo`.
+ ///
+ /// Inlining is okay across non-exact linkage types as long as they're not
+ /// interposable (see \c isInterposable), since in such cases the currently
+ /// visible variant is *a* correct implementation of the original source
+ /// function; it just isn't the *only* correct implementation.
+ bool isDefinitionExact() const {
+ return !mayBeDerefined();
+ }
+
+ /// Return true if this global has an exact defintion.
+ bool hasExactDefinition() const {
+ // While this computes exactly the same thing as
+ // isStrongDefinitionForLinker, the intended uses are different. This
+ // function is intended to help decide if specific inter-procedural
+ // transforms are correct, while isStrongDefinitionForLinker's intended use
+ // is in low level code generation.
+ return !isDeclaration() && isDefinitionExact();
+ }
+
+ /// Return true if this global's definition can be substituted with an
+ /// *arbitrary* definition at link time. We cannot do any IPO or inlinining
+ /// across interposable call edges, since the callee can be replaced with
+ /// something arbitrary at link time.
+ bool isInterposable() const { return isInterposableLinkage(getLinkage()); }
+
+ bool hasExternalLinkage() const { return isExternalLinkage(getLinkage()); }
bool hasAvailableExternallyLinkage() const {
- return isAvailableExternallyLinkage(Linkage);
- }
- bool hasLinkOnceLinkage() const {
- return isLinkOnceLinkage(Linkage);
+ return isAvailableExternallyLinkage(getLinkage());
}
- bool hasLinkOnceODRLinkage() const { return isLinkOnceODRLinkage(Linkage); }
- bool hasWeakLinkage() const {
- return isWeakLinkage(Linkage);
+ bool hasLinkOnceLinkage() const { return isLinkOnceLinkage(getLinkage()); }
+ bool hasLinkOnceODRLinkage() const {
+ return isLinkOnceODRLinkage(getLinkage());
}
- bool hasWeakAnyLinkage() const {
- return isWeakAnyLinkage(Linkage);
+ bool hasWeakLinkage() const { return isWeakLinkage(getLinkage()); }
+ bool hasWeakAnyLinkage() const { return isWeakAnyLinkage(getLinkage()); }
+ bool hasWeakODRLinkage() const { return isWeakODRLinkage(getLinkage()); }
+ bool hasAppendingLinkage() const { return isAppendingLinkage(getLinkage()); }
+ bool hasInternalLinkage() const { return isInternalLinkage(getLinkage()); }
+ bool hasPrivateLinkage() const { return isPrivateLinkage(getLinkage()); }
+ bool hasLocalLinkage() const { return isLocalLinkage(getLinkage()); }
+ bool hasExternalWeakLinkage() const {
+ return isExternalWeakLinkage(getLinkage());
}
- bool hasWeakODRLinkage() const {
- return isWeakODRLinkage(Linkage);
+ bool hasCommonLinkage() const { return isCommonLinkage(getLinkage()); }
+ bool hasValidDeclarationLinkage() const {
+ return isValidDeclarationLinkage(getLinkage());
}
- bool hasAppendingLinkage() const { return isAppendingLinkage(Linkage); }
- bool hasInternalLinkage() const { return isInternalLinkage(Linkage); }
- bool hasPrivateLinkage() const { return isPrivateLinkage(Linkage); }
- bool hasLocalLinkage() const { return isLocalLinkage(Linkage); }
- bool hasExternalWeakLinkage() const { return isExternalWeakLinkage(Linkage); }
- bool hasCommonLinkage() const { return isCommonLinkage(Linkage); }
void setLinkage(LinkageTypes LT) {
if (isLocalLinkage(LT))
Visibility = DefaultVisibility;
Linkage = LT;
}
- LinkageTypes getLinkage() const { return Linkage; }
+ LinkageTypes getLinkage() const { return LinkageTypes(Linkage); }
bool isDiscardableIfUnused() const {
- return isDiscardableIfUnused(Linkage);
+ return isDiscardableIfUnused(getLinkage());
}
- bool mayBeOverridden() const { return mayBeOverridden(Linkage); }
-
- bool isWeakForLinker() const { return isWeakForLinker(Linkage); }
+ bool isWeakForLinker() const { return isWeakForLinker(getLinkage()); }
/// Copy all additional attributes (those not needed to create a GlobalValue)
/// from the GlobalValue Src to this one.
@@ -311,11 +423,37 @@ public:
return Name;
}
-/// @name Materialization
-/// Materialization is used to construct functions only as they're needed. This
-/// is useful to reduce memory usage in LLVM or parsing work done by the
-/// BitcodeReader to load the Module.
-/// @{
+ /// Return the modified name for a global value suitable to be
+ /// used as the key for a global lookup (e.g. profile or ThinLTO).
+ /// The value's original name is \c Name and has linkage of type
+ /// \c Linkage. The value is defined in module \c FileName.
+ static std::string getGlobalIdentifier(StringRef Name,
+ GlobalValue::LinkageTypes Linkage,
+ StringRef FileName);
+
+ /// Return the modified name for this global value suitable to be
+ /// used as the key for a global lookup (e.g. profile or ThinLTO).
+ std::string getGlobalIdentifier() const;
+
+ /// Declare a type to represent a global unique identifier for a global value.
+ /// This is a 64 bits hash that is used by PGO and ThinLTO to have a compact
+ /// unique way to identify a symbol.
+ using GUID = uint64_t;
+
+ /// Return a 64-bit global unique ID constructed from global value name
+ /// (i.e. returned by getGlobalIdentifier()).
+ static GUID getGUID(StringRef GlobalName) { return MD5Hash(GlobalName); }
+
+ /// Return a 64-bit global unique ID constructed from global value name
+ /// (i.e. returned by getGlobalIdentifier()).
+ GUID getGUID() const { return getGUID(getGlobalIdentifier()); }
+
+ /// @name Materialization
+ /// Materialization is used to construct functions only as they're needed.
+ /// This
+ /// is useful to reduce memory usage in LLVM or parsing work done by the
+ /// BitcodeReader to load the Module.
+ /// @{
/// If this function's Module is being lazily streamed in functions from disk
/// or some other source, this method can be used to check to see if the
@@ -342,6 +480,10 @@ public:
/// Returns true if this global's definition will be the one chosen by the
/// linker.
+ ///
+ /// NB! Ideally this should not be used at the IR level at all. If you're
+ /// interested in optimization constraints implied by the linker's ability to
+ /// choose an implementation, prefer using \c hasExactDefinition.
bool isStrongDefinitionForLinker() const {
return !(isDeclarationForLinker() || isWeakForLinker());
}
@@ -365,7 +507,8 @@ public:
static bool classof(const Value *V) {
return V->getValueID() == Value::FunctionVal ||
V->getValueID() == Value::GlobalVariableVal ||
- V->getValueID() == Value::GlobalAliasVal;
+ V->getValueID() == Value::GlobalAliasVal ||
+ V->getValueID() == Value::GlobalIFuncVal;
}
};
diff --git a/include/llvm/IR/GlobalVariable.h b/include/llvm/IR/GlobalVariable.h
index 342bdc01bfbd..ebeb635468d0 100644
--- a/include/llvm/IR/GlobalVariable.h
+++ b/include/llvm/IR/GlobalVariable.h
@@ -65,6 +65,8 @@ public:
bool isExternallyInitialized = false);
~GlobalVariable() override {
+ dropAllReferences();
+
// FIXME: needed by operator delete
setGlobalVariableNumOperands(1);
}
@@ -94,9 +96,9 @@ public:
/// unique.
inline bool hasDefinitiveInitializer() const {
return hasInitializer() &&
- // The initializer of a global variable with weak linkage may change at
- // link time.
- !mayBeOverridden() &&
+ // The initializer of a global variable may change to something arbitrary
+ // at link time.
+ !isInterposable() &&
// The initializer of a global variable with the externally_initialized
// marker may change at runtime before C++ initializers are evaluated.
!isExternallyInitialized();
@@ -159,6 +161,10 @@ public:
///
void eraseFromParent() override;
+ /// Drop all references in preparation to destroy the GlobalVariable. This
+ /// drops not only the reference to the initializer but also to any metadata.
+ void dropAllReferences();
+
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const Value *V) {
return V->getValueID() == Value::GlobalVariableVal;
diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h
index 2f8c3c499295..016e9e1d2c50 100644
--- a/include/llvm/IR/IRBuilder.h
+++ b/include/llvm/IR/IRBuilder.h
@@ -16,36 +16,54 @@
#define LLVM_IR_IRBUILDER_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Constant.h"
#include "llvm/IR/ConstantFolder.h"
+#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DebugLoc.h"
+#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalVariable.h"
+#include "llvm/IR/InstrTypes.h"
+#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Operator.h"
+#include "llvm/IR/Type.h"
+#include "llvm/IR/Value.h"
#include "llvm/IR/ValueHandle.h"
+#include "llvm/Support/AtomicOrdering.h"
#include "llvm/Support/CBindingWrapping.h"
+#include "llvm/Support/Casting.h"
+#include "llvm-c/Types.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
namespace llvm {
+
+class APInt;
class MDNode;
+class Module;
+class Use;
/// \brief This provides the default implementation of the IRBuilder
/// 'InsertHelper' method that is called whenever an instruction is created by
/// IRBuilder and needs to be inserted.
///
/// By default, this inserts the instruction at the insertion point.
-template <bool preserveNames = true>
class IRBuilderDefaultInserter {
protected:
void InsertHelper(Instruction *I, const Twine &Name,
BasicBlock *BB, BasicBlock::iterator InsertPt) const {
if (BB) BB->getInstList().insert(InsertPt, I);
- if (preserveNames)
- I->setName(Name);
+ I->setName(Name);
}
};
@@ -436,6 +454,16 @@ public:
CallInst *CreateMaskedStore(Value *Val, Value *Ptr, unsigned Align,
Value *Mask);
+ /// \brief Create a call to Masked Gather intrinsic
+ CallInst *CreateMaskedGather(Value *Ptrs, unsigned Align,
+ Value *Mask = nullptr,
+ Value *PassThru = nullptr,
+ const Twine& Name = "");
+
+ /// \brief Create a call to Masked Scatter intrinsic
+ CallInst *CreateMaskedScatter(Value *Val, Value *Ptrs, unsigned Align,
+ Value *Mask = nullptr);
+
/// \brief Create an assume intrinsic call that allows the optimizer to
/// assume that the provided condition will be true.
CallInst *CreateAssumption(Value *Cond);
@@ -512,9 +540,9 @@ public:
private:
/// \brief Create a call to a masked intrinsic with given Id.
- /// Masked intrinsic has only one overloaded type - data type.
CallInst *CreateMaskedIntrinsic(Intrinsic::ID Id, ArrayRef<Value *> Ops,
- Type *DataTy, const Twine &Name = "");
+ ArrayRef<Type *> OverloadedTypes,
+ const Twine &Name = "");
Value *getCastedInt8PtrValue(Value *Ptr);
};
@@ -529,14 +557,12 @@ private:
/// created. Convenience state exists to specify fast-math flags and fp-math
/// tags.
///
-/// The first template argument handles whether or not to preserve names in the
-/// final instruction output. This defaults to on. The second template argument
-/// specifies a class to use for creating constants. This defaults to creating
-/// minimally folded constants. The third template argument allows clients to
-/// specify custom insertion hooks that are called on every newly created
-/// insertion.
-template<bool preserveNames = true, typename T = ConstantFolder,
- typename Inserter = IRBuilderDefaultInserter<preserveNames> >
+/// The first template argument specifies a class to use for creating constants.
+/// This defaults to creating minimally folded constants. The second template
+/// argument allows clients to specify custom insertion hooks that are called on
+/// every newly created insertion.
+template <typename T = ConstantFolder,
+ typename Inserter = IRBuilderDefaultInserter>
class IRBuilder : public IRBuilderBase, public Inserter {
T Folder;
@@ -586,10 +612,6 @@ public:
/// \brief Get the constant folder being used.
const T &getFolder() { return Folder; }
- /// \brief Return true if this builder is configured to actually add the
- /// requested names to IR created through it.
- bool isNamePreserving() const { return preserveNames; }
-
/// \brief Insert and return the specified instruction.
template<typename InstTy>
InstTy *Insert(InstTy *I, const Twine &Name = "") const {
@@ -676,28 +698,10 @@ public:
return Insert(IndirectBrInst::Create(Addr, NumDests));
}
- InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest,
- BasicBlock *UnwindDest, const Twine &Name = "") {
- return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest, None),
- Name);
- }
- InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest,
- BasicBlock *UnwindDest, Value *Arg1,
- const Twine &Name = "") {
- return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest, Arg1),
- Name);
- }
- InvokeInst *CreateInvoke3(Value *Callee, BasicBlock *NormalDest,
- BasicBlock *UnwindDest, Value *Arg1,
- Value *Arg2, Value *Arg3,
- const Twine &Name = "") {
- Value *Args[] = { Arg1, Arg2, Arg3 };
- return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest, Args),
- Name);
- }
/// \brief Create an invoke instruction.
InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest,
- BasicBlock *UnwindDest, ArrayRef<Value *> Args,
+ BasicBlock *UnwindDest,
+ ArrayRef<Value *> Args = None,
const Twine &Name = "") {
return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest, Args),
Name);
@@ -1569,12 +1573,19 @@ public:
}
Value *CreateSelect(Value *C, Value *True, Value *False,
- const Twine &Name = "") {
+ const Twine &Name = "", Instruction *MDFrom = nullptr) {
if (Constant *CC = dyn_cast<Constant>(C))
if (Constant *TC = dyn_cast<Constant>(True))
if (Constant *FC = dyn_cast<Constant>(False))
return Insert(Folder.CreateSelect(CC, TC, FC), Name);
- return Insert(SelectInst::Create(C, True, False), Name);
+
+ SelectInst *Sel = SelectInst::Create(C, True, False);
+ if (MDFrom) {
+ MDNode *Prof = MDFrom->getMetadata(LLVMContext::MD_prof);
+ MDNode *Unpred = MDFrom->getMetadata(LLVMContext::MD_unpredictable);
+ Sel = addBranchMetadata(Sel, Prof, Unpred);
+ }
+ return Insert(Sel, Name);
}
VAArgInst *CreateVAArg(Value *List, Type *Ty, const Twine &Name = "") {
@@ -1617,13 +1628,9 @@ public:
return Insert(new ShuffleVectorInst(V1, V2, Mask), Name);
}
- Value *CreateShuffleVector(Value *V1, Value *V2, ArrayRef<int> IntMask,
+ Value *CreateShuffleVector(Value *V1, Value *V2, ArrayRef<uint32_t> IntMask,
const Twine &Name = "") {
- size_t MaskSize = IntMask.size();
- SmallVector<Constant*, 8> MaskVec(MaskSize);
- for (size_t i = 0; i != MaskSize; ++i)
- MaskVec[i] = getInt32(IntMask[i]);
- Value *Mask = ConstantVector::get(MaskVec);
+ Value *Mask = ConstantDataVector::get(Context, IntMask);
return CreateShuffleVector(V1, V2, Mask, Name);
}
diff --git a/include/llvm/IR/IRPrintingPasses.h b/include/llvm/IR/IRPrintingPasses.h
index 88b18e826daf..bc6de19a6c3a 100644
--- a/include/llvm/IR/IRPrintingPasses.h
+++ b/include/llvm/IR/IRPrintingPasses.h
@@ -30,6 +30,7 @@ class Module;
class ModulePass;
class PreservedAnalyses;
class raw_ostream;
+template <typename IRUnitT> class AnalysisManager;
/// \brief Create and return a pass that writes the module to the specified
/// \c raw_ostream.
@@ -67,7 +68,7 @@ public:
PrintModulePass(raw_ostream &OS, const std::string &Banner = "",
bool ShouldPreserveUseListOrder = false);
- PreservedAnalyses run(Module &M);
+ PreservedAnalyses run(Module &M, AnalysisManager<Module> &);
static StringRef name() { return "PrintModulePass"; }
};
@@ -84,7 +85,7 @@ public:
PrintFunctionPass();
PrintFunctionPass(raw_ostream &OS, const std::string &Banner = "");
- PreservedAnalyses run(Function &F);
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &);
static StringRef name() { return "PrintFunctionPass"; }
};
diff --git a/include/llvm/IR/InlineAsm.h b/include/llvm/IR/InlineAsm.h
index d2e9e48539ce..40ba830b8819 100644
--- a/include/llvm/IR/InlineAsm.h
+++ b/include/llvm/IR/InlineAsm.h
@@ -223,6 +223,7 @@ public:
Extra_AsmDialect = 4,
Extra_MayLoad = 8,
Extra_MayStore = 16,
+ Extra_IsConvergent = 32,
// Inline asm operands map to multiple SDNode / MachineInstr operands.
// The first operand is an immediate describing the asm operand, the low
@@ -271,6 +272,16 @@ public:
return Kind | (NumOps << 3);
}
+ static bool isRegDefKind(unsigned Flag){ return getKind(Flag) == Kind_RegDef;}
+ static bool isImmKind(unsigned Flag) { return getKind(Flag) == Kind_Imm; }
+ static bool isMemKind(unsigned Flag) { return getKind(Flag) == Kind_Mem; }
+ static bool isRegDefEarlyClobberKind(unsigned Flag) {
+ return getKind(Flag) == Kind_RegDefEarlyClobber;
+ }
+ static bool isClobberKind(unsigned Flag) {
+ return getKind(Flag) == Kind_Clobber;
+ }
+
/// getFlagWordForMatchingOp - Augment an existing flag word returned by
/// getFlagWord with information indicating that this input operand is tied
/// to a previous output operand.
@@ -289,6 +300,8 @@ public:
static unsigned getFlagWordForRegClass(unsigned InputFlag, unsigned RC) {
// Store RC + 1, reserve the value 0 to mean 'no register class'.
++RC;
+ assert(!isImmKind(InputFlag) && "Immediates cannot have a register class");
+ assert(!isMemKind(InputFlag) && "Memory operand cannot have a register class");
assert(RC <= 0x7fff && "Too large register class ID");
assert((InputFlag & ~0xffff) == 0 && "High bits already contain data");
return InputFlag | (RC << 16);
@@ -297,6 +310,7 @@ public:
/// Augment an existing flag word returned by getFlagWord with the constraint
/// code for a memory constraint.
static unsigned getFlagWordForMem(unsigned InputFlag, unsigned Constraint) {
+ assert(isMemKind(InputFlag) && "InputFlag is not a memory constraint!");
assert(Constraint <= 0x7fff && "Too large a memory constraint ID");
assert(Constraint <= Constraints_Max && "Unknown constraint ID");
assert((InputFlag & ~0xffff) == 0 && "High bits already contain data");
@@ -312,16 +326,6 @@ public:
return Flags & 7;
}
- static bool isRegDefKind(unsigned Flag){ return getKind(Flag) == Kind_RegDef;}
- static bool isImmKind(unsigned Flag) { return getKind(Flag) == Kind_Imm; }
- static bool isMemKind(unsigned Flag) { return getKind(Flag) == Kind_Mem; }
- static bool isRegDefEarlyClobberKind(unsigned Flag) {
- return getKind(Flag) == Kind_RegDefEarlyClobber;
- }
- static bool isClobberKind(unsigned Flag) {
- return getKind(Flag) == Kind_Clobber;
- }
-
static unsigned getMemoryConstraintID(unsigned Flag) {
assert(isMemKind(Flag));
return (Flag >> Constraints_ShiftAmount) & 0x7fff;
diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h
index 5091bb407833..39514c5675a7 100644
--- a/include/llvm/IR/InstrTypes.h
+++ b/include/llvm/IR/InstrTypes.h
@@ -386,6 +386,15 @@ public:
}
#include "llvm/IR/Instruction.def"
+ static BinaryOperator *CreateWithCopiedFlags(BinaryOps Opc,
+ Value *V1, Value *V2,
+ BinaryOperator *CopyBO,
+ const Twine &Name = "") {
+ BinaryOperator *BO = Create(Opc, V1, V2, Name);
+ BO->copyIRFlags(CopyBO);
+ return BO;
+ }
+
static BinaryOperator *CreateNSW(BinaryOps Opc, Value *V1, Value *V2,
const Twine &Name = "") {
BinaryOperator *BO = Create(Opc, V1, V2, Name);
@@ -526,35 +535,6 @@ public:
///
bool swapOperands();
- /// Set or clear the nsw flag on this instruction, which must be an operator
- /// which supports this flag. See LangRef.html for the meaning of this flag.
- void setHasNoUnsignedWrap(bool b = true);
-
- /// Set or clear the nsw flag on this instruction, which must be an operator
- /// which supports this flag. See LangRef.html for the meaning of this flag.
- void setHasNoSignedWrap(bool b = true);
-
- /// Set or clear the exact flag on this instruction, which must be an operator
- /// which supports this flag. See LangRef.html for the meaning of this flag.
- void setIsExact(bool b = true);
-
- /// Determine whether the no unsigned wrap flag is set.
- bool hasNoUnsignedWrap() const;
-
- /// Determine whether the no signed wrap flag is set.
- bool hasNoSignedWrap() const;
-
- /// Determine whether the exact flag is set.
- bool isExact() const;
-
- /// Convenience method to copy supported wrapping, exact, and fast-math flags
- /// from V to this instruction.
- void copyIRFlags(const Value *V);
-
- /// Logical 'and' of any supported wrapping, exact, and fast-math flags of
- /// V and this instruction.
- void andIRFlags(const Value *V);
-
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const Instruction *I) {
return I->isBinaryOp();
@@ -879,6 +859,10 @@ public:
/// Values in the range 0-31 are reserved for FCmpInst, while values in the
/// range 32-64 are reserved for ICmpInst. This is necessary to ensure the
/// predicate values are not overlapping between the classes.
+ ///
+ /// Some passes (e.g. InstCombine) depend on the bit-wise characteristics of
+ /// FCMP_* values. Changing the bit patterns requires a potential change to
+ /// those passes.
enum Predicate {
// Opcode U L G E Intuitive operation
FCMP_FALSE = 0, ///< 0 0 0 0 Always false (always folded)
@@ -1058,6 +1042,18 @@ public:
return isFalseWhenEqual(getPredicate());
}
+ /// @brief Determine if Pred1 implies Pred2 is true when two compares have
+ /// matching operands.
+ bool isImpliedTrueByMatchingCmp(Predicate Pred2) {
+ return isImpliedTrueByMatchingCmp(getPredicate(), Pred2);
+ }
+
+ /// @brief Determine if Pred1 implies Pred2 is false when two compares have
+ /// matching operands.
+ bool isImpliedFalseByMatchingCmp(Predicate Pred2) {
+ return isImpliedFalseByMatchingCmp(getPredicate(), Pred2);
+ }
+
/// @returns true if the predicate is unsigned, false otherwise.
/// @brief Determine if the predicate is an unsigned operation.
static bool isUnsigned(Predicate predicate);
@@ -1078,6 +1074,14 @@ public:
/// Determine if the predicate is false when comparing a value with itself.
static bool isFalseWhenEqual(Predicate predicate);
+ /// Determine if Pred1 implies Pred2 is true when two compares have matching
+ /// operands.
+ static bool isImpliedTrueByMatchingCmp(Predicate Pred1, Predicate Pred2);
+
+ /// Determine if Pred1 implies Pred2 is false when two compares have matching
+ /// operands.
+ static bool isImpliedFalseByMatchingCmp(Predicate Pred1, Predicate Pred2);
+
/// @brief Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::ICmp ||
@@ -1469,6 +1473,17 @@ public:
Other.bundle_op_info_begin());
};
+ /// \brief Return true if this operand bundle user contains operand bundles
+ /// with tags other than those specified in \p IDs.
+ bool hasOperandBundlesOtherThan(ArrayRef<uint32_t> IDs) const {
+ for (unsigned i = 0, e = getNumOperandBundles(); i != e; ++i) {
+ uint32_t ID = getOperandBundleAt(i).getTagID();
+ if (std::find(IDs.begin(), IDs.end(), ID) == IDs.end())
+ return true;
+ }
+ return false;
+ }
+
protected:
/// \brief Is the function attribute S disallowed by some operand bundle on
/// this operand bundle user?
diff --git a/include/llvm/IR/Instruction.h b/include/llvm/IR/Instruction.h
index 03c45497fa95..df4f8df78b12 100644
--- a/include/llvm/IR/Instruction.h
+++ b/include/llvm/IR/Instruction.h
@@ -42,23 +42,23 @@ class Instruction : public User,
DebugLoc DbgLoc; // 'dbg' Metadata cache.
enum {
- /// HasMetadataBit - This is a bit stored in the SubClassData field which
- /// indicates whether this instruction has metadata attached to it or not.
+ /// This is a bit stored in the SubClassData field which indicates whether
+ /// this instruction has metadata attached to it or not.
HasMetadataBit = 1 << 15
};
public:
// Out of line virtual method, so the vtable, etc has a home.
~Instruction() override;
- /// user_back - Specialize the methods defined in Value, as we know that an
- /// instruction can only be used by other instructions.
+ /// Specialize the methods defined in Value, as we know that an instruction
+ /// can only be used by other instructions.
Instruction *user_back() { return cast<Instruction>(*user_begin());}
const Instruction *user_back() const { return cast<Instruction>(*user_begin());}
inline const BasicBlock *getParent() const { return Parent; }
inline BasicBlock *getParent() { return Parent; }
- /// \brief Return the module owning the function this instruction belongs to
+ /// Return the module owning the function this instruction belongs to
/// or nullptr it the function does not have a module.
///
/// Note: this is undefined behavior if the instruction does not have a
@@ -66,20 +66,18 @@ public:
const Module *getModule() const;
Module *getModule();
- /// \brief Return the function this instruction belongs to.
+ /// Return the function this instruction belongs to.
///
/// Note: it is undefined behavior to call this on an instruction not
/// currently inserted into a function.
const Function *getFunction() const;
Function *getFunction();
- /// removeFromParent - This method unlinks 'this' from the containing basic
- /// block, but does not delete it.
- ///
+ /// This method unlinks 'this' from the containing basic block, but does not
+ /// delete it.
void removeFromParent();
- /// eraseFromParent - This method unlinks 'this' from the containing basic
- /// block and deletes it.
+ /// This method unlinks 'this' from the containing basic block and deletes it.
///
/// \returns an iterator pointing to the element after the erased one
SymbolTableList<Instruction>::iterator eraseFromParent();
@@ -92,16 +90,15 @@ public:
/// specified instruction.
void insertAfter(Instruction *InsertPos);
- /// moveBefore - Unlink this instruction from its current basic block and
- /// insert it into the basic block that MovePos lives in, right before
- /// MovePos.
+ /// Unlink this instruction from its current basic block and insert it into
+ /// the basic block that MovePos lives in, right before MovePos.
void moveBefore(Instruction *MovePos);
//===--------------------------------------------------------------------===//
// Subclass classification.
//===--------------------------------------------------------------------===//
- /// getOpcode() returns a member of one of the enums like Instruction::Add.
+ /// Returns a member of one of the enums like Instruction::Add.
unsigned getOpcode() const { return getValueID() - InstructionVal; }
const char *getOpcodeName() const { return getOpcodeName(getOpcode()); }
@@ -121,28 +118,27 @@ public:
return Opcode >= BinaryOpsBegin && Opcode < BinaryOpsEnd;
}
- /// @brief Determine if the Opcode is one of the shift instructions.
+ /// Determine if the Opcode is one of the shift instructions.
static inline bool isShift(unsigned Opcode) {
return Opcode >= Shl && Opcode <= AShr;
}
- /// isLogicalShift - Return true if this is a logical shift left or a logical
- /// shift right.
+ /// Return true if this is a logical shift left or a logical shift right.
inline bool isLogicalShift() const {
return getOpcode() == Shl || getOpcode() == LShr;
}
- /// isArithmeticShift - Return true if this is an arithmetic shift right.
+ /// Return true if this is an arithmetic shift right.
inline bool isArithmeticShift() const {
return getOpcode() == AShr;
}
- /// @brief Determine if the OpCode is one of the CastInst instructions.
+ /// Determine if the OpCode is one of the CastInst instructions.
static inline bool isCast(unsigned OpCode) {
return OpCode >= CastOpsBegin && OpCode < CastOpsEnd;
}
- /// @brief Determine if the OpCode is one of the FuncletPadInst instructions.
+ /// Determine if the OpCode is one of the FuncletPadInst instructions.
static inline bool isFuncletPad(unsigned OpCode) {
return OpCode >= FuncletPadOpsBegin && OpCode < FuncletPadOpsEnd;
}
@@ -151,55 +147,53 @@ public:
// Metadata manipulation.
//===--------------------------------------------------------------------===//
- /// hasMetadata() - Return true if this instruction has any metadata attached
- /// to it.
+ /// Return true if this instruction has any metadata attached to it.
bool hasMetadata() const { return DbgLoc || hasMetadataHashEntry(); }
- /// hasMetadataOtherThanDebugLoc - Return true if this instruction has
- /// metadata attached to it other than a debug location.
+ /// Return true if this instruction has metadata attached to it other than a
+ /// debug location.
bool hasMetadataOtherThanDebugLoc() const {
return hasMetadataHashEntry();
}
- /// getMetadata - Get the metadata of given kind attached to this Instruction.
+ /// Get the metadata of given kind attached to this Instruction.
/// If the metadata is not found then return null.
MDNode *getMetadata(unsigned KindID) const {
if (!hasMetadata()) return nullptr;
return getMetadataImpl(KindID);
}
- /// getMetadata - Get the metadata of given kind attached to this Instruction.
+ /// Get the metadata of given kind attached to this Instruction.
/// If the metadata is not found then return null.
MDNode *getMetadata(StringRef Kind) const {
if (!hasMetadata()) return nullptr;
return getMetadataImpl(Kind);
}
- /// getAllMetadata - Get all metadata attached to this Instruction. The first
- /// element of each pair returned is the KindID, the second element is the
- /// metadata value. This list is returned sorted by the KindID.
+ /// Get all metadata attached to this Instruction. The first element of each
+ /// pair returned is the KindID, the second element is the metadata value.
+ /// This list is returned sorted by the KindID.
void
getAllMetadata(SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const {
if (hasMetadata())
getAllMetadataImpl(MDs);
}
- /// getAllMetadataOtherThanDebugLoc - This does the same thing as
- /// getAllMetadata, except that it filters out the debug location.
+ /// This does the same thing as getAllMetadata, except that it filters out the
+ /// debug location.
void getAllMetadataOtherThanDebugLoc(
SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const {
if (hasMetadataOtherThanDebugLoc())
getAllMetadataOtherThanDebugLocImpl(MDs);
}
- /// getAAMetadata - Fills the AAMDNodes structure with AA metadata from
- /// this instruction. When Merge is true, the existing AA metadata is
- /// merged with that from this instruction providing the most-general result.
+ /// Fills the AAMDNodes structure with AA metadata from this instruction.
+ /// When Merge is true, the existing AA metadata is merged with that from this
+ /// instruction providing the most-general result.
void getAAMetadata(AAMDNodes &N, bool Merge = false) const;
- /// setMetadata - Set the metadata of the specified kind to the specified
- /// node. This updates/replaces metadata if already present, or removes it if
- /// Node is null.
+ /// Set the metadata of the specified kind to the specified node. This updates
+ /// or replaces metadata if already present, or removes it if Node is null.
void setMetadata(unsigned KindID, MDNode *Node);
void setMetadata(StringRef Kind, MDNode *Node);
@@ -220,16 +214,46 @@ public:
}
/// @}
- /// setAAMetadata - Sets the metadata on this instruction from the
- /// AAMDNodes structure.
+ /// Sets the metadata on this instruction from the AAMDNodes structure.
void setAAMetadata(const AAMDNodes &N);
- /// setDebugLoc - Set the debug location information for this instruction.
+ /// Retrieve the raw weight values of a conditional branch or select.
+ /// Returns true on success with profile weights filled in.
+ /// Returns false if no metadata or invalid metadata was found.
+ bool extractProfMetadata(uint64_t &TrueVal, uint64_t &FalseVal);
+
+ /// Retrieve total raw weight values of a branch.
+ /// Returns true on success with profile total weights filled in.
+ /// Returns false if no metadata was found.
+ bool extractProfTotalWeight(uint64_t &TotalVal);
+
+ /// Set the debug location information for this instruction.
void setDebugLoc(DebugLoc Loc) { DbgLoc = std::move(Loc); }
- /// getDebugLoc - Return the debug location for this node as a DebugLoc.
+ /// Return the debug location for this node as a DebugLoc.
const DebugLoc &getDebugLoc() const { return DbgLoc; }
+ /// Set or clear the nsw flag on this instruction, which must be an operator
+ /// which supports this flag. See LangRef.html for the meaning of this flag.
+ void setHasNoUnsignedWrap(bool b = true);
+
+ /// Set or clear the nsw flag on this instruction, which must be an operator
+ /// which supports this flag. See LangRef.html for the meaning of this flag.
+ void setHasNoSignedWrap(bool b = true);
+
+ /// Set or clear the exact flag on this instruction, which must be an operator
+ /// which supports this flag. See LangRef.html for the meaning of this flag.
+ void setIsExact(bool b = true);
+
+ /// Determine whether the no unsigned wrap flag is set.
+ bool hasNoUnsignedWrap() const;
+
+ /// Determine whether the no signed wrap flag is set.
+ bool hasNoSignedWrap() const;
+
+ /// Determine whether the exact flag is set.
+ bool isExact() const;
+
/// Set or clear the unsafe-algebra flag on this instruction, which must be an
/// operator which supports this flag. See LangRef.html for the meaning of
/// this flag.
@@ -288,9 +312,16 @@ public:
/// Copy I's fast-math flags
void copyFastMathFlags(const Instruction *I);
+ /// Convenience method to copy supported wrapping, exact, and fast-math flags
+ /// from V to this instruction.
+ void copyIRFlags(const Value *V);
+
+ /// Logical 'and' of any supported wrapping, exact, and fast-math flags of
+ /// V and this instruction.
+ void andIRFlags(const Value *V);
+
private:
- /// hasMetadataHashEntry - Return true if we have an entry in the on-the-side
- /// metadata hash.
+ /// Return true if we have an entry in the on-the-side metadata hash.
bool hasMetadataHashEntry() const {
return (getSubclassDataFromValue() & HasMetadataBit) != 0;
}
@@ -302,6 +333,7 @@ private:
getAllMetadataImpl(SmallVectorImpl<std::pair<unsigned, MDNode *>> &) const;
void getAllMetadataOtherThanDebugLocImpl(
SmallVectorImpl<std::pair<unsigned, MDNode *>> &) const;
+ /// Clear all hashtable-based metadata from this instruction.
void clearMetadataHashEntries();
public:
//===--------------------------------------------------------------------===//
@@ -309,7 +341,7 @@ public:
//===--------------------------------------------------------------------===//
- /// isAssociative - Return true if the instruction is associative:
+ /// Return true if the instruction is associative:
///
/// Associative operators satisfy: x op (y op z) === (x op y) op z
///
@@ -318,7 +350,7 @@ public:
bool isAssociative() const;
static bool isAssociative(unsigned op);
- /// isCommutative - Return true if the instruction is commutative:
+ /// Return true if the instruction is commutative:
///
/// Commutative operators satisfy: (x op y) === (y op x)
///
@@ -328,7 +360,7 @@ public:
bool isCommutative() const { return isCommutative(getOpcode()); }
static bool isCommutative(unsigned op);
- /// isIdempotent - Return true if the instruction is idempotent:
+ /// Return true if the instruction is idempotent:
///
/// Idempotent operators satisfy: x op x === x
///
@@ -337,7 +369,7 @@ public:
bool isIdempotent() const { return isIdempotent(getOpcode()); }
static bool isIdempotent(unsigned op);
- /// isNilpotent - Return true if the instruction is nilpotent:
+ /// Return true if the instruction is nilpotent:
///
/// Nilpotent operators satisfy: x op x === Id,
///
@@ -349,47 +381,50 @@ public:
bool isNilpotent() const { return isNilpotent(getOpcode()); }
static bool isNilpotent(unsigned op);
- /// mayWriteToMemory - Return true if this instruction may modify memory.
- ///
+ /// Return true if this instruction may modify memory.
bool mayWriteToMemory() const;
- /// mayReadFromMemory - Return true if this instruction may read memory.
- ///
+ /// Return true if this instruction may read memory.
bool mayReadFromMemory() const;
- /// mayReadOrWriteMemory - Return true if this instruction may read or
- /// write memory.
- ///
+ /// Return true if this instruction may read or write memory.
bool mayReadOrWriteMemory() const {
return mayReadFromMemory() || mayWriteToMemory();
}
- /// isAtomic - Return true if this instruction has an
- /// AtomicOrdering of unordered or higher.
- ///
+ /// Return true if this instruction has an AtomicOrdering of unordered or
+ /// higher.
bool isAtomic() const;
- /// mayThrow - Return true if this instruction may throw an exception.
- ///
+ /// Return true if this instruction may throw an exception.
bool mayThrow() const;
- /// mayReturn - Return true if this is a function that may return.
- /// this is true for all normal instructions. The only exception
- /// is functions that are marked with the 'noreturn' attribute.
- ///
- bool mayReturn() const;
+ /// Return true if this instruction behaves like a memory fence: it can load
+ /// or store to memory location without being given a memory location.
+ bool isFenceLike() const {
+ switch (getOpcode()) {
+ default:
+ return false;
+ // This list should be kept in sync with the list in mayWriteToMemory for
+ // all opcodes which don't have a memory location.
+ case Instruction::Fence:
+ case Instruction::CatchPad:
+ case Instruction::CatchRet:
+ case Instruction::Call:
+ case Instruction::Invoke:
+ return true;
+ }
+ }
- /// mayHaveSideEffects - Return true if the instruction may have side effects.
+ /// Return true if the instruction may have side effects.
///
/// Note that this does not consider malloc and alloca to have side
/// effects because the newly allocated memory is completely invisible to
/// instructions which don't use the returned value. For cases where this
/// matters, isSafeToSpeculativelyExecute may be more appropriate.
- bool mayHaveSideEffects() const {
- return mayWriteToMemory() || mayThrow() || !mayReturn();
- }
+ bool mayHaveSideEffects() const { return mayWriteToMemory() || mayThrow(); }
- /// \brief Return true if the instruction is a variety of EH-block.
+ /// Return true if the instruction is a variety of EH-block.
bool isEHPad() const {
switch (getOpcode()) {
case Instruction::CatchSwitch:
@@ -402,21 +437,21 @@ public:
}
}
- /// clone() - Create a copy of 'this' instruction that is identical in all
- /// ways except the following:
+ /// Create a copy of 'this' instruction that is identical in all ways except
+ /// the following:
/// * The instruction has no parent
/// * The instruction has no name
///
Instruction *clone() const;
- /// isIdenticalTo - Return true if the specified instruction is exactly
- /// identical to the current one. This means that all operands match and any
- /// extra information (e.g. load is volatile) agree.
+ /// Return true if the specified instruction is exactly identical to the
+ /// current one. This means that all operands match and any extra information
+ /// (e.g. load is volatile) agree.
bool isIdenticalTo(const Instruction *I) const;
- /// isIdenticalToWhenDefined - This is like isIdenticalTo, except that it
- /// ignores the SubclassOptionalData flags, which specify conditions
- /// under which the instruction's result is undefined.
+ /// This is like isIdenticalTo, except that it ignores the
+ /// SubclassOptionalData flags, which specify conditions under which the
+ /// instruction's result is undefined.
bool isIdenticalToWhenDefined(const Instruction *I) const;
/// When checking for operation equivalence (using isSameOperationAs) it is
@@ -439,10 +474,9 @@ public:
/// @brief Determine if one instruction is the same operation as another.
bool isSameOperationAs(const Instruction *I, unsigned flags = 0) const;
- /// isUsedOutsideOfBlock - Return true if there are any uses of this
- /// instruction in blocks other than the specified block. Note that PHI nodes
- /// are considered to evaluate their operands in the corresponding predecessor
- /// block.
+ /// Return true if there are any uses of this instruction in blocks other than
+ /// the specified block. Note that PHI nodes are considered to evaluate their
+ /// operands in the corresponding predecessor block.
bool isUsedOutsideOfBlock(const BasicBlock *BB) const;
diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h
index 28e1fd90fdf6..be077725f7bc 100644
--- a/include/llvm/IR/Instructions.h
+++ b/include/llvm/IR/Instructions.h
@@ -25,6 +25,7 @@
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/InstrTypes.h"
+#include "llvm/Support/AtomicOrdering.h"
#include "llvm/Support/ErrorHandling.h"
#include <iterator>
@@ -36,38 +37,11 @@ class ConstantRange;
class DataLayout;
class LLVMContext;
-enum AtomicOrdering {
- NotAtomic = 0,
- Unordered = 1,
- Monotonic = 2,
- // Consume = 3, // Not specified yet.
- Acquire = 4,
- Release = 5,
- AcquireRelease = 6,
- SequentiallyConsistent = 7
-};
-
enum SynchronizationScope {
SingleThread = 0,
CrossThread = 1
};
-/// Returns true if the ordering is at least as strong as acquire
-/// (i.e. acquire, acq_rel or seq_cst)
-inline bool isAtLeastAcquire(AtomicOrdering Ord) {
- return (Ord == Acquire ||
- Ord == AcquireRelease ||
- Ord == SequentiallyConsistent);
-}
-
-/// Returns true if the ordering is at least as strong as release
-/// (i.e. release, acq_rel or seq_cst)
-inline bool isAtLeastRelease(AtomicOrdering Ord) {
-return (Ord == Release ||
- Ord == AcquireRelease ||
- Ord == SequentiallyConsistent);
-}
-
//===----------------------------------------------------------------------===//
// AllocaInst Class
//===----------------------------------------------------------------------===//
@@ -152,6 +126,18 @@ public:
(V ? 32 : 0));
}
+ /// \brief Return true if this alloca is used as a swifterror argument to a
+ /// call.
+ bool isSwiftError() const {
+ return getSubclassDataFromInstruction() & 64;
+ }
+
+ /// \brief Specify whether this alloca is used to represent a swifterror.
+ void setSwiftError(bool V) {
+ setInstructionSubclassData((getSubclassDataFromInstruction() & ~64) |
+ (V ? 64 : 0));
+ }
+
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const Instruction *I) {
return (I->getOpcode() == Instruction::Alloca);
@@ -257,7 +243,7 @@ public:
/// AcquireRelease.
void setOrdering(AtomicOrdering Ordering) {
setInstructionSubclassData((getSubclassDataFromInstruction() & ~(7 << 7)) |
- (Ordering << 7));
+ ((unsigned)Ordering << 7));
}
SynchronizationScope getSynchScope() const {
@@ -280,7 +266,9 @@ public:
bool isSimple() const { return !isAtomic() && !isVolatile(); }
bool isUnordered() const {
- return getOrdering() <= Unordered && !isVolatile();
+ return (getOrdering() == AtomicOrdering::NotAtomic ||
+ getOrdering() == AtomicOrdering::Unordered) &&
+ !isVolatile();
}
Value *getPointerOperand() { return getOperand(0); }
@@ -378,7 +366,7 @@ public:
/// AcquireRelease.
void setOrdering(AtomicOrdering Ordering) {
setInstructionSubclassData((getSubclassDataFromInstruction() & ~(7 << 7)) |
- (Ordering << 7));
+ ((unsigned)Ordering << 7));
}
SynchronizationScope getSynchScope() const {
@@ -401,7 +389,9 @@ public:
bool isSimple() const { return !isAtomic() && !isVolatile(); }
bool isUnordered() const {
- return getOrdering() <= Unordered && !isVolatile();
+ return (getOrdering() == AtomicOrdering::NotAtomic ||
+ getOrdering() == AtomicOrdering::Unordered) &&
+ !isVolatile();
}
Value *getValueOperand() { return getOperand(0); }
@@ -477,7 +467,7 @@ public:
/// AcquireRelease, or SequentiallyConsistent.
void setOrdering(AtomicOrdering Ordering) {
setInstructionSubclassData((getSubclassDataFromInstruction() & 1) |
- (Ordering << 1));
+ ((unsigned)Ordering << 1));
}
SynchronizationScope getSynchScope() const {
@@ -572,17 +562,17 @@ public:
/// Set the ordering constraint on this cmpxchg.
void setSuccessOrdering(AtomicOrdering Ordering) {
- assert(Ordering != NotAtomic &&
+ assert(Ordering != AtomicOrdering::NotAtomic &&
"CmpXchg instructions can only be atomic.");
setInstructionSubclassData((getSubclassDataFromInstruction() & ~0x1c) |
- (Ordering << 2));
+ ((unsigned)Ordering << 2));
}
void setFailureOrdering(AtomicOrdering Ordering) {
- assert(Ordering != NotAtomic &&
+ assert(Ordering != AtomicOrdering::NotAtomic &&
"CmpXchg instructions can only be atomic.");
setInstructionSubclassData((getSubclassDataFromInstruction() & ~0xe0) |
- (Ordering << 5));
+ ((unsigned)Ordering << 5));
}
/// Specify whether this cmpxchg is atomic and orders other operations with
@@ -634,15 +624,16 @@ public:
static AtomicOrdering
getStrongestFailureOrdering(AtomicOrdering SuccessOrdering) {
switch (SuccessOrdering) {
- default: llvm_unreachable("invalid cmpxchg success ordering");
- case Release:
- case Monotonic:
- return Monotonic;
- case AcquireRelease:
- case Acquire:
- return Acquire;
- case SequentiallyConsistent:
- return SequentiallyConsistent;
+ default:
+ llvm_unreachable("invalid cmpxchg success ordering");
+ case AtomicOrdering::Release:
+ case AtomicOrdering::Monotonic:
+ return AtomicOrdering::Monotonic;
+ case AtomicOrdering::AcquireRelease:
+ case AtomicOrdering::Acquire:
+ return AtomicOrdering::Acquire;
+ case AtomicOrdering::SequentiallyConsistent:
+ return AtomicOrdering::SequentiallyConsistent;
}
}
@@ -758,10 +749,10 @@ public:
/// Set the ordering constraint on this RMW.
void setOrdering(AtomicOrdering Ordering) {
- assert(Ordering != NotAtomic &&
+ assert(Ordering != AtomicOrdering::NotAtomic &&
"atomicrmw instructions can only be atomic.");
setInstructionSubclassData((getSubclassDataFromInstruction() & ~(7 << 2)) |
- (Ordering << 2));
+ ((unsigned)Ordering << 2));
}
/// Specify whether this RMW orders other operations with respect to all
@@ -1490,9 +1481,29 @@ public:
Value *AllocSize, Value *ArraySize = nullptr,
Function* MallocF = nullptr,
const Twine &Name = "");
+ static Instruction *CreateMalloc(Instruction *InsertBefore,
+ Type *IntPtrTy, Type *AllocTy,
+ Value *AllocSize, Value *ArraySize = nullptr,
+ ArrayRef<OperandBundleDef> Bundles = None,
+ Function* MallocF = nullptr,
+ const Twine &Name = "");
+ static Instruction *CreateMalloc(BasicBlock *InsertAtEnd,
+ Type *IntPtrTy, Type *AllocTy,
+ Value *AllocSize, Value *ArraySize = nullptr,
+ ArrayRef<OperandBundleDef> Bundles = None,
+ Function* MallocF = nullptr,
+ const Twine &Name = "");
/// CreateFree - Generate the IR for a call to the builtin free function.
- static Instruction* CreateFree(Value* Source, Instruction *InsertBefore);
- static Instruction* CreateFree(Value* Source, BasicBlock *InsertAtEnd);
+ static Instruction *CreateFree(Value *Source,
+ Instruction *InsertBefore);
+ static Instruction *CreateFree(Value *Source,
+ BasicBlock *InsertAtEnd);
+ static Instruction *CreateFree(Value *Source,
+ ArrayRef<OperandBundleDef> Bundles,
+ Instruction *InsertBefore);
+ static Instruction *CreateFree(Value *Source,
+ ArrayRef<OperandBundleDef> Bundles,
+ BasicBlock *InsertAtEnd);
~CallInst() override;
@@ -1586,6 +1597,10 @@ public:
return getOperandUse(i);
}
+ /// If one of the arguments has the 'returned' attribute, return its
+ /// operand value. Otherwise, return nullptr.
+ Value *getReturnedArgOperand() const;
+
/// getCallingConv/setCallingConv - Get or set the calling convention of this
/// function call.
CallingConv::ID getCallingConv() const {
@@ -1607,13 +1622,22 @@ public:
void setAttributes(const AttributeSet &Attrs) { AttributeList = Attrs; }
/// addAttribute - adds the attribute to the list of attributes.
- void addAttribute(unsigned i, Attribute::AttrKind attr);
+ void addAttribute(unsigned i, Attribute::AttrKind Kind);
/// addAttribute - adds the attribute to the list of attributes.
void addAttribute(unsigned i, StringRef Kind, StringRef Value);
+ /// addAttribute - adds the attribute to the list of attributes.
+ void addAttribute(unsigned i, Attribute Attr);
+
+ /// removeAttribute - removes the attribute from the list of attributes.
+ void removeAttribute(unsigned i, Attribute::AttrKind Kind);
+
+ /// removeAttribute - removes the attribute from the list of attributes.
+ void removeAttribute(unsigned i, StringRef Kind);
+
/// removeAttribute - removes the attribute from the list of attributes.
- void removeAttribute(unsigned i, Attribute attr);
+ void removeAttribute(unsigned i, Attribute Attr);
/// \brief adds the dereferenceable attribute to the list of attributes.
void addDereferenceableAttr(unsigned i, uint64_t Bytes);
@@ -1623,19 +1647,25 @@ public:
void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes);
/// \brief Determine whether this call has the given attribute.
- bool hasFnAttr(Attribute::AttrKind A) const {
- assert(A != Attribute::NoBuiltin &&
+ bool hasFnAttr(Attribute::AttrKind Kind) const {
+ assert(Kind != Attribute::NoBuiltin &&
"Use CallInst::isNoBuiltin() to check for Attribute::NoBuiltin");
- return hasFnAttrImpl(A);
+ return hasFnAttrImpl(Kind);
}
/// \brief Determine whether this call has the given attribute.
- bool hasFnAttr(StringRef A) const {
- return hasFnAttrImpl(A);
+ bool hasFnAttr(StringRef Kind) const {
+ return hasFnAttrImpl(Kind);
}
/// \brief Determine whether the call or the callee has the given attributes.
- bool paramHasAttr(unsigned i, Attribute::AttrKind A) const;
+ bool paramHasAttr(unsigned i, Attribute::AttrKind Kind) const;
+
+ /// \brief Get the attribute of a given kind at a position.
+ Attribute getAttribute(unsigned i, Attribute::AttrKind Kind) const;
+
+ /// \brief Get the attribute of a given kind at a position.
+ Attribute getAttribute(unsigned i, StringRef Kind) const;
/// \brief Return true if the data operand at index \p i has the attribute \p
/// A.
@@ -1650,7 +1680,7 @@ public:
/// \p i in [1, arg_size + 1) -> argument number (\p i - 1)
/// \p i in [arg_size + 1, data_operand_size + 1) -> bundle operand at index
/// (\p i - 1) in the operand list.
- bool dataOperandHasImpliedAttr(unsigned i, Attribute::AttrKind A) const;
+ bool dataOperandHasImpliedAttr(unsigned i, Attribute::AttrKind Kind) const;
/// \brief Extract the alignment for a call or parameter (0=unknown).
unsigned getParamAlignment(unsigned i) const {
@@ -1713,6 +1743,14 @@ public:
addAttribute(AttributeSet::FunctionIndex, Attribute::ReadOnly);
}
+ /// \brief Determine if the call does not access or only writes memory.
+ bool doesNotReadMemory() const {
+ return doesNotAccessMemory() || hasFnAttr(Attribute::WriteOnly);
+ }
+ void setDoesNotReadMemory() {
+ addAttribute(AttributeSet::FunctionIndex, Attribute::WriteOnly);
+ }
+
/// @brief Determine if the call can access memmory only using pointers based
/// on its arguments.
bool onlyAccessesArgMemory() const {
@@ -1745,6 +1783,10 @@ public:
void setConvergent() {
addAttribute(AttributeSet::FunctionIndex, Attribute::Convergent);
}
+ void setNotConvergent() {
+ removeAttribute(AttributeSet::FunctionIndex,
+ Attribute::get(getContext(), Attribute::Convergent));
+ }
/// \brief Determine if the call returns a structure through first
/// pointer argument.
@@ -1906,6 +1948,10 @@ public:
Value *getTrueValue() { return Op<1>(); }
Value *getFalseValue() { return Op<2>(); }
+ void setCondition(Value *V) { Op<0>() = V; }
+ void setTrueValue(Value *V) { Op<1>() = V; }
+ void setFalseValue(Value *V) { Op<2>() = V; }
+
/// areInvalidOperands - Return a string if the specified operands are invalid
/// for a select operation, otherwise return null.
static const char *areInvalidOperands(Value *Cond, Value *True, Value *False);
@@ -2619,6 +2665,11 @@ public:
/// same value, return the value, otherwise return null.
Value *hasConstantValue() const;
+ /// hasConstantOrUndefValue - Whether the specified PHI node always merges
+ /// together the same value, assuming undefs are equal to a unique
+ /// non-undef value.
+ bool hasConstantOrUndefValue() const;
+
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::PHI;
@@ -2928,7 +2979,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BranchInst, Value)
//===----------------------------------------------------------------------===//
//===---------------------------------------------------------------------------
-/// SwitchInst - Multiway switch
+/// Multiway switch
///
class SwitchInst : public TerminatorInst {
void *operator new(size_t, unsigned) = delete;
@@ -2944,17 +2995,17 @@ class SwitchInst : public TerminatorInst {
void *operator new(size_t s) {
return User::operator new(s);
}
- /// SwitchInst ctor - Create a new switch instruction, specifying a value to
- /// switch on and a default destination. The number of additional cases can
- /// be specified here to make memory allocation more efficient. This
- /// constructor can also autoinsert before another instruction.
+ /// Create a new switch instruction, specifying a value to switch on and a
+ /// default destination. The number of additional cases can be specified here
+ /// to make memory allocation more efficient. This constructor can also
+ /// auto-insert before another instruction.
SwitchInst(Value *Value, BasicBlock *Default, unsigned NumCases,
Instruction *InsertBefore);
- /// SwitchInst ctor - Create a new switch instruction, specifying a value to
- /// switch on and a default destination. The number of additional cases can
- /// be specified here to make memory allocation more efficient. This
- /// constructor also autoinserts at the end of the specified BasicBlock.
+ /// Create a new switch instruction, specifying a value to switch on and a
+ /// default destination. The number of additional cases can be specified here
+ /// to make memory allocation more efficient. This constructor also
+ /// auto-inserts at the end of the specified BasicBlock.
SwitchInst(Value *Value, BasicBlock *Default, unsigned NumCases,
BasicBlock *InsertAtEnd);
@@ -3104,40 +3155,40 @@ public:
setOperand(1, reinterpret_cast<Value*>(DefaultCase));
}
- /// getNumCases - return the number of 'cases' in this switch instruction,
- /// except the default case
+ /// Return the number of 'cases' in this switch instruction, excluding the
+ /// default case.
unsigned getNumCases() const {
return getNumOperands()/2 - 1;
}
- /// Returns a read/write iterator that points to the first
- /// case in SwitchInst.
+ /// Returns a read/write iterator that points to the first case in the
+ /// SwitchInst.
CaseIt case_begin() {
return CaseIt(this, 0);
}
- /// Returns a read-only iterator that points to the first
- /// case in the SwitchInst.
+ /// Returns a read-only iterator that points to the first case in the
+ /// SwitchInst.
ConstCaseIt case_begin() const {
return ConstCaseIt(this, 0);
}
- /// Returns a read/write iterator that points one past the last
- /// in the SwitchInst.
+ /// Returns a read/write iterator that points one past the last in the
+ /// SwitchInst.
CaseIt case_end() {
return CaseIt(this, getNumCases());
}
- /// Returns a read-only iterator that points one past the last
- /// in the SwitchInst.
+ /// Returns a read-only iterator that points one past the last in the
+ /// SwitchInst.
ConstCaseIt case_end() const {
return ConstCaseIt(this, getNumCases());
}
- /// cases - iteration adapter for range-for loops.
+ /// Iteration adapter for range-for loops.
iterator_range<CaseIt> cases() {
return make_range(case_begin(), case_end());
}
- /// cases - iteration adapter for range-for loops.
+ /// Constant iteration adapter for range-for loops.
iterator_range<ConstCaseIt> cases() const {
return make_range(case_begin(), case_end());
}
@@ -3154,10 +3205,10 @@ public:
return ConstCaseIt(this, DefaultPseudoIndex);
}
- /// findCaseValue - Search all of the case values for the specified constant.
- /// If it is explicitly handled, return the case iterator of it, otherwise
- /// return default case iterator to indicate
- /// that it is handled by the default handler.
+ /// Search all of the case values for the specified constant. If it is
+ /// explicitly handled, return the case iterator of it, otherwise return
+ /// default case iterator to indicate that it is handled by the default
+ /// handler.
CaseIt findCaseValue(const ConstantInt *C) {
for (CaseIt i = case_begin(), e = case_end(); i != e; ++i)
if (i.getCaseValue() == C)
@@ -3171,8 +3222,8 @@ public:
return case_default();
}
- /// findCaseDest - Finds the unique case value for a given successor. Returns
- /// null if the successor is not found, not unique, or is the default case.
+ /// Finds the unique case value for a given successor. Returns null if the
+ /// successor is not found, not unique, or is the default case.
ConstantInt *findCaseDest(BasicBlock *BB) {
if (BB == getDefaultDest()) return nullptr;
@@ -3186,15 +3237,15 @@ public:
return CI;
}
- /// addCase - Add an entry to the switch instruction...
+ /// Add an entry to the switch instruction.
/// Note:
/// This action invalidates case_end(). Old case_end() iterator will
/// point to the added case.
void addCase(ConstantInt *OnVal, BasicBlock *Dest);
- /// removeCase - This method removes the specified case and its successor
- /// from the switch instruction. Note that this operation may reorder the
- /// remaining cases at index idx and above.
+ /// This method removes the specified case and its successor from the switch
+ /// instruction. Note that this operation may reorder the remaining cases at
+ /// index idx and above.
/// Note:
/// This action invalidates iterators for all cases following the one removed,
/// including the case_end() iterator.
@@ -3519,6 +3570,10 @@ public:
return getOperandUse(i);
}
+ /// If one of the arguments has the 'returned' attribute, return its
+ /// operand value. Otherwise, return nullptr.
+ Value *getReturnedArgOperand() const;
+
/// getCallingConv/setCallingConv - Get or set the calling convention of this
/// function call.
CallingConv::ID getCallingConv() const {
@@ -3539,10 +3594,19 @@ public:
void setAttributes(const AttributeSet &Attrs) { AttributeList = Attrs; }
/// addAttribute - adds the attribute to the list of attributes.
- void addAttribute(unsigned i, Attribute::AttrKind attr);
+ void addAttribute(unsigned i, Attribute::AttrKind Kind);
+
+ /// addAttribute - adds the attribute to the list of attributes.
+ void addAttribute(unsigned i, Attribute Attr);
+
+ /// removeAttribute - removes the attribute from the list of attributes.
+ void removeAttribute(unsigned i, Attribute::AttrKind Kind);
+
+ /// removeAttribute - removes the attribute from the list of attributes.
+ void removeAttribute(unsigned i, StringRef Kind);
/// removeAttribute - removes the attribute from the list of attributes.
- void removeAttribute(unsigned i, Attribute attr);
+ void removeAttribute(unsigned i, Attribute Attr);
/// \brief adds the dereferenceable attribute to the list of attributes.
void addDereferenceableAttr(unsigned i, uint64_t Bytes);
@@ -3552,19 +3616,25 @@ public:
void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes);
/// \brief Determine whether this call has the given attribute.
- bool hasFnAttr(Attribute::AttrKind A) const {
- assert(A != Attribute::NoBuiltin &&
+ bool hasFnAttr(Attribute::AttrKind Kind) const {
+ assert(Kind != Attribute::NoBuiltin &&
"Use CallInst::isNoBuiltin() to check for Attribute::NoBuiltin");
- return hasFnAttrImpl(A);
+ return hasFnAttrImpl(Kind);
}
/// \brief Determine whether this call has the given attribute.
- bool hasFnAttr(StringRef A) const {
- return hasFnAttrImpl(A);
+ bool hasFnAttr(StringRef Kind) const {
+ return hasFnAttrImpl(Kind);
}
/// \brief Determine whether the call or the callee has the given attributes.
- bool paramHasAttr(unsigned i, Attribute::AttrKind A) const;
+ bool paramHasAttr(unsigned i, Attribute::AttrKind Kind) const;
+
+ /// \brief Get the attribute of a given kind at a position.
+ Attribute getAttribute(unsigned i, Attribute::AttrKind Kind) const;
+
+ /// \brief Get the attribute of a given kind at a position.
+ Attribute getAttribute(unsigned i, StringRef Kind) const;
/// \brief Return true if the data operand at index \p i has the attribute \p
/// A.
@@ -3580,7 +3650,7 @@ public:
/// \p i in [1, arg_size + 1) -> argument number (\p i - 1)
/// \p i in [arg_size + 1, data_operand_size + 1) -> bundle operand at index
/// (\p i - 1) in the operand list.
- bool dataOperandHasImpliedAttr(unsigned i, Attribute::AttrKind A) const;
+ bool dataOperandHasImpliedAttr(unsigned i, Attribute::AttrKind Kind) const;
/// \brief Extract the alignment for a call or parameter (0=unknown).
unsigned getParamAlignment(unsigned i) const {
@@ -3637,6 +3707,14 @@ public:
addAttribute(AttributeSet::FunctionIndex, Attribute::ReadOnly);
}
+ /// \brief Determine if the call does not access or only writes memory.
+ bool doesNotReadMemory() const {
+ return doesNotAccessMemory() || hasFnAttr(Attribute::WriteOnly);
+ }
+ void setDoesNotReadMemory() {
+ addAttribute(AttributeSet::FunctionIndex, Attribute::WriteOnly);
+ }
+
/// @brief Determine if the call access memmory only using it's pointer
/// arguments.
bool onlyAccessesArgMemory() const {
@@ -3664,6 +3742,16 @@ public:
addAttribute(AttributeSet::FunctionIndex, Attribute::NoDuplicate);
}
+ /// \brief Determine if the invoke is convergent
+ bool isConvergent() const { return hasFnAttr(Attribute::Convergent); }
+ void setConvergent() {
+ addAttribute(AttributeSet::FunctionIndex, Attribute::Convergent);
+ }
+ void setNotConvergent() {
+ removeAttribute(AttributeSet::FunctionIndex,
+ Attribute::get(getContext(), Attribute::Convergent));
+ }
+
/// \brief Determine if the call returns a structure through first
/// pointer argument.
bool hasStructRetAttr() const {
@@ -4160,7 +4248,9 @@ public:
}
unsigned getNumSuccessors() const { return 1; }
- Value *getParentPad() const {
+ /// Get the parentPad of this catchret's catchpad's catchswitch.
+ /// The successor block is implicitly a member of this funclet.
+ Value *getCatchSwitchParentPad() const {
return getCatchPad()->getCatchSwitch()->getParentPad();
}
@@ -4826,6 +4916,31 @@ public:
static inline bool classof(const Value *V) {
return isa<Instruction>(V) && classof(cast<Instruction>(V));
}
+
+ /// \brief Gets the pointer operand.
+ Value *getPointerOperand() {
+ return getOperand(0);
+ }
+
+ /// \brief Gets the pointer operand.
+ const Value *getPointerOperand() const {
+ return getOperand(0);
+ }
+
+ /// \brief Gets the operand index of the pointer operand.
+ static unsigned getPointerOperandIndex() {
+ return 0U;
+ }
+
+ /// \brief Returns the address space of the pointer operand.
+ unsigned getSrcAddressSpace() const {
+ return getPointerOperand()->getType()->getPointerAddressSpace();
+ }
+
+ /// \brief Returns the address space of the result.
+ unsigned getDestAddressSpace() const {
+ return getType()->getPointerAddressSpace();
+ }
};
} // End llvm namespace
diff --git a/include/llvm/IR/IntrinsicInst.h b/include/llvm/IR/IntrinsicInst.h
index 169bcc021984..52044e0a0cc8 100644
--- a/include/llvm/IR/IntrinsicInst.h
+++ b/include/llvm/IR/IntrinsicInst.h
@@ -31,16 +31,15 @@
#include "llvm/IR/Metadata.h"
namespace llvm {
- /// IntrinsicInst - A useful wrapper class for inspecting calls to intrinsic
- /// functions. This allows the standard isa/dyncast/cast functionality to
- /// work with calls to intrinsic functions.
+ /// A wrapper class for inspecting calls to intrinsic functions.
+ /// This allows the standard isa/dyncast/cast functionality to work with calls
+ /// to intrinsic functions.
class IntrinsicInst : public CallInst {
IntrinsicInst() = delete;
IntrinsicInst(const IntrinsicInst&) = delete;
void operator=(const IntrinsicInst&) = delete;
public:
- /// getIntrinsicID - Return the intrinsic ID of this intrinsic.
- ///
+ /// Return the intrinsic ID of this intrinsic.
Intrinsic::ID getIntrinsicID() const {
return getCalledFunction()->getIntrinsicID();
}
@@ -56,10 +55,13 @@ namespace llvm {
}
};
- /// DbgInfoIntrinsic - This is the common base class for debug info intrinsics
- ///
+ /// This is the common base class for debug info intrinsics.
class DbgInfoIntrinsic : public IntrinsicInst {
public:
+ /// Get the location corresponding to the variable referenced by the debug
+ /// info intrinsic. Depending on the intrinsic, this could be the
+ /// variable's value or its address.
+ Value *getVariableLocation(bool AllowNullOp = true) const;
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const IntrinsicInst *I) {
@@ -73,15 +75,12 @@ namespace llvm {
static inline bool classof(const Value *V) {
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
}
-
- static Value *StripCast(Value *C);
};
- /// DbgDeclareInst - This represents the llvm.dbg.declare instruction.
- ///
+ /// This represents the llvm.dbg.declare instruction.
class DbgDeclareInst : public DbgInfoIntrinsic {
public:
- Value *getAddress() const;
+ Value *getAddress() const { return getVariableLocation(); }
DILocalVariable *getVariable() const {
return cast<DILocalVariable>(getRawVariable());
}
@@ -105,12 +104,12 @@ namespace llvm {
}
};
- /// DbgValueInst - This represents the llvm.dbg.value instruction.
- ///
+ /// This represents the llvm.dbg.value instruction.
class DbgValueInst : public DbgInfoIntrinsic {
public:
- const Value *getValue() const;
- Value *getValue();
+ Value *getValue() const {
+ return getVariableLocation(/* AllowNullOp = */ false);
+ }
uint64_t getOffset() const {
return cast<ConstantInt>(
const_cast<Value*>(getArgOperand(1)))->getZExtValue();
@@ -138,8 +137,7 @@ namespace llvm {
}
};
- /// MemIntrinsic - This is the common base class for memset/memcpy/memmove.
- ///
+ /// This is the common base class for memset/memcpy/memmove.
class MemIntrinsic : public IntrinsicInst {
public:
Value *getRawDest() const { return const_cast<Value*>(getArgOperand(0)); }
@@ -169,13 +167,12 @@ namespace llvm {
return cast<PointerType>(getRawDest()->getType())->getAddressSpace();
}
- /// getDest - This is just like getRawDest, but it strips off any cast
+ /// This is just like getRawDest, but it strips off any cast
/// instructions that feed it, giving the original input. The returned
/// value is guaranteed to be a pointer.
Value *getDest() const { return getRawDest()->stripPointerCasts(); }
- /// set* - Set the specified arguments of the instruction.
- ///
+ /// Set the specified arguments of the instruction.
void setDest(Value *Ptr) {
assert(getRawDest()->getType() == Ptr->getType() &&
"setDest called with pointer of wrong type!");
@@ -215,12 +212,10 @@ namespace llvm {
}
};
- /// MemSetInst - This class wraps the llvm.memset intrinsic.
- ///
+ /// This class wraps the llvm.memset intrinsic.
class MemSetInst : public MemIntrinsic {
public:
- /// get* - Return the arguments to the instruction.
- ///
+ /// Return the arguments to the instruction.
Value *getValue() const { return const_cast<Value*>(getArgOperand(1)); }
const Use &getValueUse() const { return getArgOperandUse(1); }
Use &getValueUse() { return getArgOperandUse(1); }
@@ -240,17 +235,15 @@ namespace llvm {
}
};
- /// MemTransferInst - This class wraps the llvm.memcpy/memmove intrinsics.
- ///
+ /// This class wraps the llvm.memcpy/memmove intrinsics.
class MemTransferInst : public MemIntrinsic {
public:
- /// get* - Return the arguments to the instruction.
- ///
+ /// Return the arguments to the instruction.
Value *getRawSource() const { return const_cast<Value*>(getArgOperand(1)); }
const Use &getRawSourceUse() const { return getArgOperandUse(1); }
Use &getRawSourceUse() { return getArgOperandUse(1); }
- /// getSource - This is just like getRawSource, but it strips off any cast
+ /// This is just like getRawSource, but it strips off any cast
/// instructions that feed it, giving the original input. The returned
/// value is guaranteed to be a pointer.
Value *getSource() const { return getRawSource()->stripPointerCasts(); }
@@ -276,8 +269,7 @@ namespace llvm {
};
- /// MemCpyInst - This class wraps the llvm.memcpy intrinsic.
- ///
+ /// This class wraps the llvm.memcpy intrinsic.
class MemCpyInst : public MemTransferInst {
public:
// Methods for support type inquiry through isa, cast, and dyn_cast:
@@ -289,8 +281,7 @@ namespace llvm {
}
};
- /// MemMoveInst - This class wraps the llvm.memmove intrinsic.
- ///
+ /// This class wraps the llvm.memmove intrinsic.
class MemMoveInst : public MemTransferInst {
public:
// Methods for support type inquiry through isa, cast, and dyn_cast:
@@ -302,8 +293,7 @@ namespace llvm {
}
};
- /// VAStartInst - This represents the llvm.va_start intrinsic.
- ///
+ /// This represents the llvm.va_start intrinsic.
class VAStartInst : public IntrinsicInst {
public:
static inline bool classof(const IntrinsicInst *I) {
@@ -316,8 +306,7 @@ namespace llvm {
Value *getArgList() const { return const_cast<Value*>(getArgOperand(0)); }
};
- /// VAEndInst - This represents the llvm.va_end intrinsic.
- ///
+ /// This represents the llvm.va_end intrinsic.
class VAEndInst : public IntrinsicInst {
public:
static inline bool classof(const IntrinsicInst *I) {
@@ -330,8 +319,7 @@ namespace llvm {
Value *getArgList() const { return const_cast<Value*>(getArgOperand(0)); }
};
- /// VACopyInst - This represents the llvm.va_copy intrinsic.
- ///
+ /// This represents the llvm.va_copy intrinsic.
class VACopyInst : public IntrinsicInst {
public:
static inline bool classof(const IntrinsicInst *I) {
diff --git a/include/llvm/IR/Intrinsics.h b/include/llvm/IR/Intrinsics.h
index 314e2aaecf4b..7a87c2167710 100644
--- a/include/llvm/IR/Intrinsics.h
+++ b/include/llvm/IR/Intrinsics.h
@@ -17,6 +17,8 @@
#define LLVM_IR_INTRINSICS_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
#include <string>
namespace llvm {
@@ -69,6 +71,13 @@ namespace Intrinsic {
/// the intrinsic.
Function *getDeclaration(Module *M, ID id, ArrayRef<Type*> Tys = None);
+ /// Looks up Name in NameTable via binary search. NameTable must be sorted
+ /// and all entries must start with "llvm.". If NameTable contains an exact
+ /// match for Name or a prefix of Name followed by a dot, its index in
+ /// NameTable is returned. Otherwise, -1 is returned.
+ int lookupLLVMIntrinsicByName(ArrayRef<const char *> NameTable,
+ StringRef Name);
+
/// Map a GCC builtin name to an intrinsic ID.
ID getIntrinsicForGCCBuiltin(const char *Prefix, const char *BuiltinName);
@@ -126,6 +135,25 @@ namespace Intrinsic {
/// of IITDescriptors.
void getIntrinsicInfoTableEntries(ID id, SmallVectorImpl<IITDescriptor> &T);
+ /// Match the specified type (which comes from an intrinsic argument or return
+ /// value) with the type constraints specified by the .td file. If the given
+ /// type is an overloaded type it is pushed to the ArgTys vector.
+ ///
+ /// Returns false if the given type matches with the constraints, true
+ /// otherwise.
+ bool matchIntrinsicType(Type *Ty, ArrayRef<IITDescriptor> &Infos,
+ SmallVectorImpl<Type*> &ArgTys);
+
+ /// Verify if the intrinsic has variable arguments. This method is intended to
+ /// be called after all the fixed arguments have been matched first.
+ ///
+ /// This method returns true on error.
+ bool matchIntrinsicVarArg(bool isVarArg, ArrayRef<IITDescriptor> &Infos);
+
+ // Checks if the intrinsic name matches with its signature and if not
+ // returns the declaration with the same signature and remangled name.
+ llvm::Optional<Function*> remangleIntrinsicFunction(Function *F);
+
} // End Intrinsic namespace
} // End llvm namespace
diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td
index f67029ab56e3..5ece731fa143 100644
--- a/include/llvm/IR/Intrinsics.td
+++ b/include/llvm/IR/Intrinsics.td
@@ -19,9 +19,7 @@ include "llvm/CodeGen/ValueTypes.td"
class IntrinsicProperty;
-// Intr*Mem - Memory properties. An intrinsic is allowed to have at most one of
-// these properties set. They are listed from the most aggressive (best to use
-// if correct) to the least aggressive. If no property is set, the worst case
+// Intr*Mem - Memory properties. If no property is set, the worst case
// is assumed (it may read and write any memory it can get access to and it may
// have other side effects).
@@ -29,20 +27,21 @@ class IntrinsicProperty;
// effects. It may be CSE'd deleted if dead, etc.
def IntrNoMem : IntrinsicProperty;
-// IntrReadArgMem - This intrinsic reads only from memory that one of its
-// pointer-typed arguments points to, but may read an unspecified amount.
-def IntrReadArgMem : IntrinsicProperty;
-
-// IntrReadMem - This intrinsic reads from unspecified memory, so it cannot be
-// moved across stores. However, it can be reordered otherwise and can be
-// deleted if dead.
+// IntrReadMem - This intrinsic only reads from memory. It does not write to
+// memory and has no other side effects. Therefore, it cannot be moved across
+// potentially aliasing stores. However, it can be reordered otherwise and can
+// be deleted if dead.
def IntrReadMem : IntrinsicProperty;
-// IntrReadWriteArgMem - This intrinsic reads and writes only from memory that
-// one of its arguments points to, but may access an unspecified amount. The
-// reads and writes may be volatile, but except for this it has no other side
-// effects.
-def IntrReadWriteArgMem : IntrinsicProperty;
+// IntrWriteMem - This intrinsic only writes to memory, but does not read from
+// memory, and has no other side effects. This means dead stores before calls
+// to this intrinsics may be removed.
+def IntrWriteMem : IntrinsicProperty;
+
+// IntrArgMemOnly - This intrinsic only accesses memory that its pointer-typed
+// argument(s) points to, but may access an unspecified amount. Other than
+// reads from and (possibly volatile) writes to memory, it has no side effects.
+def IntrArgMemOnly : IntrinsicProperty;
// Commutative - This intrinsic is commutative: X op Y == Y op X.
def Commutative : IntrinsicProperty;
@@ -55,12 +54,24 @@ class NoCapture<int argNo> : IntrinsicProperty {
int ArgNo = argNo;
}
+// Returned - The specified argument is always the return value of the
+// intrinsic.
+class Returned<int argNo> : IntrinsicProperty {
+ int ArgNo = argNo;
+}
+
// ReadOnly - The specified argument pointer is not written to through the
// pointer by the intrinsic.
class ReadOnly<int argNo> : IntrinsicProperty {
int ArgNo = argNo;
}
+// WriteOnly - The intrinsic does not read memory through the specified
+// argument pointer.
+class WriteOnly<int argNo> : IntrinsicProperty {
+ int ArgNo = argNo;
+}
+
// ReadNone - The specified argument pointer is not dereferenced by the
// intrinsic.
class ReadNone<int argNo> : IntrinsicProperty {
@@ -240,7 +251,7 @@ class Intrinsic<list<LLVMType> ret_types,
string TargetPrefix = ""; // Set to a prefix for target-specific intrinsics.
list<LLVMType> RetTypes = ret_types;
list<LLVMType> ParamTypes = param_types;
- list<IntrinsicProperty> Properties = properties;
+ list<IntrinsicProperty> IntrProperties = properties;
bit isTarget = 0;
}
@@ -271,10 +282,10 @@ def int_gcroot : Intrinsic<[],
[llvm_ptrptr_ty, llvm_ptr_ty]>;
def int_gcread : Intrinsic<[llvm_ptr_ty],
[llvm_ptr_ty, llvm_ptrptr_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_gcwrite : Intrinsic<[],
[llvm_ptr_ty, llvm_ptr_ty, llvm_ptrptr_ty],
- [IntrReadWriteArgMem, NoCapture<1>, NoCapture<2>]>;
+ [IntrArgMemOnly, NoCapture<1>, NoCapture<2>]>;
//===--------------------- Code Generator Intrinsics ----------------------===//
//
@@ -306,13 +317,16 @@ def int_stackrestore : Intrinsic<[], [llvm_ptr_ty]>,
def int_get_dynamic_area_offset : Intrinsic<[llvm_anyint_ty]>;
-// IntrReadWriteArgMem is more pessimistic than strictly necessary for prefetch,
+def int_thread_pointer : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>,
+ GCCBuiltin<"__builtin_thread_pointer">;
+
+// IntrArgMemOnly is more pessimistic than strictly necessary for prefetch,
// however it does conveniently prevent the prefetch from being reordered
// with respect to nearby accesses to the same memory.
def int_prefetch : Intrinsic<[],
[llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty,
llvm_i32_ty],
- [IntrReadWriteArgMem, NoCapture<0>]>;
+ [IntrArgMemOnly, NoCapture<0>]>;
def int_pcmarker : Intrinsic<[], [llvm_i32_ty]>;
def int_readcyclecounter : Intrinsic<[llvm_i64_ty]>;
@@ -324,8 +338,7 @@ def int_assume : Intrinsic<[], [llvm_i1_ty], []>;
// Stack Protector Intrinsic - The stackprotector intrinsic writes the stack
// guard to the correct place on the stack frame.
def int_stackprotector : Intrinsic<[], [llvm_ptr_ty, llvm_ptrptr_ty], []>;
-def int_stackprotectorcheck : Intrinsic<[], [llvm_ptrptr_ty],
- [IntrReadWriteArgMem]>;
+def int_stackguard : Intrinsic<[llvm_ptr_ty], [], []>;
// A counter increment for instrumentation based profiling.
def int_instrprof_increment : Intrinsic<[],
@@ -347,19 +360,19 @@ def int_instrprof_value_profile : Intrinsic<[],
def int_memcpy : Intrinsic<[],
[llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty,
llvm_i32_ty, llvm_i1_ty],
- [IntrReadWriteArgMem, NoCapture<0>, NoCapture<1>,
- ReadOnly<1>]>;
+ [IntrArgMemOnly, NoCapture<0>, NoCapture<1>,
+ WriteOnly<0>, ReadOnly<1>]>;
def int_memmove : Intrinsic<[],
[llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty,
llvm_i32_ty, llvm_i1_ty],
- [IntrReadWriteArgMem, NoCapture<0>, NoCapture<1>,
+ [IntrArgMemOnly, NoCapture<0>, NoCapture<1>,
ReadOnly<1>]>;
def int_memset : Intrinsic<[],
[llvm_anyptr_ty, llvm_i8_ty, llvm_anyint_ty,
llvm_i32_ty, llvm_i1_ty],
- [IntrReadWriteArgMem, NoCapture<0>]>;
+ [IntrArgMemOnly, NoCapture<0>, WriteOnly<0>]>;
-let Properties = [IntrNoMem] in {
+let IntrProperties = [IntrNoMem] in {
def int_fma : Intrinsic<[llvm_anyfloat_ty],
[LLVMMatchType<0>, LLVMMatchType<0>,
LLVMMatchType<0>]>;
@@ -382,8 +395,6 @@ let Properties = [IntrNoMem] in {
def int_exp : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
def int_exp2 : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
def int_fabs : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
- def int_minnum : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>]>;
- def int_maxnum : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>]>;
def int_copysign : Intrinsic<[llvm_anyfloat_ty],
[LLVMMatchType<0>, LLVMMatchType<0>]>;
def int_floor : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
@@ -396,6 +407,13 @@ let Properties = [IntrNoMem] in {
[IntrNoMem]>;
}
+def int_minnum : Intrinsic<[llvm_anyfloat_ty],
+ [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, Commutative]
+>;
+def int_maxnum : Intrinsic<[llvm_anyfloat_ty],
+ [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, Commutative]
+>;
+
// NOTE: these are internal interfaces.
def int_setjmp : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>;
def int_longjmp : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], [IntrNoReturn]>;
@@ -416,7 +434,7 @@ def int_expect : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>,
//
// None of these intrinsics accesses memory at all.
-let Properties = [IntrNoMem] in {
+let IntrProperties = [IntrNoMem] in {
def int_bswap: Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>;
def int_ctpop: Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>;
def int_ctlz : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, llvm_i1_ty]>;
@@ -430,7 +448,7 @@ let Properties = [IntrNoMem] in {
// None of these intrinsics accesses memory at all...but that doesn't mean the
// optimizers can change them aggressively. Special handling needed in a few
// places.
-let Properties = [IntrNoMem] in {
+let IntrProperties = [IntrNoMem] in {
def int_dbg_declare : Intrinsic<[],
[llvm_metadata_ty,
llvm_metadata_ty,
@@ -467,7 +485,7 @@ def int_eh_unwind_init: Intrinsic<[]>,
def int_eh_dwarf_cfa : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty]>;
-let Properties = [IntrNoMem] in {
+let IntrProperties = [IntrNoMem] in {
def int_eh_sjlj_lsda : Intrinsic<[llvm_ptr_ty]>;
def int_eh_sjlj_callsite : Intrinsic<[], [llvm_i32_ty]>;
}
@@ -495,11 +513,11 @@ def int_annotation : Intrinsic<[llvm_anyint_ty],
//
def int_init_trampoline : Intrinsic<[],
[llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty],
- [IntrReadWriteArgMem, NoCapture<0>]>,
+ [IntrArgMemOnly, NoCapture<0>]>,
GCCBuiltin<"__builtin_init_trampoline">;
def int_adjust_trampoline : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty],
- [IntrReadArgMem]>,
+ [IntrReadMem, IntrArgMemOnly]>,
GCCBuiltin<"__builtin_adjust_trampoline">;
//===------------------------ Overflow Intrinsics -------------------------===//
@@ -531,17 +549,17 @@ def int_umul_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty],
//
def int_lifetime_start : Intrinsic<[],
[llvm_i64_ty, llvm_ptr_ty],
- [IntrReadWriteArgMem, NoCapture<1>]>;
+ [IntrArgMemOnly, NoCapture<1>]>;
def int_lifetime_end : Intrinsic<[],
[llvm_i64_ty, llvm_ptr_ty],
- [IntrReadWriteArgMem, NoCapture<1>]>;
+ [IntrArgMemOnly, NoCapture<1>]>;
def int_invariant_start : Intrinsic<[llvm_descriptor_ty],
[llvm_i64_ty, llvm_ptr_ty],
- [IntrReadWriteArgMem, NoCapture<1>]>;
+ [IntrArgMemOnly, NoCapture<1>]>;
def int_invariant_end : Intrinsic<[],
[llvm_descriptor_ty, llvm_i64_ty,
llvm_ptr_ty],
- [IntrReadWriteArgMem, NoCapture<2>]>;
+ [IntrArgMemOnly, NoCapture<2>]>;
def int_invariant_group_barrier : Intrinsic<[llvm_ptr_ty],
[llvm_ptr_ty],
@@ -588,11 +606,19 @@ def int_trap : Intrinsic<[], [], [IntrNoReturn]>,
def int_debugtrap : Intrinsic<[]>,
GCCBuiltin<"__builtin_debugtrap">;
+// Support for dynamic deoptimization (or de-specialization)
+def int_experimental_deoptimize : Intrinsic<[llvm_any_ty], [llvm_vararg_ty],
+ [Throws]>;
+
+// Support for speculative runtime guards
+def int_experimental_guard : Intrinsic<[], [llvm_i1_ty, llvm_vararg_ty],
+ [Throws]>;
+
// NOP: calls/invokes to this intrinsic are removed by codegen
def int_donothing : Intrinsic<[], [], [IntrNoMem]>;
// Intrisics to support half precision floating point format
-let Properties = [IntrNoMem] in {
+let IntrProperties = [IntrNoMem] in {
def int_convert_to_fp16 : Intrinsic<[llvm_i16_ty], [llvm_anyfloat_ty]>;
def int_convert_from_fp16 : Intrinsic<[llvm_anyfloat_ty], [llvm_i16_ty]>;
}
@@ -627,31 +653,40 @@ def int_clear_cache : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty],
//===-------------------------- Masked Intrinsics -------------------------===//
//
-def int_masked_store : Intrinsic<[], [llvm_anyvector_ty, LLVMPointerTo<0>,
+def int_masked_store : Intrinsic<[], [llvm_anyvector_ty,
+ LLVMAnyPointerType<LLVMMatchType<0>>,
llvm_i32_ty,
LLVMVectorSameWidth<0, llvm_i1_ty>],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_masked_load : Intrinsic<[llvm_anyvector_ty],
- [LLVMPointerTo<0>, llvm_i32_ty,
+ [LLVMAnyPointerType<LLVMMatchType<0>>, llvm_i32_ty,
LLVMVectorSameWidth<0, llvm_i1_ty>, LLVMMatchType<0>],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_masked_gather: Intrinsic<[llvm_anyvector_ty],
[LLVMVectorOfPointersToElt<0>, llvm_i32_ty,
LLVMVectorSameWidth<0, llvm_i1_ty>,
LLVMMatchType<0>],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_masked_scatter: Intrinsic<[],
[llvm_anyvector_ty,
LLVMVectorOfPointersToElt<0>, llvm_i32_ty,
LLVMVectorSameWidth<0, llvm_i1_ty>],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
+
+// Test whether a pointer is associated with a type metadata identifier.
+def int_type_test : Intrinsic<[llvm_i1_ty], [llvm_ptr_ty, llvm_metadata_ty],
+ [IntrNoMem]>;
+
+// Safely loads a function pointer from a virtual table pointer using type metadata.
+def int_type_checked_load : Intrinsic<[llvm_ptr_ty, llvm_i1_ty],
+ [llvm_ptr_ty, llvm_i32_ty, llvm_metadata_ty],
+ [IntrNoMem]>;
-// Intrinsics to support bit sets.
-def int_bitset_test : Intrinsic<[llvm_i1_ty], [llvm_ptr_ty, llvm_metadata_ty],
- [IntrNoMem]>;
+def int_load_relative: Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_anyint_ty],
+ [IntrReadMem, IntrArgMemOnly]>;
//===----------------------------------------------------------------------===//
// Target-specific intrinsics
diff --git a/include/llvm/IR/IntrinsicsAArch64.td b/include/llvm/IR/IntrinsicsAArch64.td
index 578f259aae14..d1e331775b7b 100644
--- a/include/llvm/IR/IntrinsicsAArch64.td
+++ b/include/llvm/IR/IntrinsicsAArch64.td
@@ -13,9 +13,6 @@
let TargetPrefix = "aarch64" in {
-def int_aarch64_thread_pointer : GCCBuiltin<"__builtin_thread_pointer">,
- Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>;
-
def int_aarch64_ldxr : Intrinsic<[llvm_i64_ty], [llvm_anyptr_ty]>;
def int_aarch64_ldaxr : Intrinsic<[llvm_i64_ty], [llvm_anyptr_ty]>;
def int_aarch64_stxr : Intrinsic<[llvm_i32_ty], [llvm_i64_ty, llvm_anyptr_ty]>;
@@ -159,7 +156,7 @@ let TargetPrefix = "aarch64" in { // All intrinsics start with "llvm.aarch64.".
// Arithmetic ops
-let Properties = [IntrNoMem] in {
+let TargetPrefix = "aarch64", IntrProperties = [IntrNoMem] in {
// Vector Add Across Lanes
def int_aarch64_neon_saddv : AdvSIMD_1VectorArg_Int_Across_Intrinsic;
def int_aarch64_neon_uaddv : AdvSIMD_1VectorArg_Int_Across_Intrinsic;
@@ -212,7 +209,7 @@ let Properties = [IntrNoMem] in {
// Vector Extending Multiply
def int_aarch64_neon_fmulx : AdvSIMD_2FloatArg_Intrinsic {
- let Properties = [IntrNoMem, Commutative];
+ let IntrProperties = [IntrNoMem, Commutative];
}
// Vector Saturating Doubling Long Multiply
@@ -436,70 +433,70 @@ def int_aarch64_neon_vcopy_lane: AdvSIMD_2Vector2Index_Intrinsic;
let TargetPrefix = "aarch64" in { // All intrinsics start with "llvm.aarch64.".
class AdvSIMD_1Vec_Load_Intrinsic
: Intrinsic<[llvm_anyvector_ty], [LLVMAnyPointerType<LLVMMatchType<0>>],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
class AdvSIMD_1Vec_Store_Lane_Intrinsic
: Intrinsic<[], [llvm_anyvector_ty, llvm_i64_ty, llvm_anyptr_ty],
- [IntrReadWriteArgMem, NoCapture<2>]>;
+ [IntrArgMemOnly, NoCapture<2>]>;
class AdvSIMD_2Vec_Load_Intrinsic
: Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>],
[LLVMAnyPointerType<LLVMMatchType<0>>],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
class AdvSIMD_2Vec_Load_Lane_Intrinsic
: Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>],
[LLVMMatchType<0>, LLVMMatchType<0>,
llvm_i64_ty, llvm_anyptr_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
class AdvSIMD_2Vec_Store_Intrinsic
: Intrinsic<[], [llvm_anyvector_ty, LLVMMatchType<0>,
LLVMAnyPointerType<LLVMMatchType<0>>],
- [IntrReadWriteArgMem, NoCapture<2>]>;
+ [IntrArgMemOnly, NoCapture<2>]>;
class AdvSIMD_2Vec_Store_Lane_Intrinsic
: Intrinsic<[], [llvm_anyvector_ty, LLVMMatchType<0>,
llvm_i64_ty, llvm_anyptr_ty],
- [IntrReadWriteArgMem, NoCapture<3>]>;
+ [IntrArgMemOnly, NoCapture<3>]>;
class AdvSIMD_3Vec_Load_Intrinsic
: Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, LLVMMatchType<0>],
[LLVMAnyPointerType<LLVMMatchType<0>>],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
class AdvSIMD_3Vec_Load_Lane_Intrinsic
: Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, LLVMMatchType<0>],
[LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>,
llvm_i64_ty, llvm_anyptr_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
class AdvSIMD_3Vec_Store_Intrinsic
: Intrinsic<[], [llvm_anyvector_ty, LLVMMatchType<0>,
LLVMMatchType<0>, LLVMAnyPointerType<LLVMMatchType<0>>],
- [IntrReadWriteArgMem, NoCapture<3>]>;
+ [IntrArgMemOnly, NoCapture<3>]>;
class AdvSIMD_3Vec_Store_Lane_Intrinsic
: Intrinsic<[], [llvm_anyvector_ty,
LLVMMatchType<0>, LLVMMatchType<0>,
llvm_i64_ty, llvm_anyptr_ty],
- [IntrReadWriteArgMem, NoCapture<4>]>;
+ [IntrArgMemOnly, NoCapture<4>]>;
class AdvSIMD_4Vec_Load_Intrinsic
: Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>,
LLVMMatchType<0>, LLVMMatchType<0>],
[LLVMAnyPointerType<LLVMMatchType<0>>],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
class AdvSIMD_4Vec_Load_Lane_Intrinsic
: Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>,
LLVMMatchType<0>, LLVMMatchType<0>],
[LLVMMatchType<0>, LLVMMatchType<0>,
LLVMMatchType<0>, LLVMMatchType<0>,
llvm_i64_ty, llvm_anyptr_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
class AdvSIMD_4Vec_Store_Intrinsic
: Intrinsic<[], [llvm_anyvector_ty, LLVMMatchType<0>,
LLVMMatchType<0>, LLVMMatchType<0>,
LLVMAnyPointerType<LLVMMatchType<0>>],
- [IntrReadWriteArgMem, NoCapture<4>]>;
+ [IntrArgMemOnly, NoCapture<4>]>;
class AdvSIMD_4Vec_Store_Lane_Intrinsic
: Intrinsic<[], [llvm_anyvector_ty, LLVMMatchType<0>,
LLVMMatchType<0>, LLVMMatchType<0>,
llvm_i64_ty, llvm_anyptr_ty],
- [IntrReadWriteArgMem, NoCapture<5>]>;
+ [IntrArgMemOnly, NoCapture<5>]>;
}
// Memory ops
diff --git a/include/llvm/IR/IntrinsicsAMDGPU.td b/include/llvm/IR/IntrinsicsAMDGPU.td
index 84582e8b9925..9bf2a4dd5a1d 100644
--- a/include/llvm/IR/IntrinsicsAMDGPU.td
+++ b/include/llvm/IR/IntrinsicsAMDGPU.td
@@ -11,28 +11,45 @@
//
//===----------------------------------------------------------------------===//
+class AMDGPUReadPreloadRegisterIntrinsic
+ : Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>;
+
+class AMDGPUReadPreloadRegisterIntrinsicNamed<string name>
+ : Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, GCCBuiltin<name>;
+
let TargetPrefix = "r600" in {
-class R600ReadPreloadRegisterIntrinsic<string name>
- : Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>,
- GCCBuiltin<name>;
+multiclass AMDGPUReadPreloadRegisterIntrinsic_xyz {
+ def _x : AMDGPUReadPreloadRegisterIntrinsic;
+ def _y : AMDGPUReadPreloadRegisterIntrinsic;
+ def _z : AMDGPUReadPreloadRegisterIntrinsic;
+}
-multiclass R600ReadPreloadRegisterIntrinsic_xyz<string prefix> {
- def _x : R600ReadPreloadRegisterIntrinsic<!strconcat(prefix, "_x")>;
- def _y : R600ReadPreloadRegisterIntrinsic<!strconcat(prefix, "_y")>;
- def _z : R600ReadPreloadRegisterIntrinsic<!strconcat(prefix, "_z")>;
+multiclass AMDGPUReadPreloadRegisterIntrinsic_xyz_named<string prefix> {
+ def _x : AMDGPUReadPreloadRegisterIntrinsicNamed<!strconcat(prefix, "_x")>;
+ def _y : AMDGPUReadPreloadRegisterIntrinsicNamed<!strconcat(prefix, "_y")>;
+ def _z : AMDGPUReadPreloadRegisterIntrinsicNamed<!strconcat(prefix, "_z")>;
}
-defm int_r600_read_global_size : R600ReadPreloadRegisterIntrinsic_xyz <
- "__builtin_r600_read_global_size">;
-defm int_r600_read_local_size : R600ReadPreloadRegisterIntrinsic_xyz <
- "__builtin_r600_read_local_size">;
-defm int_r600_read_ngroups : R600ReadPreloadRegisterIntrinsic_xyz <
- "__builtin_r600_read_ngroups">;
-defm int_r600_read_tgid : R600ReadPreloadRegisterIntrinsic_xyz <
- "__builtin_r600_read_tgid">;
-defm int_r600_read_tidig : R600ReadPreloadRegisterIntrinsic_xyz <
- "__builtin_r600_read_tidig">;
+defm int_r600_read_global_size : AMDGPUReadPreloadRegisterIntrinsic_xyz_named
+ <"__builtin_r600_read_global_size">;
+defm int_r600_read_ngroups : AMDGPUReadPreloadRegisterIntrinsic_xyz_named
+ <"__builtin_r600_read_ngroups">;
+defm int_r600_read_tgid : AMDGPUReadPreloadRegisterIntrinsic_xyz_named
+ <"__builtin_r600_read_tgid">;
+
+defm int_r600_read_local_size : AMDGPUReadPreloadRegisterIntrinsic_xyz;
+defm int_r600_read_tidig : AMDGPUReadPreloadRegisterIntrinsic_xyz;
+
+def int_r600_read_workdim : AMDGPUReadPreloadRegisterIntrinsic;
+
+def int_r600_group_barrier : GCCBuiltin<"__builtin_r600_group_barrier">,
+ Intrinsic<[], [], [IntrConvergent]>;
+
+// AS 7 is PARAM_I_ADDRESS, used for kernel arguments
+def int_r600_implicitarg_ptr :
+ GCCBuiltin<"__builtin_r600_implicitarg_ptr">,
+ Intrinsic<[LLVMQualPointerType<llvm_i8_ty, 7>], [], [IntrNoMem]>;
def int_r600_rat_store_typed :
// 1st parameter: Data
@@ -41,69 +58,253 @@ def int_r600_rat_store_typed :
Intrinsic<[], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], []>,
GCCBuiltin<"__builtin_r600_rat_store_typed">;
+def int_r600_recipsqrt_ieee : Intrinsic<
+ [llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]
+>;
+
+def int_r600_recipsqrt_clamped : Intrinsic<
+ [llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]
+>;
+
} // End TargetPrefix = "r600"
-let TargetPrefix = "AMDGPU" in {
+let TargetPrefix = "amdgcn" in {
-class AMDGPUReadPreloadRegisterIntrinsic<string name>
- : Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>,
- GCCBuiltin<name>;
+defm int_amdgcn_workitem_id : AMDGPUReadPreloadRegisterIntrinsic_xyz;
+defm int_amdgcn_workgroup_id : AMDGPUReadPreloadRegisterIntrinsic_xyz_named
+ <"__builtin_amdgcn_workgroup_id">;
-def int_AMDGPU_div_scale : GCCBuiltin<"__builtin_amdgpu_div_scale">,
+def int_amdgcn_s_barrier : GCCBuiltin<"__builtin_amdgcn_s_barrier">,
+ Intrinsic<[], [], [IntrConvergent]>;
+
+def int_amdgcn_s_waitcnt : Intrinsic<[], [llvm_i32_ty], []>;
+
+def int_amdgcn_div_scale : Intrinsic<
// 1st parameter: Numerator
// 2nd parameter: Denominator
// 3rd parameter: Constant to select select between first and
// second. (0 = first, 1 = second).
- Intrinsic<[llvm_anyfloat_ty, llvm_i1_ty],
- [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i1_ty],
- [IntrNoMem]>;
-
-def int_AMDGPU_div_fmas : GCCBuiltin<"__builtin_amdgpu_div_fmas">,
- Intrinsic<[llvm_anyfloat_ty],
- [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>, llvm_i1_ty],
- [IntrNoMem]>;
-
-def int_AMDGPU_div_fixup : GCCBuiltin<"__builtin_amdgpu_div_fixup">,
- Intrinsic<[llvm_anyfloat_ty],
- [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>],
- [IntrNoMem]>;
-
-def int_AMDGPU_trig_preop : GCCBuiltin<"__builtin_amdgpu_trig_preop">,
- Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_i32_ty],
- [IntrNoMem]>;
-
-def int_AMDGPU_rcp : GCCBuiltin<"__builtin_amdgpu_rcp">,
- Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>;
-
-def int_AMDGPU_rsq : GCCBuiltin<"__builtin_amdgpu_rsq">,
- Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>;
-
-def int_AMDGPU_rsq_clamped : GCCBuiltin<"__builtin_amdgpu_rsq_clamped">,
- Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>;
-
-def int_AMDGPU_ldexp : GCCBuiltin<"__builtin_amdgpu_ldexp">,
- Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_i32_ty], [IntrNoMem]>;
+ [llvm_anyfloat_ty, llvm_i1_ty],
+ [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i1_ty],
+ [IntrNoMem]
+>;
+
+def int_amdgcn_div_fmas : Intrinsic<[llvm_anyfloat_ty],
+ [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>, llvm_i1_ty],
+ [IntrNoMem]
+>;
+
+def int_amdgcn_div_fixup : Intrinsic<[llvm_anyfloat_ty],
+ [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>],
+ [IntrNoMem]
+>;
+
+def int_amdgcn_trig_preop : Intrinsic<
+ [llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_i32_ty], [IntrNoMem]
+>;
+
+def int_amdgcn_sin : Intrinsic<
+ [llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]
+>;
+
+def int_amdgcn_cos : Intrinsic<
+ [llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]
+>;
+
+def int_amdgcn_log_clamp : Intrinsic<
+ [llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]
+>;
+
+def int_amdgcn_rcp : Intrinsic<
+ [llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]
+>;
+
+def int_amdgcn_rsq : Intrinsic<
+ [llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]
+>;
+
+def int_amdgcn_rsq_legacy : GCCBuiltin<"__builtin_amdgcn_rsq_legacy">,
+ Intrinsic<
+ [llvm_float_ty], [llvm_float_ty], [IntrNoMem]
+>;
+
+def int_amdgcn_rsq_clamp : Intrinsic<
+ [llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>;
+
+def int_amdgcn_ldexp : Intrinsic<
+ [llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_i32_ty], [IntrNoMem]
+>;
+
+def int_amdgcn_frexp_mant : Intrinsic<
+ [llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]
+>;
+
+def int_amdgcn_frexp_exp : Intrinsic<
+ [llvm_i32_ty], [llvm_anyfloat_ty], [IntrNoMem]
+>;
+
+// v_fract is buggy on SI/CI. It mishandles infinities, may return 1.0
+// and always uses rtz, so is not suitable for implementing the OpenCL
+// fract function. It should be ok on VI.
+def int_amdgcn_fract : Intrinsic<
+ [llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]
+>;
+
+def int_amdgcn_class : Intrinsic<
+ [llvm_i1_ty], [llvm_anyfloat_ty, llvm_i32_ty], [IntrNoMem]
+>;
+
+def int_amdgcn_cubeid : GCCBuiltin<"__builtin_amdgcn_cubeid">,
+ Intrinsic<[llvm_float_ty],
+ [llvm_float_ty, llvm_float_ty, llvm_float_ty], [IntrNoMem]
+>;
-def int_AMDGPU_class : GCCBuiltin<"__builtin_amdgpu_class">,
- Intrinsic<[llvm_i1_ty], [llvm_anyfloat_ty, llvm_i32_ty], [IntrNoMem]>;
+def int_amdgcn_cubema : GCCBuiltin<"__builtin_amdgcn_cubema">,
+ Intrinsic<[llvm_float_ty],
+ [llvm_float_ty, llvm_float_ty, llvm_float_ty], [IntrNoMem]
+>;
-def int_AMDGPU_read_workdim : AMDGPUReadPreloadRegisterIntrinsic <
- "__builtin_amdgpu_read_workdim">;
+def int_amdgcn_cubesc : GCCBuiltin<"__builtin_amdgcn_cubesc">,
+ Intrinsic<[llvm_float_ty],
+ [llvm_float_ty, llvm_float_ty, llvm_float_ty], [IntrNoMem]
+>;
-} // End TargetPrefix = "AMDGPU"
+def int_amdgcn_cubetc : GCCBuiltin<"__builtin_amdgcn_cubetc">,
+ Intrinsic<[llvm_float_ty],
+ [llvm_float_ty, llvm_float_ty, llvm_float_ty], [IntrNoMem]
+>;
+
+// TODO: Do we want an ordering for these?
+def int_amdgcn_atomic_inc : Intrinsic<[llvm_anyint_ty],
+ [llvm_anyptr_ty, LLVMMatchType<0>],
+ [IntrArgMemOnly, NoCapture<0>]
+>;
+
+def int_amdgcn_atomic_dec : Intrinsic<[llvm_anyint_ty],
+ [llvm_anyptr_ty, LLVMMatchType<0>],
+ [IntrArgMemOnly, NoCapture<0>]
+>;
+
+class AMDGPUImageLoad : Intrinsic <
+ [llvm_v4f32_ty], // vdata(VGPR)
+ [llvm_anyint_ty, // vaddr(VGPR)
+ llvm_v8i32_ty, // rsrc(SGPR)
+ llvm_i32_ty, // dmask(imm)
+ llvm_i1_ty, // r128(imm)
+ llvm_i1_ty, // da(imm)
+ llvm_i1_ty, // glc(imm)
+ llvm_i1_ty], // slc(imm)
+ [IntrReadMem]>;
+
+def int_amdgcn_image_load : AMDGPUImageLoad;
+def int_amdgcn_image_load_mip : AMDGPUImageLoad;
+
+class AMDGPUImageStore : Intrinsic <
+ [],
+ [llvm_v4f32_ty, // vdata(VGPR)
+ llvm_anyint_ty, // vaddr(VGPR)
+ llvm_v8i32_ty, // rsrc(SGPR)
+ llvm_i32_ty, // dmask(imm)
+ llvm_i1_ty, // r128(imm)
+ llvm_i1_ty, // da(imm)
+ llvm_i1_ty, // glc(imm)
+ llvm_i1_ty], // slc(imm)
+ []>;
+
+def int_amdgcn_image_store : AMDGPUImageStore;
+def int_amdgcn_image_store_mip : AMDGPUImageStore;
+
+class AMDGPUImageAtomic : Intrinsic <
+ [llvm_i32_ty],
+ [llvm_i32_ty, // vdata(VGPR)
+ llvm_anyint_ty, // vaddr(VGPR)
+ llvm_v8i32_ty, // rsrc(SGPR)
+ llvm_i1_ty, // r128(imm)
+ llvm_i1_ty, // da(imm)
+ llvm_i1_ty], // slc(imm)
+ []>;
+
+def int_amdgcn_image_atomic_swap : AMDGPUImageAtomic;
+def int_amdgcn_image_atomic_add : AMDGPUImageAtomic;
+def int_amdgcn_image_atomic_sub : AMDGPUImageAtomic;
+def int_amdgcn_image_atomic_smin : AMDGPUImageAtomic;
+def int_amdgcn_image_atomic_umin : AMDGPUImageAtomic;
+def int_amdgcn_image_atomic_smax : AMDGPUImageAtomic;
+def int_amdgcn_image_atomic_umax : AMDGPUImageAtomic;
+def int_amdgcn_image_atomic_and : AMDGPUImageAtomic;
+def int_amdgcn_image_atomic_or : AMDGPUImageAtomic;
+def int_amdgcn_image_atomic_xor : AMDGPUImageAtomic;
+def int_amdgcn_image_atomic_inc : AMDGPUImageAtomic;
+def int_amdgcn_image_atomic_dec : AMDGPUImageAtomic;
+def int_amdgcn_image_atomic_cmpswap : Intrinsic <
+ [llvm_i32_ty],
+ [llvm_i32_ty, // src(VGPR)
+ llvm_i32_ty, // cmp(VGPR)
+ llvm_anyint_ty, // vaddr(VGPR)
+ llvm_v8i32_ty, // rsrc(SGPR)
+ llvm_i1_ty, // r128(imm)
+ llvm_i1_ty, // da(imm)
+ llvm_i1_ty], // slc(imm)
+ []>;
+
+class AMDGPUBufferLoad : Intrinsic <
+ [llvm_anyfloat_ty],
+ [llvm_v4i32_ty, // rsrc(SGPR)
+ llvm_i32_ty, // vindex(VGPR)
+ llvm_i32_ty, // offset(SGPR/VGPR/imm)
+ llvm_i1_ty, // glc(imm)
+ llvm_i1_ty], // slc(imm)
+ [IntrReadMem]>;
+def int_amdgcn_buffer_load_format : AMDGPUBufferLoad;
+def int_amdgcn_buffer_load : AMDGPUBufferLoad;
+
+class AMDGPUBufferStore : Intrinsic <
+ [],
+ [llvm_anyfloat_ty, // vdata(VGPR) -- can currently only select f32, v2f32, v4f32
+ llvm_v4i32_ty, // rsrc(SGPR)
+ llvm_i32_ty, // vindex(VGPR)
+ llvm_i32_ty, // offset(SGPR/VGPR/imm)
+ llvm_i1_ty, // glc(imm)
+ llvm_i1_ty], // slc(imm)
+ [IntrWriteMem]>;
+def int_amdgcn_buffer_store_format : AMDGPUBufferStore;
+def int_amdgcn_buffer_store : AMDGPUBufferStore;
+
+class AMDGPUBufferAtomic : Intrinsic <
+ [llvm_i32_ty],
+ [llvm_i32_ty, // vdata(VGPR)
+ llvm_v4i32_ty, // rsrc(SGPR)
+ llvm_i32_ty, // vindex(VGPR)
+ llvm_i32_ty, // offset(SGPR/VGPR/imm)
+ llvm_i1_ty], // slc(imm)
+ []>;
+def int_amdgcn_buffer_atomic_swap : AMDGPUBufferAtomic;
+def int_amdgcn_buffer_atomic_add : AMDGPUBufferAtomic;
+def int_amdgcn_buffer_atomic_sub : AMDGPUBufferAtomic;
+def int_amdgcn_buffer_atomic_smin : AMDGPUBufferAtomic;
+def int_amdgcn_buffer_atomic_umin : AMDGPUBufferAtomic;
+def int_amdgcn_buffer_atomic_smax : AMDGPUBufferAtomic;
+def int_amdgcn_buffer_atomic_umax : AMDGPUBufferAtomic;
+def int_amdgcn_buffer_atomic_and : AMDGPUBufferAtomic;
+def int_amdgcn_buffer_atomic_or : AMDGPUBufferAtomic;
+def int_amdgcn_buffer_atomic_xor : AMDGPUBufferAtomic;
+def int_amdgcn_buffer_atomic_cmpswap : Intrinsic<
+ [llvm_i32_ty],
+ [llvm_i32_ty, // src(VGPR)
+ llvm_i32_ty, // cmp(VGPR)
+ llvm_v4i32_ty, // rsrc(SGPR)
+ llvm_i32_ty, // vindex(VGPR)
+ llvm_i32_ty, // offset(SGPR/VGPR/imm)
+ llvm_i1_ty], // slc(imm)
+ []>;
+
+def int_amdgcn_read_workdim : AMDGPUReadPreloadRegisterIntrinsic;
-let TargetPrefix = "amdgcn" in {
-// SI only
def int_amdgcn_buffer_wbinvl1_sc :
GCCBuiltin<"__builtin_amdgcn_buffer_wbinvl1_sc">,
Intrinsic<[], [], []>;
-// On CI+
-def int_amdgcn_buffer_wbinvl1_vol :
- GCCBuiltin<"__builtin_amdgcn_buffer_wbinvl1_vol">,
- Intrinsic<[], [], []>;
-
def int_amdgcn_buffer_wbinvl1 :
GCCBuiltin<"__builtin_amdgcn_buffer_wbinvl1">,
Intrinsic<[], [], []>;
@@ -112,25 +313,39 @@ def int_amdgcn_s_dcache_inv :
GCCBuiltin<"__builtin_amdgcn_s_dcache_inv">,
Intrinsic<[], [], []>;
-// CI+
-def int_amdgcn_s_dcache_inv_vol :
- GCCBuiltin<"__builtin_amdgcn_s_dcache_inv_vol">,
- Intrinsic<[], [], []>;
+def int_amdgcn_s_memtime :
+ GCCBuiltin<"__builtin_amdgcn_s_memtime">,
+ Intrinsic<[llvm_i64_ty], [], []>;
-// VI
-def int_amdgcn_s_dcache_wb :
- GCCBuiltin<"__builtin_amdgcn_s_dcache_wb">,
- Intrinsic<[], [], []>;
+def int_amdgcn_s_sleep :
+ GCCBuiltin<"__builtin_amdgcn_s_sleep">,
+ Intrinsic<[], [llvm_i32_ty], []> {
+}
-// VI
-def int_amdgcn_s_dcache_wb_vol :
- GCCBuiltin<"__builtin_amdgcn_s_dcache_wb_vol">,
- Intrinsic<[], [], []>;
+def int_amdgcn_s_getreg :
+ GCCBuiltin<"__builtin_amdgcn_s_getreg">,
+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrReadMem]>;
+
+def int_amdgcn_groupstaticsize :
+ GCCBuiltin<"__builtin_amdgcn_groupstaticsize">,
+ Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>;
def int_amdgcn_dispatch_ptr :
GCCBuiltin<"__builtin_amdgcn_dispatch_ptr">,
Intrinsic<[LLVMQualPointerType<llvm_i8_ty, 2>], [], [IntrNoMem]>;
+def int_amdgcn_queue_ptr :
+ GCCBuiltin<"__builtin_amdgcn_queue_ptr">,
+ Intrinsic<[LLVMQualPointerType<llvm_i8_ty, 2>], [], [IntrNoMem]>;
+
+def int_amdgcn_kernarg_segment_ptr :
+ GCCBuiltin<"__builtin_amdgcn_kernarg_segment_ptr">,
+ Intrinsic<[LLVMQualPointerType<llvm_i8_ty, 2>], [], [IntrNoMem]>;
+
+def int_amdgcn_implicitarg_ptr :
+ GCCBuiltin<"__builtin_amdgcn_implicitarg_ptr">,
+ Intrinsic<[LLVMQualPointerType<llvm_i8_ty, 2>], [], [IntrNoMem]>;
+
// __builtin_amdgcn_interp_p1 <i>, <attr_chan>, <attr>, <m0>
def int_amdgcn_interp_p1 :
GCCBuiltin<"__builtin_amdgcn_interp_p1">,
@@ -147,6 +362,13 @@ def int_amdgcn_interp_p2 :
[IntrNoMem]>; // See int_amdgcn_v_interp_p1 for why this is
// IntrNoMem.
+// Pixel shaders only: whether the current pixel is live (i.e. not a helper
+// invocation for derivative computation).
+def int_amdgcn_ps_live : Intrinsic <
+ [llvm_i1_ty],
+ [],
+ [IntrNoMem]>;
+
def int_amdgcn_mbcnt_lo :
GCCBuiltin<"__builtin_amdgcn_mbcnt_lo">,
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
@@ -154,4 +376,57 @@ def int_amdgcn_mbcnt_lo :
def int_amdgcn_mbcnt_hi :
GCCBuiltin<"__builtin_amdgcn_mbcnt_hi">,
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
+
+// llvm.amdgcn.ds.swizzle src offset
+def int_amdgcn_ds_swizzle :
+ GCCBuiltin<"__builtin_amdgcn_ds_swizzle">,
+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem, IntrConvergent]>;
+
+// llvm.amdgcn.lerp
+def int_amdgcn_lerp :
+ GCCBuiltin<"__builtin_amdgcn_lerp">,
+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
+
+//===----------------------------------------------------------------------===//
+// CI+ Intrinsics
+//===----------------------------------------------------------------------===//
+
+def int_amdgcn_s_dcache_inv_vol :
+ GCCBuiltin<"__builtin_amdgcn_s_dcache_inv_vol">,
+ Intrinsic<[], [], []>;
+
+def int_amdgcn_buffer_wbinvl1_vol :
+ GCCBuiltin<"__builtin_amdgcn_buffer_wbinvl1_vol">,
+ Intrinsic<[], [], []>;
+
+//===----------------------------------------------------------------------===//
+// VI Intrinsics
+//===----------------------------------------------------------------------===//
+
+// llvm.amdgcn.mov.dpp.i32 <src> <dpp_ctrl> <row_mask> <bank_mask> <bound_ctrl>
+def int_amdgcn_mov_dpp :
+ Intrinsic<[llvm_anyint_ty],
+ [LLVMMatchType<0>, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty,
+ llvm_i1_ty], [IntrNoMem, IntrConvergent]>;
+
+def int_amdgcn_s_dcache_wb :
+ GCCBuiltin<"__builtin_amdgcn_s_dcache_wb">,
+ Intrinsic<[], [], []>;
+
+def int_amdgcn_s_dcache_wb_vol :
+ GCCBuiltin<"__builtin_amdgcn_s_dcache_wb_vol">,
+ Intrinsic<[], [], []>;
+
+def int_amdgcn_s_memrealtime :
+ GCCBuiltin<"__builtin_amdgcn_s_memrealtime">,
+ Intrinsic<[llvm_i64_ty], [], []>;
+
+// llvm.amdgcn.ds.permute <index> <src>
+def int_amdgcn_ds_permute :
+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem, IntrConvergent]>;
+
+// llvm.amdgcn.ds.bpermute <index> <src>
+def int_amdgcn_ds_bpermute :
+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem, IntrConvergent]>;
+
}
diff --git a/include/llvm/IR/IntrinsicsARM.td b/include/llvm/IR/IntrinsicsARM.td
index c1d911cefee2..099598596885 100644
--- a/include/llvm/IR/IntrinsicsARM.td
+++ b/include/llvm/IR/IntrinsicsARM.td
@@ -17,9 +17,6 @@
let TargetPrefix = "arm" in { // All intrinsics start with "llvm.arm.".
-def int_arm_thread_pointer : GCCBuiltin<"__builtin_thread_pointer">,
- Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>;
-
// A space-consuming intrinsic primarily for testing ARMConstantIslands. The
// first argument is the number of bytes this "instruction" takes up, the second
// and return value are essentially chains, used to force ordering during ISel.
@@ -81,6 +78,24 @@ def int_arm_vcvtru : Intrinsic<[llvm_float_ty], [llvm_anyfloat_ty],
//===----------------------------------------------------------------------===//
// Coprocessor
+def int_arm_ldc : GCCBuiltin<"__builtin_arm_ldc">,
+ Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], []>;
+def int_arm_ldcl : GCCBuiltin<"__builtin_arm_ldcl">,
+ Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], []>;
+def int_arm_ldc2 : GCCBuiltin<"__builtin_arm_ldc2">,
+ Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], []>;
+def int_arm_ldc2l : GCCBuiltin<"__builtin_arm_ldc2l">,
+ Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], []>;
+
+def int_arm_stc : GCCBuiltin<"__builtin_arm_stc">,
+ Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], []>;
+def int_arm_stcl : GCCBuiltin<"__builtin_arm_stcl">,
+ Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], []>;
+def int_arm_stc2 : GCCBuiltin<"__builtin_arm_stc2">,
+ Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], []>;
+def int_arm_stc2l : GCCBuiltin<"__builtin_arm_stc2l">,
+ Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], []>;
+
// Move to coprocessor
def int_arm_mcr : GCCBuiltin<"__builtin_arm_mcr">,
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty,
@@ -108,12 +123,15 @@ def int_arm_cdp2 : GCCBuiltin<"__builtin_arm_cdp2">,
llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>;
// Move from two registers to coprocessor
-def int_arm_mcrr : GCCBuiltin<"__builtin_arm_mcrr">,
- Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty,
- llvm_i32_ty, llvm_i32_ty], []>;
-def int_arm_mcrr2 : GCCBuiltin<"__builtin_arm_mcrr2">,
- Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty,
- llvm_i32_ty, llvm_i32_ty], []>;
+def int_arm_mcrr : Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty,
+ llvm_i32_ty, llvm_i32_ty], []>;
+def int_arm_mcrr2 : Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty,
+ llvm_i32_ty, llvm_i32_ty], []>;
+
+def int_arm_mrrc : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [llvm_i32_ty,
+ llvm_i32_ty, llvm_i32_ty], []>;
+def int_arm_mrrc2 : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [llvm_i32_ty,
+ llvm_i32_ty, llvm_i32_ty], []>;
//===----------------------------------------------------------------------===//
// CRC32
@@ -207,7 +225,7 @@ class Neon_Tbl6Arg_Intrinsic
// Arithmetic ops
-let Properties = [IntrNoMem, Commutative] in {
+let IntrProperties = [IntrNoMem, Commutative] in {
// Vector Add.
def int_arm_neon_vhadds : Neon_2Arg_Intrinsic;
@@ -406,18 +424,18 @@ def int_arm_neon_vrintp : Neon_1Arg_Intrinsic;
// Source operands are the address and alignment.
def int_arm_neon_vld1 : Intrinsic<[llvm_anyvector_ty],
[llvm_anyptr_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_arm_neon_vld2 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>],
[llvm_anyptr_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_arm_neon_vld3 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>,
LLVMMatchType<0>],
[llvm_anyptr_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_arm_neon_vld4 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>,
LLVMMatchType<0>, LLVMMatchType<0>],
[llvm_anyptr_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
// Vector load N-element structure to one lane.
// Source operands are: the address, the N input vectors (since only one
@@ -425,38 +443,38 @@ def int_arm_neon_vld4 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>,
def int_arm_neon_vld2lane : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>],
[llvm_anyptr_ty, LLVMMatchType<0>,
LLVMMatchType<0>, llvm_i32_ty,
- llvm_i32_ty], [IntrReadArgMem]>;
+ llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>;
def int_arm_neon_vld3lane : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>,
LLVMMatchType<0>],
[llvm_anyptr_ty, LLVMMatchType<0>,
LLVMMatchType<0>, LLVMMatchType<0>,
llvm_i32_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_arm_neon_vld4lane : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>,
LLVMMatchType<0>, LLVMMatchType<0>],
[llvm_anyptr_ty, LLVMMatchType<0>,
LLVMMatchType<0>, LLVMMatchType<0>,
LLVMMatchType<0>, llvm_i32_ty,
- llvm_i32_ty], [IntrReadArgMem]>;
+ llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>;
// Interleaving vector stores from N-element structures.
// Source operands are: the address, the N vectors, and the alignment.
def int_arm_neon_vst1 : Intrinsic<[],
[llvm_anyptr_ty, llvm_anyvector_ty,
- llvm_i32_ty], [IntrReadWriteArgMem]>;
+ llvm_i32_ty], [IntrArgMemOnly]>;
def int_arm_neon_vst2 : Intrinsic<[],
[llvm_anyptr_ty, llvm_anyvector_ty,
LLVMMatchType<1>, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_arm_neon_vst3 : Intrinsic<[],
[llvm_anyptr_ty, llvm_anyvector_ty,
LLVMMatchType<1>, LLVMMatchType<1>,
- llvm_i32_ty], [IntrReadWriteArgMem]>;
+ llvm_i32_ty], [IntrArgMemOnly]>;
def int_arm_neon_vst4 : Intrinsic<[],
[llvm_anyptr_ty, llvm_anyvector_ty,
LLVMMatchType<1>, LLVMMatchType<1>,
LLVMMatchType<1>, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
// Vector store N-element structure from one lane.
// Source operands are: the address, the N vectors, the lane number, and
@@ -464,17 +482,17 @@ def int_arm_neon_vst4 : Intrinsic<[],
def int_arm_neon_vst2lane : Intrinsic<[],
[llvm_anyptr_ty, llvm_anyvector_ty,
LLVMMatchType<1>, llvm_i32_ty,
- llvm_i32_ty], [IntrReadWriteArgMem]>;
+ llvm_i32_ty], [IntrArgMemOnly]>;
def int_arm_neon_vst3lane : Intrinsic<[],
[llvm_anyptr_ty, llvm_anyvector_ty,
LLVMMatchType<1>, LLVMMatchType<1>,
llvm_i32_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_arm_neon_vst4lane : Intrinsic<[],
[llvm_anyptr_ty, llvm_anyvector_ty,
LLVMMatchType<1>, LLVMMatchType<1>,
LLVMMatchType<1>, llvm_i32_ty,
- llvm_i32_ty], [IntrReadWriteArgMem]>;
+ llvm_i32_ty], [IntrArgMemOnly]>;
// Vector bitwise select.
def int_arm_neon_vbsl : Intrinsic<[llvm_anyvector_ty],
diff --git a/include/llvm/IR/IntrinsicsHexagon.td b/include/llvm/IR/IntrinsicsHexagon.td
index ca6fcbd44337..6519f051deeb 100644
--- a/include/llvm/IR/IntrinsicsHexagon.td
+++ b/include/llvm/IR/IntrinsicsHexagon.td
@@ -428,42 +428,42 @@ class Hexagon_mem_memmemsi_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
[llvm_ptr_ty], [llvm_ptr_ty, llvm_ptr_ty,
llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
class Hexagon_mem_memsisi_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
[llvm_ptr_ty], [llvm_ptr_ty, llvm_i32_ty,
llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
class Hexagon_mem_memdisi_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
[llvm_ptr_ty], [llvm_ptr_ty, llvm_i64_ty,
llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
class Hexagon_mem_memmemsisi_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
[llvm_ptr_ty], [llvm_ptr_ty, llvm_ptr_ty,
llvm_i32_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
class Hexagon_mem_memsisisi_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
[llvm_ptr_ty], [llvm_ptr_ty, llvm_i32_ty,
llvm_i32_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
class Hexagon_mem_memdisisi_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
[llvm_ptr_ty], [llvm_ptr_ty, llvm_i64_ty,
llvm_i32_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
class Hexagon_v256_v256v256_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
//
// Hexagon_sf_df_Intrinsic<string GCCIntSuffix>
@@ -2998,7 +2998,7 @@ Hexagon_di_di_Intrinsic<"HEXAGON_A2_tfrp">;
// BUILTIN_INFO(HEXAGON.A2_tfrpi,DI_ftype_SI,1)
//
def int_hexagon_A2_tfrpi :
-Hexagon_di_di_Intrinsic<"HEXAGON_A2_tfrpi">;
+Hexagon_di_si_Intrinsic<"HEXAGON_A2_tfrpi">;
//
// BUILTIN_INFO(HEXAGON.A2_zxtb,SI_ftype_SI,1)
//
@@ -4971,17 +4971,17 @@ def llvm_ptr64_ty : LLVMPointerType<llvm_i64_ty>;
// Mark locked loads as read/write to prevent any accidental reordering.
def int_hexagon_L2_loadw_locked :
Hexagon_Intrinsic<"HEXAGON_L2_loadw_locked", [llvm_i32_ty], [llvm_ptr32_ty],
- [IntrReadWriteArgMem, NoCapture<0>]>;
+ [IntrArgMemOnly, NoCapture<0>]>;
def int_hexagon_L4_loadd_locked :
Hexagon_Intrinsic<"HEXAGON_L4_loadd_locked", [llvm_i64_ty], [llvm_ptr64_ty],
- [IntrReadWriteArgMem, NoCapture<0>]>;
+ [IntrArgMemOnly, NoCapture<0>]>;
def int_hexagon_S2_storew_locked :
Hexagon_Intrinsic<"HEXAGON_S2_storew_locked", [llvm_i32_ty],
- [llvm_ptr32_ty, llvm_i32_ty], [IntrReadWriteArgMem, NoCapture<0>]>;
+ [llvm_ptr32_ty, llvm_i32_ty], [IntrArgMemOnly, NoCapture<0>]>;
def int_hexagon_S4_stored_locked :
Hexagon_Intrinsic<"HEXAGON_S4_stored_locked", [llvm_i32_ty],
- [llvm_ptr64_ty, llvm_i64_ty], [IntrReadWriteArgMem, NoCapture<0>]>;
+ [llvm_ptr64_ty, llvm_i64_ty], [IntrArgMemOnly, NoCapture<0>]>;
// V60
diff --git a/include/llvm/IR/IntrinsicsMips.td b/include/llvm/IR/IntrinsicsMips.td
index 34557612cb96..421a79be4ebc 100644
--- a/include/llvm/IR/IntrinsicsMips.td
+++ b/include/llvm/IR/IntrinsicsMips.td
@@ -264,11 +264,11 @@ def int_mips_bposge32: GCCBuiltin<"__builtin_mips_bposge32">,
Intrinsic<[llvm_i32_ty], [], [IntrReadMem]>;
def int_mips_lbux: GCCBuiltin<"__builtin_mips_lbux">,
- Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrReadArgMem]>;
+ Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>;
def int_mips_lhx: GCCBuiltin<"__builtin_mips_lhx">,
- Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrReadArgMem]>;
+ Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>;
def int_mips_lwx: GCCBuiltin<"__builtin_mips_lwx">,
- Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrReadArgMem]>;
+ Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>;
//===----------------------------------------------------------------------===//
// MIPS DSP Rev 2
@@ -1261,16 +1261,16 @@ def int_mips_insve_d : GCCBuiltin<"__builtin_msa_insve_d">,
def int_mips_ld_b : GCCBuiltin<"__builtin_msa_ld_b">,
Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_mips_ld_h : GCCBuiltin<"__builtin_msa_ld_h">,
Intrinsic<[llvm_v8i16_ty], [llvm_ptr_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_mips_ld_w : GCCBuiltin<"__builtin_msa_ld_w">,
Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_mips_ld_d : GCCBuiltin<"__builtin_msa_ld_d">,
Intrinsic<[llvm_v2i64_ty], [llvm_ptr_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_mips_ldi_b : GCCBuiltin<"__builtin_msa_ldi_b">,
Intrinsic<[llvm_v16i8_ty], [llvm_i32_ty], [IntrNoMem]>;
@@ -1685,16 +1685,16 @@ def int_mips_srlri_d : GCCBuiltin<"__builtin_msa_srlri_d">,
def int_mips_st_b : GCCBuiltin<"__builtin_msa_st_b">,
Intrinsic<[], [llvm_v16i8_ty, llvm_ptr_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_mips_st_h : GCCBuiltin<"__builtin_msa_st_h">,
Intrinsic<[], [llvm_v8i16_ty, llvm_ptr_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_mips_st_w : GCCBuiltin<"__builtin_msa_st_w">,
Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_mips_st_d : GCCBuiltin<"__builtin_msa_st_d">,
Intrinsic<[], [llvm_v2i64_ty, llvm_ptr_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_mips_subs_s_b : GCCBuiltin<"__builtin_msa_subs_s_b">,
Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>;
diff --git a/include/llvm/IR/IntrinsicsNVVM.td b/include/llvm/IR/IntrinsicsNVVM.td
index 9deed414b50a..6919ec47eb9a 100644
--- a/include/llvm/IR/IntrinsicsNVVM.td
+++ b/include/llvm/IR/IntrinsicsNVVM.td
@@ -17,6 +17,7 @@ def llvm_anyi64ptr_ty : LLVMAnyPointerType<llvm_i64_ty>; // (space)i64*
// MISC
//
+let TargetPrefix = "nvvm" in {
def int_nvvm_clz_i : GCCBuiltin<"__nvvm_clz_i">,
Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>;
def int_nvvm_clz_ll : GCCBuiltin<"__nvvm_clz_ll">,
@@ -720,25 +721,30 @@ def llvm_anyi64ptr_ty : LLVMAnyPointerType<llvm_i64_ty>; // (space)i64*
// Atomic not available as an llvm intrinsic.
def int_nvvm_atomic_load_add_f32 : Intrinsic<[llvm_float_ty],
[LLVMAnyPointerType<llvm_float_ty>, llvm_float_ty],
- [IntrReadWriteArgMem, NoCapture<0>]>;
+ [IntrArgMemOnly, NoCapture<0>]>;
def int_nvvm_atomic_load_inc_32 : Intrinsic<[llvm_i32_ty],
[LLVMAnyPointerType<llvm_i32_ty>, llvm_i32_ty],
- [IntrReadWriteArgMem, NoCapture<0>]>;
+ [IntrArgMemOnly, NoCapture<0>]>;
def int_nvvm_atomic_load_dec_32 : Intrinsic<[llvm_i32_ty],
[LLVMAnyPointerType<llvm_i32_ty>, llvm_i32_ty],
- [IntrReadWriteArgMem, NoCapture<0>]>;
+ [IntrArgMemOnly, NoCapture<0>]>;
// Bar.Sync
- def int_cuda_syncthreads : GCCBuiltin<"__syncthreads">,
- Intrinsic<[], [], [IntrNoDuplicate]>;
- def int_nvvm_barrier0 : GCCBuiltin<"__nvvm_bar0">,
- Intrinsic<[], [], [IntrNoDuplicate]>;
+
+ // The builtin for "bar.sync 0" is called __syncthreads. Unlike most of the
+ // intrinsics in this file, this one is a user-facing API.
+ def int_nvvm_barrier0 : GCCBuiltin<"__syncthreads">,
+ Intrinsic<[], [], [IntrConvergent]>;
def int_nvvm_barrier0_popc : GCCBuiltin<"__nvvm_bar0_popc">,
- Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoDuplicate]>;
+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrConvergent]>;
def int_nvvm_barrier0_and : GCCBuiltin<"__nvvm_bar0_and">,
- Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoDuplicate]>;
+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrConvergent]>;
def int_nvvm_barrier0_or : GCCBuiltin<"__nvvm_bar0_or">,
- Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoDuplicate]>;
+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrConvergent]>;
+
+ def int_nvvm_bar_sync :
+ Intrinsic<[], [llvm_i32_ty], [IntrConvergent]>,
+ GCCBuiltin<"__nvvm_bar_sync">;
// Membar
def int_nvvm_membar_cta : GCCBuiltin<"__nvvm_membar_cta">,
@@ -748,79 +754,34 @@ def llvm_anyi64ptr_ty : LLVMAnyPointerType<llvm_i64_ty>; // (space)i64*
def int_nvvm_membar_sys : GCCBuiltin<"__nvvm_membar_sys">,
Intrinsic<[], [], []>;
-
-// Accessing special registers
- def int_nvvm_read_ptx_sreg_tid_x :
- Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>,
- GCCBuiltin<"__nvvm_read_ptx_sreg_tid_x">;
- def int_nvvm_read_ptx_sreg_tid_y :
- Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>,
- GCCBuiltin<"__nvvm_read_ptx_sreg_tid_y">;
- def int_nvvm_read_ptx_sreg_tid_z :
- Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>,
- GCCBuiltin<"__nvvm_read_ptx_sreg_tid_z">;
-
- def int_nvvm_read_ptx_sreg_ntid_x :
- Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>,
- GCCBuiltin<"__nvvm_read_ptx_sreg_ntid_x">;
- def int_nvvm_read_ptx_sreg_ntid_y :
- Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>,
- GCCBuiltin<"__nvvm_read_ptx_sreg_ntid_y">;
- def int_nvvm_read_ptx_sreg_ntid_z :
- Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>,
- GCCBuiltin<"__nvvm_read_ptx_sreg_ntid_z">;
-
- def int_nvvm_read_ptx_sreg_ctaid_x :
- Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>,
- GCCBuiltin<"__nvvm_read_ptx_sreg_ctaid_x">;
- def int_nvvm_read_ptx_sreg_ctaid_y :
- Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>,
- GCCBuiltin<"__nvvm_read_ptx_sreg_ctaid_y">;
- def int_nvvm_read_ptx_sreg_ctaid_z :
- Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>,
- GCCBuiltin<"__nvvm_read_ptx_sreg_ctaid_z">;
-
- def int_nvvm_read_ptx_sreg_nctaid_x :
- Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>,
- GCCBuiltin<"__nvvm_read_ptx_sreg_nctaid_x">;
- def int_nvvm_read_ptx_sreg_nctaid_y :
- Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>,
- GCCBuiltin<"__nvvm_read_ptx_sreg_nctaid_y">;
- def int_nvvm_read_ptx_sreg_nctaid_z :
- Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>,
- GCCBuiltin<"__nvvm_read_ptx_sreg_nctaid_z">;
-
- def int_nvvm_read_ptx_sreg_warpsize :
- Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>,
- GCCBuiltin<"__nvvm_read_ptx_sreg_warpsize">;
-
-
-// Generated within nvvm. Use for ldu on sm_20 or later
+// Generated within nvvm. Use for ldu on sm_20 or later. Second arg is the
+// pointer's alignment.
def int_nvvm_ldu_global_i : Intrinsic<[llvm_anyint_ty],
[LLVMAnyPointerType<LLVMMatchType<0>>, llvm_i32_ty],
- [IntrReadMem, NoCapture<0>],
+ [IntrReadMem, IntrArgMemOnly, NoCapture<0>],
"llvm.nvvm.ldu.global.i">;
def int_nvvm_ldu_global_f : Intrinsic<[llvm_anyfloat_ty],
[LLVMAnyPointerType<LLVMMatchType<0>>, llvm_i32_ty],
- [IntrReadMem, NoCapture<0>],
+ [IntrReadMem, IntrArgMemOnly, NoCapture<0>],
"llvm.nvvm.ldu.global.f">;
def int_nvvm_ldu_global_p : Intrinsic<[llvm_anyptr_ty],
[LLVMAnyPointerType<LLVMMatchType<0>>, llvm_i32_ty],
- [IntrReadMem, NoCapture<0>],
+ [IntrReadMem, IntrArgMemOnly, NoCapture<0>],
"llvm.nvvm.ldu.global.p">;
-// Generated within nvvm. Use for ldg on sm_35 or later
+// Generated within nvvm. Use for ldg on sm_35 or later. Second arg is the
+// pointer's alignment.
def int_nvvm_ldg_global_i : Intrinsic<[llvm_anyint_ty],
[LLVMAnyPointerType<LLVMMatchType<0>>, llvm_i32_ty],
- [IntrReadMem, NoCapture<0>],
+ [IntrReadMem, IntrArgMemOnly, NoCapture<0>],
"llvm.nvvm.ldg.global.i">;
def int_nvvm_ldg_global_f : Intrinsic<[llvm_anyfloat_ty],
[LLVMAnyPointerType<LLVMMatchType<0>>, llvm_i32_ty],
- [IntrReadMem, NoCapture<0>],
+ [IntrReadMem, IntrArgMemOnly, NoCapture<0>],
"llvm.nvvm.ldg.global.f">;
def int_nvvm_ldg_global_p : Intrinsic<[llvm_anyptr_ty],
[LLVMAnyPointerType<LLVMMatchType<0>>, llvm_i32_ty],
- [IntrReadMem, NoCapture<0>],
+ [IntrReadMem, IntrArgMemOnly, NoCapture<0>],
"llvm.nvvm.ldg.global.p">;
// Use for generic pointers
@@ -3666,9 +3627,8 @@ def int_nvvm_swap_lo_hi_b64
GCCBuiltin<"__nvvm_swap_lo_hi_b64">;
-// Old PTX back-end intrinsics retained here for backwards-compatibility
-
-multiclass PTXReadSpecialRegisterIntrinsic_v4i32<string prefix> {
+// Accessing special registers.
+multiclass PTXReadSRegIntrinsic_v4i32<string regname> {
// FIXME: Do we need the 128-bit integer type version?
// def _r64 : Intrinsic<[llvm_i128_ty], [], [IntrNoMem]>;
@@ -3676,71 +3636,99 @@ multiclass PTXReadSpecialRegisterIntrinsic_v4i32<string prefix> {
// def _v4i16 : Intrinsic<[llvm_v4i32_ty], [], [IntrNoMem]>;
def _x : Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>,
- GCCBuiltin<!strconcat(prefix, "_x")>;
+ GCCBuiltin<"__nvvm_read_ptx_sreg_" # regname # "_x">;
def _y : Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>,
- GCCBuiltin<!strconcat(prefix, "_y")>;
+ GCCBuiltin<"__nvvm_read_ptx_sreg_" # regname # "_y">;
def _z : Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>,
- GCCBuiltin<!strconcat(prefix, "_z")>;
+ GCCBuiltin<"__nvvm_read_ptx_sreg_" # regname # "_z">;
def _w : Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>,
- GCCBuiltin<!strconcat(prefix, "_w")>;
+ GCCBuiltin<"__nvvm_read_ptx_sreg_" # regname # "_w">;
}
-class PTXReadSpecialRegisterIntrinsic_r32<string name>
+class PTXReadSRegIntrinsic_r32<string name>
: Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>,
- GCCBuiltin<name>;
+ GCCBuiltin<"__nvvm_read_ptx_sreg_" # name>;
-class PTXReadSpecialRegisterIntrinsic_r64<string name>
+class PTXReadSRegIntrinsic_r64<string name>
: Intrinsic<[llvm_i64_ty], [], [IntrNoMem]>,
- GCCBuiltin<name>;
-
-defm int_ptx_read_tid : PTXReadSpecialRegisterIntrinsic_v4i32
- <"__builtin_ptx_read_tid">;
-defm int_ptx_read_ntid : PTXReadSpecialRegisterIntrinsic_v4i32
- <"__builtin_ptx_read_ntid">;
-
-def int_ptx_read_laneid : PTXReadSpecialRegisterIntrinsic_r32
- <"__builtin_ptx_read_laneid">;
-def int_ptx_read_warpid : PTXReadSpecialRegisterIntrinsic_r32
- <"__builtin_ptx_read_warpid">;
-def int_ptx_read_nwarpid : PTXReadSpecialRegisterIntrinsic_r32
- <"__builtin_ptx_read_nwarpid">;
-
-defm int_ptx_read_ctaid : PTXReadSpecialRegisterIntrinsic_v4i32
- <"__builtin_ptx_read_ctaid">;
-defm int_ptx_read_nctaid : PTXReadSpecialRegisterIntrinsic_v4i32
- <"__builtin_ptx_read_nctaid">;
-
-def int_ptx_read_smid : PTXReadSpecialRegisterIntrinsic_r32
- <"__builtin_ptx_read_smid">;
-def int_ptx_read_nsmid : PTXReadSpecialRegisterIntrinsic_r32
- <"__builtin_ptx_read_nsmid">;
-def int_ptx_read_gridid : PTXReadSpecialRegisterIntrinsic_r32
- <"__builtin_ptx_read_gridid">;
-
-def int_ptx_read_lanemask_eq : PTXReadSpecialRegisterIntrinsic_r32
- <"__builtin_ptx_read_lanemask_eq">;
-def int_ptx_read_lanemask_le : PTXReadSpecialRegisterIntrinsic_r32
- <"__builtin_ptx_read_lanemask_le">;
-def int_ptx_read_lanemask_lt : PTXReadSpecialRegisterIntrinsic_r32
- <"__builtin_ptx_read_lanemask_lt">;
-def int_ptx_read_lanemask_ge : PTXReadSpecialRegisterIntrinsic_r32
- <"__builtin_ptx_read_lanemask_ge">;
-def int_ptx_read_lanemask_gt : PTXReadSpecialRegisterIntrinsic_r32
- <"__builtin_ptx_read_lanemask_gt">;
-
-def int_ptx_read_clock : PTXReadSpecialRegisterIntrinsic_r32
- <"__builtin_ptx_read_clock">;
-def int_ptx_read_clock64 : PTXReadSpecialRegisterIntrinsic_r64
- <"__builtin_ptx_read_clock64">;
-
-def int_ptx_read_pm0 : PTXReadSpecialRegisterIntrinsic_r32
- <"__builtin_ptx_read_pm0">;
-def int_ptx_read_pm1 : PTXReadSpecialRegisterIntrinsic_r32
- <"__builtin_ptx_read_pm1">;
-def int_ptx_read_pm2 : PTXReadSpecialRegisterIntrinsic_r32
- <"__builtin_ptx_read_pm2">;
-def int_ptx_read_pm3 : PTXReadSpecialRegisterIntrinsic_r32
- <"__builtin_ptx_read_pm3">;
-
-def int_ptx_bar_sync : Intrinsic<[], [llvm_i32_ty], []>,
- GCCBuiltin<"__builtin_ptx_bar_sync">;
+ GCCBuiltin<"__nvvm_read_ptx_sreg_" # name>;
+
+defm int_nvvm_read_ptx_sreg_tid : PTXReadSRegIntrinsic_v4i32<"tid">;
+defm int_nvvm_read_ptx_sreg_ntid : PTXReadSRegIntrinsic_v4i32<"ntid">;
+
+def int_nvvm_read_ptx_sreg_laneid : PTXReadSRegIntrinsic_r32<"laneid">;
+def int_nvvm_read_ptx_sreg_warpid : PTXReadSRegIntrinsic_r32<"warpid">;
+def int_nvvm_read_ptx_sreg_nwarpid : PTXReadSRegIntrinsic_r32<"nwarpid">;
+
+defm int_nvvm_read_ptx_sreg_ctaid : PTXReadSRegIntrinsic_v4i32<"ctaid">;
+defm int_nvvm_read_ptx_sreg_nctaid : PTXReadSRegIntrinsic_v4i32<"nctaid">;
+
+def int_nvvm_read_ptx_sreg_smid : PTXReadSRegIntrinsic_r32<"smid">;
+def int_nvvm_read_ptx_sreg_nsmid : PTXReadSRegIntrinsic_r32<"nsmid">;
+def int_nvvm_read_ptx_sreg_gridid : PTXReadSRegIntrinsic_r32<"gridid">;
+
+def int_nvvm_read_ptx_sreg_lanemask_eq :
+ PTXReadSRegIntrinsic_r32<"lanemask_eq">;
+def int_nvvm_read_ptx_sreg_lanemask_le :
+ PTXReadSRegIntrinsic_r32<"lanemask_le">;
+def int_nvvm_read_ptx_sreg_lanemask_lt :
+ PTXReadSRegIntrinsic_r32<"lanemask_lt">;
+def int_nvvm_read_ptx_sreg_lanemask_ge :
+ PTXReadSRegIntrinsic_r32<"lanemask_ge">;
+def int_nvvm_read_ptx_sreg_lanemask_gt :
+ PTXReadSRegIntrinsic_r32<"lanemask_gt">;
+
+def int_nvvm_read_ptx_sreg_clock : PTXReadSRegIntrinsic_r32<"clock">;
+def int_nvvm_read_ptx_sreg_clock64 : PTXReadSRegIntrinsic_r64<"clock64">;
+
+def int_nvvm_read_ptx_sreg_pm0 : PTXReadSRegIntrinsic_r32<"pm0">;
+def int_nvvm_read_ptx_sreg_pm1 : PTXReadSRegIntrinsic_r32<"pm1">;
+def int_nvvm_read_ptx_sreg_pm2 : PTXReadSRegIntrinsic_r32<"pm2">;
+def int_nvvm_read_ptx_sreg_pm3 : PTXReadSRegIntrinsic_r32<"pm3">;
+
+def int_nvvm_read_ptx_sreg_warpsize : PTXReadSRegIntrinsic_r32<"warpsize">;
+
+//
+// SHUFFLE
+//
+
+// shfl.down.b32 dest, val, offset, mask_and_clamp
+def int_nvvm_shfl_down_i32 :
+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
+ [IntrNoMem, IntrConvergent], "llvm.nvvm.shfl.down.i32">,
+ GCCBuiltin<"__nvvm_shfl_down_i32">;
+def int_nvvm_shfl_down_f32 :
+ Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_i32_ty, llvm_i32_ty],
+ [IntrNoMem, IntrConvergent], "llvm.nvvm.shfl.down.f32">,
+ GCCBuiltin<"__nvvm_shfl_down_f32">;
+
+// shfl.up.b32 dest, val, offset, mask_and_clamp
+def int_nvvm_shfl_up_i32 :
+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
+ [IntrNoMem, IntrConvergent], "llvm.nvvm.shfl.up.i32">,
+ GCCBuiltin<"__nvvm_shfl_up_i32">;
+def int_nvvm_shfl_up_f32 :
+ Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_i32_ty, llvm_i32_ty],
+ [IntrNoMem, IntrConvergent], "llvm.nvvm.shfl.up.f32">,
+ GCCBuiltin<"__nvvm_shfl_up_f32">;
+
+// shfl.bfly.b32 dest, val, offset, mask_and_clamp
+def int_nvvm_shfl_bfly_i32 :
+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
+ [IntrNoMem, IntrConvergent], "llvm.nvvm.shfl.bfly.i32">,
+ GCCBuiltin<"__nvvm_shfl_bfly_i32">;
+def int_nvvm_shfl_bfly_f32 :
+ Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_i32_ty, llvm_i32_ty],
+ [IntrNoMem, IntrConvergent], "llvm.nvvm.shfl.bfly.f32">,
+ GCCBuiltin<"__nvvm_shfl_bfly_f32">;
+
+// shfl.idx.b32 dest, val, lane, mask_and_clamp
+def int_nvvm_shfl_idx_i32 :
+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
+ [IntrNoMem, IntrConvergent], "llvm.nvvm.shfl.idx.i32">,
+ GCCBuiltin<"__nvvm_shfl_idx_i32">;
+def int_nvvm_shfl_idx_f32 :
+ Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_i32_ty, llvm_i32_ty],
+ [IntrNoMem, IntrConvergent], "llvm.nvvm.shfl.idx.f32">,
+ GCCBuiltin<"__nvvm_shfl_idx_f32">;
+}
diff --git a/include/llvm/IR/IntrinsicsPowerPC.td b/include/llvm/IR/IntrinsicsPowerPC.td
index 5512b1063fb0..e195c0ebac3a 100644
--- a/include/llvm/IR/IntrinsicsPowerPC.td
+++ b/include/llvm/IR/IntrinsicsPowerPC.td
@@ -23,9 +23,9 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.".
def int_ppc_dcbi : Intrinsic<[], [llvm_ptr_ty], []>;
def int_ppc_dcbst : Intrinsic<[], [llvm_ptr_ty], []>;
def int_ppc_dcbt : Intrinsic<[], [llvm_ptr_ty],
- [IntrReadWriteArgMem, NoCapture<0>]>;
+ [IntrArgMemOnly, NoCapture<0>]>;
def int_ppc_dcbtst: Intrinsic<[], [llvm_ptr_ty],
- [IntrReadWriteArgMem, NoCapture<0>]>;
+ [IntrArgMemOnly, NoCapture<0>]>;
def int_ppc_dcbz : Intrinsic<[], [llvm_ptr_ty], []>;
def int_ppc_dcbzl : Intrinsic<[], [llvm_ptr_ty], []>;
@@ -189,33 +189,33 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.".
// Loads. These don't map directly to GCC builtins because they represent the
// source address with a single pointer.
def int_ppc_altivec_lvx :
- Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty], [IntrReadArgMem]>;
+ Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>;
def int_ppc_altivec_lvxl :
- Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty], [IntrReadArgMem]>;
+ Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>;
def int_ppc_altivec_lvebx :
- Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty], [IntrReadArgMem]>;
+ Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>;
def int_ppc_altivec_lvehx :
- Intrinsic<[llvm_v8i16_ty], [llvm_ptr_ty], [IntrReadArgMem]>;
+ Intrinsic<[llvm_v8i16_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>;
def int_ppc_altivec_lvewx :
- Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty], [IntrReadArgMem]>;
+ Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>;
// Stores. These don't map directly to GCC builtins because they represent the
// source address with a single pointer.
def int_ppc_altivec_stvx :
Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_ppc_altivec_stvxl :
Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_ppc_altivec_stvebx :
Intrinsic<[], [llvm_v16i8_ty, llvm_ptr_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_ppc_altivec_stvehx :
Intrinsic<[], [llvm_v8i16_ty, llvm_ptr_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_ppc_altivec_stvewx :
Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
// Comparisons setting a vector.
def int_ppc_altivec_vcmpbfp : GCCBuiltin<"__builtin_altivec_vcmpbfp">,
@@ -664,15 +664,15 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.".
// Vector load.
def int_ppc_vsx_lxvw4x :
- Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty], [IntrReadArgMem]>;
+ Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>;
def int_ppc_vsx_lxvd2x :
- Intrinsic<[llvm_v2f64_ty], [llvm_ptr_ty], [IntrReadArgMem]>;
+ Intrinsic<[llvm_v2f64_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>;
// Vector store.
def int_ppc_vsx_stxvw4x :
- Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty], [IntrReadWriteArgMem]>;
+ Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty], [IntrArgMemOnly]>;
def int_ppc_vsx_stxvd2x :
- Intrinsic<[], [llvm_v2f64_ty, llvm_ptr_ty], [IntrReadWriteArgMem]>;
+ Intrinsic<[], [llvm_v2f64_ty, llvm_ptr_ty], [IntrArgMemOnly]>;
// Vector and scalar maximum.
def int_ppc_vsx_xvmaxdp : PowerPC_VSX_Vec_DDD_Intrinsic<"xvmaxdp">;
@@ -790,7 +790,7 @@ class PowerPC_QPX_FFFF_Intrinsic<string GCCIntSuffix>
/// and returns a v4f64.
class PowerPC_QPX_Load_Intrinsic<string GCCIntSuffix>
: PowerPC_QPX_Intrinsic<GCCIntSuffix,
- [llvm_v4f64_ty], [llvm_ptr_ty], [IntrReadArgMem]>;
+ [llvm_v4f64_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>;
/// PowerPC_QPX_LoadPerm_Intrinsic - A PowerPC intrinsic that takes a pointer
/// and returns a v4f64 permutation.
@@ -803,7 +803,7 @@ class PowerPC_QPX_LoadPerm_Intrinsic<string GCCIntSuffix>
class PowerPC_QPX_Store_Intrinsic<string GCCIntSuffix>
: PowerPC_QPX_Intrinsic<GCCIntSuffix,
[], [llvm_v4f64_ty, llvm_ptr_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
//===----------------------------------------------------------------------===//
// PowerPC QPX Intrinsic Definitions.
diff --git a/include/llvm/IR/IntrinsicsSystemZ.td b/include/llvm/IR/IntrinsicsSystemZ.td
index 96e7ca525696..bfc15b9bc09e 100644
--- a/include/llvm/IR/IntrinsicsSystemZ.td
+++ b/include/llvm/IR/IntrinsicsSystemZ.td
@@ -217,7 +217,7 @@ let TargetPrefix = "s390" in {
Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>;
def int_s390_ntstg : Intrinsic<[], [llvm_i64_ty, llvm_ptr64_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_s390_ppa_txassist : GCCBuiltin<"__builtin_tx_assist">,
Intrinsic<[], [llvm_i32_ty]>;
@@ -236,11 +236,11 @@ let TargetPrefix = "s390" in {
def int_s390_vlbb : GCCBuiltin<"__builtin_s390_vlbb">,
Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_s390_vll : GCCBuiltin<"__builtin_s390_vll">,
Intrinsic<[llvm_v16i8_ty], [llvm_i32_ty, llvm_ptr_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_s390_vpdi : GCCBuiltin<"__builtin_s390_vpdi">,
Intrinsic<[llvm_v2i64_ty],
@@ -262,7 +262,7 @@ let TargetPrefix = "s390" in {
Intrinsic<[], [llvm_v16i8_ty, llvm_i32_ty, llvm_ptr_ty],
// In fact write-only but there's no property
// for that.
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
defm int_s390_vupl : SystemZUnaryExtBHWF<"vupl">;
defm int_s390_vupll : SystemZUnaryExtBHF<"vupll">;
@@ -374,3 +374,14 @@ let TargetPrefix = "s390" in {
[llvm_v2f64_ty, llvm_i32_ty, llvm_i32_ty],
[IntrNoMem]>;
}
+
+//===----------------------------------------------------------------------===//
+//
+// Misc intrinsics
+//
+//===----------------------------------------------------------------------===//
+
+let TargetPrefix = "s390" in {
+ def int_s390_tdc : Intrinsic<[llvm_i32_ty], [llvm_anyfloat_ty, llvm_i64_ty],
+ [IntrNoMem]>;
+}
diff --git a/include/llvm/IR/IntrinsicsWebAssembly.td b/include/llvm/IR/IntrinsicsWebAssembly.td
index 3953aef43dad..4234c466d973 100644
--- a/include/llvm/IR/IntrinsicsWebAssembly.td
+++ b/include/llvm/IR/IntrinsicsWebAssembly.td
@@ -14,9 +14,9 @@
let TargetPrefix = "wasm" in { // All intrinsics start with "llvm.wasm.".
-// Note that memory_size is not IntrNoMem because it must be sequenced with
+// Note that current_memory is not IntrNoMem because it must be sequenced with
// respect to grow_memory calls.
-def int_wasm_memory_size : Intrinsic<[llvm_anyint_ty], [], [IntrReadMem]>;
+def int_wasm_current_memory : Intrinsic<[llvm_anyint_ty], [], [IntrReadMem]>;
def int_wasm_grow_memory : Intrinsic<[], [llvm_anyint_ty], []>;
}
diff --git a/include/llvm/IR/IntrinsicsX86.td b/include/llvm/IR/IntrinsicsX86.td
index 8023a9f6e8e9..74c971552bb3 100644
--- a/include/llvm/IR/IntrinsicsX86.td
+++ b/include/llvm/IR/IntrinsicsX86.td
@@ -25,6 +25,9 @@ let TargetPrefix = "x86" in {
// Marks the EH registration node created in LLVM IR prior to code generation.
def int_x86_seh_ehregnode : Intrinsic<[], [llvm_ptr_ty], []>;
+ // Marks the EH guard slot node created in LLVM IR prior to code generation.
+ def int_x86_seh_ehguard : Intrinsic<[], [llvm_ptr_ty], []>;
+
// Given a pointer to the end of an EH registration object, returns the true
// parent frame address that can be used with llvm.localrecover.
def int_x86_seh_recoverfp : Intrinsic<[llvm_ptr_ty],
@@ -51,7 +54,7 @@ let TargetPrefix = "x86" in {
def int_x86_rdtsc : GCCBuiltin<"__builtin_ia32_rdtsc">,
Intrinsic<[llvm_i64_ty], [], []>;
def int_x86_rdtscp : GCCBuiltin<"__builtin_ia32_rdtscp">,
- Intrinsic<[llvm_i64_ty], [llvm_ptr_ty], [IntrReadWriteArgMem]>;
+ Intrinsic<[llvm_i64_ty], [llvm_ptr_ty], [IntrArgMemOnly]>;
}
// Read Performance-Monitoring Counter.
@@ -142,16 +145,16 @@ let TargetPrefix = "x86" in {
// Arithmetic ops
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_sse_add_ss : GCCBuiltin<"__builtin_ia32_addss">,
+ def int_x86_sse_add_ss :
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty,
llvm_v4f32_ty], [IntrNoMem]>;
- def int_x86_sse_sub_ss : GCCBuiltin<"__builtin_ia32_subss">,
+ def int_x86_sse_sub_ss :
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty,
llvm_v4f32_ty], [IntrNoMem]>;
- def int_x86_sse_mul_ss : GCCBuiltin<"__builtin_ia32_mulss">,
+ def int_x86_sse_mul_ss :
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty,
llvm_v4f32_ty], [IntrNoMem]>;
- def int_x86_sse_div_ss : GCCBuiltin<"__builtin_ia32_divss">,
+ def int_x86_sse_div_ss :
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty,
llvm_v4f32_ty], [IntrNoMem]>;
def int_x86_sse_sqrt_ss : GCCBuiltin<"__builtin_ia32_sqrtss">,
@@ -191,7 +194,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_sse_cmp_ss : GCCBuiltin<"__builtin_ia32_cmpss">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty,
llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_sse_cmp_ps : GCCBuiltin<"__builtin_ia32_cmpps">,
+ def int_x86_sse_cmp_ps :
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty,
llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_sse_comieq_ss : GCCBuiltin<"__builtin_ia32_comieq">,
@@ -259,13 +262,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
llvm_x86mmx_ty], [IntrNoMem]>;
}
-// SIMD store ops
-let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_sse_storeu_ps : GCCBuiltin<"__builtin_ia32_storeups">,
- Intrinsic<[], [llvm_ptr_ty,
- llvm_v4f32_ty], [IntrReadWriteArgMem]>;
-}
-
// Cacheability support ops
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_sse_sfence : GCCBuiltin<"__builtin_ia32_sfence">,
@@ -291,16 +287,16 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
// FP arithmetic ops
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_sse2_add_sd : GCCBuiltin<"__builtin_ia32_addsd">,
+ def int_x86_sse2_add_sd :
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty,
llvm_v2f64_ty], [IntrNoMem]>;
- def int_x86_sse2_sub_sd : GCCBuiltin<"__builtin_ia32_subsd">,
+ def int_x86_sse2_sub_sd :
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty,
llvm_v2f64_ty], [IntrNoMem]>;
- def int_x86_sse2_mul_sd : GCCBuiltin<"__builtin_ia32_mulsd">,
+ def int_x86_sse2_mul_sd :
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty,
llvm_v2f64_ty], [IntrNoMem]>;
- def int_x86_sse2_div_sd : GCCBuiltin<"__builtin_ia32_divsd">,
+ def int_x86_sse2_div_sd :
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty,
llvm_v2f64_ty], [IntrNoMem]>;
def int_x86_sse2_sqrt_sd : GCCBuiltin<"__builtin_ia32_sqrtsd">,
@@ -328,7 +324,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_sse2_cmp_sd : GCCBuiltin<"__builtin_ia32_cmpsd">,
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty,
llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_sse2_cmp_pd : GCCBuiltin<"__builtin_ia32_cmppd">,
+ def int_x86_sse2_cmp_pd :
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty,
llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_sse2_comieq_sd : GCCBuiltin<"__builtin_ia32_comisdeq">,
@@ -413,18 +409,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_sse2_pavg_w : GCCBuiltin<"__builtin_ia32_pavgw128">,
Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty,
llvm_v8i16_ty], [IntrNoMem, Commutative]>;
- def int_x86_sse2_pmaxu_b : GCCBuiltin<"__builtin_ia32_pmaxub128">,
- Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty,
- llvm_v16i8_ty], [IntrNoMem, Commutative]>;
- def int_x86_sse2_pmaxs_w : GCCBuiltin<"__builtin_ia32_pmaxsw128">,
- Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty,
- llvm_v8i16_ty], [IntrNoMem, Commutative]>;
- def int_x86_sse2_pminu_b : GCCBuiltin<"__builtin_ia32_pminub128">,
- Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty,
- llvm_v16i8_ty], [IntrNoMem, Commutative]>;
- def int_x86_sse2_pmins_w : GCCBuiltin<"__builtin_ia32_pminsw128">,
- Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty,
- llvm_v8i16_ty], [IntrNoMem, Commutative]>;
def int_x86_sse2_psad_bw : GCCBuiltin<"__builtin_ia32_psadbw128">,
Intrinsic<[llvm_v2i64_ty], [llvm_v16i8_ty,
llvm_v16i8_ty], [IntrNoMem, Commutative]>;
@@ -485,8 +469,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
// Conversion ops
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_sse2_cvtdq2pd : GCCBuiltin<"__builtin_ia32_cvtdq2pd">,
- Intrinsic<[llvm_v2f64_ty], [llvm_v4i32_ty], [IntrNoMem]>;
def int_x86_sse2_cvtdq2ps : GCCBuiltin<"__builtin_ia32_cvtdq2ps">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4i32_ty], [IntrNoMem]>;
def int_x86_sse2_cvtpd2dq : GCCBuiltin<"__builtin_ia32_cvtpd2dq">,
@@ -497,10 +479,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v4f32_ty], [llvm_v2f64_ty], [IntrNoMem]>;
def int_x86_sse2_cvtps2dq : GCCBuiltin<"__builtin_ia32_cvtps2dq">,
Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>;
- def int_x86_sse2_cvttps2dq : GCCBuiltin<"__builtin_ia32_cvttps2dq">,
- Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>;
- def int_x86_sse2_cvtps2pd : GCCBuiltin<"__builtin_ia32_cvtps2pd">,
- Intrinsic<[llvm_v2f64_ty], [llvm_v4f32_ty], [IntrNoMem]>;
def int_x86_sse2_cvtsd2si : GCCBuiltin<"__builtin_ia32_cvtsd2si">,
Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty], [IntrNoMem]>;
def int_x86_sse2_cvtsd2si64 : GCCBuiltin<"__builtin_ia32_cvtsd2si64">,
@@ -529,19 +507,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v2f64_ty], [llvm_x86mmx_ty], [IntrNoMem]>;
}
-// SIMD store ops
-let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_sse2_storeu_pd : GCCBuiltin<"__builtin_ia32_storeupd">,
- Intrinsic<[], [llvm_ptr_ty,
- llvm_v2f64_ty], [IntrReadWriteArgMem]>;
- def int_x86_sse2_storeu_dq : GCCBuiltin<"__builtin_ia32_storedqu">,
- Intrinsic<[], [llvm_ptr_ty,
- llvm_v16i8_ty], [IntrReadWriteArgMem]>;
- def int_x86_sse2_storel_dq : GCCBuiltin<"__builtin_ia32_storelv4si">,
- Intrinsic<[], [llvm_ptr_ty,
- llvm_v4i32_ty], [IntrReadWriteArgMem]>;
-}
-
// Misc.
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_sse2_packsswb_128 : GCCBuiltin<"__builtin_ia32_packsswb128">,
@@ -688,15 +653,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_ssse3_pshuf_b_128 : GCCBuiltin<"__builtin_ia32_pshufb128">,
Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty,
llvm_v16i8_ty], [IntrNoMem]>;
- def int_x86_sse2_pshuf_d : GCCBuiltin<"__builtin_ia32_pshufd">,
- Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i8_ty],
- [IntrNoMem]>;
- def int_x86_sse2_pshufl_w : GCCBuiltin<"__builtin_ia32_pshuflw">,
- Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i8_ty],
- [IntrNoMem]>;
- def int_x86_sse2_pshufh_w : GCCBuiltin<"__builtin_ia32_pshufhw">,
- Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i8_ty],
- [IntrNoMem]>;
def int_x86_sse_pshuf_w : GCCBuiltin<"__builtin_ia32_pshufw">,
Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_i8_ty],
[IntrNoMem]>;
@@ -763,46 +719,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
llvm_i32_ty], [IntrNoMem]>;
}
-// Vector sign and zero extend
-let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_sse41_pmovsxbd : GCCBuiltin<"__builtin_ia32_pmovsxbd128">,
- Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty],
- [IntrNoMem]>;
- def int_x86_sse41_pmovsxbq : GCCBuiltin<"__builtin_ia32_pmovsxbq128">,
- Intrinsic<[llvm_v2i64_ty], [llvm_v16i8_ty],
- [IntrNoMem]>;
- def int_x86_sse41_pmovsxbw : GCCBuiltin<"__builtin_ia32_pmovsxbw128">,
- Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty],
- [IntrNoMem]>;
- def int_x86_sse41_pmovsxdq : GCCBuiltin<"__builtin_ia32_pmovsxdq128">,
- Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty],
- [IntrNoMem]>;
- def int_x86_sse41_pmovsxwd : GCCBuiltin<"__builtin_ia32_pmovsxwd128">,
- Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty],
- [IntrNoMem]>;
- def int_x86_sse41_pmovsxwq : GCCBuiltin<"__builtin_ia32_pmovsxwq128">,
- Intrinsic<[llvm_v2i64_ty], [llvm_v8i16_ty],
- [IntrNoMem]>;
- def int_x86_sse41_pmovzxbd : GCCBuiltin<"__builtin_ia32_pmovzxbd128">,
- Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty],
- [IntrNoMem]>;
- def int_x86_sse41_pmovzxbq : GCCBuiltin<"__builtin_ia32_pmovzxbq128">,
- Intrinsic<[llvm_v2i64_ty], [llvm_v16i8_ty],
- [IntrNoMem]>;
- def int_x86_sse41_pmovzxbw : GCCBuiltin<"__builtin_ia32_pmovzxbw128">,
- Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty],
- [IntrNoMem]>;
- def int_x86_sse41_pmovzxdq : GCCBuiltin<"__builtin_ia32_pmovzxdq128">,
- Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty],
- [IntrNoMem]>;
- def int_x86_sse41_pmovzxwd : GCCBuiltin<"__builtin_ia32_pmovzxwd128">,
- Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty],
- [IntrNoMem]>;
- def int_x86_sse41_pmovzxwq : GCCBuiltin<"__builtin_ia32_pmovzxwq128">,
- Intrinsic<[llvm_v2i64_ty], [llvm_v8i16_ty],
- [IntrNoMem]>;
-}
-
// Vector min element
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_sse41_phminposuw : GCCBuiltin<"__builtin_ia32_phminposuw128">,
@@ -810,34 +726,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
[IntrNoMem]>;
}
-// Vector compare, min, max
-let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_sse41_pmaxsb : GCCBuiltin<"__builtin_ia32_pmaxsb128">,
- Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty],
- [IntrNoMem, Commutative]>;
- def int_x86_sse41_pmaxsd : GCCBuiltin<"__builtin_ia32_pmaxsd128">,
- Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty],
- [IntrNoMem, Commutative]>;
- def int_x86_sse41_pmaxud : GCCBuiltin<"__builtin_ia32_pmaxud128">,
- Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty],
- [IntrNoMem, Commutative]>;
- def int_x86_sse41_pmaxuw : GCCBuiltin<"__builtin_ia32_pmaxuw128">,
- Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty],
- [IntrNoMem, Commutative]>;
- def int_x86_sse41_pminsb : GCCBuiltin<"__builtin_ia32_pminsb128">,
- Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty],
- [IntrNoMem, Commutative]>;
- def int_x86_sse41_pminsd : GCCBuiltin<"__builtin_ia32_pminsd128">,
- Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty],
- [IntrNoMem, Commutative]>;
- def int_x86_sse41_pminud : GCCBuiltin<"__builtin_ia32_pminud128">,
- Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty],
- [IntrNoMem, Commutative]>;
- def int_x86_sse41_pminuw : GCCBuiltin<"__builtin_ia32_pminuw128">,
- Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty],
- [IntrNoMem, Commutative]>;
-}
-
// Advanced Encryption Standard (AES) Instructions
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_aesni_aesimc : GCCBuiltin<"__builtin_ia32_aesimc128">,
@@ -882,22 +770,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
[IntrNoMem, Commutative]>;
}
-// Vector extract
-let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_sse41_pextrb :
- Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty, llvm_i32_ty],
- [IntrNoMem]>;
- def int_x86_sse41_pextrd :
- Intrinsic<[llvm_i32_ty], [llvm_v4i32_ty, llvm_i32_ty],
- [IntrNoMem]>;
- def int_x86_sse41_pextrq :
- Intrinsic<[llvm_i64_ty], [llvm_v2i64_ty, llvm_i32_ty],
- [IntrNoMem]>;
- def int_x86_sse41_extractps : GCCBuiltin<"__builtin_ia32_extractps128">,
- Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, llvm_i32_ty],
- [IntrNoMem]>;
-}
-
// Vector insert
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_sse41_insertps : GCCBuiltin<"__builtin_ia32_insertps128">,
@@ -1056,11 +928,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_sse4a_insertq : GCCBuiltin<"__builtin_ia32_insertq">,
Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>;
-
- def int_x86_sse4a_movnt_ss : GCCBuiltin<"__builtin_ia32_movntss">,
- Intrinsic<[], [llvm_ptr_ty, llvm_v4f32_ty], []>;
- def int_x86_sse4a_movnt_sd : GCCBuiltin<"__builtin_ia32_movntsd">,
- Intrinsic<[], [llvm_ptr_ty, llvm_v2f64_ty], []>;
}
//===----------------------------------------------------------------------===//
@@ -1151,91 +1018,91 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty,
llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpermi2var_d_128 :
+ def int_x86_avx512_mask_vpermi2var_d_128 :
GCCBuiltin<"__builtin_ia32_vpermi2vard128_mask">,
Intrinsic<[llvm_v4i32_ty],
[llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_vpermi2var_d_256 :
+ def int_x86_avx512_mask_vpermi2var_d_256 :
GCCBuiltin<"__builtin_ia32_vpermi2vard256_mask">,
Intrinsic<[llvm_v8i32_ty],
[llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_vpermi2var_d_512 :
+ def int_x86_avx512_mask_vpermi2var_d_512 :
GCCBuiltin<"__builtin_ia32_vpermi2vard512_mask">,
Intrinsic<[llvm_v16i32_ty],
[llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_vpermi2var_hi_128 :
+ def int_x86_avx512_mask_vpermi2var_hi_128 :
GCCBuiltin<"__builtin_ia32_vpermi2varhi128_mask">,
Intrinsic<[llvm_v8i16_ty],
[llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_vpermi2var_hi_256 :
+ def int_x86_avx512_mask_vpermi2var_hi_256 :
GCCBuiltin<"__builtin_ia32_vpermi2varhi256_mask">,
Intrinsic<[llvm_v16i16_ty],
[llvm_v16i16_ty, llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_vpermi2var_hi_512 :
+ def int_x86_avx512_mask_vpermi2var_hi_512 :
GCCBuiltin<"__builtin_ia32_vpermi2varhi512_mask">,
Intrinsic<[llvm_v32i16_ty],
[llvm_v32i16_ty, llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_vpermi2var_pd_128 :
+ def int_x86_avx512_mask_vpermi2var_pd_128 :
GCCBuiltin<"__builtin_ia32_vpermi2varpd128_mask">,
Intrinsic<[llvm_v2f64_ty],
[llvm_v2f64_ty, llvm_v2i64_ty, llvm_v2f64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_vpermi2var_pd_256 :
+ def int_x86_avx512_mask_vpermi2var_pd_256 :
GCCBuiltin<"__builtin_ia32_vpermi2varpd256_mask">,
Intrinsic<[llvm_v4f64_ty],
[llvm_v4f64_ty, llvm_v4i64_ty, llvm_v4f64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_vpermi2var_pd_512 :
+ def int_x86_avx512_mask_vpermi2var_pd_512 :
GCCBuiltin<"__builtin_ia32_vpermi2varpd512_mask">,
Intrinsic<[llvm_v8f64_ty],
[llvm_v8f64_ty, llvm_v8i64_ty, llvm_v8f64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_vpermi2var_ps_128 :
+ def int_x86_avx512_mask_vpermi2var_ps_128 :
GCCBuiltin<"__builtin_ia32_vpermi2varps128_mask">,
Intrinsic<[llvm_v4f32_ty],
[llvm_v4f32_ty, llvm_v4i32_ty, llvm_v4f32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_vpermi2var_ps_256 :
+ def int_x86_avx512_mask_vpermi2var_ps_256 :
GCCBuiltin<"__builtin_ia32_vpermi2varps256_mask">,
Intrinsic<[llvm_v8f32_ty],
[llvm_v8f32_ty, llvm_v8i32_ty, llvm_v8f32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_vpermi2var_ps_512 :
+ def int_x86_avx512_mask_vpermi2var_ps_512 :
GCCBuiltin<"__builtin_ia32_vpermi2varps512_mask">,
Intrinsic<[llvm_v16f32_ty],
[llvm_v16f32_ty, llvm_v16i32_ty, llvm_v16f32_ty, llvm_i16_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_vpermi2var_q_128 :
+ def int_x86_avx512_mask_vpermi2var_q_128 :
GCCBuiltin<"__builtin_ia32_vpermi2varq128_mask">,
Intrinsic<[llvm_v2i64_ty],
[llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_vpermi2var_q_256 :
+ def int_x86_avx512_mask_vpermi2var_q_256 :
GCCBuiltin<"__builtin_ia32_vpermi2varq256_mask">,
Intrinsic<[llvm_v4i64_ty],
[llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_vpermi2var_q_512 :
+ def int_x86_avx512_mask_vpermi2var_q_512 :
GCCBuiltin<"__builtin_ia32_vpermi2varq512_mask">,
Intrinsic<[llvm_v8i64_ty],
[llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
@@ -1261,196 +1128,214 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v8f64_ty], [llvm_v8i64_ty,
llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpermt2var_d_128 :
+ def int_x86_avx512_mask_vpermt2var_d_128 :
GCCBuiltin<"__builtin_ia32_vpermt2vard128_mask">,
Intrinsic<[llvm_v4i32_ty],
[llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_maskz_vpermt2var_d_128 :
+ def int_x86_avx512_maskz_vpermt2var_d_128 :
GCCBuiltin<"__builtin_ia32_vpermt2vard128_maskz">,
Intrinsic<[llvm_v4i32_ty],
[llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_vpermt2var_d_256 :
+ def int_x86_avx512_mask_vpermt2var_d_256 :
GCCBuiltin<"__builtin_ia32_vpermt2vard256_mask">,
Intrinsic<[llvm_v8i32_ty],
[llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_maskz_vpermt2var_d_256 :
+ def int_x86_avx512_maskz_vpermt2var_d_256 :
GCCBuiltin<"__builtin_ia32_vpermt2vard256_maskz">,
Intrinsic<[llvm_v8i32_ty],
[llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_maskz_vpermt2var_d_512 :
+ def int_x86_avx512_maskz_vpermt2var_d_512 :
GCCBuiltin<"__builtin_ia32_vpermt2vard512_maskz">,
Intrinsic<[llvm_v16i32_ty],
[llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_vpermt2var_hi_128 :
+ def int_x86_avx512_mask_vpermt2var_hi_128 :
GCCBuiltin<"__builtin_ia32_vpermt2varhi128_mask">,
Intrinsic<[llvm_v8i16_ty],
[llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_maskz_vpermt2var_hi_128 :
+ def int_x86_avx512_maskz_vpermt2var_hi_128 :
GCCBuiltin<"__builtin_ia32_vpermt2varhi128_maskz">,
Intrinsic<[llvm_v8i16_ty],
[llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_vpermt2var_hi_256 :
+ def int_x86_avx512_mask_vpermt2var_hi_256 :
GCCBuiltin<"__builtin_ia32_vpermt2varhi256_mask">,
Intrinsic<[llvm_v16i16_ty],
[llvm_v16i16_ty, llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty],
[IntrNoMem]>;
- def int_x86_avx512_maskz_vpermt2var_hi_256 :
+ def int_x86_avx512_maskz_vpermt2var_hi_256 :
GCCBuiltin<"__builtin_ia32_vpermt2varhi256_maskz">,
Intrinsic<[llvm_v16i16_ty],
[llvm_v16i16_ty, llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_vpermt2var_hi_512 :
+ def int_x86_avx512_mask_vpermt2var_hi_512 :
GCCBuiltin<"__builtin_ia32_vpermt2varhi512_mask">,
Intrinsic<[llvm_v32i16_ty],
[llvm_v32i16_ty, llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_maskz_vpermt2var_hi_512 :
+ def int_x86_avx512_maskz_vpermt2var_hi_512 :
GCCBuiltin<"__builtin_ia32_vpermt2varhi512_maskz">,
Intrinsic<[llvm_v32i16_ty],
[llvm_v32i16_ty, llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_vpermt2var_pd_128 :
+ def int_x86_avx512_mask_vpermt2var_pd_128 :
GCCBuiltin<"__builtin_ia32_vpermt2varpd128_mask">,
Intrinsic<[llvm_v2f64_ty],
[llvm_v2i64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_maskz_vpermt2var_pd_128 :
+ def int_x86_avx512_maskz_vpermt2var_pd_128 :
GCCBuiltin<"__builtin_ia32_vpermt2varpd128_maskz">,
Intrinsic<[llvm_v2f64_ty],
[llvm_v2i64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_vpermt2var_pd_256 :
+ def int_x86_avx512_mask_vpermt2var_pd_256 :
GCCBuiltin<"__builtin_ia32_vpermt2varpd256_mask">,
Intrinsic<[llvm_v4f64_ty],
[llvm_v4i64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_maskz_vpermt2var_pd_256 :
+ def int_x86_avx512_maskz_vpermt2var_pd_256 :
GCCBuiltin<"__builtin_ia32_vpermt2varpd256_maskz">,
Intrinsic<[llvm_v4f64_ty],
[llvm_v4i64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_maskz_vpermt2var_pd_512 :
+ def int_x86_avx512_maskz_vpermt2var_pd_512 :
GCCBuiltin<"__builtin_ia32_vpermt2varpd512_maskz">,
Intrinsic<[llvm_v8f64_ty],
[llvm_v8i64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_vpermt2var_ps_128 :
+ def int_x86_avx512_mask_vpermt2var_ps_128 :
GCCBuiltin<"__builtin_ia32_vpermt2varps128_mask">,
Intrinsic<[llvm_v4f32_ty],
[llvm_v4i32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_maskz_vpermt2var_ps_128 :
+ def int_x86_avx512_maskz_vpermt2var_ps_128 :
GCCBuiltin<"__builtin_ia32_vpermt2varps128_maskz">,
Intrinsic<[llvm_v4f32_ty],
[llvm_v4i32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_vpermt2var_ps_256 :
+ def int_x86_avx512_mask_vpermt2var_ps_256 :
GCCBuiltin<"__builtin_ia32_vpermt2varps256_mask">,
Intrinsic<[llvm_v8f32_ty],
[llvm_v8i32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_maskz_vpermt2var_ps_256 :
+ def int_x86_avx512_maskz_vpermt2var_ps_256 :
GCCBuiltin<"__builtin_ia32_vpermt2varps256_maskz">,
Intrinsic<[llvm_v8f32_ty],
[llvm_v8i32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_maskz_vpermt2var_ps_512 :
+ def int_x86_avx512_maskz_vpermt2var_ps_512 :
GCCBuiltin<"__builtin_ia32_vpermt2varps512_maskz">,
Intrinsic<[llvm_v16f32_ty],
[llvm_v16i32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_vpermt2var_q_128 :
+ def int_x86_avx512_mask_vpermt2var_q_128 :
GCCBuiltin<"__builtin_ia32_vpermt2varq128_mask">,
Intrinsic<[llvm_v2i64_ty],
[llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_maskz_vpermt2var_q_128 :
+ def int_x86_avx512_maskz_vpermt2var_q_128 :
GCCBuiltin<"__builtin_ia32_vpermt2varq128_maskz">,
Intrinsic<[llvm_v2i64_ty],
[llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_vpermt2var_q_256 :
+ def int_x86_avx512_mask_vpermt2var_q_256 :
GCCBuiltin<"__builtin_ia32_vpermt2varq256_mask">,
Intrinsic<[llvm_v4i64_ty],
[llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_maskz_vpermt2var_q_256 :
+ def int_x86_avx512_maskz_vpermt2var_q_256 :
GCCBuiltin<"__builtin_ia32_vpermt2varq256_maskz">,
Intrinsic<[llvm_v4i64_ty],
[llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_maskz_vpermt2var_q_512 :
+ def int_x86_avx512_maskz_vpermt2var_q_512 :
GCCBuiltin<"__builtin_ia32_vpermt2varq512_maskz">,
Intrinsic<[llvm_v8i64_ty],
[llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_vpermil_pd_128 :
- GCCBuiltin<"__builtin_ia32_vpermilpd_mask">,
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2f64_ty, llvm_i32_ty, llvm_v2f64_ty, llvm_i8_ty],
+ def int_x86_avx512_mask_vpermi2var_qi_128 :
+ GCCBuiltin<"__builtin_ia32_vpermi2varqi128_mask">,
+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty,
+ llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_vpermil_pd_256 :
- GCCBuiltin<"__builtin_ia32_vpermilpd256_mask">,
- Intrinsic<[llvm_v4f64_ty],
- [llvm_v4f64_ty, llvm_i32_ty, llvm_v4f64_ty, llvm_i8_ty],
+ def int_x86_avx512_mask_vpermt2var_qi_128 :
+ GCCBuiltin<"__builtin_ia32_vpermt2varqi128_mask">,
+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty,
+ llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_vpermil_pd_512 :
- GCCBuiltin<"__builtin_ia32_vpermilpd512_mask">,
- Intrinsic<[llvm_v8f64_ty],
- [llvm_v8f64_ty, llvm_i32_ty, llvm_v8f64_ty, llvm_i8_ty],
+ def int_x86_avx512_maskz_vpermt2var_qi_128 :
+ GCCBuiltin<"__builtin_ia32_vpermt2varqi128_maskz">,
+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty,
+ llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_vpermil_ps_128 :
- GCCBuiltin<"__builtin_ia32_vpermilps_mask">,
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4f32_ty, llvm_i32_ty, llvm_v4f32_ty, llvm_i8_ty],
+ def int_x86_avx512_mask_vpermi2var_qi_256 :
+ GCCBuiltin<"__builtin_ia32_vpermi2varqi256_mask">,
+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty,
+ llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_vpermil_ps_256 :
- GCCBuiltin<"__builtin_ia32_vpermilps256_mask">,
- Intrinsic<[llvm_v8f32_ty],
- [llvm_v8f32_ty, llvm_i32_ty, llvm_v8f32_ty, llvm_i8_ty],
+ def int_x86_avx512_mask_vpermt2var_qi_256 :
+ GCCBuiltin<"__builtin_ia32_vpermt2varqi256_mask">,
+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty,
+ llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_vpermil_ps_512 :
- GCCBuiltin<"__builtin_ia32_vpermilps512_mask">,
- Intrinsic<[llvm_v16f32_ty],
- [llvm_v16f32_ty, llvm_i32_ty, llvm_v16f32_ty, llvm_i16_ty],
+ def int_x86_avx512_maskz_vpermt2var_qi_256 :
+ GCCBuiltin<"__builtin_ia32_vpermt2varqi256_maskz">,
+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty,
+ llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+
+ def int_x86_avx512_mask_vpermi2var_qi_512 :
+ GCCBuiltin<"__builtin_ia32_vpermi2varqi512_mask">,
+ Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty,
+ llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty],
+ [IntrNoMem]>;
+
+ def int_x86_avx512_mask_vpermt2var_qi_512 :
+ GCCBuiltin<"__builtin_ia32_vpermt2varqi512_mask">,
+ Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty,
+ llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty],
+ [IntrNoMem]>;
+
+ def int_x86_avx512_maskz_vpermt2var_qi_512 :
+ GCCBuiltin<"__builtin_ia32_vpermt2varqi512_maskz">,
+ Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty,
+ llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty],
[IntrNoMem]>;
def int_x86_avx512_mask_vpermilvar_pd_256 :
@@ -1489,78 +1374,24 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
[llvm_v4f32_ty, llvm_v4i32_ty, llvm_v4f32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_pshuf_b_128 :
+ def int_x86_avx512_mask_pshuf_b_128 :
GCCBuiltin<"__builtin_ia32_pshufb128_mask">,
Intrinsic<[llvm_v16i8_ty],
[llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_pshuf_b_256 :
+ def int_x86_avx512_mask_pshuf_b_256 :
GCCBuiltin<"__builtin_ia32_pshufb256_mask">,
Intrinsic<[llvm_v32i8_ty],
[llvm_v32i8_ty, llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_pshuf_b_512 :
+ def int_x86_avx512_mask_pshuf_b_512 :
GCCBuiltin<"__builtin_ia32_pshufb512_mask">,
Intrinsic<[llvm_v64i8_ty],
[llvm_v64i8_ty, llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_pshuf_d_128 :
- GCCBuiltin<"__builtin_ia32_pshufd128_mask">,
- Intrinsic<[llvm_v4i32_ty],
- [llvm_v4i32_ty, llvm_i16_ty, llvm_v4i32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_pshuf_d_256 :
- GCCBuiltin<"__builtin_ia32_pshufd256_mask">,
- Intrinsic<[llvm_v8i32_ty],
- [llvm_v8i32_ty, llvm_i16_ty, llvm_v8i32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_pshuf_d_512 :
- GCCBuiltin<"__builtin_ia32_pshufd512_mask">,
- Intrinsic<[llvm_v16i32_ty],
- [llvm_v16i32_ty, llvm_i16_ty, llvm_v16i32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_pshufh_w_128 :
- GCCBuiltin<"__builtin_ia32_pshufhw128_mask">,
- Intrinsic<[llvm_v8i16_ty],
- [llvm_v8i16_ty, llvm_i8_ty, llvm_v8i16_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_pshufh_w_256 :
- GCCBuiltin<"__builtin_ia32_pshufhw256_mask">,
- Intrinsic<[llvm_v16i16_ty],
- [llvm_v16i16_ty, llvm_i8_ty, llvm_v16i16_ty, llvm_i16_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_pshufh_w_512 :
- GCCBuiltin<"__builtin_ia32_pshufhw512_mask">,
- Intrinsic<[llvm_v32i16_ty],
- [llvm_v32i16_ty, llvm_i8_ty, llvm_v32i16_ty, llvm_i32_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_pshufl_w_128 :
- GCCBuiltin<"__builtin_ia32_pshuflw128_mask">,
- Intrinsic<[llvm_v8i16_ty],
- [llvm_v8i16_ty, llvm_i8_ty, llvm_v8i16_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_pshufl_w_256 :
- GCCBuiltin<"__builtin_ia32_pshuflw256_mask">,
- Intrinsic<[llvm_v16i16_ty],
- [llvm_v16i16_ty, llvm_i8_ty, llvm_v16i16_ty, llvm_i16_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_pshufl_w_512 :
- GCCBuiltin<"__builtin_ia32_pshuflw512_mask">,
- Intrinsic<[llvm_v32i16_ty],
- [llvm_v32i16_ty, llvm_i8_ty, llvm_v32i16_ty, llvm_i32_ty],
- [IntrNoMem]>;
-
def int_x86_avx512_mask_shuf_f32x4_256 :
GCCBuiltin<"__builtin_ia32_shuf_f32x4_256_mask">,
Intrinsic<[llvm_v8f32_ty],
@@ -1644,60 +1475,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v16f32_ty],
[llvm_v16f32_ty, llvm_v16f32_ty, llvm_i32_ty, llvm_v16f32_ty, llvm_i16_ty],
[IntrNoMem]>;
-
- def int_x86_avx512_mask_movshdup_128 :
- GCCBuiltin<"__builtin_ia32_movshdup128_mask">,
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_movshdup_256 :
- GCCBuiltin<"__builtin_ia32_movshdup256_mask">,
- Intrinsic<[llvm_v8f32_ty],
- [llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_movshdup_512 :
- GCCBuiltin<"__builtin_ia32_movshdup512_mask">,
- Intrinsic<[llvm_v16f32_ty],
- [llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_movsldup_128 :
- GCCBuiltin<"__builtin_ia32_movsldup128_mask">,
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_movsldup_256 :
- GCCBuiltin<"__builtin_ia32_movsldup256_mask">,
- Intrinsic<[llvm_v8f32_ty],
- [llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_movsldup_512 :
- GCCBuiltin<"__builtin_ia32_movsldup512_mask">,
- Intrinsic<[llvm_v16f32_ty],
- [llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_movddup_128 :
- GCCBuiltin<"__builtin_ia32_movddup128_mask">,
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_movddup_256 :
- GCCBuiltin<"__builtin_ia32_movddup256_mask">,
- Intrinsic<[llvm_v4f64_ty],
- [llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_movddup_512 :
- GCCBuiltin<"__builtin_ia32_movddup512_mask">,
- Intrinsic<[llvm_v8f64_ty],
- [llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
}
// Vector blend
@@ -1719,32 +1496,24 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
// Vector compare
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_avx_cmp_pd_256 : GCCBuiltin<"__builtin_ia32_cmppd256">,
+ def int_x86_avx_cmp_pd_256 :
Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty,
llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx_cmp_ps_256 : GCCBuiltin<"__builtin_ia32_cmpps256">,
+ def int_x86_avx_cmp_ps_256 :
Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty,
llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>;
}
// Vector convert
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_avx_cvtdq2_pd_256 : GCCBuiltin<"__builtin_ia32_cvtdq2pd256">,
- Intrinsic<[llvm_v4f64_ty], [llvm_v4i32_ty], [IntrNoMem]>;
def int_x86_avx_cvtdq2_ps_256 : GCCBuiltin<"__builtin_ia32_cvtdq2ps256">,
Intrinsic<[llvm_v8f32_ty], [llvm_v8i32_ty], [IntrNoMem]>;
def int_x86_avx_cvt_pd2_ps_256 : GCCBuiltin<"__builtin_ia32_cvtpd2ps256">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f64_ty], [IntrNoMem]>;
def int_x86_avx_cvt_ps2dq_256 : GCCBuiltin<"__builtin_ia32_cvtps2dq256">,
Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty], [IntrNoMem]>;
- def int_x86_avx_cvt_ps2_pd_256 : GCCBuiltin<"__builtin_ia32_cvtps2pd256">,
- Intrinsic<[llvm_v4f64_ty], [llvm_v4f32_ty], [IntrNoMem]>;
- def int_x86_avx_cvtt_pd2dq_256 : GCCBuiltin<"__builtin_ia32_cvttpd2dq256">,
- Intrinsic<[llvm_v4i32_ty], [llvm_v4f64_ty], [IntrNoMem]>;
def int_x86_avx_cvt_pd2dq_256 : GCCBuiltin<"__builtin_ia32_cvtpd2dq256">,
Intrinsic<[llvm_v4i32_ty], [llvm_v4f64_ty], [IntrNoMem]>;
- def int_x86_avx_cvtt_ps2dq_256 : GCCBuiltin<"__builtin_ia32_cvttps2dq256">,
- Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty], [IntrNoMem]>;
}
// Vector bit test
@@ -1794,42 +1563,111 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx_ptestnzc_256 : GCCBuiltin<"__builtin_ia32_ptestnzc256">,
Intrinsic<[llvm_i32_ty], [llvm_v4i64_ty,
llvm_v4i64_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_ptestm_d_512 : GCCBuiltin<"__builtin_ia32_ptestmd512">,
+ def int_x86_avx512_ptestm_d_512 : GCCBuiltin<"__builtin_ia32_ptestmd512">,
Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_ptestm_q_512 : GCCBuiltin<"__builtin_ia32_ptestmq512">,
+ def int_x86_avx512_ptestm_q_512 : GCCBuiltin<"__builtin_ia32_ptestmq512">,
Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty,
llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_fpclass_pd_128 :
+
+ def int_x86_avx512_ptestm_b_128 : GCCBuiltin<"__builtin_ia32_ptestmb128">,
+ Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty,
+ llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_ptestm_b_256 : GCCBuiltin<"__builtin_ia32_ptestmb256">,
+ Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty,
+ llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_ptestm_b_512 : GCCBuiltin<"__builtin_ia32_ptestmb512">,
+ Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty,
+ llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>;
+ def int_x86_avx512_ptestm_d_128 : GCCBuiltin<"__builtin_ia32_ptestmd128">,
+ Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty,
+ llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_ptestm_d_256 : GCCBuiltin<"__builtin_ia32_ptestmd256">,
+ Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty,
+ llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_ptestm_q_128 : GCCBuiltin<"__builtin_ia32_ptestmq128">,
+ Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty,
+ llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_ptestm_q_256 : GCCBuiltin<"__builtin_ia32_ptestmq256">,
+ Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty,
+ llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_ptestm_w_128 : GCCBuiltin<"__builtin_ia32_ptestmw128">,
+ Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty,
+ llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_ptestm_w_256 : GCCBuiltin<"__builtin_ia32_ptestmw256">,
+ Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty,
+ llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_ptestm_w_512 : GCCBuiltin<"__builtin_ia32_ptestmw512">,
+ Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty,
+ llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_ptestnm_b_128 : GCCBuiltin<"__builtin_ia32_ptestnmb128">,
+ Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty,
+ llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_ptestnm_b_256 : GCCBuiltin<"__builtin_ia32_ptestnmb256">,
+ Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty,
+ llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_ptestnm_b_512 : GCCBuiltin<"__builtin_ia32_ptestnmb512">,
+ Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty,
+ llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>;
+ def int_x86_avx512_ptestnm_d_128 : GCCBuiltin<"__builtin_ia32_ptestnmd128">,
+ Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty,
+ llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_ptestnm_d_256 : GCCBuiltin<"__builtin_ia32_ptestnmd256">,
+ Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty,
+ llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_ptestnm_d_512 : GCCBuiltin<"__builtin_ia32_ptestnmd512">,
+ Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty,
+ llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_ptestnm_q_128 : GCCBuiltin<"__builtin_ia32_ptestnmq128">,
+ Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty,
+ llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_ptestnm_q_256 : GCCBuiltin<"__builtin_ia32_ptestnmq256">,
+ Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty,
+ llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_ptestnm_q_512 : GCCBuiltin<"__builtin_ia32_ptestnmq512">,
+ Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty,
+ llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_ptestnm_w_128 : GCCBuiltin<"__builtin_ia32_ptestnmw128">,
+ Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty,
+ llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_ptestnm_w_256 : GCCBuiltin<"__builtin_ia32_ptestnmw256">,
+ Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty,
+ llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_ptestnm_w_512 : GCCBuiltin<"__builtin_ia32_ptestnmw512">,
+ Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty,
+ llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_mask_fpclass_pd_128 :
GCCBuiltin<"__builtin_ia32_fpclasspd128_mask">,
Intrinsic<[llvm_i8_ty], [llvm_v2f64_ty, llvm_i32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_fpclass_pd_256 :
+ def int_x86_avx512_mask_fpclass_pd_256 :
GCCBuiltin<"__builtin_ia32_fpclasspd256_mask">,
Intrinsic<[llvm_i8_ty], [llvm_v4f64_ty, llvm_i32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_fpclass_pd_512 :
+ def int_x86_avx512_mask_fpclass_pd_512 :
GCCBuiltin<"__builtin_ia32_fpclasspd512_mask">,
Intrinsic<[llvm_i8_ty], [llvm_v8f64_ty, llvm_i32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_fpclass_ps_128 :
+ def int_x86_avx512_mask_fpclass_ps_128 :
GCCBuiltin<"__builtin_ia32_fpclassps128_mask">,
Intrinsic<[llvm_i8_ty], [llvm_v4f32_ty, llvm_i32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_fpclass_ps_256 :
+ def int_x86_avx512_mask_fpclass_ps_256 :
GCCBuiltin<"__builtin_ia32_fpclassps256_mask">,
Intrinsic<[llvm_i8_ty], [llvm_v8f32_ty, llvm_i32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_fpclass_ps_512 :
+ def int_x86_avx512_mask_fpclass_ps_512 :
GCCBuiltin<"__builtin_ia32_fpclassps512_mask">,
Intrinsic<[llvm_i16_ty], [llvm_v16f32_ty, llvm_i32_ty, llvm_i16_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_fpclass_sd :
- GCCBuiltin<"__builtin_ia32_fpclasssd">,
+ def int_x86_avx512_mask_fpclass_sd :
+ GCCBuiltin<"__builtin_ia32_fpclasssd_mask">,
Intrinsic<[llvm_i8_ty], [llvm_v2f64_ty, llvm_i32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_fpclass_ss :
- GCCBuiltin<"__builtin_ia32_fpclassss">,
+ def int_x86_avx512_mask_fpclass_ss :
+ GCCBuiltin<"__builtin_ia32_fpclassss_mask">,
Intrinsic<[llvm_i8_ty], [llvm_v4f32_ty, llvm_i32_ty, llvm_i8_ty],
[IntrNoMem]>;
}
@@ -1854,10 +1692,10 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx_vbroadcastf128_pd_256 :
GCCBuiltin<"__builtin_ia32_vbroadcastf128_pd256">,
- Intrinsic<[llvm_v4f64_ty], [llvm_ptr_ty], [IntrReadArgMem]>;
+ Intrinsic<[llvm_v4f64_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx_vbroadcastf128_ps_256 :
GCCBuiltin<"__builtin_ia32_vbroadcastf128_ps256">,
- Intrinsic<[llvm_v8f32_ty], [llvm_ptr_ty], [IntrReadArgMem]>;
+ Intrinsic<[llvm_v8f32_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>;
}
// SIMD load ops
@@ -1866,91 +1704,32 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v32i8_ty], [llvm_ptr_ty], [IntrReadMem]>;
}
-// SIMD store ops
-let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_avx_storeu_pd_256 : GCCBuiltin<"__builtin_ia32_storeupd256">,
- Intrinsic<[], [llvm_ptr_ty, llvm_v4f64_ty], [IntrReadWriteArgMem]>;
- def int_x86_avx_storeu_ps_256 : GCCBuiltin<"__builtin_ia32_storeups256">,
- Intrinsic<[], [llvm_ptr_ty, llvm_v8f32_ty], [IntrReadWriteArgMem]>;
- def int_x86_avx_storeu_dq_256 : GCCBuiltin<"__builtin_ia32_storedqu256">,
- Intrinsic<[], [llvm_ptr_ty, llvm_v32i8_ty], [IntrReadWriteArgMem]>;
-}
-
// Conditional load ops
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx_maskload_pd : GCCBuiltin<"__builtin_ia32_maskloadpd">,
Intrinsic<[llvm_v2f64_ty], [llvm_ptr_ty, llvm_v2i64_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx_maskload_ps : GCCBuiltin<"__builtin_ia32_maskloadps">,
Intrinsic<[llvm_v4f32_ty], [llvm_ptr_ty, llvm_v4i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx_maskload_pd_256 : GCCBuiltin<"__builtin_ia32_maskloadpd256">,
Intrinsic<[llvm_v4f64_ty], [llvm_ptr_ty, llvm_v4i64_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx_maskload_ps_256 : GCCBuiltin<"__builtin_ia32_maskloadps256">,
Intrinsic<[llvm_v8f32_ty], [llvm_ptr_ty, llvm_v8i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
+}
- def int_x86_avx512_mask_loadu_ps_128 :
- GCCBuiltin<"__builtin_ia32_loadups128_mask">,
- Intrinsic<[llvm_v4f32_ty],
- [llvm_ptr_ty, llvm_v4f32_ty, llvm_i8_ty], [IntrReadArgMem]>;
- def int_x86_avx512_mask_loadu_ps_256 :
- GCCBuiltin<"__builtin_ia32_loadups256_mask">,
- Intrinsic<[llvm_v8f32_ty],
- [llvm_ptr_ty, llvm_v8f32_ty, llvm_i8_ty], [IntrReadArgMem]>;
- def int_x86_avx512_mask_loadu_ps_512 :
- GCCBuiltin<"__builtin_ia32_loadups512_mask">,
- Intrinsic<[llvm_v16f32_ty],
- [llvm_ptr_ty, llvm_v16f32_ty, llvm_i16_ty], [IntrReadArgMem]>;
-
- def int_x86_avx512_mask_loadu_pd_128 :
- GCCBuiltin<"__builtin_ia32_loadupd128_mask">,
- Intrinsic<[llvm_v2f64_ty],
- [llvm_ptr_ty, llvm_v2f64_ty, llvm_i8_ty], [IntrReadArgMem]>;
- def int_x86_avx512_mask_loadu_pd_256 :
- GCCBuiltin<"__builtin_ia32_loadupd256_mask">,
- Intrinsic<[llvm_v4f64_ty],
- [llvm_ptr_ty, llvm_v4f64_ty, llvm_i8_ty], [IntrReadArgMem]>;
- def int_x86_avx512_mask_loadu_pd_512 :
- GCCBuiltin<"__builtin_ia32_loadupd512_mask">,
- Intrinsic<[llvm_v8f64_ty],
- [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty], [IntrReadArgMem]>;
-
- def int_x86_avx512_mask_load_ps_128 :
- GCCBuiltin<"__builtin_ia32_loadaps128_mask">,
- Intrinsic<[llvm_v4f32_ty],
- [llvm_ptr_ty, llvm_v4f32_ty, llvm_i8_ty], [IntrReadArgMem]>;
- def int_x86_avx512_mask_load_ps_256 :
- GCCBuiltin<"__builtin_ia32_loadaps256_mask">,
- Intrinsic<[llvm_v8f32_ty],
- [llvm_ptr_ty, llvm_v8f32_ty, llvm_i8_ty], [IntrReadArgMem]>;
- def int_x86_avx512_mask_load_ps_512 :
- GCCBuiltin<"__builtin_ia32_loadaps512_mask">,
- Intrinsic<[llvm_v16f32_ty],
- [llvm_ptr_ty, llvm_v16f32_ty, llvm_i16_ty], [IntrReadArgMem]>;
-
- def int_x86_avx512_mask_load_pd_128 :
- GCCBuiltin<"__builtin_ia32_loadapd128_mask">,
- Intrinsic<[llvm_v2f64_ty],
- [llvm_ptr_ty, llvm_v2f64_ty, llvm_i8_ty], [IntrReadArgMem]>;
- def int_x86_avx512_mask_load_pd_256 :
- GCCBuiltin<"__builtin_ia32_loadapd256_mask">,
- Intrinsic<[llvm_v4f64_ty],
- [llvm_ptr_ty, llvm_v4f64_ty, llvm_i8_ty], [IntrReadArgMem]>;
- def int_x86_avx512_mask_load_pd_512 :
- GCCBuiltin<"__builtin_ia32_loadapd512_mask">,
- Intrinsic<[llvm_v8f64_ty],
- [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty], [IntrReadArgMem]>;
-
- def int_x86_avx512_mask_move_ss :
+// Conditional move ops
+let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
+ def int_x86_avx512_mask_move_ss :
GCCBuiltin<"__builtin_ia32_movss_mask">,
- Intrinsic<[llvm_v4f32_ty],
+ Intrinsic<[llvm_v4f32_ty],
[llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_move_sd :
+ def int_x86_avx512_mask_move_sd :
GCCBuiltin<"__builtin_ia32_movsd_mask">,
- Intrinsic<[llvm_v2f64_ty],
+ Intrinsic<[llvm_v2f64_ty],
[llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty],
[IntrNoMem]>;
}
@@ -1959,38 +1738,23 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx_maskstore_pd : GCCBuiltin<"__builtin_ia32_maskstorepd">,
Intrinsic<[], [llvm_ptr_ty,
- llvm_v2i64_ty, llvm_v2f64_ty], [IntrReadWriteArgMem]>;
+ llvm_v2i64_ty, llvm_v2f64_ty], [IntrArgMemOnly]>;
def int_x86_avx_maskstore_ps : GCCBuiltin<"__builtin_ia32_maskstoreps">,
Intrinsic<[], [llvm_ptr_ty,
- llvm_v4i32_ty, llvm_v4f32_ty], [IntrReadWriteArgMem]>;
+ llvm_v4i32_ty, llvm_v4f32_ty], [IntrArgMemOnly]>;
def int_x86_avx_maskstore_pd_256 :
GCCBuiltin<"__builtin_ia32_maskstorepd256">,
Intrinsic<[], [llvm_ptr_ty,
- llvm_v4i64_ty, llvm_v4f64_ty], [IntrReadWriteArgMem]>;
+ llvm_v4i64_ty, llvm_v4f64_ty], [IntrArgMemOnly]>;
def int_x86_avx_maskstore_ps_256 :
GCCBuiltin<"__builtin_ia32_maskstoreps256">,
Intrinsic<[], [llvm_ptr_ty,
- llvm_v8i32_ty, llvm_v8f32_ty], [IntrReadWriteArgMem]>;
- def int_x86_avx512_mask_storeu_ps_512 :
- GCCBuiltin<"__builtin_ia32_storeups512_mask">,
- Intrinsic<[], [llvm_ptr_ty, llvm_v16f32_ty, llvm_i16_ty],
- [IntrReadWriteArgMem]>;
- def int_x86_avx512_mask_storeu_pd_512 :
- GCCBuiltin<"__builtin_ia32_storeupd512_mask">,
- Intrinsic<[], [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
- def int_x86_avx512_mask_store_ps_512 :
- GCCBuiltin<"__builtin_ia32_storeaps512_mask">,
- Intrinsic<[], [llvm_ptr_ty, llvm_v16f32_ty, llvm_i16_ty],
- [IntrReadWriteArgMem]>;
- def int_x86_avx512_mask_store_pd_512 :
- GCCBuiltin<"__builtin_ia32_storeapd512_mask">,
- Intrinsic<[], [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ llvm_v8i32_ty, llvm_v8f32_ty], [IntrArgMemOnly]>;
+
def int_x86_avx512_mask_store_ss :
GCCBuiltin<"__builtin_ia32_storess_mask">,
Intrinsic<[], [llvm_ptr_ty, llvm_v4f32_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
}
//===----------------------------------------------------------------------===//
@@ -2050,83 +1814,47 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
// Vector min, max
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_avx2_pmaxu_b : GCCBuiltin<"__builtin_ia32_pmaxub256">,
- Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty,
- llvm_v32i8_ty], [IntrNoMem, Commutative]>;
- def int_x86_avx2_pmaxu_w : GCCBuiltin<"__builtin_ia32_pmaxuw256">,
- Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty,
- llvm_v16i16_ty], [IntrNoMem, Commutative]>;
- def int_x86_avx2_pmaxu_d : GCCBuiltin<"__builtin_ia32_pmaxud256">,
- Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty,
- llvm_v8i32_ty], [IntrNoMem, Commutative]>;
- def int_x86_avx2_pmaxs_b : GCCBuiltin<"__builtin_ia32_pmaxsb256">,
- Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty,
- llvm_v32i8_ty], [IntrNoMem, Commutative]>;
- def int_x86_avx2_pmaxs_w : GCCBuiltin<"__builtin_ia32_pmaxsw256">,
- Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty,
- llvm_v16i16_ty], [IntrNoMem, Commutative]>;
- def int_x86_avx2_pmaxs_d : GCCBuiltin<"__builtin_ia32_pmaxsd256">,
- Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty,
- llvm_v8i32_ty], [IntrNoMem, Commutative]>;
- def int_x86_avx2_pminu_b : GCCBuiltin<"__builtin_ia32_pminub256">,
- Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty,
- llvm_v32i8_ty], [IntrNoMem, Commutative]>;
- def int_x86_avx2_pminu_w : GCCBuiltin<"__builtin_ia32_pminuw256">,
- Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty,
- llvm_v16i16_ty], [IntrNoMem, Commutative]>;
- def int_x86_avx2_pminu_d : GCCBuiltin<"__builtin_ia32_pminud256">,
- Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty,
- llvm_v8i32_ty], [IntrNoMem, Commutative]>;
- def int_x86_avx2_pmins_b : GCCBuiltin<"__builtin_ia32_pminsb256">,
- Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty,
- llvm_v32i8_ty], [IntrNoMem, Commutative]>;
- def int_x86_avx2_pmins_w : GCCBuiltin<"__builtin_ia32_pminsw256">,
- Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty,
- llvm_v16i16_ty], [IntrNoMem, Commutative]>;
- def int_x86_avx2_pmins_d : GCCBuiltin<"__builtin_ia32_pminsd256">,
- Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty,
- llvm_v8i32_ty], [IntrNoMem, Commutative]>;
def int_x86_avx512_mask_pmaxs_b_128 : GCCBuiltin<"__builtin_ia32_pmaxsb128_mask">,
- Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,
+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,
llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pmaxs_b_256 : GCCBuiltin<"__builtin_ia32_pmaxsb256_mask">,
- Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty,
+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty,
llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pmaxs_b_512 : GCCBuiltin<"__builtin_ia32_pmaxsb512_mask">,
- Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty,
+ Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty,
llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pmaxu_b_128 : GCCBuiltin<"__builtin_ia32_pmaxub128_mask">,
- Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,
+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,
llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pmaxu_b_256 : GCCBuiltin<"__builtin_ia32_pmaxub256_mask">,
- Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty,
+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty,
llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pmaxu_b_512 : GCCBuiltin<"__builtin_ia32_pmaxub512_mask">,
- Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty,
+ Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty,
llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pmaxs_w_128 : GCCBuiltin<"__builtin_ia32_pmaxsw128_mask">,
- Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pmaxs_w_256 : GCCBuiltin<"__builtin_ia32_pmaxsw256_mask">,
- Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pmaxs_w_512 : GCCBuiltin<"__builtin_ia32_pmaxsw512_mask">,
- Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty,
+ Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty,
llvm_v32i16_ty, llvm_i32_ty],[IntrNoMem]>;
def int_x86_avx512_mask_pmaxu_w_128 : GCCBuiltin<"__builtin_ia32_pmaxuw128_mask">,
- Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pmaxu_w_256 : GCCBuiltin<"__builtin_ia32_pmaxuw256_mask">,
- Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pmaxu_w_512 : GCCBuiltin<"__builtin_ia32_pmaxuw512_mask">,
Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty,
llvm_v32i16_ty, llvm_i32_ty],[IntrNoMem]>;
def int_x86_avx512_mask_pmins_b_128 : GCCBuiltin<"__builtin_ia32_pminsb128_mask">,
- Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,
+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,
llvm_v16i8_ty,llvm_i16_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pmins_b_256 : GCCBuiltin<"__builtin_ia32_pminsb256_mask">,
- Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty,
+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty,
llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pmins_b_512 : GCCBuiltin<"__builtin_ia32_pminsb512_mask">,
Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty,
@@ -2135,28 +1863,28 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,
llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pminu_b_256 : GCCBuiltin<"__builtin_ia32_pminub256_mask">,
- Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty,
+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty,
llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pminu_b_512 : GCCBuiltin<"__builtin_ia32_pminub512_mask">,
- Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty,
+ Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty,
llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pmins_w_128 : GCCBuiltin<"__builtin_ia32_pminsw128_mask">,
- Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pmins_w_256 : GCCBuiltin<"__builtin_ia32_pminsw256_mask">,
- Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pmins_w_512 : GCCBuiltin<"__builtin_ia32_pminsw512_mask">,
Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty,
llvm_v32i16_ty, llvm_i32_ty],[IntrNoMem]>;
def int_x86_avx512_mask_pminu_w_128 : GCCBuiltin<"__builtin_ia32_pminuw128_mask">,
- Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pminu_w_256 : GCCBuiltin<"__builtin_ia32_pminuw256_mask">,
- Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pminu_w_512 : GCCBuiltin<"__builtin_ia32_pminuw512_mask">,
- Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty,
+ Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty,
llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pmaxu_d_512 : GCCBuiltin<"__builtin_ia32_pmaxud512_mask">,
Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
@@ -2284,25 +2012,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty,
llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pslli_d : GCCBuiltin<"__builtin_ia32_pslldi512">,
- Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
- llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pslli_q : GCCBuiltin<"__builtin_ia32_psllqi512">,
- Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
- llvm_i32_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_psrli_d : GCCBuiltin<"__builtin_ia32_psrldi512">,
- Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
- llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_psrli_q : GCCBuiltin<"__builtin_ia32_psrlqi512">,
- Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
- llvm_i32_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_psrai_d : GCCBuiltin<"__builtin_ia32_psradi512">,
- Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
- llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_psrai_q : GCCBuiltin<"__builtin_ia32_psraqi512">,
- Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
- llvm_i32_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
-
def int_x86_avx512_mask_psrl_w_128 : GCCBuiltin<"__builtin_ia32_psrlw128_mask">,
Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty,
llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
@@ -2314,13 +2023,13 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
llvm_v8i16_ty, llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psrl_wi_128 : GCCBuiltin<"__builtin_ia32_psrlwi128_mask">,
Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty,
- llvm_i8_ty, llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
+ llvm_i32_ty, llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psrl_wi_256 : GCCBuiltin<"__builtin_ia32_psrlwi256_mask">,
Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty,
- llvm_i8_ty, llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
+ llvm_i32_ty, llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psrl_wi_512 : GCCBuiltin<"__builtin_ia32_psrlwi512_mask">,
Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty,
- llvm_i8_ty, llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
+ llvm_i32_ty, llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psra_w_128 : GCCBuiltin<"__builtin_ia32_psraw128_mask">,
Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty,
@@ -2333,13 +2042,13 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
llvm_v8i16_ty, llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psra_wi_128 : GCCBuiltin<"__builtin_ia32_psrawi128_mask">,
Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty,
- llvm_i8_ty, llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
+ llvm_i32_ty, llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psra_wi_256 : GCCBuiltin<"__builtin_ia32_psrawi256_mask">,
Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty,
- llvm_i8_ty, llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
+ llvm_i32_ty, llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psra_wi_512 : GCCBuiltin<"__builtin_ia32_psrawi512_mask">,
Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty,
- llvm_i8_ty, llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
+ llvm_i32_ty, llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psll_d : GCCBuiltin<"__builtin_ia32_pslld512_mask">,
Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
@@ -2371,13 +2080,13 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
llvm_v8i16_ty, llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psll_wi_128 : GCCBuiltin<"__builtin_ia32_psllwi128_mask">,
Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty,
- llvm_i8_ty, llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
+ llvm_i32_ty, llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psll_wi_256 : GCCBuiltin<"__builtin_ia32_psllwi256_mask">,
Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty,
- llvm_i8_ty, llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
+ llvm_i32_ty, llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psll_wi_512 : GCCBuiltin<"__builtin_ia32_psllwi512_mask">,
Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty,
- llvm_i8_ty, llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
+ llvm_i32_ty, llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psllv16_hi : GCCBuiltin<"__builtin_ia32_psllv16hi_mask">,
Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty,
llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
@@ -2404,64 +2113,76 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty,
llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psra_d_256 : GCCBuiltin<"__builtin_ia32_psrad256_mask">,
- Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty,
+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty,
llvm_v4i32_ty, llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psra_di_128 : GCCBuiltin<"__builtin_ia32_psradi128_mask">,
- Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty,
- llvm_i8_ty, llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty,
+ llvm_i32_ty, llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psra_di_256 : GCCBuiltin<"__builtin_ia32_psradi256_mask">,
- Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty,
- llvm_i8_ty, llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty,
+ llvm_i32_ty, llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psra_di_512 : GCCBuiltin<"__builtin_ia32_psradi512_mask">,
Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
- llvm_i8_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
+ llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psra_q_128 : GCCBuiltin<"__builtin_ia32_psraq128_mask">,
- Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty,
+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty,
llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psra_q_256 : GCCBuiltin<"__builtin_ia32_psraq256_mask">,
- Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty,
+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty,
llvm_v2i64_ty, llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psra_qi_128 : GCCBuiltin<"__builtin_ia32_psraqi128_mask">,
- Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty,
- llvm_i8_ty, llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty,
+ llvm_i32_ty, llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psra_qi_256 : GCCBuiltin<"__builtin_ia32_psraqi256_mask">,
- Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty,
- llvm_i8_ty, llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty,
+ llvm_i32_ty, llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psra_qi_512 : GCCBuiltin<"__builtin_ia32_psraqi512_mask">,
- Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
- llvm_i8_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
+ llvm_i32_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psrl_d_128: GCCBuiltin<"__builtin_ia32_psrld128_mask">,
Intrinsic<[llvm_v4i32_ty], [ llvm_v4i32_ty,
llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty ], [IntrNoMem]>;
def int_x86_avx512_mask_psrl_d_256: GCCBuiltin<"__builtin_ia32_psrld256_mask">,
- Intrinsic<[llvm_v8i32_ty], [ llvm_v8i32_ty,
+ Intrinsic<[llvm_v8i32_ty], [ llvm_v8i32_ty,
llvm_v4i32_ty, llvm_v8i32_ty, llvm_i8_ty ], [IntrNoMem]>;
def int_x86_avx512_mask_psrl_di_128: GCCBuiltin<"__builtin_ia32_psrldi128_mask">,
- Intrinsic<[llvm_v4i32_ty], [ llvm_v4i32_ty,
- llvm_i8_ty, llvm_v4i32_ty, llvm_i8_ty ], [IntrNoMem]>;
+ Intrinsic<[llvm_v4i32_ty], [ llvm_v4i32_ty,
+ llvm_i32_ty, llvm_v4i32_ty, llvm_i8_ty ], [IntrNoMem]>;
def int_x86_avx512_mask_psrl_di_256: GCCBuiltin<"__builtin_ia32_psrldi256_mask">,
- Intrinsic<[llvm_v8i32_ty], [ llvm_v8i32_ty,
- llvm_i8_ty, llvm_v8i32_ty, llvm_i8_ty ], [IntrNoMem]>;
+ Intrinsic<[llvm_v8i32_ty], [ llvm_v8i32_ty,
+ llvm_i32_ty, llvm_v8i32_ty, llvm_i8_ty ], [IntrNoMem]>;
def int_x86_avx512_mask_psrl_di_512: GCCBuiltin<"__builtin_ia32_psrldi512_mask">,
- Intrinsic<[llvm_v16i32_ty], [ llvm_v16i32_ty,
- llvm_i8_ty, llvm_v16i32_ty, llvm_i16_ty ], [IntrNoMem]>;
+ Intrinsic<[llvm_v16i32_ty], [ llvm_v16i32_ty,
+ llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty ], [IntrNoMem]>;
def int_x86_avx512_mask_psrl_q_128: GCCBuiltin<"__builtin_ia32_psrlq128_mask">,
- Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty,
+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty,
llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psrl_q_256: GCCBuiltin<"__builtin_ia32_psrlq256_mask">,
- Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty,
+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty,
llvm_v2i64_ty, llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psrl_qi_128: GCCBuiltin<"__builtin_ia32_psrlqi128_mask">,
Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty,
- llvm_i8_ty, llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ llvm_i32_ty, llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psrl_qi_256: GCCBuiltin<"__builtin_ia32_psrlqi256_mask">,
Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty,
- llvm_i8_ty, llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ llvm_i32_ty, llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psrl_qi_512: GCCBuiltin<"__builtin_ia32_psrlqi512_mask">,
- Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
- llvm_i8_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
+ llvm_i32_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pmultishift_qb_128:
+ GCCBuiltin<"__builtin_ia32_vpmultishiftqb128_mask">,
+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty,
+ llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pmultishift_qb_256:
+ GCCBuiltin<"__builtin_ia32_vpmultishiftqb256_mask">,
+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty,
+ llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pmultishift_qb_512:
+ GCCBuiltin<"__builtin_ia32_vpmultishiftqb512_mask">,
+ Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty,
+ llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>;
}
// Pack ops.
@@ -2489,73 +2210,73 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx2_pabs_d : GCCBuiltin<"__builtin_ia32_pabsd256">,
Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pabs_b_128 :
+ def int_x86_avx512_mask_pabs_b_128 :
GCCBuiltin<"__builtin_ia32_pabsb128_mask">,
Intrinsic<[llvm_v16i8_ty],
[llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_pabs_b_256 :
+ def int_x86_avx512_mask_pabs_b_256 :
GCCBuiltin<"__builtin_ia32_pabsb256_mask">,
Intrinsic<[llvm_v32i8_ty],
[llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_pabs_b_512 :
+ def int_x86_avx512_mask_pabs_b_512 :
GCCBuiltin<"__builtin_ia32_pabsb512_mask">,
Intrinsic<[llvm_v64i8_ty],
[llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_pabs_d_128 :
+ def int_x86_avx512_mask_pabs_d_128 :
GCCBuiltin<"__builtin_ia32_pabsd128_mask">,
Intrinsic<[llvm_v4i32_ty],
[llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_pabs_d_256 :
+ def int_x86_avx512_mask_pabs_d_256 :
GCCBuiltin<"__builtin_ia32_pabsd256_mask">,
Intrinsic<[llvm_v8i32_ty],
[llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_pabs_d_512 :
+ def int_x86_avx512_mask_pabs_d_512 :
GCCBuiltin<"__builtin_ia32_pabsd512_mask">,
Intrinsic<[llvm_v16i32_ty],
[llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_pabs_q_128 :
+ def int_x86_avx512_mask_pabs_q_128 :
GCCBuiltin<"__builtin_ia32_pabsq128_mask">,
Intrinsic<[llvm_v2i64_ty],
[llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_pabs_q_256 :
+ def int_x86_avx512_mask_pabs_q_256 :
GCCBuiltin<"__builtin_ia32_pabsq256_mask">,
Intrinsic<[llvm_v4i64_ty],
[llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_pabs_q_512 :
+ def int_x86_avx512_mask_pabs_q_512 :
GCCBuiltin<"__builtin_ia32_pabsq512_mask">,
Intrinsic<[llvm_v8i64_ty],
[llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_pabs_w_128 :
+ def int_x86_avx512_mask_pabs_w_128 :
GCCBuiltin<"__builtin_ia32_pabsw128_mask">,
Intrinsic<[llvm_v8i16_ty],
[llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_pabs_w_256 :
+ def int_x86_avx512_mask_pabs_w_256 :
GCCBuiltin<"__builtin_ia32_pabsw256_mask">,
Intrinsic<[llvm_v16i16_ty],
[llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_pabs_w_512 :
+ def int_x86_avx512_mask_pabs_w_512 :
GCCBuiltin<"__builtin_ia32_pabsw512_mask">,
Intrinsic<[llvm_v32i16_ty],
[llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty],
@@ -2606,56 +2327,16 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty,
llvm_v16i16_ty], [IntrNoMem, Commutative]>;
def int_x86_avx512_mask_pmul_hr_sw_128 : GCCBuiltin<"__builtin_ia32_pmulhrsw128_mask">,
- Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pmul_hr_sw_256 : GCCBuiltin<"__builtin_ia32_pmulhrsw256_mask">,
- Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pmul_hr_sw_512 : GCCBuiltin<"__builtin_ia32_pmulhrsw512_mask">,
- Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty,
+ Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty,
llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
}
-// Vector sign and zero extend
-let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_avx2_pmovsxbd : GCCBuiltin<"__builtin_ia32_pmovsxbd256">,
- Intrinsic<[llvm_v8i32_ty], [llvm_v16i8_ty],
- [IntrNoMem]>;
- def int_x86_avx2_pmovsxbq : GCCBuiltin<"__builtin_ia32_pmovsxbq256">,
- Intrinsic<[llvm_v4i64_ty], [llvm_v16i8_ty],
- [IntrNoMem]>;
- def int_x86_avx2_pmovsxbw : GCCBuiltin<"__builtin_ia32_pmovsxbw256">,
- Intrinsic<[llvm_v16i16_ty], [llvm_v16i8_ty],
- [IntrNoMem]>;
- def int_x86_avx2_pmovsxdq : GCCBuiltin<"__builtin_ia32_pmovsxdq256">,
- Intrinsic<[llvm_v4i64_ty], [llvm_v4i32_ty],
- [IntrNoMem]>;
- def int_x86_avx2_pmovsxwd : GCCBuiltin<"__builtin_ia32_pmovsxwd256">,
- Intrinsic<[llvm_v8i32_ty], [llvm_v8i16_ty],
- [IntrNoMem]>;
- def int_x86_avx2_pmovsxwq : GCCBuiltin<"__builtin_ia32_pmovsxwq256">,
- Intrinsic<[llvm_v4i64_ty], [llvm_v8i16_ty],
- [IntrNoMem]>;
- def int_x86_avx2_pmovzxbd : GCCBuiltin<"__builtin_ia32_pmovzxbd256">,
- Intrinsic<[llvm_v8i32_ty], [llvm_v16i8_ty],
- [IntrNoMem]>;
- def int_x86_avx2_pmovzxbq : GCCBuiltin<"__builtin_ia32_pmovzxbq256">,
- Intrinsic<[llvm_v4i64_ty], [llvm_v16i8_ty],
- [IntrNoMem]>;
- def int_x86_avx2_pmovzxbw : GCCBuiltin<"__builtin_ia32_pmovzxbw256">,
- Intrinsic<[llvm_v16i16_ty], [llvm_v16i8_ty],
- [IntrNoMem]>;
- def int_x86_avx2_pmovzxdq : GCCBuiltin<"__builtin_ia32_pmovzxdq256">,
- Intrinsic<[llvm_v4i64_ty], [llvm_v4i32_ty],
- [IntrNoMem]>;
- def int_x86_avx2_pmovzxwd : GCCBuiltin<"__builtin_ia32_pmovzxwd256">,
- Intrinsic<[llvm_v8i32_ty], [llvm_v8i16_ty],
- [IntrNoMem]>;
- def int_x86_avx2_pmovzxwq : GCCBuiltin<"__builtin_ia32_pmovzxwq256">,
- Intrinsic<[llvm_v4i64_ty], [llvm_v8i16_ty],
- [IntrNoMem]>;
-}
-
// Vector blend
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx2_pblendvb : GCCBuiltin<"__builtin_ia32_pblendvb256">,
@@ -2665,18 +2346,62 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
// Vector load with broadcast
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
+ def int_x86_avx512_mask_pbroadcast_b_gpr_128 :
+ GCCBuiltin<"__builtin_ia32_pbroadcastb128_gpr_mask">,
+ Intrinsic<[llvm_v16i8_ty],
+ [llvm_i8_ty, llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pbroadcast_b_gpr_256 :
+ GCCBuiltin<"__builtin_ia32_pbroadcastb256_gpr_mask">,
+ Intrinsic<[llvm_v32i8_ty],
+ [llvm_i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pbroadcast_b_gpr_512 :
+ GCCBuiltin<"__builtin_ia32_pbroadcastb512_gpr_mask">,
+ Intrinsic<[llvm_v64i8_ty],
+ [llvm_i8_ty, llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_mask_pbroadcast_w_gpr_128 :
+ GCCBuiltin<"__builtin_ia32_pbroadcastw128_gpr_mask">,
+ Intrinsic<[llvm_v8i16_ty],
+ [llvm_i16_ty, llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pbroadcast_w_gpr_256 :
+ GCCBuiltin<"__builtin_ia32_pbroadcastw256_gpr_mask">,
+ Intrinsic<[llvm_v16i16_ty],
+ [llvm_i16_ty, llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pbroadcast_w_gpr_512 :
+ GCCBuiltin<"__builtin_ia32_pbroadcastw512_gpr_mask">,
+ Intrinsic<[llvm_v32i16_ty],
+ [llvm_i16_ty, llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_mask_pbroadcast_d_gpr_128 :
+ GCCBuiltin<"__builtin_ia32_pbroadcastd128_gpr_mask">,
+ Intrinsic<[llvm_v4i32_ty],
+ [llvm_i32_ty, llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pbroadcast_d_gpr_256 :
+ GCCBuiltin<"__builtin_ia32_pbroadcastd256_gpr_mask">,
+ Intrinsic<[llvm_v8i32_ty],
+ [llvm_i32_ty, llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pbroadcast_d_gpr_512 :
- GCCBuiltin<"__builtin_ia32_pbroadcastd512_gpr_mask">,
- Intrinsic<[llvm_v16i32_ty], [llvm_i32_ty, llvm_v16i32_ty,
- llvm_i16_ty], [IntrNoMem]>;
+ GCCBuiltin<"__builtin_ia32_pbroadcastd512_gpr_mask">,
+ Intrinsic<[llvm_v16i32_ty],
+ [llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_mask_pbroadcast_q_gpr_128 :
+ GCCBuiltin<"__builtin_ia32_pbroadcastq128_gpr_mask">,
+ Intrinsic<[llvm_v2i64_ty],
+ [llvm_i64_ty, llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pbroadcast_q_gpr_256 :
+ GCCBuiltin<"__builtin_ia32_pbroadcastq256_gpr_mask">,
+ Intrinsic<[llvm_v4i64_ty],
+ [llvm_i64_ty, llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pbroadcast_q_gpr_512 :
- GCCBuiltin<"__builtin_ia32_pbroadcastq512_gpr_mask">,
- Intrinsic<[llvm_v8i64_ty], [llvm_i64_ty, llvm_v8i64_ty,
- llvm_i8_ty], [IntrNoMem]>;
+ GCCBuiltin<"__builtin_ia32_pbroadcastq512_gpr_mask">,
+ Intrinsic<[llvm_v8i64_ty],
+ [llvm_i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+
def int_x86_avx512_mask_pbroadcast_q_mem_512 :
- GCCBuiltin<"__builtin_ia32_pbroadcastq512_mem_mask">,
- Intrinsic<[llvm_v8i64_ty], [llvm_i64_ty, llvm_v8i64_ty,
- llvm_i8_ty], [IntrNoMem]>;
+ GCCBuiltin<"__builtin_ia32_pbroadcastq512_mem_mask">,
+ Intrinsic<[llvm_v8i64_ty],
+ [llvm_i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
}
// Vector permutation
@@ -2750,9 +2475,9 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
[IntrNoMem]>;
def int_x86_avx512_mask_insertf32x4_512 :
- GCCBuiltin<"__builtin_ia32_insertf32x4_512_mask">,
+ GCCBuiltin<"__builtin_ia32_insertf32x4_mask">,
Intrinsic<[llvm_v16f32_ty],
- [llvm_v16f32_ty, llvm_v4f32_ty, llvm_i32_ty, llvm_v16f32_ty, llvm_i8_ty],
+ [llvm_v16f32_ty, llvm_v4f32_ty, llvm_i32_ty, llvm_v16f32_ty, llvm_i16_ty],
[IntrNoMem]>;
def int_x86_avx512_mask_insertf32x8_512 :
@@ -2786,9 +2511,9 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
[IntrNoMem]>;
def int_x86_avx512_mask_inserti32x4_512 :
- GCCBuiltin<"__builtin_ia32_inserti32x4_512_mask">,
+ GCCBuiltin<"__builtin_ia32_inserti32x4_mask">,
Intrinsic<[llvm_v16i32_ty],
- [llvm_v16i32_ty, llvm_v4i32_ty, llvm_i32_ty, llvm_v16i32_ty, llvm_i8_ty],
+ [llvm_v16i32_ty, llvm_v4i32_ty, llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty],
[IntrNoMem]>;
def int_x86_avx512_mask_inserti32x8_512 :
@@ -2813,55 +2538,41 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
GCCBuiltin<"__builtin_ia32_inserti64x4_mask">,
Intrinsic<[llvm_v8i64_ty],
[llvm_v8i64_ty, llvm_v4i64_ty, llvm_i32_ty, llvm_v8i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
+ [IntrNoMem]>;
}
// Conditional load ops
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx2_maskload_d : GCCBuiltin<"__builtin_ia32_maskloadd">,
Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty, llvm_v4i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx2_maskload_q : GCCBuiltin<"__builtin_ia32_maskloadq">,
Intrinsic<[llvm_v2i64_ty], [llvm_ptr_ty, llvm_v2i64_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx2_maskload_d_256 : GCCBuiltin<"__builtin_ia32_maskloadd256">,
Intrinsic<[llvm_v8i32_ty], [llvm_ptr_ty, llvm_v8i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx2_maskload_q_256 : GCCBuiltin<"__builtin_ia32_maskloadq256">,
Intrinsic<[llvm_v4i64_ty], [llvm_ptr_ty, llvm_v4i64_ty],
- [IntrReadArgMem]>;
- def int_x86_avx512_mask_loadu_d_512 : GCCBuiltin<"__builtin_ia32_loaddqusi512_mask">,
- Intrinsic<[llvm_v16i32_ty], [llvm_ptr_ty, llvm_v16i32_ty, llvm_i16_ty],
- [IntrReadArgMem]>;
- def int_x86_avx512_mask_loadu_q_512 : GCCBuiltin<"__builtin_ia32_loaddqudi512_mask">,
- Intrinsic<[llvm_v8i64_ty], [llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
}
// Conditional store ops
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx2_maskstore_d : GCCBuiltin<"__builtin_ia32_maskstored">,
Intrinsic<[], [llvm_ptr_ty, llvm_v4i32_ty, llvm_v4i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx2_maskstore_q : GCCBuiltin<"__builtin_ia32_maskstoreq">,
Intrinsic<[], [llvm_ptr_ty, llvm_v2i64_ty, llvm_v2i64_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx2_maskstore_d_256 :
GCCBuiltin<"__builtin_ia32_maskstored256">,
Intrinsic<[], [llvm_ptr_ty, llvm_v8i32_ty, llvm_v8i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx2_maskstore_q_256 :
GCCBuiltin<"__builtin_ia32_maskstoreq256">,
Intrinsic<[], [llvm_ptr_ty, llvm_v4i64_ty, llvm_v4i64_ty],
- [IntrReadWriteArgMem]>;
- def int_x86_avx512_mask_storeu_d_512 :
- GCCBuiltin<"__builtin_ia32_storedqusi512_mask">,
- Intrinsic<[], [llvm_ptr_ty, llvm_v16i32_ty, llvm_i16_ty],
- [IntrReadWriteArgMem]>;
- def int_x86_avx512_mask_storeu_q_512 :
- GCCBuiltin<"__builtin_ia32_storedqudi512_mask">,
- Intrinsic<[], [llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
}
// Variable bit shift ops
@@ -2905,7 +2616,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
[IntrNoMem]>;
def int_x86_avx512_mask_psllv_q : GCCBuiltin<"__builtin_ia32_psllv8di_mask">,
Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
- llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
+ llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
[IntrNoMem]>;
def int_x86_avx512_mask_psrav_d : GCCBuiltin<"__builtin_ia32_psrav16si_mask">,
Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
@@ -2921,66 +2632,60 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
[IntrNoMem]>;
def int_x86_avx512_mask_psrlv_q : GCCBuiltin<"__builtin_ia32_psrlv8di_mask">,
Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
- llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
- def int_x86_avx512_psll_dq_512 : GCCBuiltin<"__builtin_ia32_pslldq512">,
- Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_i32_ty],
+ llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_psrl_dq_512 : GCCBuiltin<"__builtin_ia32_psrldq512">,
- Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_i32_ty],
- [IntrNoMem]>;
def int_x86_avx512_mask_psll_d_128 : GCCBuiltin<"__builtin_ia32_pslld128_mask">,
Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty,
llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psll_d_256 : GCCBuiltin<"__builtin_ia32_pslld256_mask">,
- Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty,
+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty,
llvm_v4i32_ty, llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psll_di_128 : GCCBuiltin<"__builtin_ia32_pslldi128_mask">,
- Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty,
- llvm_i8_ty, llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty,
+ llvm_i32_ty, llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psll_di_256 : GCCBuiltin<"__builtin_ia32_pslldi256_mask">,
- Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty,
- llvm_i8_ty, llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty,
+ llvm_i32_ty, llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psll_di_512 : GCCBuiltin<"__builtin_ia32_pslldi512_mask">,
- Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
- llvm_i8_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
+ Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
+ llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psll_q_128 : GCCBuiltin<"__builtin_ia32_psllq128_mask">,
Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty,
llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psll_q_256 : GCCBuiltin<"__builtin_ia32_psllq256_mask">,
- Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty,
+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty,
llvm_v2i64_ty, llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psll_qi_128 : GCCBuiltin<"__builtin_ia32_psllqi128_mask">,
- Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty,
- llvm_i8_ty, llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty,
+ llvm_i32_ty, llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psll_qi_256 : GCCBuiltin<"__builtin_ia32_psllqi256_mask">,
- Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty,
- llvm_i8_ty, llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty,
+ llvm_i32_ty, llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psll_qi_512 : GCCBuiltin<"__builtin_ia32_psllqi512_mask">,
- Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
- llvm_i8_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
+ llvm_i32_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psrav16_hi : GCCBuiltin<"__builtin_ia32_psrav16hi_mask">,
- Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty,
+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty,
llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psrav32_hi : GCCBuiltin<"__builtin_ia32_psrav32hi_mask">,
- Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty,
+ Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty,
llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psrav4_si : GCCBuiltin<"__builtin_ia32_psrav4si_mask">,
- Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty,
+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty,
llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psrav8_hi : GCCBuiltin<"__builtin_ia32_psrav8hi_mask">,
- Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty,
+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty,
llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psrav8_si : GCCBuiltin<"__builtin_ia32_psrav8si_mask">,
- Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty,
+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty,
llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psrav_q_128 : GCCBuiltin<"__builtin_ia32_psravq128_mask">,
- Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty,
+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty,
llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psrav_q_256 : GCCBuiltin<"__builtin_ia32_psravq256_mask">,
- Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty,
+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty,
llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psrlv16_hi : GCCBuiltin<"__builtin_ia32_psrlv16hi_mask">,
@@ -2990,19 +2695,19 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty,
llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psrlv32hi : GCCBuiltin<"__builtin_ia32_psrlv32hi_mask">,
- Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty,
+ Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty,
llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psrlv4_di : GCCBuiltin<"__builtin_ia32_psrlv4di_mask">,
- Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty,
+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty,
llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psrlv4_si : GCCBuiltin<"__builtin_ia32_psrlv4si_mask">,
- Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty,
+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty,
llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psrlv8_hi : GCCBuiltin<"__builtin_ia32_psrlv8hi_mask">,
- Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty,
+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty,
llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psrlv8_si : GCCBuiltin<"__builtin_ia32_psrlv8si_mask">,
- Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty,
+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty,
llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_prorv_d_128 : GCCBuiltin<"__builtin_ia32_prorvd128_mask">,
@@ -3026,22 +2731,22 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx512_mask_prol_d_128 : GCCBuiltin<"__builtin_ia32_prold128_mask">,
Intrinsic<[llvm_v4i32_ty] , [llvm_v4i32_ty,
- llvm_i8_ty, llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ llvm_i32_ty, llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_prol_d_256 : GCCBuiltin<"__builtin_ia32_prold256_mask">,
Intrinsic<[llvm_v8i32_ty] , [llvm_v8i32_ty,
- llvm_i8_ty, llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ llvm_i32_ty, llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_prol_d_512 : GCCBuiltin<"__builtin_ia32_prold512_mask">,
Intrinsic<[llvm_v16i32_ty] , [llvm_v16i32_ty,
- llvm_i8_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
+ llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
def int_x86_avx512_mask_prol_q_128 : GCCBuiltin<"__builtin_ia32_prolq128_mask">,
Intrinsic<[llvm_v2i64_ty] , [llvm_v2i64_ty,
- llvm_i8_ty, llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ llvm_i32_ty, llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_prol_q_256 : GCCBuiltin<"__builtin_ia32_prolq256_mask">,
Intrinsic<[llvm_v4i64_ty] , [llvm_v4i64_ty,
- llvm_i8_ty, llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ llvm_i32_ty, llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_prol_q_512 : GCCBuiltin<"__builtin_ia32_prolq512_mask">,
Intrinsic<[llvm_v8i64_ty] , [llvm_v8i64_ty,
- llvm_i8_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ llvm_i32_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_prolv_d_128 : GCCBuiltin<"__builtin_ia32_prolvd128_mask">,
@@ -3064,22 +2769,22 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pror_d_128 : GCCBuiltin<"__builtin_ia32_prord128_mask">,
Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty,
- llvm_i8_ty, llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ llvm_i32_ty, llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pror_d_256 : GCCBuiltin<"__builtin_ia32_prord256_mask">,
Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty,
- llvm_i8_ty, llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ llvm_i32_ty, llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pror_d_512 : GCCBuiltin<"__builtin_ia32_prord512_mask">,
Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
- llvm_i8_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
+ llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pror_q_128 : GCCBuiltin<"__builtin_ia32_prorq128_mask">,
Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty,
- llvm_i8_ty, llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ llvm_i32_ty, llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pror_q_256 : GCCBuiltin<"__builtin_ia32_prorq256_mask">,
- Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty,
- llvm_i8_ty, llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty,
+ llvm_i32_ty, llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pror_q_512 : GCCBuiltin<"__builtin_ia32_prorq512_mask">,
- Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
- llvm_i8_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
+ llvm_i32_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
}
@@ -3088,68 +2793,68 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx2_gather_d_pd : GCCBuiltin<"__builtin_ia32_gatherd_pd">,
Intrinsic<[llvm_v2f64_ty],
[llvm_v2f64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v2f64_ty, llvm_i8_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx2_gather_d_pd_256 : GCCBuiltin<"__builtin_ia32_gatherd_pd256">,
Intrinsic<[llvm_v4f64_ty],
[llvm_v4f64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4f64_ty, llvm_i8_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx2_gather_q_pd : GCCBuiltin<"__builtin_ia32_gatherq_pd">,
Intrinsic<[llvm_v2f64_ty],
[llvm_v2f64_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v2f64_ty, llvm_i8_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx2_gather_q_pd_256 : GCCBuiltin<"__builtin_ia32_gatherq_pd256">,
Intrinsic<[llvm_v4f64_ty],
[llvm_v4f64_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4f64_ty, llvm_i8_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx2_gather_d_ps : GCCBuiltin<"__builtin_ia32_gatherd_ps">,
Intrinsic<[llvm_v4f32_ty],
[llvm_v4f32_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4f32_ty, llvm_i8_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx2_gather_d_ps_256 : GCCBuiltin<"__builtin_ia32_gatherd_ps256">,
Intrinsic<[llvm_v8f32_ty],
[llvm_v8f32_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_v8f32_ty, llvm_i8_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx2_gather_q_ps : GCCBuiltin<"__builtin_ia32_gatherq_ps">,
Intrinsic<[llvm_v4f32_ty],
[llvm_v4f32_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v4f32_ty, llvm_i8_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx2_gather_q_ps_256 : GCCBuiltin<"__builtin_ia32_gatherq_ps256">,
Intrinsic<[llvm_v4f32_ty],
[llvm_v4f32_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4f32_ty, llvm_i8_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx2_gather_d_q : GCCBuiltin<"__builtin_ia32_gatherd_q">,
Intrinsic<[llvm_v2i64_ty],
[llvm_v2i64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v2i64_ty, llvm_i8_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx2_gather_d_q_256 : GCCBuiltin<"__builtin_ia32_gatherd_q256">,
Intrinsic<[llvm_v4i64_ty],
[llvm_v4i64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4i64_ty, llvm_i8_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx2_gather_q_q : GCCBuiltin<"__builtin_ia32_gatherq_q">,
Intrinsic<[llvm_v2i64_ty],
[llvm_v2i64_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx2_gather_q_q_256 : GCCBuiltin<"__builtin_ia32_gatherq_q256">,
Intrinsic<[llvm_v4i64_ty],
[llvm_v4i64_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx2_gather_d_d : GCCBuiltin<"__builtin_ia32_gatherd_d">,
Intrinsic<[llvm_v4i32_ty],
[llvm_v4i32_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx2_gather_d_d_256 : GCCBuiltin<"__builtin_ia32_gatherd_d256">,
Intrinsic<[llvm_v8i32_ty],
[llvm_v8i32_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx2_gather_q_d : GCCBuiltin<"__builtin_ia32_gatherq_d">,
Intrinsic<[llvm_v4i32_ty],
[llvm_v4i32_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v4i32_ty, llvm_i8_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx2_gather_q_d_256 : GCCBuiltin<"__builtin_ia32_gatherq_d256">,
Intrinsic<[llvm_v4i32_ty],
[llvm_v4i32_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4i32_ty, llvm_i8_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
}
// Misc.
@@ -3520,6 +3225,43 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
[llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty,
llvm_i32_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_mask_vfmadd_sd :
+ GCCBuiltin<"__builtin_ia32_vfmaddsd3_mask">,
+ Intrinsic<[llvm_v2f64_ty],
+ [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty,
+ llvm_i32_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_mask_vfmadd_ss :
+ GCCBuiltin<"__builtin_ia32_vfmaddss3_mask">,
+ Intrinsic<[llvm_v4f32_ty],
+ [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty,
+ llvm_i32_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_maskz_vfmadd_sd :
+ GCCBuiltin<"__builtin_ia32_vfmaddsd3_maskz">,
+ Intrinsic<[llvm_v2f64_ty],
+ [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty,
+ llvm_i32_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_maskz_vfmadd_ss :
+ GCCBuiltin<"__builtin_ia32_vfmaddss3_maskz">,
+ Intrinsic<[llvm_v4f32_ty],
+ [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty,
+ llvm_i32_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_mask3_vfmadd_sd :
+ GCCBuiltin<"__builtin_ia32_vfmaddsd3_mask3">,
+ Intrinsic<[llvm_v2f64_ty],
+ [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty,
+ llvm_i32_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_mask3_vfmadd_ss :
+ GCCBuiltin<"__builtin_ia32_vfmaddss3_mask3">,
+ Intrinsic<[llvm_v4f32_ty],
+ [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty,
+ llvm_i32_ty], [IntrNoMem]>;
+
def int_x86_avx512_mask3_vfmsub_pd_128 :
GCCBuiltin<"__builtin_ia32_vfmsubpd128_mask3">,
Intrinsic<[llvm_v2f64_ty],
@@ -3700,30 +3442,79 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
[llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty,
llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_vpmadd52h_uq_128 :
+ GCCBuiltin<"__builtin_ia32_vpmadd52huq128_mask">,
+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty,
+ llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_maskz_vpmadd52h_uq_128 :
+ GCCBuiltin<"__builtin_ia32_vpmadd52huq128_maskz">,
+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty,
+ llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_vpmadd52l_uq_128 :
+ GCCBuiltin<"__builtin_ia32_vpmadd52luq128_mask">,
+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty,
+ llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_maskz_vpmadd52l_uq_128 :
+ GCCBuiltin<"__builtin_ia32_vpmadd52luq128_maskz">,
+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty,
+ llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_vpmadd52h_uq_256 :
+ GCCBuiltin<"__builtin_ia32_vpmadd52huq256_mask">,
+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty,
+ llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_maskz_vpmadd52h_uq_256 :
+ GCCBuiltin<"__builtin_ia32_vpmadd52huq256_maskz">,
+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty,
+ llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_vpmadd52l_uq_256 :
+ GCCBuiltin<"__builtin_ia32_vpmadd52luq256_mask">,
+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty,
+ llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_maskz_vpmadd52l_uq_256 :
+ GCCBuiltin<"__builtin_ia32_vpmadd52luq256_maskz">,
+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty,
+ llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_vpmadd52h_uq_512 :
+ GCCBuiltin<"__builtin_ia32_vpmadd52huq512_mask">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty,
+ llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_maskz_vpmadd52h_uq_512 :
+ GCCBuiltin<"__builtin_ia32_vpmadd52huq512_maskz">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty,
+ llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_vpmadd52l_uq_512 :
+ GCCBuiltin<"__builtin_ia32_vpmadd52luq512_mask">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty,
+ llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_maskz_vpmadd52l_uq_512 :
+ GCCBuiltin<"__builtin_ia32_vpmadd52luq512_maskz">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty,
+ llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
}
//===----------------------------------------------------------------------===//
// XOP
+let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_xop_vpermil2pd : GCCBuiltin<"__builtin_ia32_vpermil2pd">,
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
- llvm_v2f64_ty, llvm_i8_ty],
+ llvm_v2i64_ty, llvm_i8_ty],
[IntrNoMem]>;
def int_x86_xop_vpermil2pd_256 :
GCCBuiltin<"__builtin_ia32_vpermil2pd256">,
Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty,
- llvm_v4f64_ty, llvm_i8_ty],
+ llvm_v4i64_ty, llvm_i8_ty],
[IntrNoMem]>;
def int_x86_xop_vpermil2ps : GCCBuiltin<"__builtin_ia32_vpermil2ps">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
- llvm_v4f32_ty, llvm_i8_ty],
+ llvm_v4i32_ty, llvm_i8_ty],
[IntrNoMem]>;
def int_x86_xop_vpermil2ps_256 :
GCCBuiltin<"__builtin_ia32_vpermil2ps256">,
Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty,
- llvm_v8f32_ty, llvm_i8_ty],
+ llvm_v8i32_ty, llvm_i8_ty],
[IntrNoMem]>;
def int_x86_xop_vfrcz_pd : GCCBuiltin<"__builtin_ia32_vfrczpd">,
@@ -3943,6 +3734,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
GCCBuiltin<"__builtin_ia32_vpshlw">,
Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty],
[IntrNoMem]>;
+}
//===----------------------------------------------------------------------===//
// MMX
@@ -4131,7 +3923,51 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty,
llvm_i32_ty], [IntrNoMem]>;
}
-
+// Permute
+let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
+ def int_x86_avx512_mask_permvar_df_256 : GCCBuiltin<"__builtin_ia32_permvardf256_mask">,
+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty,
+ llvm_v4i64_ty, llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_permvar_df_512 : GCCBuiltin<"__builtin_ia32_permvardf512_mask">,
+ Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty,
+ llvm_v8i64_ty, llvm_v8f64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_permvar_di_256 : GCCBuiltin<"__builtin_ia32_permvardi256_mask">,
+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty,
+ llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_permvar_di_512 : GCCBuiltin<"__builtin_ia32_permvardi512_mask">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
+ llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_permvar_hi_128 : GCCBuiltin<"__builtin_ia32_permvarhi128_mask">,
+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty,
+ llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_permvar_hi_256 : GCCBuiltin<"__builtin_ia32_permvarhi256_mask">,
+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty,
+ llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_permvar_hi_512 : GCCBuiltin<"__builtin_ia32_permvarhi512_mask">,
+ Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty,
+ llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_permvar_qi_128 : GCCBuiltin<"__builtin_ia32_permvarqi128_mask">,
+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty,
+ llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_permvar_qi_256 : GCCBuiltin<"__builtin_ia32_permvarqi256_mask">,
+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty,
+ llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_permvar_qi_512 : GCCBuiltin<"__builtin_ia32_permvarqi512_mask">,
+ Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty,
+ llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_permvar_sf_256 : GCCBuiltin<"__builtin_ia32_permvarsf256_mask">,
+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty,
+ llvm_v8i32_ty, llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_permvar_sf_512 : GCCBuiltin<"__builtin_ia32_permvarsf512_mask">,
+ Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty,
+ llvm_v16i32_ty, llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_permvar_si_256 : GCCBuiltin<"__builtin_ia32_permvarsi256_mask">,
+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty,
+ llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_permvar_si_512 : GCCBuiltin<"__builtin_ia32_permvarsi512_mask">,
+ Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
+ llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
+}
// Pack ops.
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_mmx_packsswb : GCCBuiltin<"__builtin_ia32_packsswb">,
@@ -4301,6 +4137,13 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
}
//===----------------------------------------------------------------------===//
+// CLFLUSHOPT
+let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
+ def int_x86_clflushopt : GCCBuiltin<"__builtin_ia32_clflushopt">,
+ Intrinsic<[], [llvm_ptr_ty], []>;
+}
+
+//===----------------------------------------------------------------------===//
// Support protection key
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_rdpkru : GCCBuiltin <"__builtin_ia32_rdpkru">,
@@ -4374,22 +4217,22 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_addcarryx_u32: GCCBuiltin<"__builtin_ia32_addcarryx_u32">,
Intrinsic<[llvm_i8_ty], [llvm_i8_ty, llvm_i32_ty, llvm_i32_ty,
- llvm_ptr_ty], [IntrReadWriteArgMem]>;
+ llvm_ptr_ty], [IntrArgMemOnly]>;
def int_x86_addcarryx_u64: GCCBuiltin<"__builtin_ia32_addcarryx_u64">,
Intrinsic<[llvm_i8_ty], [llvm_i8_ty, llvm_i64_ty, llvm_i64_ty,
- llvm_ptr_ty], [IntrReadWriteArgMem]>;
+ llvm_ptr_ty], [IntrArgMemOnly]>;
def int_x86_addcarry_u32: GCCBuiltin<"__builtin_ia32_addcarry_u32">,
Intrinsic<[llvm_i8_ty], [llvm_i8_ty, llvm_i32_ty, llvm_i32_ty,
- llvm_ptr_ty], [IntrReadWriteArgMem]>;
+ llvm_ptr_ty], [IntrArgMemOnly]>;
def int_x86_addcarry_u64: GCCBuiltin<"__builtin_ia32_addcarry_u64">,
Intrinsic<[llvm_i8_ty], [llvm_i8_ty, llvm_i64_ty, llvm_i64_ty,
- llvm_ptr_ty], [IntrReadWriteArgMem]>;
+ llvm_ptr_ty], [IntrArgMemOnly]>;
def int_x86_subborrow_u32: GCCBuiltin<"__builtin_ia32_subborrow_u32">,
Intrinsic<[llvm_i8_ty], [llvm_i8_ty, llvm_i32_ty, llvm_i32_ty,
- llvm_ptr_ty], [IntrReadWriteArgMem]>;
+ llvm_ptr_ty], [IntrArgMemOnly]>;
def int_x86_subborrow_u64: GCCBuiltin<"__builtin_ia32_subborrow_u64">,
Intrinsic<[llvm_i8_ty], [llvm_i8_ty, llvm_i64_ty, llvm_i64_ty,
- llvm_ptr_ty], [IntrReadWriteArgMem]>;
+ llvm_ptr_ty], [IntrArgMemOnly]>;
}
//===----------------------------------------------------------------------===//
@@ -4401,7 +4244,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_xend : GCCBuiltin<"__builtin_ia32_xend">,
Intrinsic<[], [], []>;
def int_x86_xabort : GCCBuiltin<"__builtin_ia32_xabort">,
- Intrinsic<[], [llvm_i8_ty], [IntrNoReturn]>;
+ Intrinsic<[], [llvm_i8_ty], []>;
def int_x86_xtest : GCCBuiltin<"__builtin_ia32_xtest">,
Intrinsic<[llvm_i32_ty], [], []>;
}
@@ -4445,7 +4288,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx512_kortestc_w : GCCBuiltin<"__builtin_ia32_kortestchi">,
Intrinsic<[llvm_i32_ty], [llvm_i16_ty, llvm_i16_ty],
[IntrNoMem]>;
-
+
def int_x86_avx512_mask_pmovsxb_d_128 : GCCBuiltin<"__builtin_ia32_pmovsxbd128_mask">,
Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty,
llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
@@ -4504,10 +4347,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
// Conversion ops
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_avx512_cvtss2usi : GCCBuiltin<"__builtin_ia32_cvtss2usi">,
- Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty], [IntrNoMem]>;
- def int_x86_avx512_cvtss2usi64 : GCCBuiltin<"__builtin_ia32_cvtss2usi64">,
- Intrinsic<[llvm_i64_ty], [llvm_v4f32_ty], [IntrNoMem]>;
def int_x86_avx512_cvttss2si : GCCBuiltin<"__builtin_ia32_vcvttss2si32">,
Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_cvttss2si64 : GCCBuiltin<"__builtin_ia32_vcvttss2si64">,
@@ -4522,11 +4361,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx512_cvtusi642ss : GCCBuiltin<"__builtin_ia32_cvtusi2ss64">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty,
llvm_i64_ty, llvm_i32_ty], [IntrNoMem]>;
-
- def int_x86_avx512_cvtsd2usi : GCCBuiltin<"__builtin_ia32_cvtsd2usi">,
- Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty], [IntrNoMem]>;
- def int_x86_avx512_cvtsd2usi64 : GCCBuiltin<"__builtin_ia32_cvtsd2usi64">,
- Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty], [IntrNoMem]>;
def int_x86_avx512_cvttsd2si : GCCBuiltin<"__builtin_ia32_vcvttsd2si32">,
Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_cvttsd2si64 : GCCBuiltin<"__builtin_ia32_vcvttsd2si64">,
@@ -4541,7 +4375,22 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx512_cvtusi642sd : GCCBuiltin<"__builtin_ia32_cvtusi2sd64">,
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty,
llvm_i64_ty, llvm_i32_ty], [IntrNoMem]>;
-
+ def int_x86_avx512_vcvtss2usi32 : GCCBuiltin<"__builtin_ia32_vcvtss2usi32">,
+ Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_vcvtss2usi64 : GCCBuiltin<"__builtin_ia32_vcvtss2usi64">,
+ Intrinsic<[llvm_i64_ty], [llvm_v4f32_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_vcvtss2si32 : GCCBuiltin<"__builtin_ia32_vcvtss2si32">,
+ Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_vcvtss2si64 : GCCBuiltin<"__builtin_ia32_vcvtss2si64">,
+ Intrinsic<[llvm_i64_ty], [llvm_v4f32_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_vcvtsd2usi32 : GCCBuiltin<"__builtin_ia32_vcvtsd2usi32">,
+ Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_vcvtsd2usi64 : GCCBuiltin<"__builtin_ia32_vcvtsd2usi64">,
+ Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_vcvtsd2si32 : GCCBuiltin<"__builtin_ia32_vcvtsd2si32">,
+ Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_vcvtsd2si64 : GCCBuiltin<"__builtin_ia32_vcvtsd2si64">,
+ Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_cvtsi2ss32 : GCCBuiltin<"__builtin_ia32_cvtsi2ss32">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty,
llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
@@ -4553,7 +4402,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_cvtsi2sd64 : GCCBuiltin<"__builtin_ia32_cvtsi2sd64">,
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty,
- llvm_i64_ty, llvm_i32_ty], [IntrNoMem]>;
+ llvm_i64_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_cvtb2mask_128 : GCCBuiltin<"__builtin_ia32_cvtb2mask128">,
Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty], [IntrNoMem]>;
@@ -4561,23 +4410,23 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty], [IntrNoMem]>;
def int_x86_avx512_cvtb2mask_512 : GCCBuiltin<"__builtin_ia32_cvtb2mask512">,
Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty], [IntrNoMem]>;
-
+
def int_x86_avx512_cvtw2mask_128 : GCCBuiltin<"__builtin_ia32_cvtw2mask128">,
Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty], [IntrNoMem]>;
def int_x86_avx512_cvtw2mask_256 : GCCBuiltin<"__builtin_ia32_cvtw2mask256">,
Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty], [IntrNoMem]>;
def int_x86_avx512_cvtw2mask_512 : GCCBuiltin<"__builtin_ia32_cvtw2mask512">,
Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty], [IntrNoMem]>;
-
+
def int_x86_avx512_cvtd2mask_128 : GCCBuiltin<"__builtin_ia32_cvtd2mask128">,
Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty], [IntrNoMem]>;
def int_x86_avx512_cvtd2mask_256 : GCCBuiltin<"__builtin_ia32_cvtd2mask256">,
- Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty], [IntrNoMem]>;
+ Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty], [IntrNoMem]>;
def int_x86_avx512_cvtd2mask_512 : GCCBuiltin<"__builtin_ia32_cvtd2mask512">,
Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty], [IntrNoMem]>;
def int_x86_avx512_cvtq2mask_128 : GCCBuiltin<"__builtin_ia32_cvtq2mask128">,
- Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty], [IntrNoMem]>;
+ Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty], [IntrNoMem]>;
def int_x86_avx512_cvtq2mask_256 : GCCBuiltin<"__builtin_ia32_cvtq2mask256">,
Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty], [IntrNoMem]>;
def int_x86_avx512_cvtq2mask_512 : GCCBuiltin<"__builtin_ia32_cvtq2mask512">,
@@ -4589,28 +4438,28 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v32i8_ty], [llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_cvtmask2b_512 : GCCBuiltin<"__builtin_ia32_cvtmask2b512">,
Intrinsic<[llvm_v64i8_ty], [llvm_i64_ty], [IntrNoMem]>;
-
+
def int_x86_avx512_cvtmask2w_128 : GCCBuiltin<"__builtin_ia32_cvtmask2w128">,
Intrinsic<[llvm_v8i16_ty], [llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_cvtmask2w_256 : GCCBuiltin<"__builtin_ia32_cvtmask2w256">,
Intrinsic<[llvm_v16i16_ty], [llvm_i16_ty], [IntrNoMem]>;
def int_x86_avx512_cvtmask2w_512 : GCCBuiltin<"__builtin_ia32_cvtmask2w512">,
Intrinsic<[llvm_v32i16_ty], [llvm_i32_ty], [IntrNoMem]>;
-
+
def int_x86_avx512_cvtmask2d_128 : GCCBuiltin<"__builtin_ia32_cvtmask2d128">,
Intrinsic<[llvm_v4i32_ty], [llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_cvtmask2d_256 : GCCBuiltin<"__builtin_ia32_cvtmask2d256">,
- Intrinsic<[llvm_v8i32_ty], [llvm_i8_ty], [IntrNoMem]>;
+ Intrinsic<[llvm_v8i32_ty], [llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_cvtmask2d_512 : GCCBuiltin<"__builtin_ia32_cvtmask2d512">,
Intrinsic<[llvm_v16i32_ty], [llvm_i16_ty], [IntrNoMem]>;
-
+
def int_x86_avx512_cvtmask2q_128 : GCCBuiltin<"__builtin_ia32_cvtmask2q128">,
- Intrinsic<[llvm_v2i64_ty], [llvm_i8_ty], [IntrNoMem]>;
+ Intrinsic<[llvm_v2i64_ty], [llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_cvtmask2q_256 : GCCBuiltin<"__builtin_ia32_cvtmask2q256">,
Intrinsic<[llvm_v4i64_ty], [llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_cvtmask2q_512 : GCCBuiltin<"__builtin_ia32_cvtmask2q512">,
Intrinsic<[llvm_v8i64_ty], [llvm_i8_ty], [IntrNoMem]>;
-
+
}
// Pack ops.
@@ -4622,7 +4471,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty,llvm_v16i16_ty,
llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_packsswb_512 : GCCBuiltin<"__builtin_ia32_packsswb512_mask">,
- Intrinsic<[llvm_v64i8_ty], [llvm_v32i16_ty,llvm_v32i16_ty,
+ Intrinsic<[llvm_v64i8_ty], [llvm_v32i16_ty,llvm_v32i16_ty,
llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>;
def int_x86_avx512_mask_packssdw_128 : GCCBuiltin<"__builtin_ia32_packssdw128_mask">,
Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
@@ -4640,7 +4489,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty,llvm_v16i16_ty,
llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_packuswb_512 : GCCBuiltin<"__builtin_ia32_packuswb512_mask">,
- Intrinsic<[llvm_v64i8_ty], [llvm_v32i16_ty,llvm_v32i16_ty,
+ Intrinsic<[llvm_v64i8_ty], [llvm_v32i16_ty,llvm_v32i16_ty,
llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>;
def int_x86_avx512_mask_packusdw_128 : GCCBuiltin<"__builtin_ia32_packusdw128_mask">,
Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
@@ -4653,702 +4502,483 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
}
-// Unpack ops.
-let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_avx512_mask_unpckh_pd_128 :
- GCCBuiltin<"__builtin_ia32_unpckhpd128_mask">,
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_unpckh_pd_256 :
- GCCBuiltin<"__builtin_ia32_unpckhpd256_mask">,
- Intrinsic<[llvm_v4f64_ty],
- [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_unpckh_pd_512 :
- GCCBuiltin<"__builtin_ia32_unpckhpd512_mask">,
- Intrinsic<[llvm_v8f64_ty],
- [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_unpckh_ps_128 :
- GCCBuiltin<"__builtin_ia32_unpckhps128_mask">,
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_unpckh_ps_256 :
- GCCBuiltin<"__builtin_ia32_unpckhps256_mask">,
- Intrinsic<[llvm_v8f32_ty],
- [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_unpckh_ps_512 :
- GCCBuiltin<"__builtin_ia32_unpckhps512_mask">,
- Intrinsic<[llvm_v16f32_ty],
- [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_unpckl_pd_128 :
- GCCBuiltin<"__builtin_ia32_unpcklpd128_mask">,
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_unpckl_pd_256 :
- GCCBuiltin<"__builtin_ia32_unpcklpd256_mask">,
- Intrinsic<[llvm_v4f64_ty],
- [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_unpckl_pd_512 :
- GCCBuiltin<"__builtin_ia32_unpcklpd512_mask">,
- Intrinsic<[llvm_v8f64_ty],
- [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_unpckl_ps_128 :
- GCCBuiltin<"__builtin_ia32_unpcklps128_mask">,
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_unpckl_ps_256 :
- GCCBuiltin<"__builtin_ia32_unpcklps256_mask">,
- Intrinsic<[llvm_v8f32_ty],
- [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_unpckl_ps_512 :
- GCCBuiltin<"__builtin_ia32_unpcklps512_mask">,
- Intrinsic<[llvm_v16f32_ty],
- [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_punpckhb_w_128 :
- GCCBuiltin<"__builtin_ia32_punpckhbw128_mask">,
- Intrinsic<[llvm_v16i8_ty],
- [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_punpckhb_w_256 :
- GCCBuiltin<"__builtin_ia32_punpckhbw256_mask">,
- Intrinsic<[llvm_v32i8_ty],
- [llvm_v32i8_ty, llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_punpckhb_w_512 :
- GCCBuiltin<"__builtin_ia32_punpckhbw512_mask">,
- Intrinsic<[llvm_v64i8_ty],
- [llvm_v64i8_ty, llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_punpckhd_q_128 :
- GCCBuiltin<"__builtin_ia32_punpckhdq128_mask">,
- Intrinsic<[llvm_v4i32_ty],
- [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_punpckhd_q_256 :
- GCCBuiltin<"__builtin_ia32_punpckhdq256_mask">,
- Intrinsic<[llvm_v8i32_ty],
- [llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_punpckhd_q_512 :
- GCCBuiltin<"__builtin_ia32_punpckhdq512_mask">,
- Intrinsic<[llvm_v16i32_ty],
- [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_punpckhqd_q_128 :
- GCCBuiltin<"__builtin_ia32_punpckhqdq128_mask">,
- Intrinsic<[llvm_v2i64_ty],
- [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_punpckhqd_q_256 :
- GCCBuiltin<"__builtin_ia32_punpckhqdq256_mask">,
- Intrinsic<[llvm_v4i64_ty],
- [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_punpckhqd_q_512 :
- GCCBuiltin<"__builtin_ia32_punpckhqdq512_mask">,
- Intrinsic<[llvm_v8i64_ty],
- [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_punpckhw_d_128 :
- GCCBuiltin<"__builtin_ia32_punpckhwd128_mask">,
- Intrinsic<[llvm_v8i16_ty],
- [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_punpckhw_d_256 :
- GCCBuiltin<"__builtin_ia32_punpckhwd256_mask">,
- Intrinsic<[llvm_v16i16_ty],
- [llvm_v16i16_ty, llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_punpckhw_d_512 :
- GCCBuiltin<"__builtin_ia32_punpckhwd512_mask">,
- Intrinsic<[llvm_v32i16_ty],
- [llvm_v32i16_ty, llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_punpcklb_w_128 :
- GCCBuiltin<"__builtin_ia32_punpcklbw128_mask">,
- Intrinsic<[llvm_v16i8_ty],
- [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_punpcklb_w_256 :
- GCCBuiltin<"__builtin_ia32_punpcklbw256_mask">,
- Intrinsic<[llvm_v32i8_ty],
- [llvm_v32i8_ty, llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_punpcklb_w_512 :
- GCCBuiltin<"__builtin_ia32_punpcklbw512_mask">,
- Intrinsic<[llvm_v64i8_ty],
- [llvm_v64i8_ty, llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_punpckld_q_128 :
- GCCBuiltin<"__builtin_ia32_punpckldq128_mask">,
- Intrinsic<[llvm_v4i32_ty],
- [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_punpckld_q_256 :
- GCCBuiltin<"__builtin_ia32_punpckldq256_mask">,
- Intrinsic<[llvm_v8i32_ty],
- [llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_punpckld_q_512 :
- GCCBuiltin<"__builtin_ia32_punpckldq512_mask">,
- Intrinsic<[llvm_v16i32_ty],
- [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_punpcklqd_q_128 :
- GCCBuiltin<"__builtin_ia32_punpcklqdq128_mask">,
- Intrinsic<[llvm_v2i64_ty],
- [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_punpcklqd_q_256 :
- GCCBuiltin<"__builtin_ia32_punpcklqdq256_mask">,
- Intrinsic<[llvm_v4i64_ty],
- [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_punpcklqd_q_512 :
- GCCBuiltin<"__builtin_ia32_punpcklqdq512_mask">,
- Intrinsic<[llvm_v8i64_ty],
- [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_punpcklw_d_128 :
- GCCBuiltin<"__builtin_ia32_punpcklwd128_mask">,
- Intrinsic<[llvm_v8i16_ty],
- [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_punpcklw_d_256 :
- GCCBuiltin<"__builtin_ia32_punpcklwd256_mask">,
- Intrinsic<[llvm_v16i16_ty],
- [llvm_v16i16_ty, llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_punpcklw_d_512 :
- GCCBuiltin<"__builtin_ia32_punpcklwd512_mask">,
- Intrinsic<[llvm_v32i16_ty],
- [llvm_v32i16_ty, llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty],
- [IntrNoMem]>;
-}
-
// Vector convert
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_avx512_mask_cvtdq2pd_128 :
+ def int_x86_avx512_mask_cvtdq2pd_128 :
GCCBuiltin<"__builtin_ia32_cvtdq2pd128_mask">,
Intrinsic<[llvm_v2f64_ty],
[llvm_v4i32_ty, llvm_v2f64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtdq2pd_256 :
+ def int_x86_avx512_mask_cvtdq2pd_256 :
GCCBuiltin<"__builtin_ia32_cvtdq2pd256_mask">,
Intrinsic<[llvm_v4f64_ty],
[llvm_v4i32_ty, llvm_v4f64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtdq2pd_512 :
+ def int_x86_avx512_mask_cvtdq2pd_512 :
GCCBuiltin<"__builtin_ia32_cvtdq2pd512_mask">,
Intrinsic<[llvm_v8f64_ty],
[llvm_v8i32_ty, llvm_v8f64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtdq2ps_128 :
+ def int_x86_avx512_mask_cvtdq2ps_128 :
GCCBuiltin<"__builtin_ia32_cvtdq2ps128_mask">,
Intrinsic<[llvm_v4f32_ty],
[llvm_v4i32_ty, llvm_v4f32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtdq2ps_256 :
+ def int_x86_avx512_mask_cvtdq2ps_256 :
GCCBuiltin<"__builtin_ia32_cvtdq2ps256_mask">,
Intrinsic<[llvm_v8f32_ty],
[llvm_v8i32_ty, llvm_v8f32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtdq2ps_512 :
+ def int_x86_avx512_mask_cvtdq2ps_512 :
GCCBuiltin<"__builtin_ia32_cvtdq2ps512_mask">,
Intrinsic<[llvm_v16f32_ty],
[llvm_v16i32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtpd2dq_128 :
+ def int_x86_avx512_mask_cvtpd2dq_128 :
GCCBuiltin<"__builtin_ia32_cvtpd2dq128_mask">,
Intrinsic<[llvm_v4i32_ty],
[llvm_v2f64_ty, llvm_v4i32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtpd2dq_256 :
+ def int_x86_avx512_mask_cvtpd2dq_256 :
GCCBuiltin<"__builtin_ia32_cvtpd2dq256_mask">,
Intrinsic<[llvm_v4i32_ty],
[llvm_v4f64_ty, llvm_v4i32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtpd2dq_512 :
+ def int_x86_avx512_mask_cvtpd2dq_512 :
GCCBuiltin<"__builtin_ia32_cvtpd2dq512_mask">,
Intrinsic<[llvm_v8i32_ty],
[llvm_v8f64_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtpd2ps_256 :
+ def int_x86_avx512_mask_cvtpd2ps_256 :
GCCBuiltin<"__builtin_ia32_cvtpd2ps256_mask">,
Intrinsic<[llvm_v4f32_ty],
[llvm_v4f64_ty, llvm_v4f32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtpd2ps_512 :
+ def int_x86_avx512_mask_cvtpd2ps_512 :
GCCBuiltin<"__builtin_ia32_cvtpd2ps512_mask">,
Intrinsic<[llvm_v8f32_ty],
[llvm_v8f64_ty, llvm_v8f32_ty, llvm_i8_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtsd2ss_round :
- GCCBuiltin<"__builtin_ia32_cvtsd2ss_round">,
+ def int_x86_avx512_mask_cvtsd2ss_round :
+ GCCBuiltin<"__builtin_ia32_cvtsd2ss_round_mask">,
Intrinsic<[llvm_v4f32_ty],
- [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty],
+ [llvm_v4f32_ty, llvm_v2f64_ty, llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtss2sd_round :
- GCCBuiltin<"__builtin_ia32_cvtss2sd_round">,
+ def int_x86_avx512_mask_cvtss2sd_round :
+ GCCBuiltin<"__builtin_ia32_cvtss2sd_round_mask">,
Intrinsic<[llvm_v2f64_ty],
- [ llvm_v4f32_ty, llvm_v4f32_ty, llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty],
+ [llvm_v2f64_ty, llvm_v4f32_ty, llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtpd2ps :
+ def int_x86_avx512_mask_cvtpd2ps :
GCCBuiltin<"__builtin_ia32_cvtpd2ps_mask">,
Intrinsic<[llvm_v4f32_ty],
[llvm_v2f64_ty, llvm_v4f32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtpd2qq_128 :
+ def int_x86_avx512_mask_cvtpd2qq_128 :
GCCBuiltin<"__builtin_ia32_cvtpd2qq128_mask">,
Intrinsic<[llvm_v2i64_ty],
[llvm_v2f64_ty, llvm_v2i64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtpd2qq_256 :
+ def int_x86_avx512_mask_cvtpd2qq_256 :
GCCBuiltin<"__builtin_ia32_cvtpd2qq256_mask">,
Intrinsic<[llvm_v4i64_ty],
[llvm_v4f64_ty, llvm_v4i64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtpd2qq_512 :
+ def int_x86_avx512_mask_cvtpd2qq_512 :
GCCBuiltin<"__builtin_ia32_cvtpd2qq512_mask">,
Intrinsic<[llvm_v8i64_ty],
[llvm_v8f64_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtpd2udq_128 :
+ def int_x86_avx512_mask_cvtpd2udq_128 :
GCCBuiltin<"__builtin_ia32_cvtpd2udq128_mask">,
Intrinsic<[llvm_v4i32_ty],
[llvm_v2f64_ty, llvm_v4i32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtpd2udq_256 :
+ def int_x86_avx512_mask_cvtpd2udq_256 :
GCCBuiltin<"__builtin_ia32_cvtpd2udq256_mask">,
Intrinsic<[llvm_v4i32_ty],
[llvm_v4f64_ty, llvm_v4i32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtpd2udq_512 :
+ def int_x86_avx512_mask_cvtpd2udq_512 :
GCCBuiltin<"__builtin_ia32_cvtpd2udq512_mask">,
Intrinsic<[llvm_v8i32_ty],
[llvm_v8f64_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtpd2uqq_128 :
+ def int_x86_avx512_mask_cvtpd2uqq_128 :
GCCBuiltin<"__builtin_ia32_cvtpd2uqq128_mask">,
Intrinsic<[llvm_v2i64_ty],
[llvm_v2f64_ty, llvm_v2i64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtpd2uqq_256 :
+ def int_x86_avx512_mask_cvtpd2uqq_256 :
GCCBuiltin<"__builtin_ia32_cvtpd2uqq256_mask">,
Intrinsic<[llvm_v4i64_ty],
[llvm_v4f64_ty, llvm_v4i64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtpd2uqq_512 :
+ def int_x86_avx512_mask_cvtpd2uqq_512 :
GCCBuiltin<"__builtin_ia32_cvtpd2uqq512_mask">,
Intrinsic<[llvm_v8i64_ty],
[llvm_v8f64_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtps2dq_128 :
+ def int_x86_avx512_mask_cvtps2dq_128 :
GCCBuiltin<"__builtin_ia32_cvtps2dq128_mask">,
Intrinsic<[llvm_v4i32_ty],
[llvm_v4f32_ty, llvm_v4i32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtps2dq_256 :
+ def int_x86_avx512_mask_cvtps2dq_256 :
GCCBuiltin<"__builtin_ia32_cvtps2dq256_mask">,
Intrinsic<[llvm_v8i32_ty],
[llvm_v8f32_ty, llvm_v8i32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtps2dq_512 :
+ def int_x86_avx512_mask_cvtps2dq_512 :
GCCBuiltin<"__builtin_ia32_cvtps2dq512_mask">,
Intrinsic<[llvm_v16i32_ty],
[llvm_v16f32_ty, llvm_v16i32_ty, llvm_i16_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtps2pd_128 :
+ def int_x86_avx512_mask_cvtps2pd_128 :
GCCBuiltin<"__builtin_ia32_cvtps2pd128_mask">,
Intrinsic<[llvm_v2f64_ty],
[llvm_v4f32_ty, llvm_v2f64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtps2pd_256 :
+ def int_x86_avx512_mask_cvtps2pd_256 :
GCCBuiltin<"__builtin_ia32_cvtps2pd256_mask">,
Intrinsic<[llvm_v4f64_ty],
[llvm_v4f32_ty, llvm_v4f64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtps2pd_512 :
+ def int_x86_avx512_mask_cvtps2pd_512 :
GCCBuiltin<"__builtin_ia32_cvtps2pd512_mask">,
Intrinsic<[llvm_v8f64_ty],
[llvm_v8f32_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtps2qq_128 :
+ def int_x86_avx512_mask_cvtps2qq_128 :
GCCBuiltin<"__builtin_ia32_cvtps2qq128_mask">,
Intrinsic<[llvm_v2i64_ty],
[llvm_v4f32_ty, llvm_v2i64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtps2qq_256 :
+ def int_x86_avx512_mask_cvtps2qq_256 :
GCCBuiltin<"__builtin_ia32_cvtps2qq256_mask">,
Intrinsic<[llvm_v4i64_ty],
[llvm_v4f32_ty, llvm_v4i64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtps2qq_512 :
+ def int_x86_avx512_mask_cvtps2qq_512 :
GCCBuiltin<"__builtin_ia32_cvtps2qq512_mask">,
Intrinsic<[llvm_v8i64_ty],
[llvm_v8f32_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtps2udq_128 :
+ def int_x86_avx512_mask_cvtps2udq_128 :
GCCBuiltin<"__builtin_ia32_cvtps2udq128_mask">,
Intrinsic<[llvm_v4i32_ty],
[llvm_v4f32_ty, llvm_v4i32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtps2udq_256 :
+ def int_x86_avx512_mask_cvtps2udq_256 :
GCCBuiltin<"__builtin_ia32_cvtps2udq256_mask">,
Intrinsic<[llvm_v8i32_ty],
[llvm_v8f32_ty, llvm_v8i32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtps2udq_512 :
+ def int_x86_avx512_mask_cvtps2udq_512 :
GCCBuiltin<"__builtin_ia32_cvtps2udq512_mask">,
Intrinsic<[llvm_v16i32_ty],
[llvm_v16f32_ty, llvm_v16i32_ty, llvm_i16_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtps2uqq_128 :
+ def int_x86_avx512_mask_cvtps2uqq_128 :
GCCBuiltin<"__builtin_ia32_cvtps2uqq128_mask">,
Intrinsic<[llvm_v2i64_ty],
[llvm_v4f32_ty, llvm_v2i64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtps2uqq_256 :
+ def int_x86_avx512_mask_cvtps2uqq_256 :
GCCBuiltin<"__builtin_ia32_cvtps2uqq256_mask">,
Intrinsic<[llvm_v4i64_ty],
[llvm_v4f32_ty, llvm_v4i64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtps2uqq_512 :
+ def int_x86_avx512_mask_cvtps2uqq_512 :
GCCBuiltin<"__builtin_ia32_cvtps2uqq512_mask">,
Intrinsic<[llvm_v8i64_ty],
[llvm_v8f32_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtqq2pd_128 :
+ def int_x86_avx512_mask_cvtqq2pd_128 :
GCCBuiltin<"__builtin_ia32_cvtqq2pd128_mask">,
Intrinsic<[llvm_v2f64_ty],
[llvm_v2i64_ty, llvm_v2f64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtqq2pd_256 :
+ def int_x86_avx512_mask_cvtqq2pd_256 :
GCCBuiltin<"__builtin_ia32_cvtqq2pd256_mask">,
Intrinsic<[llvm_v4f64_ty],
[llvm_v4i64_ty, llvm_v4f64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtqq2pd_512 :
+ def int_x86_avx512_mask_cvtqq2pd_512 :
GCCBuiltin<"__builtin_ia32_cvtqq2pd512_mask">,
Intrinsic<[llvm_v8f64_ty],
[llvm_v8i64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtqq2ps_128 :
+ def int_x86_avx512_mask_cvtqq2ps_128 :
GCCBuiltin<"__builtin_ia32_cvtqq2ps128_mask">,
Intrinsic<[llvm_v4f32_ty],
[llvm_v2i64_ty, llvm_v4f32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtqq2ps_256 :
+ def int_x86_avx512_mask_cvtqq2ps_256 :
GCCBuiltin<"__builtin_ia32_cvtqq2ps256_mask">,
Intrinsic<[llvm_v4f32_ty],
[llvm_v4i64_ty, llvm_v4f32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtqq2ps_512 :
+ def int_x86_avx512_mask_cvtqq2ps_512 :
GCCBuiltin<"__builtin_ia32_cvtqq2ps512_mask">,
Intrinsic<[llvm_v8f32_ty],
[llvm_v8i64_ty, llvm_v8f32_ty, llvm_i8_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvttpd2dq_128 :
+ def int_x86_avx512_mask_cvttpd2dq_128 :
GCCBuiltin<"__builtin_ia32_cvttpd2dq128_mask">,
Intrinsic<[llvm_v4i32_ty],
[llvm_v2f64_ty, llvm_v4i32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvttpd2dq_256 :
+ def int_x86_avx512_mask_cvttpd2dq_256 :
GCCBuiltin<"__builtin_ia32_cvttpd2dq256_mask">,
Intrinsic<[llvm_v4i32_ty],
[llvm_v4f64_ty, llvm_v4i32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvttpd2dq_512 :
+ def int_x86_avx512_mask_cvttpd2dq_512 :
GCCBuiltin<"__builtin_ia32_cvttpd2dq512_mask">,
Intrinsic<[llvm_v8i32_ty],
[llvm_v8f64_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvttpd2qq_128 :
+ def int_x86_avx512_mask_cvttpd2qq_128 :
GCCBuiltin<"__builtin_ia32_cvttpd2qq128_mask">,
Intrinsic<[llvm_v2i64_ty],
[llvm_v2f64_ty, llvm_v2i64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvttpd2qq_256 :
+ def int_x86_avx512_mask_cvttpd2qq_256 :
GCCBuiltin<"__builtin_ia32_cvttpd2qq256_mask">,
Intrinsic<[llvm_v4i64_ty],
[llvm_v4f64_ty, llvm_v4i64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvttpd2qq_512 :
+ def int_x86_avx512_mask_cvttpd2qq_512 :
GCCBuiltin<"__builtin_ia32_cvttpd2qq512_mask">,
Intrinsic<[llvm_v8i64_ty],
[llvm_v8f64_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvttpd2udq_128 :
+ def int_x86_avx512_mask_cvttpd2udq_128 :
GCCBuiltin<"__builtin_ia32_cvttpd2udq128_mask">,
Intrinsic<[llvm_v4i32_ty],
[llvm_v2f64_ty, llvm_v4i32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvttpd2udq_256 :
+ def int_x86_avx512_mask_cvttpd2udq_256 :
GCCBuiltin<"__builtin_ia32_cvttpd2udq256_mask">,
Intrinsic<[llvm_v4i32_ty],
[llvm_v4f64_ty, llvm_v4i32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvttpd2udq_512 :
+ def int_x86_avx512_mask_cvttpd2udq_512 :
GCCBuiltin<"__builtin_ia32_cvttpd2udq512_mask">,
Intrinsic<[llvm_v8i32_ty],
[llvm_v8f64_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvttpd2uqq_128 :
+ def int_x86_avx512_mask_cvttpd2uqq_128 :
GCCBuiltin<"__builtin_ia32_cvttpd2uqq128_mask">,
Intrinsic<[llvm_v2i64_ty],
[llvm_v2f64_ty, llvm_v2i64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvttpd2uqq_256 :
+ def int_x86_avx512_mask_cvttpd2uqq_256 :
GCCBuiltin<"__builtin_ia32_cvttpd2uqq256_mask">,
Intrinsic<[llvm_v4i64_ty],
[llvm_v4f64_ty, llvm_v4i64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvttpd2uqq_512 :
+ def int_x86_avx512_mask_cvttpd2uqq_512 :
GCCBuiltin<"__builtin_ia32_cvttpd2uqq512_mask">,
Intrinsic<[llvm_v8i64_ty],
[llvm_v8f64_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvttps2dq_128 :
+ def int_x86_avx512_mask_cvttps2dq_128 :
GCCBuiltin<"__builtin_ia32_cvttps2dq128_mask">,
Intrinsic<[llvm_v4i32_ty],
[llvm_v4f32_ty, llvm_v4i32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvttps2dq_256 :
+ def int_x86_avx512_mask_cvttps2dq_256 :
GCCBuiltin<"__builtin_ia32_cvttps2dq256_mask">,
Intrinsic<[llvm_v8i32_ty],
[llvm_v8f32_ty, llvm_v8i32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvttps2dq_512 :
+ def int_x86_avx512_mask_cvttps2dq_512 :
GCCBuiltin<"__builtin_ia32_cvttps2dq512_mask">,
Intrinsic<[llvm_v16i32_ty],
[llvm_v16f32_ty, llvm_v16i32_ty, llvm_i16_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvttps2qq_128 :
+ def int_x86_avx512_mask_cvttps2qq_128 :
GCCBuiltin<"__builtin_ia32_cvttps2qq128_mask">,
Intrinsic<[llvm_v2i64_ty],
[llvm_v4f32_ty, llvm_v2i64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvttps2qq_256 :
+ def int_x86_avx512_mask_cvttps2qq_256 :
GCCBuiltin<"__builtin_ia32_cvttps2qq256_mask">,
Intrinsic<[llvm_v4i64_ty],
[llvm_v4f32_ty, llvm_v4i64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvttps2qq_512 :
+ def int_x86_avx512_mask_cvttps2qq_512 :
GCCBuiltin<"__builtin_ia32_cvttps2qq512_mask">,
Intrinsic<[llvm_v8i64_ty],
[llvm_v8f32_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvttps2udq_128 :
+ def int_x86_avx512_mask_cvttps2udq_128 :
GCCBuiltin<"__builtin_ia32_cvttps2udq128_mask">,
Intrinsic<[llvm_v4i32_ty],
[llvm_v4f32_ty, llvm_v4i32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvttps2udq_256 :
+ def int_x86_avx512_mask_cvttps2udq_256 :
GCCBuiltin<"__builtin_ia32_cvttps2udq256_mask">,
Intrinsic<[llvm_v8i32_ty],
[llvm_v8f32_ty, llvm_v8i32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvttps2udq_512 :
+ def int_x86_avx512_mask_cvttps2udq_512 :
GCCBuiltin<"__builtin_ia32_cvttps2udq512_mask">,
Intrinsic<[llvm_v16i32_ty],
[llvm_v16f32_ty, llvm_v16i32_ty, llvm_i16_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvttps2uqq_128 :
+ def int_x86_avx512_mask_cvttps2uqq_128 :
GCCBuiltin<"__builtin_ia32_cvttps2uqq128_mask">,
Intrinsic<[llvm_v2i64_ty],
[llvm_v4f32_ty, llvm_v2i64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvttps2uqq_256 :
+ def int_x86_avx512_mask_cvttps2uqq_256 :
GCCBuiltin<"__builtin_ia32_cvttps2uqq256_mask">,
Intrinsic<[llvm_v4i64_ty],
[llvm_v4f32_ty, llvm_v4i64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvttps2uqq_512 :
+ def int_x86_avx512_mask_cvttps2uqq_512 :
GCCBuiltin<"__builtin_ia32_cvttps2uqq512_mask">,
Intrinsic<[llvm_v8i64_ty],
[llvm_v8f32_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtudq2pd_128 :
+ def int_x86_avx512_mask_cvtudq2pd_128 :
GCCBuiltin<"__builtin_ia32_cvtudq2pd128_mask">,
Intrinsic<[llvm_v2f64_ty],
[llvm_v4i32_ty, llvm_v2f64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtudq2pd_256 :
+ def int_x86_avx512_mask_cvtudq2pd_256 :
GCCBuiltin<"__builtin_ia32_cvtudq2pd256_mask">,
Intrinsic<[llvm_v4f64_ty],
[llvm_v4i32_ty, llvm_v4f64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtudq2pd_512 :
+ def int_x86_avx512_mask_cvtudq2pd_512 :
GCCBuiltin<"__builtin_ia32_cvtudq2pd512_mask">,
Intrinsic<[llvm_v8f64_ty],
[llvm_v8i32_ty, llvm_v8f64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtudq2ps_128 :
+ def int_x86_avx512_mask_cvtudq2ps_128 :
GCCBuiltin<"__builtin_ia32_cvtudq2ps128_mask">,
Intrinsic<[llvm_v4f32_ty],
[llvm_v4i32_ty, llvm_v4f32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtudq2ps_256 :
+ def int_x86_avx512_mask_cvtudq2ps_256 :
GCCBuiltin<"__builtin_ia32_cvtudq2ps256_mask">,
Intrinsic<[llvm_v8f32_ty],
[llvm_v8i32_ty, llvm_v8f32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtudq2ps_512 :
+ def int_x86_avx512_mask_cvtudq2ps_512 :
GCCBuiltin<"__builtin_ia32_cvtudq2ps512_mask">,
Intrinsic<[llvm_v16f32_ty],
[llvm_v16i32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtuqq2pd_128 :
+ def int_x86_avx512_mask_cvtuqq2pd_128 :
GCCBuiltin<"__builtin_ia32_cvtuqq2pd128_mask">,
Intrinsic<[llvm_v2f64_ty],
[llvm_v2i64_ty, llvm_v2f64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtuqq2pd_256 :
+ def int_x86_avx512_mask_cvtuqq2pd_256 :
GCCBuiltin<"__builtin_ia32_cvtuqq2pd256_mask">,
Intrinsic<[llvm_v4f64_ty],
[llvm_v4i64_ty, llvm_v4f64_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtuqq2pd_512 :
+ def int_x86_avx512_mask_cvtuqq2pd_512 :
GCCBuiltin<"__builtin_ia32_cvtuqq2pd512_mask">,
Intrinsic<[llvm_v8f64_ty],
[llvm_v8i64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtuqq2ps_128 :
+ def int_x86_avx512_mask_cvtuqq2ps_128 :
GCCBuiltin<"__builtin_ia32_cvtuqq2ps128_mask">,
Intrinsic<[llvm_v4f32_ty],
[llvm_v2i64_ty, llvm_v4f32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtuqq2ps_256 :
+ def int_x86_avx512_mask_cvtuqq2ps_256 :
GCCBuiltin<"__builtin_ia32_cvtuqq2ps256_mask">,
Intrinsic<[llvm_v4f32_ty],
[llvm_v4i64_ty, llvm_v4f32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtuqq2ps_512 :
+ def int_x86_avx512_mask_cvtuqq2ps_512 :
GCCBuiltin<"__builtin_ia32_cvtuqq2ps512_mask">,
Intrinsic<[llvm_v8f32_ty],
[llvm_v8i64_ty, llvm_v8f32_ty, llvm_i8_ty, llvm_i32_ty],
@@ -5358,7 +4988,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_i32_ty,
llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_rndscale_pd_256 : GCCBuiltin<"__builtin_ia32_rndscalepd_256_mask">,
- Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_i32_ty,
+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_i32_ty,
llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_rndscale_pd_512 : GCCBuiltin<"__builtin_ia32_rndscalepd_mask">,
Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_i32_ty, llvm_v8f64_ty,
@@ -5367,13 +4997,13 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_i32_ty,
llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_rndscale_ps_256 : GCCBuiltin<"__builtin_ia32_rndscaleps_256_mask">,
- Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_i32_ty,
+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_i32_ty,
llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_rndscale_ps_512 : GCCBuiltin<"__builtin_ia32_rndscaleps_mask">,
Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_i32_ty, llvm_v16f32_ty,
llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_reduce_pd_128 : GCCBuiltin<"__builtin_ia32_reducepd128_mask">,
- Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_i32_ty,
+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_i32_ty,
llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_reduce_pd_256 : GCCBuiltin<"__builtin_ia32_reducepd256_mask">,
Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_i32_ty,
@@ -5382,7 +5012,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_i32_ty, llvm_v8f64_ty,
llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_reduce_ps_128 : GCCBuiltin<"__builtin_ia32_reduceps128_mask">,
- Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_i32_ty,
+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_i32_ty,
llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_reduce_ps_256 : GCCBuiltin<"__builtin_ia32_reduceps256_mask">,
Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_i32_ty,
@@ -5391,7 +5021,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_i32_ty, llvm_v16f32_ty,
llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_range_pd_128 : GCCBuiltin<"__builtin_ia32_rangepd128_mask">,
- Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i32_ty,
+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i32_ty,
llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_range_pd_256 : GCCBuiltin<"__builtin_ia32_rangepd256_mask">,
Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_i32_ty,
@@ -5403,7 +5033,7 @@ def int_x86_avx512_mask_range_ps_128 : GCCBuiltin<"__builtin_ia32_rangeps128_mas
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i32_ty,
llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_range_ps_256 : GCCBuiltin<"__builtin_ia32_rangeps256_mask">,
- Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, llvm_i32_ty,
+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, llvm_i32_ty,
llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_range_ps_512 : GCCBuiltin<"__builtin_ia32_rangeps512_mask">,
Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_i32_ty,
@@ -5414,75 +5044,11 @@ def int_x86_avx512_mask_range_ps_512 : GCCBuiltin<"__builtin_ia32_rangeps512_mas
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx512_vbroadcast_ss_512 :
GCCBuiltin<"__builtin_ia32_vbroadcastss512">,
- Intrinsic<[llvm_v16f32_ty], [llvm_ptr_ty], [IntrReadArgMem]>;
- def int_x86_avx512_mask_broadcast_ss_ps_512 :
- GCCBuiltin<"__builtin_ia32_broadcastss512">,
- Intrinsic<[llvm_v16f32_ty], [llvm_v4f32_ty, llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_broadcast_ss_ps_256 :
- GCCBuiltin<"__builtin_ia32_broadcastss256_mask">,
- Intrinsic<[llvm_v8f32_ty], [llvm_v4f32_ty, llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_broadcast_ss_ps_128 :
- GCCBuiltin<"__builtin_ia32_broadcastss128_mask">,
- Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>;
+ Intrinsic<[llvm_v16f32_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx512_vbroadcast_sd_512 :
GCCBuiltin<"__builtin_ia32_vbroadcastsd512">,
- Intrinsic<[llvm_v8f64_ty], [llvm_ptr_ty], [IntrReadArgMem]>;
- def int_x86_avx512_mask_broadcast_sd_pd_512 :
- GCCBuiltin<"__builtin_ia32_broadcastsd512">,
- Intrinsic<[llvm_v8f64_ty], [llvm_v2f64_ty, llvm_v8f64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_broadcast_sd_pd_256 :
- GCCBuiltin<"__builtin_ia32_broadcastsd256_mask">,
- Intrinsic<[llvm_v4f64_ty], [llvm_v2f64_ty, llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>;
-
- def int_x86_avx512_pbroadcastb_128 :
- GCCBuiltin<"__builtin_ia32_pbroadcastb128_mask">,
- Intrinsic<[llvm_v16i8_ty],
- [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_pbroadcastb_256 :
- GCCBuiltin<"__builtin_ia32_pbroadcastb256_mask">,
- Intrinsic<[llvm_v32i8_ty],
- [llvm_v16i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_pbroadcastb_512 :
- GCCBuiltin<"__builtin_ia32_pbroadcastb512_mask">,
- Intrinsic<[llvm_v64i8_ty],
- [llvm_v16i8_ty, llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>;
- def int_x86_avx512_pbroadcastw_128 :
- GCCBuiltin<"__builtin_ia32_pbroadcastw128_mask">,
- Intrinsic<[llvm_v8i16_ty],
- [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_pbroadcastw_256 :
- GCCBuiltin<"__builtin_ia32_pbroadcastw256_mask">,
- Intrinsic<[llvm_v16i16_ty],
- [llvm_v8i16_ty, llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_pbroadcastw_512 :
- GCCBuiltin<"__builtin_ia32_pbroadcastw512_mask">,
- Intrinsic<[llvm_v32i16_ty],
- [llvm_v8i16_ty, llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_pbroadcastd_128 :
- GCCBuiltin<"__builtin_ia32_pbroadcastd128_mask">,
- Intrinsic<[llvm_v4i32_ty],
- [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_pbroadcastd_256 :
- GCCBuiltin<"__builtin_ia32_pbroadcastd256_mask">,
- Intrinsic<[llvm_v8i32_ty],
- [llvm_v4i32_ty, llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_pbroadcastd_512 :
- GCCBuiltin<"__builtin_ia32_pbroadcastd512">,
- Intrinsic<[llvm_v16i32_ty],
- [llvm_v4i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_pbroadcastq_128 :
- GCCBuiltin<"__builtin_ia32_pbroadcastq128_mask">,
- Intrinsic<[llvm_v2i64_ty],
- [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_pbroadcastq_256 :
- GCCBuiltin<"__builtin_ia32_pbroadcastq256_mask">,
- Intrinsic<[llvm_v4i64_ty],
- [llvm_v2i64_ty, llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_pbroadcastq_512 :
- GCCBuiltin<"__builtin_ia32_pbroadcastq512">,
- Intrinsic<[llvm_v8i64_ty],
- [llvm_v2i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ Intrinsic<[llvm_v8f64_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx512_mask_broadcastf32x2_256 :
GCCBuiltin<"__builtin_ia32_broadcastf32x2_256_mask">,
@@ -5569,11 +5135,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v8i64_ty],
[llvm_v4i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_pbroadcastd_i32_512 :
- Intrinsic<[llvm_v16i32_ty], [llvm_i32_ty], [IntrNoMem]>;
-
- def int_x86_avx512_pbroadcastq_i64_512 :
- Intrinsic<[llvm_v8i64_ty], [llvm_i64_ty], [IntrNoMem]>;
def int_x86_avx512_broadcastmw_512 :
GCCBuiltin<"__builtin_ia32_broadcastmw512">,
Intrinsic<[llvm_v16i32_ty], [llvm_i16_ty], [IntrNoMem]>;
@@ -5668,81 +5229,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
}
-//Bitwise Ops
-let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_avx512_mask_pand_d_128 : GCCBuiltin<"__builtin_ia32_pandd128_mask">,
- Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
- llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pand_d_256 : GCCBuiltin<"__builtin_ia32_pandd256_mask">,
- Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty,
- llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pand_d_512 : GCCBuiltin<"__builtin_ia32_pandd512_mask">,
- Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
- llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pand_q_128 : GCCBuiltin<"__builtin_ia32_pandq128_mask">,
- Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty,
- llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pand_q_256 : GCCBuiltin<"__builtin_ia32_pandq256_mask">,
- Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty,
- llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pand_q_512 : GCCBuiltin<"__builtin_ia32_pandq512_mask">,
- Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty,
- llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pandn_d_128 : GCCBuiltin<"__builtin_ia32_pandnd128_mask">,
- Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
- llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pandn_d_256 : GCCBuiltin<"__builtin_ia32_pandnd256_mask">,
- Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty,
- llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pandn_d_512 : GCCBuiltin<"__builtin_ia32_pandnd512_mask">,
- Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
- llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pandn_q_128 : GCCBuiltin<"__builtin_ia32_pandnq128_mask">,
- Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty,
- llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pandn_q_256 : GCCBuiltin<"__builtin_ia32_pandnq256_mask">,
- Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty,
- llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pandn_q_512 : GCCBuiltin<"__builtin_ia32_pandnq512_mask">,
- Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty,
- llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_por_d_128 : GCCBuiltin<"__builtin_ia32_pord128_mask">,
- Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
- llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_por_d_256 : GCCBuiltin<"__builtin_ia32_pord256_mask">,
- Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty,
- llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_por_d_512 : GCCBuiltin<"__builtin_ia32_pord512_mask">,
- Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
- llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_por_q_128 : GCCBuiltin<"__builtin_ia32_porq128_mask">,
- Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty,
- llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_por_q_256 : GCCBuiltin<"__builtin_ia32_porq256_mask">,
- Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty,
- llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_por_q_512 : GCCBuiltin<"__builtin_ia32_porq512_mask">,
- Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty,
- llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pxor_d_128 : GCCBuiltin<"__builtin_ia32_pxord128_mask">,
- Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
- llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pxor_d_256 : GCCBuiltin<"__builtin_ia32_pxord256_mask">,
- Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty,
- llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pxor_d_512 : GCCBuiltin<"__builtin_ia32_pxord512_mask">,
- Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
- llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pxor_q_128 : GCCBuiltin<"__builtin_ia32_pxorq128_mask">,
- Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty,
- llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pxor_q_256 : GCCBuiltin<"__builtin_ia32_pxorq256_mask">,
- Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty,
- llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pxor_q_512 : GCCBuiltin<"__builtin_ia32_pxorq512_mask">,
- Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty,
- llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
-}
+
// Arithmetic ops
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
@@ -5855,96 +5342,96 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_add_ss_round : GCCBuiltin<"__builtin_ia32_addss_round">,
+ def int_x86_avx512_mask_add_ss_round : GCCBuiltin<"__builtin_ia32_addss_round_mask">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_div_ss_round : GCCBuiltin<"__builtin_ia32_divss_round">,
+ def int_x86_avx512_mask_div_ss_round : GCCBuiltin<"__builtin_ia32_divss_round_mask">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_mul_ss_round : GCCBuiltin<"__builtin_ia32_mulss_round">,
+ def int_x86_avx512_mask_mul_ss_round : GCCBuiltin<"__builtin_ia32_mulss_round_mask">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_sub_ss_round : GCCBuiltin<"__builtin_ia32_subss_round">,
+ def int_x86_avx512_mask_sub_ss_round : GCCBuiltin<"__builtin_ia32_subss_round_mask">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_max_ss_round : GCCBuiltin<"__builtin_ia32_maxss_round">,
+ def int_x86_avx512_mask_max_ss_round : GCCBuiltin<"__builtin_ia32_maxss_round_mask">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_min_ss_round : GCCBuiltin<"__builtin_ia32_minss_round">,
+ def int_x86_avx512_mask_min_ss_round : GCCBuiltin<"__builtin_ia32_minss_round_mask">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_add_sd_round : GCCBuiltin<"__builtin_ia32_addsd_round">,
+ def int_x86_avx512_mask_add_sd_round : GCCBuiltin<"__builtin_ia32_addsd_round_mask">,
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_div_sd_round : GCCBuiltin<"__builtin_ia32_divsd_round">,
+ def int_x86_avx512_mask_div_sd_round : GCCBuiltin<"__builtin_ia32_divsd_round_mask">,
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_mul_sd_round : GCCBuiltin<"__builtin_ia32_mulsd_round">,
+ def int_x86_avx512_mask_mul_sd_round : GCCBuiltin<"__builtin_ia32_mulsd_round_mask">,
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_sub_sd_round : GCCBuiltin<"__builtin_ia32_subsd_round">,
+ def int_x86_avx512_mask_sub_sd_round : GCCBuiltin<"__builtin_ia32_subsd_round_mask">,
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_max_sd_round : GCCBuiltin<"__builtin_ia32_maxsd_round">,
+ def int_x86_avx512_mask_max_sd_round : GCCBuiltin<"__builtin_ia32_maxsd_round_mask">,
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_min_sd_round : GCCBuiltin<"__builtin_ia32_minsd_round">,
+ def int_x86_avx512_mask_min_sd_round : GCCBuiltin<"__builtin_ia32_minsd_round_mask">,
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_rndscale_ss : GCCBuiltin<"__builtin_ia32_rndscaless_round">,
+ def int_x86_avx512_mask_rndscale_ss : GCCBuiltin<"__builtin_ia32_rndscaless_round_mask">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty,
llvm_i8_ty, llvm_i32_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_rndscale_sd : GCCBuiltin<"__builtin_ia32_rndscalesd_round">,
+ def int_x86_avx512_mask_rndscale_sd : GCCBuiltin<"__builtin_ia32_rndscalesd_round_mask">,
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty,
llvm_i8_ty, llvm_i32_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_range_ss : GCCBuiltin<"__builtin_ia32_rangess128_round">,
+ def int_x86_avx512_mask_range_ss : GCCBuiltin<"__builtin_ia32_rangess128_round_mask">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty,
llvm_i8_ty, llvm_i32_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_range_sd : GCCBuiltin<"__builtin_ia32_rangesd128_round">,
+ def int_x86_avx512_mask_range_sd : GCCBuiltin<"__builtin_ia32_rangesd128_round_mask">,
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty,
llvm_i8_ty, llvm_i32_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_reduce_ss : GCCBuiltin<"__builtin_ia32_reducess">,
+ def int_x86_avx512_mask_reduce_ss : GCCBuiltin<"__builtin_ia32_reducess_mask">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty,
llvm_i8_ty, llvm_i32_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_reduce_sd : GCCBuiltin<"__builtin_ia32_reducesd">,
+ def int_x86_avx512_mask_reduce_sd : GCCBuiltin<"__builtin_ia32_reducesd_mask">,
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty,
llvm_i8_ty, llvm_i32_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_scalef_sd : GCCBuiltin<"__builtin_ia32_scalefsd_round">,
- Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
+ def int_x86_avx512_mask_scalef_sd : GCCBuiltin<"__builtin_ia32_scalefsd_round_mask">,
+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_scalef_ss : GCCBuiltin<"__builtin_ia32_scalefss_round">,
- Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
+ def int_x86_avx512_mask_scalef_ss : GCCBuiltin<"__builtin_ia32_scalefss_round_mask">,
+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_scalef_pd_128 : GCCBuiltin<"__builtin_ia32_scalefpd128_mask">,
- Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_scalef_pd_256 : GCCBuiltin<"__builtin_ia32_scalefpd256_mask">,
- Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty,
+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty,
llvm_v4f64_ty, llvm_i8_ty],[IntrNoMem]>;
def int_x86_avx512_mask_scalef_pd_512 : GCCBuiltin<"__builtin_ia32_scalefpd512_mask">,
- Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
+ Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_scalef_ps_128 : GCCBuiltin<"__builtin_ia32_scalefps128_mask">,
- Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_scalef_ps_256 : GCCBuiltin<"__builtin_ia32_scalefps256_mask">,
- Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty,
+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty,
llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_scalef_ps_512 : GCCBuiltin<"__builtin_ia32_scalefps512_mask">,
- Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty,
+ Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty,
llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_sqrt_ss : GCCBuiltin<"__builtin_ia32_sqrtss_round">,
+ def int_x86_avx512_mask_sqrt_ss : GCCBuiltin<"__builtin_ia32_sqrtss_round_mask">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty,
llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_sqrt_sd : GCCBuiltin<"__builtin_ia32_sqrtsd_round">,
+ def int_x86_avx512_mask_sqrt_sd : GCCBuiltin<"__builtin_ia32_sqrtsd_round_mask">,
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty,
llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
@@ -5966,6 +5453,86 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx512_mask_sqrt_ps_512 : GCCBuiltin<"__builtin_ia32_sqrtps512_mask">,
Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty,
llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_fixupimm_pd_128 :
+ GCCBuiltin<"__builtin_ia32_fixupimmpd128_mask">,
+ Intrinsic<[llvm_v2f64_ty],
+ [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2i64_ty, llvm_i32_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_maskz_fixupimm_pd_128 :
+ GCCBuiltin<"__builtin_ia32_fixupimmpd128_maskz">,
+ Intrinsic<[llvm_v2f64_ty],
+ [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2i64_ty, llvm_i32_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_fixupimm_pd_256 :
+ GCCBuiltin<"__builtin_ia32_fixupimmpd256_mask">,
+ Intrinsic<[llvm_v4f64_ty],
+ [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4i64_ty, llvm_i32_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_maskz_fixupimm_pd_256 :
+ GCCBuiltin<"__builtin_ia32_fixupimmpd256_maskz">,
+ Intrinsic<[llvm_v4f64_ty],
+ [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4i64_ty, llvm_i32_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_fixupimm_pd_512 :
+ GCCBuiltin<"__builtin_ia32_fixupimmpd512_mask">,
+ Intrinsic<[llvm_v8f64_ty],
+ [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8i64_ty, llvm_i32_ty, llvm_i8_ty,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_maskz_fixupimm_pd_512 :
+ GCCBuiltin<"__builtin_ia32_fixupimmpd512_maskz">,
+ Intrinsic<[llvm_v8f64_ty],
+ [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8i64_ty, llvm_i32_ty, llvm_i8_ty,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_fixupimm_ps_128 :
+ GCCBuiltin<"__builtin_ia32_fixupimmps128_mask">,
+ Intrinsic<[llvm_v4f32_ty],
+ [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4i32_ty, llvm_i32_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_maskz_fixupimm_ps_128 :
+ GCCBuiltin<"__builtin_ia32_fixupimmps128_maskz">,
+ Intrinsic<[llvm_v4f32_ty],
+ [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4i32_ty, llvm_i32_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_fixupimm_ps_256 :
+ GCCBuiltin<"__builtin_ia32_fixupimmps256_mask">,
+ Intrinsic<[llvm_v8f32_ty],
+ [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8i32_ty, llvm_i32_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_maskz_fixupimm_ps_256 :
+ GCCBuiltin<"__builtin_ia32_fixupimmps256_maskz">,
+ Intrinsic<[llvm_v8f32_ty],
+ [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8i32_ty, llvm_i32_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_fixupimm_ps_512 :
+ GCCBuiltin<"__builtin_ia32_fixupimmps512_mask">,
+ Intrinsic<[llvm_v16f32_ty],
+ [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16i32_ty, llvm_i32_ty,
+ llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_maskz_fixupimm_ps_512 :
+ GCCBuiltin<"__builtin_ia32_fixupimmps512_maskz">,
+ Intrinsic<[llvm_v16f32_ty],
+ [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16i32_ty, llvm_i32_ty,
+ llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_fixupimm_sd :
+ GCCBuiltin<"__builtin_ia32_fixupimmsd_mask">,
+ Intrinsic<[llvm_v2f64_ty],
+ [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2i64_ty, llvm_i32_ty, llvm_i8_ty,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_maskz_fixupimm_sd :
+ GCCBuiltin<"__builtin_ia32_fixupimmsd_maskz">,
+ Intrinsic<[llvm_v2f64_ty],
+ [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2i64_ty, llvm_i32_ty, llvm_i8_ty,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_fixupimm_ss :
+ GCCBuiltin<"__builtin_ia32_fixupimmss_mask">,
+ Intrinsic<[llvm_v4f32_ty],
+ [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4i32_ty, llvm_i32_ty, llvm_i8_ty,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_maskz_fixupimm_ss :
+ GCCBuiltin<"__builtin_ia32_fixupimmss_maskz">,
+ Intrinsic<[llvm_v4f32_ty],
+ [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4i32_ty, llvm_i32_ty, llvm_i8_ty,
+ llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_getexp_pd_128 : GCCBuiltin<"__builtin_ia32_getexppd128_mask">,
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
llvm_i8_ty], [IntrNoMem]>;
@@ -5985,10 +5552,10 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty,
llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_getexp_ss : GCCBuiltin<"__builtin_ia32_getexpss_mask">,
+ def int_x86_avx512_mask_getexp_ss : GCCBuiltin<"__builtin_ia32_getexpss128_round_mask">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty,
llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_getexp_sd : GCCBuiltin<"__builtin_ia32_getexpsd_mask">,
+ def int_x86_avx512_mask_getexp_sd : GCCBuiltin<"__builtin_ia32_getexpsd128_round_mask">,
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty,
llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
@@ -6029,21 +5596,21 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
[IntrNoMem]>;
def int_x86_avx512_mask_getmant_ss :
- GCCBuiltin<"__builtin_ia32_getmantss_round">,
+ GCCBuiltin<"__builtin_ia32_getmantss_round_mask">,
Intrinsic<[llvm_v4f32_ty],
[llvm_v4f32_ty, llvm_v4f32_ty, llvm_i32_ty, llvm_v4f32_ty,
llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_getmant_sd :
- GCCBuiltin<"__builtin_ia32_getmantsd_round">,
+ GCCBuiltin<"__builtin_ia32_getmantsd_round_mask">,
Intrinsic<[llvm_v2f64_ty],
[llvm_v2f64_ty, llvm_v2f64_ty, llvm_i32_ty, llvm_v2f64_ty,
llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_rsqrt14_ss : GCCBuiltin<"__builtin_ia32_rsqrt14ss">,
+ def int_x86_avx512_rsqrt14_ss : GCCBuiltin<"__builtin_ia32_rsqrt14ss_mask">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty,
llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_rsqrt14_sd : GCCBuiltin<"__builtin_ia32_rsqrt14sd">,
+ def int_x86_avx512_rsqrt14_sd : GCCBuiltin<"__builtin_ia32_rsqrt14sd_mask">,
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty,
llvm_i8_ty], [IntrNoMem]>;
@@ -6065,10 +5632,10 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx512_rsqrt14_ps_512 : GCCBuiltin<"__builtin_ia32_rsqrt14ps512_mask">,
Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty,
llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_rcp14_ss : GCCBuiltin<"__builtin_ia32_rcp14ss">,
+ def int_x86_avx512_rcp14_ss : GCCBuiltin<"__builtin_ia32_rcp14ss_mask">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty,
llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_rcp14_sd : GCCBuiltin<"__builtin_ia32_rcp14sd">,
+ def int_x86_avx512_rcp14_sd : GCCBuiltin<"__builtin_ia32_rcp14sd_mask">,
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty,
llvm_i8_ty], [IntrNoMem]>;
@@ -6104,11 +5671,11 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_rcp28_ss : GCCBuiltin<"__builtin_ia32_rcp28ss_round">,
+ def int_x86_avx512_rcp28_ss : GCCBuiltin<"__builtin_ia32_rcp28ss_round_mask">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_rcp28_sd : GCCBuiltin<"__builtin_ia32_rcp28sd_round">,
+ def int_x86_avx512_rcp28_sd : GCCBuiltin<"__builtin_ia32_rcp28sd_round_mask">,
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty],
[IntrNoMem]>;
@@ -6120,11 +5687,11 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
llvm_i8_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_rsqrt28_ss : GCCBuiltin<"__builtin_ia32_rsqrt28ss_round">,
+ def int_x86_avx512_rsqrt28_ss : GCCBuiltin<"__builtin_ia32_rsqrt28ss_round_mask">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_rsqrt28_sd : GCCBuiltin<"__builtin_ia32_rsqrt28sd_round">,
+ def int_x86_avx512_rsqrt28_sd : GCCBuiltin<"__builtin_ia32_rsqrt28sd_round_mask">,
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty],
[IntrNoMem]>;
@@ -6188,7 +5755,7 @@ let TargetPrefix = "x86" in {
def int_x86_avx512_mask_or_ps_512 : GCCBuiltin<"__builtin_ia32_orps512_mask">,
Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty,
llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>;
-
+
def int_x86_avx512_mask_xor_pd_128 : GCCBuiltin<"__builtin_ia32_xorpd128_mask">,
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>;
@@ -6206,7 +5773,7 @@ let TargetPrefix = "x86" in {
llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_xor_ps_512 : GCCBuiltin<"__builtin_ia32_xorps512_mask">,
Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty,
- llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>;
+ llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>;
}
// Integer arithmetic ops
let TargetPrefix = "x86" in {
@@ -6406,34 +5973,34 @@ let TargetPrefix = "x86" in {
Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty,
llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pmulhu_w_128 : GCCBuiltin<"__builtin_ia32_pmulhuw128_mask">,
- Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pmulhu_w_256 : GCCBuiltin<"__builtin_ia32_pmulhuw256_mask">,
- Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pmulh_w_128 : GCCBuiltin<"__builtin_ia32_pmulhw128_mask">,
- Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pmulh_w_256 : GCCBuiltin<"__builtin_ia32_pmulhw256_mask">,
- Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pavg_b_512 : GCCBuiltin<"__builtin_ia32_pavgb512_mask">,
- Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty,
+ Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty,
llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pavg_w_512 : GCCBuiltin<"__builtin_ia32_pavgw512_mask">,
- Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty,
+ Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty,
llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pavg_b_128 : GCCBuiltin<"__builtin_ia32_pavgb128_mask">,
- Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,
+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,
llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pavg_b_256 : GCCBuiltin<"__builtin_ia32_pavgb256_mask">,
- Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty,
+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty,
llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pavg_w_128 : GCCBuiltin<"__builtin_ia32_pavgw128_mask">,
- Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pavg_w_256 : GCCBuiltin<"__builtin_ia32_pavgw256_mask">,
- Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
def int_x86_avx512_mask_pmaddw_d_128 :
GCCBuiltin<"__builtin_ia32_pmaddwd128_mask">,
@@ -6490,293 +6057,293 @@ let TargetPrefix = "x86" in {
def int_x86_avx512_gather_dpd_512 : GCCBuiltin<"__builtin_ia32_gathersiv8df">,
Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_ptr_ty,
llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx512_gather_dps_512 : GCCBuiltin<"__builtin_ia32_gathersiv16sf">,
Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_ptr_ty,
llvm_v16i32_ty, llvm_i16_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx512_gather_qpd_512 : GCCBuiltin<"__builtin_ia32_gatherdiv8df">,
Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_ptr_ty,
llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx512_gather_qps_512 : GCCBuiltin<"__builtin_ia32_gatherdiv16sf">,
Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_ptr_ty,
llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx512_gather_dpq_512 : GCCBuiltin<"__builtin_ia32_gathersiv8di">,
Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_ptr_ty,
llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx512_gather_dpi_512 : GCCBuiltin<"__builtin_ia32_gathersiv16si">,
Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_ptr_ty,
llvm_v16i32_ty, llvm_i16_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx512_gather_qpq_512 : GCCBuiltin<"__builtin_ia32_gatherdiv8di">,
Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_ptr_ty,
llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx512_gather_qpi_512 : GCCBuiltin<"__builtin_ia32_gatherdiv16si">,
Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_ptr_ty,
llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
- def int_x86_avx512_gather3div2_df :
+ def int_x86_avx512_gather3div2_df :
GCCBuiltin<"__builtin_ia32_gather3div2df">,
Intrinsic<[llvm_v2f64_ty],
[llvm_v2f64_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
- def int_x86_avx512_gather3div2_di :
+ def int_x86_avx512_gather3div2_di :
GCCBuiltin<"__builtin_ia32_gather3div2di">,
Intrinsic<[llvm_v4i32_ty],
[llvm_v2i64_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
- def int_x86_avx512_gather3div4_df :
+ def int_x86_avx512_gather3div4_df :
GCCBuiltin<"__builtin_ia32_gather3div4df">,
Intrinsic<[llvm_v4f64_ty],
[llvm_v4f64_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
- def int_x86_avx512_gather3div4_di :
+ def int_x86_avx512_gather3div4_di :
GCCBuiltin<"__builtin_ia32_gather3div4di">,
Intrinsic<[llvm_v8i32_ty],
[llvm_v4i64_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
- def int_x86_avx512_gather3div4_sf :
+ def int_x86_avx512_gather3div4_sf :
GCCBuiltin<"__builtin_ia32_gather3div4sf">,
Intrinsic<[llvm_v4f32_ty],
[llvm_v4f32_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
- def int_x86_avx512_gather3div4_si :
+ def int_x86_avx512_gather3div4_si :
GCCBuiltin<"__builtin_ia32_gather3div4si">,
Intrinsic<[llvm_v4i32_ty],
[llvm_v4i32_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
- def int_x86_avx512_gather3div8_sf :
+ def int_x86_avx512_gather3div8_sf :
GCCBuiltin<"__builtin_ia32_gather3div8sf">,
Intrinsic<[llvm_v4f32_ty],
[llvm_v4f32_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
- def int_x86_avx512_gather3div8_si :
+ def int_x86_avx512_gather3div8_si :
GCCBuiltin<"__builtin_ia32_gather3div8si">,
Intrinsic<[llvm_v4i32_ty],
[llvm_v4i32_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
- def int_x86_avx512_gather3siv2_df :
+ def int_x86_avx512_gather3siv2_df :
GCCBuiltin<"__builtin_ia32_gather3siv2df">,
Intrinsic<[llvm_v2f64_ty],
[llvm_v2f64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
- def int_x86_avx512_gather3siv2_di :
+ def int_x86_avx512_gather3siv2_di :
GCCBuiltin<"__builtin_ia32_gather3siv2di">,
Intrinsic<[llvm_v4i32_ty],
[llvm_v2i64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
- def int_x86_avx512_gather3siv4_df :
+ def int_x86_avx512_gather3siv4_df :
GCCBuiltin<"__builtin_ia32_gather3siv4df">,
Intrinsic<[llvm_v4f64_ty],
[llvm_v4f64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
- def int_x86_avx512_gather3siv4_di :
+ def int_x86_avx512_gather3siv4_di :
GCCBuiltin<"__builtin_ia32_gather3siv4di">,
Intrinsic<[llvm_v8i32_ty],
[llvm_v4i64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
- def int_x86_avx512_gather3siv4_sf :
+ def int_x86_avx512_gather3siv4_sf :
GCCBuiltin<"__builtin_ia32_gather3siv4sf">,
Intrinsic<[llvm_v4f32_ty],
[llvm_v4f32_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
- def int_x86_avx512_gather3siv4_si :
+ def int_x86_avx512_gather3siv4_si :
GCCBuiltin<"__builtin_ia32_gather3siv4si">,
Intrinsic<[llvm_v4i32_ty],
[llvm_v4i32_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
- def int_x86_avx512_gather3siv8_sf :
+ def int_x86_avx512_gather3siv8_sf :
GCCBuiltin<"__builtin_ia32_gather3siv8sf">,
Intrinsic<[llvm_v8f32_ty],
[llvm_v8f32_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
- def int_x86_avx512_gather3siv8_si :
+ def int_x86_avx512_gather3siv8_si :
GCCBuiltin<"__builtin_ia32_gather3siv8si">,
Intrinsic<[llvm_v8i32_ty],
[llvm_v8i32_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty],
- [IntrReadArgMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
// scatter
def int_x86_avx512_scatter_dpd_512 : GCCBuiltin<"__builtin_ia32_scattersiv8df">,
Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty,
llvm_v8i32_ty, llvm_v8f64_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_scatter_dps_512 : GCCBuiltin<"__builtin_ia32_scattersiv16sf">,
Intrinsic<[], [llvm_ptr_ty, llvm_i16_ty,
llvm_v16i32_ty, llvm_v16f32_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_scatter_qpd_512 : GCCBuiltin<"__builtin_ia32_scatterdiv8df">,
Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty,
llvm_v8i64_ty, llvm_v8f64_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_scatter_qps_512 : GCCBuiltin<"__builtin_ia32_scatterdiv16sf">,
Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty,
llvm_v8i64_ty, llvm_v8f32_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_scatter_dpq_512 : GCCBuiltin<"__builtin_ia32_scattersiv8di">,
Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty,
llvm_v8i32_ty, llvm_v8i64_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_scatter_dpi_512 : GCCBuiltin<"__builtin_ia32_scattersiv16si">,
Intrinsic<[], [llvm_ptr_ty, llvm_i16_ty,
llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_scatter_qpq_512 : GCCBuiltin<"__builtin_ia32_scatterdiv8di">,
Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty,llvm_v8i64_ty, llvm_v8i64_ty,
llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_scatter_qpi_512 : GCCBuiltin<"__builtin_ia32_scatterdiv16si">,
- Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v8i64_ty, llvm_v8i32_ty,
+ Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v8i64_ty, llvm_v8i32_ty,
llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
- def int_x86_avx512_scatterdiv2_df :
+ def int_x86_avx512_scatterdiv2_df :
GCCBuiltin<"__builtin_ia32_scatterdiv2df">,
Intrinsic<[],
[llvm_ptr_ty, llvm_i8_ty, llvm_v2i64_ty, llvm_v2f64_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
- def int_x86_avx512_scatterdiv2_di :
+ def int_x86_avx512_scatterdiv2_di :
GCCBuiltin<"__builtin_ia32_scatterdiv2di">,
Intrinsic<[],
[llvm_ptr_ty, llvm_i8_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
- def int_x86_avx512_scatterdiv4_df :
+ def int_x86_avx512_scatterdiv4_df :
GCCBuiltin<"__builtin_ia32_scatterdiv4df">,
Intrinsic<[],
[llvm_ptr_ty, llvm_i8_ty, llvm_v4i64_ty, llvm_v4f64_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
- def int_x86_avx512_scatterdiv4_di :
+ def int_x86_avx512_scatterdiv4_di :
GCCBuiltin<"__builtin_ia32_scatterdiv4di">,
Intrinsic<[],
[llvm_ptr_ty, llvm_i8_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
- def int_x86_avx512_scatterdiv4_sf :
+ def int_x86_avx512_scatterdiv4_sf :
GCCBuiltin<"__builtin_ia32_scatterdiv4sf">,
Intrinsic<[],
[llvm_ptr_ty, llvm_i8_ty, llvm_v2i64_ty, llvm_v4f32_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
- def int_x86_avx512_scatterdiv4_si :
+ def int_x86_avx512_scatterdiv4_si :
GCCBuiltin<"__builtin_ia32_scatterdiv4si">,
Intrinsic<[],
[llvm_ptr_ty, llvm_i8_ty, llvm_v2i64_ty, llvm_v4i32_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
- def int_x86_avx512_scatterdiv8_sf :
+ def int_x86_avx512_scatterdiv8_sf :
GCCBuiltin<"__builtin_ia32_scatterdiv8sf">,
Intrinsic<[],
[llvm_ptr_ty, llvm_i8_ty, llvm_v4i64_ty, llvm_v4f32_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
- def int_x86_avx512_scatterdiv8_si :
+ def int_x86_avx512_scatterdiv8_si :
GCCBuiltin<"__builtin_ia32_scatterdiv8si">,
Intrinsic<[],
[llvm_ptr_ty, llvm_i8_ty, llvm_v4i64_ty, llvm_v4i32_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
- def int_x86_avx512_scattersiv2_df :
+ def int_x86_avx512_scattersiv2_df :
GCCBuiltin<"__builtin_ia32_scattersiv2df">,
Intrinsic<[],
[llvm_ptr_ty, llvm_i8_ty, llvm_v4i32_ty, llvm_v2f64_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
- def int_x86_avx512_scattersiv2_di :
+ def int_x86_avx512_scattersiv2_di :
GCCBuiltin<"__builtin_ia32_scattersiv2di">,
Intrinsic<[],
[llvm_ptr_ty, llvm_i8_ty, llvm_v4i32_ty, llvm_v2i64_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
- def int_x86_avx512_scattersiv4_df :
+ def int_x86_avx512_scattersiv4_df :
GCCBuiltin<"__builtin_ia32_scattersiv4df">,
Intrinsic<[],
[llvm_ptr_ty, llvm_i8_ty, llvm_v4i32_ty, llvm_v4f64_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
- def int_x86_avx512_scattersiv4_di :
+ def int_x86_avx512_scattersiv4_di :
GCCBuiltin<"__builtin_ia32_scattersiv4di">,
Intrinsic<[],
[llvm_ptr_ty, llvm_i8_ty, llvm_v4i32_ty, llvm_v4i64_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
- def int_x86_avx512_scattersiv4_sf :
+ def int_x86_avx512_scattersiv4_sf :
GCCBuiltin<"__builtin_ia32_scattersiv4sf">,
Intrinsic<[],
[llvm_ptr_ty, llvm_i8_ty, llvm_v4i32_ty, llvm_v4f32_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
- def int_x86_avx512_scattersiv4_si :
+ def int_x86_avx512_scattersiv4_si :
GCCBuiltin<"__builtin_ia32_scattersiv4si">,
Intrinsic<[],
[llvm_ptr_ty, llvm_i8_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
- def int_x86_avx512_scattersiv8_sf :
+ def int_x86_avx512_scattersiv8_sf :
GCCBuiltin<"__builtin_ia32_scattersiv8sf">,
Intrinsic<[],
[llvm_ptr_ty, llvm_i8_ty, llvm_v8i32_ty, llvm_v8f32_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
- def int_x86_avx512_scattersiv8_si :
+ def int_x86_avx512_scattersiv8_si :
GCCBuiltin<"__builtin_ia32_scattersiv8si">,
Intrinsic<[],
[llvm_ptr_ty, llvm_i8_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
// gather prefetch
def int_x86_avx512_gatherpf_dpd_512 : GCCBuiltin<"__builtin_ia32_gatherpfdpd">,
Intrinsic<[], [llvm_i8_ty, llvm_v8i32_ty, llvm_ptr_ty,
- llvm_i32_ty, llvm_i32_ty], [IntrReadWriteArgMem]>;
+ llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>;
def int_x86_avx512_gatherpf_dps_512 : GCCBuiltin<"__builtin_ia32_gatherpfdps">,
Intrinsic<[], [llvm_i16_ty, llvm_v16i32_ty, llvm_ptr_ty,
- llvm_i32_ty, llvm_i32_ty], [IntrReadWriteArgMem]>;
+ llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>;
def int_x86_avx512_gatherpf_qpd_512 : GCCBuiltin<"__builtin_ia32_gatherpfqpd">,
Intrinsic<[], [llvm_i8_ty, llvm_v8i64_ty, llvm_ptr_ty,
- llvm_i32_ty, llvm_i32_ty], [IntrReadWriteArgMem]>;
+ llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>;
def int_x86_avx512_gatherpf_qps_512 : GCCBuiltin<"__builtin_ia32_gatherpfqps">,
Intrinsic<[], [llvm_i8_ty, llvm_v8i64_ty, llvm_ptr_ty,
- llvm_i32_ty, llvm_i32_ty], [IntrReadWriteArgMem]>;
+ llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>;
// scatter prefetch
def int_x86_avx512_scatterpf_dpd_512 : GCCBuiltin<"__builtin_ia32_scatterpfdpd">,
Intrinsic<[], [llvm_i8_ty, llvm_v8i32_ty, llvm_ptr_ty,
- llvm_i32_ty, llvm_i32_ty], [IntrReadWriteArgMem]>;
+ llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>;
def int_x86_avx512_scatterpf_dps_512 : GCCBuiltin<"__builtin_ia32_scatterpfdps">,
Intrinsic<[], [llvm_i16_ty, llvm_v16i32_ty, llvm_ptr_ty,
- llvm_i32_ty, llvm_i32_ty], [IntrReadWriteArgMem]>;
+ llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>;
def int_x86_avx512_scatterpf_qpd_512 : GCCBuiltin<"__builtin_ia32_scatterpfqpd">,
Intrinsic<[], [llvm_i8_ty, llvm_v8i64_ty, llvm_ptr_ty,
- llvm_i32_ty, llvm_i32_ty], [IntrReadWriteArgMem]>;
+ llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>;
def int_x86_avx512_scatterpf_qps_512 : GCCBuiltin<"__builtin_ia32_scatterpfqps">,
Intrinsic<[], [llvm_i8_ty, llvm_v8i64_ty, llvm_ptr_ty,
- llvm_i32_ty, llvm_i32_ty], [IntrReadWriteArgMem]>;
+ llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>;
}
// AVX-512 conflict detection instruction
@@ -6815,117 +6382,32 @@ let TargetPrefix = "x86" in {
[IntrNoMem]>;
def int_x86_avx512_mask_lzcnt_d_128 :
- GCCBuiltin<"__builtin_ia32_vplzcntd_128_mask">,
Intrinsic<[llvm_v4i32_ty],
[llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty],
[IntrNoMem]>;
def int_x86_avx512_mask_lzcnt_d_256 :
- GCCBuiltin<"__builtin_ia32_vplzcntd_256_mask">,
Intrinsic<[llvm_v8i32_ty],
[llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty],
[IntrNoMem]>;
def int_x86_avx512_mask_lzcnt_d_512 :
- GCCBuiltin<"__builtin_ia32_vplzcntd_512_mask">,
Intrinsic<[llvm_v16i32_ty],
[llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty],
[IntrNoMem]>;
def int_x86_avx512_mask_lzcnt_q_128 :
- GCCBuiltin<"__builtin_ia32_vplzcntq_128_mask">,
Intrinsic<[llvm_v2i64_ty],
[llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty],
[IntrNoMem]>;
def int_x86_avx512_mask_lzcnt_q_256 :
- GCCBuiltin<"__builtin_ia32_vplzcntq_256_mask">,
Intrinsic<[llvm_v4i64_ty],
[llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty],
[IntrNoMem]>;
def int_x86_avx512_mask_lzcnt_q_512 :
- GCCBuiltin<"__builtin_ia32_vplzcntq_512_mask">,
Intrinsic<[llvm_v8i64_ty],
[llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
[IntrNoMem]>;
}
-// Vector blend
-let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_avx512_mask_blend_ps_512 : GCCBuiltin<"__builtin_ia32_blendmps_512_mask">,
- Intrinsic<[llvm_v16f32_ty],
- [llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_blend_ps_256 : GCCBuiltin<"__builtin_ia32_blendmps_256_mask">,
- Intrinsic<[llvm_v8f32_ty],
- [llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_blend_ps_128 : GCCBuiltin<"__builtin_ia32_blendmps_128_mask">,
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_blend_pd_512 : GCCBuiltin<"__builtin_ia32_blendmpd_512_mask">,
- Intrinsic<[llvm_v8f64_ty],
- [llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_blend_pd_256 : GCCBuiltin<"__builtin_ia32_blendmpd_256_mask">,
- Intrinsic<[llvm_v4f64_ty],
- [llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_blend_pd_128 : GCCBuiltin<"__builtin_ia32_blendmpd_128_mask">,
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_blend_d_512 : GCCBuiltin<"__builtin_ia32_blendmd_512_mask">,
- Intrinsic<[llvm_v16i32_ty],
- [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_blend_q_512 : GCCBuiltin<"__builtin_ia32_blendmq_512_mask">,
- Intrinsic<[llvm_v8i64_ty],
- [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_blend_d_256 : GCCBuiltin<"__builtin_ia32_blendmd_256_mask">,
- Intrinsic<[llvm_v8i32_ty],
- [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_blend_q_256 : GCCBuiltin<"__builtin_ia32_blendmq_256_mask">,
- Intrinsic<[llvm_v4i64_ty],
- [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_blend_d_128 : GCCBuiltin<"__builtin_ia32_blendmd_128_mask">,
- Intrinsic<[llvm_v4i32_ty],
- [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_blend_q_128 : GCCBuiltin<"__builtin_ia32_blendmq_128_mask">,
- Intrinsic<[llvm_v2i64_ty],
- [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_blend_w_512 : GCCBuiltin<"__builtin_ia32_blendmw_512_mask">,
- Intrinsic<[llvm_v32i16_ty],
- [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_blend_w_256 : GCCBuiltin<"__builtin_ia32_blendmw_256_mask">,
- Intrinsic<[llvm_v16i16_ty],
- [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_blend_w_128 : GCCBuiltin<"__builtin_ia32_blendmw_128_mask">,
- Intrinsic<[llvm_v8i16_ty],
- [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_blend_b_512 : GCCBuiltin<"__builtin_ia32_blendmb_512_mask">,
- Intrinsic<[llvm_v64i8_ty],
- [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_blend_b_256 : GCCBuiltin<"__builtin_ia32_blendmb_256_mask">,
- Intrinsic<[llvm_v32i8_ty],
- [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_blend_b_128 : GCCBuiltin<"__builtin_ia32_blendmb_128_mask">,
- Intrinsic<[llvm_v16i8_ty],
- [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty],
- [IntrNoMem]>;
-
-}
-
let TargetPrefix = "x86" in {
def int_x86_avx512_mask_valign_q_512 :
GCCBuiltin<"__builtin_ia32_alignq512_mask">,
@@ -6948,13 +6430,13 @@ let TargetPrefix = "x86" in {
def int_x86_avx512_mask_valign_d_256 :
GCCBuiltin<"__builtin_ia32_alignd256_mask">,
Intrinsic<[llvm_v8i32_ty],
- [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty, llvm_v8i32_ty,
+ [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty, llvm_v8i32_ty,
llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_valign_q_128 :
GCCBuiltin<"__builtin_ia32_alignq128_mask">,
Intrinsic<[llvm_v2i64_ty],
- [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty, llvm_v2i64_ty,
+ [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty, llvm_v2i64_ty,
llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_valign_d_128 :
@@ -6962,24 +6444,6 @@ let TargetPrefix = "x86" in {
Intrinsic<[llvm_v4i32_ty],
[llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty, llvm_v4i32_ty,
llvm_i8_ty], [IntrNoMem]>;
-
- def int_x86_avx512_mask_palignr_128 :
- GCCBuiltin<"__builtin_ia32_palignr128_mask">,
- Intrinsic<[llvm_v16i8_ty],
- [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty,
- llvm_i16_ty], [IntrNoMem]>;
-
- def int_x86_avx512_mask_palignr_256 :
- GCCBuiltin<"__builtin_ia32_palignr256_mask">,
- Intrinsic<[llvm_v32i8_ty],
- [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty, llvm_v32i8_ty,
- llvm_i32_ty], [IntrNoMem]>;
-
- def int_x86_avx512_mask_palignr_512 :
- GCCBuiltin<"__builtin_ia32_palignr512_mask">,
- Intrinsic<[llvm_v64i8_ty],
- [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i32_ty, llvm_v64i8_ty,
- llvm_i64_ty], [IntrNoMem]>;
}
// Compares
@@ -6991,161 +6455,84 @@ let TargetPrefix = "x86" in {
def int_x86_avx512_vcomi_ss : GCCBuiltin<"__builtin_ia32_vcomiss">,
Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty,
llvm_v4f32_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pcmpeq_b_512 : GCCBuiltin<"__builtin_ia32_pcmpeqb512_mask">,
- Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_pcmpeq_w_512 : GCCBuiltin<"__builtin_ia32_pcmpeqw512_mask">,
- Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_pcmpeq_d_512 : GCCBuiltin<"__builtin_ia32_pcmpeqd512_mask">,
- Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_pcmpeq_q_512 : GCCBuiltin<"__builtin_ia32_pcmpeqq512_mask">,
- Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_pcmpgt_b_512: GCCBuiltin<"__builtin_ia32_pcmpgtb512_mask">,
- Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_pcmpgt_w_512: GCCBuiltin<"__builtin_ia32_pcmpgtw512_mask">,
- Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_pcmpgt_d_512: GCCBuiltin<"__builtin_ia32_pcmpgtd512_mask">,
- Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_pcmpgt_q_512: GCCBuiltin<"__builtin_ia32_pcmpgtq512_mask">,
- Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_cmp_b_512: GCCBuiltin<"__builtin_ia32_cmpb512_mask">,
+ def int_x86_avx512_mask_cmp_b_512:
Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i32_ty,
llvm_i64_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_cmp_w_512: GCCBuiltin<"__builtin_ia32_cmpw512_mask">,
+ def int_x86_avx512_mask_cmp_w_512:
Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty,
llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_cmp_d_512: GCCBuiltin<"__builtin_ia32_cmpd512_mask">,
+ def int_x86_avx512_mask_cmp_d_512:
Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty,
llvm_i16_ty], [IntrNoMem ]>;
- def int_x86_avx512_mask_cmp_q_512: GCCBuiltin<"__builtin_ia32_cmpq512_mask">,
+ def int_x86_avx512_mask_cmp_q_512:
Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty,
llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_ucmp_b_512: GCCBuiltin<"__builtin_ia32_ucmpb512_mask">,
+ def int_x86_avx512_mask_ucmp_b_512:
Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i32_ty,
llvm_i64_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_ucmp_w_512: GCCBuiltin<"__builtin_ia32_ucmpw512_mask">,
+ def int_x86_avx512_mask_ucmp_w_512:
Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty,
llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_ucmp_d_512: GCCBuiltin<"__builtin_ia32_ucmpd512_mask">,
+ def int_x86_avx512_mask_ucmp_d_512:
Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty,
llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_ucmp_q_512: GCCBuiltin<"__builtin_ia32_ucmpq512_mask">,
+ def int_x86_avx512_mask_ucmp_q_512:
Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty,
llvm_i8_ty], [IntrNoMem]>;
// 256-bit
- def int_x86_avx512_mask_pcmpeq_b_256 : GCCBuiltin<"__builtin_ia32_pcmpeqb256_mask">,
- Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_pcmpeq_w_256 : GCCBuiltin<"__builtin_ia32_pcmpeqw256_mask">,
- Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_pcmpeq_d_256 : GCCBuiltin<"__builtin_ia32_pcmpeqd256_mask">,
- Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_pcmpeq_q_256 : GCCBuiltin<"__builtin_ia32_pcmpeqq256_mask">,
- Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_pcmpgt_b_256: GCCBuiltin<"__builtin_ia32_pcmpgtb256_mask">,
- Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_pcmpgt_w_256: GCCBuiltin<"__builtin_ia32_pcmpgtw256_mask">,
- Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_pcmpgt_d_256: GCCBuiltin<"__builtin_ia32_pcmpgtd256_mask">,
- Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_pcmpgt_q_256: GCCBuiltin<"__builtin_ia32_pcmpgtq256_mask">,
- Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_cmp_b_256: GCCBuiltin<"__builtin_ia32_cmpb256_mask">,
+ def int_x86_avx512_mask_cmp_b_256:
Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty,
llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_cmp_w_256: GCCBuiltin<"__builtin_ia32_cmpw256_mask">,
+ def int_x86_avx512_mask_cmp_w_256:
Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty,
llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_cmp_d_256: GCCBuiltin<"__builtin_ia32_cmpd256_mask">,
+ def int_x86_avx512_mask_cmp_d_256:
Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty,
llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_cmp_q_256: GCCBuiltin<"__builtin_ia32_cmpq256_mask">,
+ def int_x86_avx512_mask_cmp_q_256:
Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty,
llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_ucmp_b_256: GCCBuiltin<"__builtin_ia32_ucmpb256_mask">,
+ def int_x86_avx512_mask_ucmp_b_256:
Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty,
llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_ucmp_w_256: GCCBuiltin<"__builtin_ia32_ucmpw256_mask">,
+ def int_x86_avx512_mask_ucmp_w_256:
Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty,
llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_ucmp_d_256: GCCBuiltin<"__builtin_ia32_ucmpd256_mask">,
+ def int_x86_avx512_mask_ucmp_d_256:
Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty,
llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_ucmp_q_256: GCCBuiltin<"__builtin_ia32_ucmpq256_mask">,
+ def int_x86_avx512_mask_ucmp_q_256:
Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty,
llvm_i8_ty], [IntrNoMem]>;
// 128-bit
- def int_x86_avx512_mask_pcmpeq_b_128 : GCCBuiltin<"__builtin_ia32_pcmpeqb128_mask">,
- Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_pcmpeq_w_128 : GCCBuiltin<"__builtin_ia32_pcmpeqw128_mask">,
- Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_pcmpeq_d_128 : GCCBuiltin<"__builtin_ia32_pcmpeqd128_mask">,
- Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_pcmpeq_q_128 : GCCBuiltin<"__builtin_ia32_pcmpeqq128_mask">,
- Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_pcmpgt_b_128: GCCBuiltin<"__builtin_ia32_pcmpgtb128_mask">,
- Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_pcmpgt_w_128: GCCBuiltin<"__builtin_ia32_pcmpgtw128_mask">,
- Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_pcmpgt_d_128: GCCBuiltin<"__builtin_ia32_pcmpgtd128_mask">,
- Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_pcmpgt_q_128: GCCBuiltin<"__builtin_ia32_pcmpgtq128_mask">,
- Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_cmp_b_128: GCCBuiltin<"__builtin_ia32_cmpb128_mask">,
+ def int_x86_avx512_mask_cmp_b_128:
Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty,
llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_cmp_w_128: GCCBuiltin<"__builtin_ia32_cmpw128_mask">,
+ def int_x86_avx512_mask_cmp_w_128:
Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty,
llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_cmp_d_128: GCCBuiltin<"__builtin_ia32_cmpd128_mask">,
+ def int_x86_avx512_mask_cmp_d_128:
Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty,
llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_cmp_q_128: GCCBuiltin<"__builtin_ia32_cmpq128_mask">,
+ def int_x86_avx512_mask_cmp_q_128:
Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty,
llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_ucmp_b_128: GCCBuiltin<"__builtin_ia32_ucmpb128_mask">,
+ def int_x86_avx512_mask_ucmp_b_128:
Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty,
llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_ucmp_w_128: GCCBuiltin<"__builtin_ia32_ucmpw128_mask">,
+ def int_x86_avx512_mask_ucmp_w_128:
Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty,
llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_ucmp_d_128: GCCBuiltin<"__builtin_ia32_ucmpd128_mask">,
+ def int_x86_avx512_mask_ucmp_d_128:
Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty,
llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_ucmp_q_128: GCCBuiltin<"__builtin_ia32_ucmpq128_mask">,
+ def int_x86_avx512_mask_ucmp_q_128:
Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty,
llvm_i8_ty], [IntrNoMem]>;
}
@@ -7180,27 +6567,27 @@ let TargetPrefix = "x86" in {
def int_x86_avx512_mask_compress_store_ps_512 :
GCCBuiltin<"__builtin_ia32_compressstoresf512_mask">,
Intrinsic<[], [llvm_ptr_ty, llvm_v16f32_ty,
- llvm_i16_ty], [IntrReadWriteArgMem]>;
+ llvm_i16_ty], [IntrArgMemOnly]>;
def int_x86_avx512_mask_compress_store_pd_512 :
GCCBuiltin<"__builtin_ia32_compressstoredf512_mask">,
Intrinsic<[], [llvm_ptr_ty, llvm_v8f64_ty,
- llvm_i8_ty], [IntrReadWriteArgMem]>;
+ llvm_i8_ty], [IntrArgMemOnly]>;
def int_x86_avx512_mask_compress_store_ps_256 :
GCCBuiltin<"__builtin_ia32_compressstoresf256_mask">,
Intrinsic<[], [llvm_ptr_ty, llvm_v8f32_ty,
- llvm_i8_ty], [IntrReadWriteArgMem]>;
+ llvm_i8_ty], [IntrArgMemOnly]>;
def int_x86_avx512_mask_compress_store_pd_256 :
GCCBuiltin<"__builtin_ia32_compressstoredf256_mask">,
Intrinsic<[], [llvm_ptr_ty, llvm_v4f64_ty,
- llvm_i8_ty], [IntrReadWriteArgMem]>;
+ llvm_i8_ty], [IntrArgMemOnly]>;
def int_x86_avx512_mask_compress_store_ps_128 :
GCCBuiltin<"__builtin_ia32_compressstoresf128_mask">,
Intrinsic<[], [llvm_ptr_ty, llvm_v4f32_ty,
- llvm_i8_ty], [IntrReadWriteArgMem]>;
+ llvm_i8_ty], [IntrArgMemOnly]>;
def int_x86_avx512_mask_compress_store_pd_128 :
GCCBuiltin<"__builtin_ia32_compressstoredf128_mask">,
Intrinsic<[], [llvm_ptr_ty, llvm_v2f64_ty,
- llvm_i8_ty], [IntrReadWriteArgMem]>;
+ llvm_i8_ty], [IntrArgMemOnly]>;
def int_x86_avx512_mask_compress_d_512 :
GCCBuiltin<"__builtin_ia32_compresssi512_mask">,
@@ -7230,27 +6617,27 @@ let TargetPrefix = "x86" in {
def int_x86_avx512_mask_compress_store_d_512 :
GCCBuiltin<"__builtin_ia32_compressstoresi512_mask">,
Intrinsic<[], [llvm_ptr_ty, llvm_v16i32_ty,
- llvm_i16_ty], [IntrReadWriteArgMem]>;
+ llvm_i16_ty], [IntrArgMemOnly]>;
def int_x86_avx512_mask_compress_store_q_512 :
GCCBuiltin<"__builtin_ia32_compressstoredi512_mask">,
Intrinsic<[], [llvm_ptr_ty, llvm_v8i64_ty,
- llvm_i8_ty], [IntrReadWriteArgMem]>;
+ llvm_i8_ty], [IntrArgMemOnly]>;
def int_x86_avx512_mask_compress_store_d_256 :
GCCBuiltin<"__builtin_ia32_compressstoresi256_mask">,
Intrinsic<[], [llvm_ptr_ty, llvm_v8i32_ty,
- llvm_i8_ty], [IntrReadWriteArgMem]>;
+ llvm_i8_ty], [IntrArgMemOnly]>;
def int_x86_avx512_mask_compress_store_q_256 :
GCCBuiltin<"__builtin_ia32_compressstoredi256_mask">,
Intrinsic<[], [llvm_ptr_ty, llvm_v4i64_ty,
- llvm_i8_ty], [IntrReadWriteArgMem]>;
+ llvm_i8_ty], [IntrArgMemOnly]>;
def int_x86_avx512_mask_compress_store_d_128 :
GCCBuiltin<"__builtin_ia32_compressstoresi128_mask">,
Intrinsic<[], [llvm_ptr_ty, llvm_v4i32_ty,
- llvm_i8_ty], [IntrReadWriteArgMem]>;
+ llvm_i8_ty], [IntrArgMemOnly]>;
def int_x86_avx512_mask_compress_store_q_128 :
GCCBuiltin<"__builtin_ia32_compressstoredi128_mask">,
Intrinsic<[], [llvm_ptr_ty, llvm_v2i64_ty,
- llvm_i8_ty], [IntrReadWriteArgMem]>;
+ llvm_i8_ty], [IntrArgMemOnly]>;
// expand
def int_x86_avx512_mask_expand_ps_512 :
@@ -7281,27 +6668,27 @@ let TargetPrefix = "x86" in {
def int_x86_avx512_mask_expand_load_ps_512 :
GCCBuiltin<"__builtin_ia32_expandloadsf512_mask">,
Intrinsic<[llvm_v16f32_ty], [llvm_ptr_ty, llvm_v16f32_ty,
- llvm_i16_ty], [IntrReadArgMem]>;
+ llvm_i16_ty], [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx512_mask_expand_load_pd_512 :
GCCBuiltin<"__builtin_ia32_expandloaddf512_mask">,
Intrinsic<[llvm_v8f64_ty], [llvm_ptr_ty, llvm_v8f64_ty,
- llvm_i8_ty], [IntrReadArgMem]>;
+ llvm_i8_ty], [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx512_mask_expand_load_ps_256 :
GCCBuiltin<"__builtin_ia32_expandloadsf256_mask">,
Intrinsic<[llvm_v8f32_ty], [llvm_ptr_ty, llvm_v8f32_ty,
- llvm_i8_ty], [IntrReadArgMem]>;
+ llvm_i8_ty], [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx512_mask_expand_load_pd_256 :
GCCBuiltin<"__builtin_ia32_expandloaddf256_mask">,
Intrinsic<[llvm_v4f64_ty], [llvm_ptr_ty, llvm_v4f64_ty,
- llvm_i8_ty], [IntrReadArgMem]>;
+ llvm_i8_ty], [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx512_mask_expand_load_ps_128 :
GCCBuiltin<"__builtin_ia32_expandloadsf128_mask">,
Intrinsic<[llvm_v4f32_ty], [llvm_ptr_ty, llvm_v4f32_ty,
- llvm_i8_ty], [IntrReadArgMem]>;
+ llvm_i8_ty], [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx512_mask_expand_load_pd_128 :
GCCBuiltin<"__builtin_ia32_expandloaddf128_mask">,
Intrinsic<[llvm_v2f64_ty], [llvm_ptr_ty, llvm_v2f64_ty,
- llvm_i8_ty], [IntrReadArgMem]>;
+ llvm_i8_ty], [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx512_mask_expand_d_512 :
GCCBuiltin<"__builtin_ia32_expandsi512_mask">,
@@ -7331,27 +6718,27 @@ let TargetPrefix = "x86" in {
def int_x86_avx512_mask_expand_load_d_512 :
GCCBuiltin<"__builtin_ia32_expandloadsi512_mask">,
Intrinsic<[llvm_v16i32_ty], [llvm_ptr_ty, llvm_v16i32_ty,
- llvm_i16_ty], [IntrReadArgMem]>;
+ llvm_i16_ty], [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx512_mask_expand_load_q_512 :
GCCBuiltin<"__builtin_ia32_expandloaddi512_mask">,
Intrinsic<[llvm_v8i64_ty], [llvm_ptr_ty, llvm_v8i64_ty,
- llvm_i8_ty], [IntrReadArgMem]>;
+ llvm_i8_ty], [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx512_mask_expand_load_d_256 :
GCCBuiltin<"__builtin_ia32_expandloadsi256_mask">,
Intrinsic<[llvm_v8i32_ty], [llvm_ptr_ty, llvm_v8i32_ty,
- llvm_i8_ty], [IntrReadArgMem]>;
+ llvm_i8_ty], [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx512_mask_expand_load_q_256 :
GCCBuiltin<"__builtin_ia32_expandloaddi256_mask">,
Intrinsic<[llvm_v4i64_ty], [llvm_ptr_ty, llvm_v4i64_ty,
- llvm_i8_ty], [IntrReadArgMem]>;
+ llvm_i8_ty], [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx512_mask_expand_load_d_128 :
GCCBuiltin<"__builtin_ia32_expandloadsi128_mask">,
Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty, llvm_v4i32_ty,
- llvm_i8_ty], [IntrReadArgMem]>;
+ llvm_i8_ty], [IntrReadMem, IntrArgMemOnly]>;
def int_x86_avx512_mask_expand_load_q_128 :
GCCBuiltin<"__builtin_ia32_expandloaddi128_mask">,
Intrinsic<[llvm_v2i64_ty], [llvm_ptr_ty, llvm_v2i64_ty,
- llvm_i8_ty], [IntrReadArgMem]>;
+ llvm_i8_ty], [IntrReadMem, IntrArgMemOnly]>;
}
@@ -7366,7 +6753,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovqb128mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovs_qb_128 :
GCCBuiltin<"__builtin_ia32_pmovsqb128_mask">,
Intrinsic<[llvm_v16i8_ty],
@@ -7376,7 +6763,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovsqb128mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovus_qb_128 :
GCCBuiltin<"__builtin_ia32_pmovusqb128_mask">,
Intrinsic<[llvm_v16i8_ty],
@@ -7386,7 +6773,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovusqb128mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmov_qb_256 :
GCCBuiltin<"__builtin_ia32_pmovqb256_mask">,
Intrinsic<[llvm_v16i8_ty],
@@ -7396,7 +6783,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovqb256mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovs_qb_256 :
GCCBuiltin<"__builtin_ia32_pmovsqb256_mask">,
Intrinsic<[llvm_v16i8_ty],
@@ -7406,7 +6793,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovsqb256mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovus_qb_256 :
GCCBuiltin<"__builtin_ia32_pmovusqb256_mask">,
Intrinsic<[llvm_v16i8_ty],
@@ -7416,7 +6803,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovusqb256mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmov_qb_512 :
GCCBuiltin<"__builtin_ia32_pmovqb512_mask">,
Intrinsic<[llvm_v16i8_ty],
@@ -7426,7 +6813,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovqb512mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovs_qb_512 :
GCCBuiltin<"__builtin_ia32_pmovsqb512_mask">,
Intrinsic<[llvm_v16i8_ty],
@@ -7436,7 +6823,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovsqb512mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovus_qb_512 :
GCCBuiltin<"__builtin_ia32_pmovusqb512_mask">,
Intrinsic<[llvm_v16i8_ty],
@@ -7446,7 +6833,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovusqb512mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmov_qw_128 :
GCCBuiltin<"__builtin_ia32_pmovqw128_mask">,
Intrinsic<[llvm_v8i16_ty],
@@ -7456,7 +6843,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovqw128mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovs_qw_128 :
GCCBuiltin<"__builtin_ia32_pmovsqw128_mask">,
Intrinsic<[llvm_v8i16_ty],
@@ -7466,7 +6853,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovsqw128mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovus_qw_128 :
GCCBuiltin<"__builtin_ia32_pmovusqw128_mask">,
Intrinsic<[llvm_v8i16_ty],
@@ -7476,7 +6863,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovusqw128mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmov_qw_256 :
GCCBuiltin<"__builtin_ia32_pmovqw256_mask">,
Intrinsic<[llvm_v8i16_ty],
@@ -7486,7 +6873,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovqw256mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovs_qw_256 :
GCCBuiltin<"__builtin_ia32_pmovsqw256_mask">,
Intrinsic<[llvm_v8i16_ty],
@@ -7496,7 +6883,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovsqw256mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovus_qw_256 :
GCCBuiltin<"__builtin_ia32_pmovusqw256_mask">,
Intrinsic<[llvm_v8i16_ty],
@@ -7506,7 +6893,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovusqw256mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmov_qw_512 :
GCCBuiltin<"__builtin_ia32_pmovqw512_mask">,
Intrinsic<[llvm_v8i16_ty],
@@ -7516,7 +6903,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovqw512mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovs_qw_512 :
GCCBuiltin<"__builtin_ia32_pmovsqw512_mask">,
Intrinsic<[llvm_v8i16_ty],
@@ -7526,7 +6913,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovsqw512mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovus_qw_512 :
GCCBuiltin<"__builtin_ia32_pmovusqw512_mask">,
Intrinsic<[llvm_v8i16_ty],
@@ -7536,7 +6923,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovusqw512mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmov_qd_128 :
GCCBuiltin<"__builtin_ia32_pmovqd128_mask">,
Intrinsic<[llvm_v4i32_ty],
@@ -7546,7 +6933,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovqd128mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovs_qd_128 :
GCCBuiltin<"__builtin_ia32_pmovsqd128_mask">,
Intrinsic<[llvm_v4i32_ty],
@@ -7556,7 +6943,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovsqd128mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovus_qd_128 :
GCCBuiltin<"__builtin_ia32_pmovusqd128_mask">,
Intrinsic<[llvm_v4i32_ty],
@@ -7566,7 +6953,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovusqd128mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmov_qd_256 :
GCCBuiltin<"__builtin_ia32_pmovqd256_mask">,
Intrinsic<[llvm_v4i32_ty],
@@ -7576,7 +6963,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovqd256mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovs_qd_256 :
GCCBuiltin<"__builtin_ia32_pmovsqd256_mask">,
Intrinsic<[llvm_v4i32_ty],
@@ -7586,7 +6973,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovsqd256mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovus_qd_256 :
GCCBuiltin<"__builtin_ia32_pmovusqd256_mask">,
Intrinsic<[llvm_v4i32_ty],
@@ -7596,7 +6983,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovusqd256mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmov_qd_512 :
GCCBuiltin<"__builtin_ia32_pmovqd512_mask">,
Intrinsic<[llvm_v8i32_ty],
@@ -7606,7 +6993,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovqd512mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovs_qd_512 :
GCCBuiltin<"__builtin_ia32_pmovsqd512_mask">,
Intrinsic<[llvm_v8i32_ty],
@@ -7616,7 +7003,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovsqd512mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovus_qd_512 :
GCCBuiltin<"__builtin_ia32_pmovusqd512_mask">,
Intrinsic<[llvm_v8i32_ty],
@@ -7626,7 +7013,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovusqd512mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmov_db_128 :
GCCBuiltin<"__builtin_ia32_pmovdb128_mask">,
Intrinsic<[llvm_v16i8_ty],
@@ -7636,7 +7023,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovdb128mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovs_db_128 :
GCCBuiltin<"__builtin_ia32_pmovsdb128_mask">,
Intrinsic<[llvm_v16i8_ty],
@@ -7646,7 +7033,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovsdb128mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovus_db_128 :
GCCBuiltin<"__builtin_ia32_pmovusdb128_mask">,
Intrinsic<[llvm_v16i8_ty],
@@ -7656,7 +7043,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovusdb128mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmov_db_256 :
GCCBuiltin<"__builtin_ia32_pmovdb256_mask">,
Intrinsic<[llvm_v16i8_ty],
@@ -7666,7 +7053,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovdb256mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovs_db_256 :
GCCBuiltin<"__builtin_ia32_pmovsdb256_mask">,
Intrinsic<[llvm_v16i8_ty],
@@ -7676,7 +7063,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovsdb256mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovus_db_256 :
GCCBuiltin<"__builtin_ia32_pmovusdb256_mask">,
Intrinsic<[llvm_v16i8_ty],
@@ -7686,7 +7073,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovusdb256mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmov_db_512 :
GCCBuiltin<"__builtin_ia32_pmovdb512_mask">,
Intrinsic<[llvm_v16i8_ty],
@@ -7696,7 +7083,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovdb512mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v16i32_ty, llvm_i16_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovs_db_512 :
GCCBuiltin<"__builtin_ia32_pmovsdb512_mask">,
Intrinsic<[llvm_v16i8_ty],
@@ -7706,7 +7093,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovsdb512mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v16i32_ty, llvm_i16_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovus_db_512 :
GCCBuiltin<"__builtin_ia32_pmovusdb512_mask">,
Intrinsic<[llvm_v16i8_ty],
@@ -7716,7 +7103,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovusdb512mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v16i32_ty, llvm_i16_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmov_dw_128 :
GCCBuiltin<"__builtin_ia32_pmovdw128_mask">,
Intrinsic<[llvm_v8i16_ty],
@@ -7726,7 +7113,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovdw128mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovs_dw_128 :
GCCBuiltin<"__builtin_ia32_pmovsdw128_mask">,
Intrinsic<[llvm_v8i16_ty],
@@ -7736,7 +7123,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovsdw128mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovus_dw_128 :
GCCBuiltin<"__builtin_ia32_pmovusdw128_mask">,
Intrinsic<[llvm_v8i16_ty],
@@ -7746,7 +7133,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovusdw128mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmov_dw_256 :
GCCBuiltin<"__builtin_ia32_pmovdw256_mask">,
Intrinsic<[llvm_v8i16_ty],
@@ -7756,7 +7143,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovdw256mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovs_dw_256 :
GCCBuiltin<"__builtin_ia32_pmovsdw256_mask">,
Intrinsic<[llvm_v8i16_ty],
@@ -7766,7 +7153,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovsdw256mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovus_dw_256 :
GCCBuiltin<"__builtin_ia32_pmovusdw256_mask">,
Intrinsic<[llvm_v8i16_ty],
@@ -7776,7 +7163,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovusdw256mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmov_dw_512 :
GCCBuiltin<"__builtin_ia32_pmovdw512_mask">,
Intrinsic<[llvm_v16i16_ty],
@@ -7786,7 +7173,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovdw512mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v16i32_ty, llvm_i16_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovs_dw_512 :
GCCBuiltin<"__builtin_ia32_pmovsdw512_mask">,
Intrinsic<[llvm_v16i16_ty],
@@ -7796,7 +7183,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovsdw512mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v16i32_ty, llvm_i16_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovus_dw_512 :
GCCBuiltin<"__builtin_ia32_pmovusdw512_mask">,
Intrinsic<[llvm_v16i16_ty],
@@ -7806,7 +7193,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovusdw512mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v16i32_ty, llvm_i16_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmov_wb_128 :
GCCBuiltin<"__builtin_ia32_pmovwb128_mask">,
Intrinsic<[llvm_v16i8_ty],
@@ -7816,7 +7203,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovwb128mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v8i16_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovs_wb_128 :
GCCBuiltin<"__builtin_ia32_pmovswb128_mask">,
Intrinsic<[llvm_v16i8_ty],
@@ -7826,7 +7213,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovswb128mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v8i16_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovus_wb_128 :
GCCBuiltin<"__builtin_ia32_pmovuswb128_mask">,
Intrinsic<[llvm_v16i8_ty],
@@ -7836,7 +7223,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovuswb128mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v8i16_ty, llvm_i8_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmov_wb_256 :
GCCBuiltin<"__builtin_ia32_pmovwb256_mask">,
Intrinsic<[llvm_v16i8_ty],
@@ -7846,7 +7233,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovwb256mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v16i16_ty, llvm_i16_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovs_wb_256 :
GCCBuiltin<"__builtin_ia32_pmovswb256_mask">,
Intrinsic<[llvm_v16i8_ty],
@@ -7856,7 +7243,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovswb256mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v16i16_ty, llvm_i16_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovus_wb_256 :
GCCBuiltin<"__builtin_ia32_pmovuswb256_mask">,
Intrinsic<[llvm_v16i8_ty],
@@ -7866,7 +7253,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovuswb256mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v16i16_ty, llvm_i16_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmov_wb_512 :
GCCBuiltin<"__builtin_ia32_pmovwb512_mask">,
Intrinsic<[llvm_v32i8_ty],
@@ -7876,7 +7263,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovwb512mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v32i16_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovs_wb_512 :
GCCBuiltin<"__builtin_ia32_pmovswb512_mask">,
Intrinsic<[llvm_v32i8_ty],
@@ -7886,7 +7273,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovswb512mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v32i16_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
def int_x86_avx512_mask_pmovus_wb_512 :
GCCBuiltin<"__builtin_ia32_pmovuswb512_mask">,
Intrinsic<[llvm_v32i8_ty],
@@ -7896,7 +7283,7 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_pmovuswb512mem_mask">,
Intrinsic<[],
[llvm_ptr_ty, llvm_v32i16_ty, llvm_i32_ty],
- [IntrReadWriteArgMem]>;
+ [IntrArgMemOnly]>;
}
// Bitwise ternary logic
@@ -8034,3 +7421,14 @@ let TargetPrefix = "x86" in {
def int_x86_sha256msg2 : GCCBuiltin<"__builtin_ia32_sha256msg2">,
Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>;
}
+
+//===----------------------------------------------------------------------===//
+// Thread synchronization ops with timer.
+let TargetPrefix = "x86" in {
+ def int_x86_monitorx
+ : GCCBuiltin<"__builtin_ia32_monitorx">,
+ Intrinsic<[], [ llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty ], []>;
+ def int_x86_mwaitx
+ : GCCBuiltin<"__builtin_ia32_mwaitx">,
+ Intrinsic<[], [ llvm_i32_ty, llvm_i32_ty, llvm_i32_ty ], []>;
+}
diff --git a/include/llvm/IR/LLVMContext.h b/include/llvm/IR/LLVMContext.h
index 56aa3010d925..dbf2b4562332 100644
--- a/include/llvm/IR/LLVMContext.h
+++ b/include/llvm/IR/LLVMContext.h
@@ -16,7 +16,6 @@
#define LLVM_IR_LLVMCONTEXT_H
#include "llvm/Support/CBindingWrapping.h"
-#include "llvm/Support/Compiler.h"
#include "llvm/Support/Options.h"
namespace llvm {
@@ -26,11 +25,15 @@ class StringRef;
class Twine;
class Instruction;
class Module;
+class MDString;
+class DICompositeType;
class SMDiagnostic;
class DiagnosticInfo;
+enum DiagnosticSeverity : char;
template <typename T> class SmallVectorImpl;
class Function;
class DebugLoc;
+class OptBisect;
/// This is an important class for using LLVM in a threaded context. It
/// (opaquely) owns and manages the core "global" data of LLVM's core
@@ -46,24 +49,26 @@ public:
// Pinned metadata names, which always have the same value. This is a
// compile-time performance optimization, not a correctness optimization.
enum {
- MD_dbg = 0, // "dbg"
- MD_tbaa = 1, // "tbaa"
- MD_prof = 2, // "prof"
- MD_fpmath = 3, // "fpmath"
- MD_range = 4, // "range"
- MD_tbaa_struct = 5, // "tbaa.struct"
- MD_invariant_load = 6, // "invariant.load"
- MD_alias_scope = 7, // "alias.scope"
- MD_noalias = 8, // "noalias",
- MD_nontemporal = 9, // "nontemporal"
+ MD_dbg = 0, // "dbg"
+ MD_tbaa = 1, // "tbaa"
+ MD_prof = 2, // "prof"
+ MD_fpmath = 3, // "fpmath"
+ MD_range = 4, // "range"
+ MD_tbaa_struct = 5, // "tbaa.struct"
+ MD_invariant_load = 6, // "invariant.load"
+ MD_alias_scope = 7, // "alias.scope"
+ MD_noalias = 8, // "noalias",
+ MD_nontemporal = 9, // "nontemporal"
MD_mem_parallel_loop_access = 10, // "llvm.mem.parallel_loop_access"
- MD_nonnull = 11, // "nonnull"
- MD_dereferenceable = 12, // "dereferenceable"
- MD_dereferenceable_or_null = 13, // "dereferenceable_or_null"
- MD_make_implicit = 14, // "make.implicit"
- MD_unpredictable = 15, // "unpredictable"
- MD_invariant_group = 16, // "invariant.group"
- MD_align = 17 // "align"
+ MD_nonnull = 11, // "nonnull"
+ MD_dereferenceable = 12, // "dereferenceable"
+ MD_dereferenceable_or_null = 13, // "dereferenceable_or_null"
+ MD_make_implicit = 14, // "make.implicit"
+ MD_unpredictable = 15, // "unpredictable"
+ MD_invariant_group = 16, // "invariant.group"
+ MD_align = 17, // "align"
+ MD_loop = 18, // "llvm.loop"
+ MD_type = 19, // "type"
};
/// Known operand bundle tag IDs, which always have the same value. All
@@ -71,8 +76,9 @@ public:
/// Additionally, this scheme allows LLVM to efficiently check for specific
/// operand bundle tags without comparing strings.
enum {
- OB_deopt = 0, // "deopt"
- OB_funclet = 1, // "funclet"
+ OB_deopt = 0, // "deopt"
+ OB_funclet = 1, // "funclet"
+ OB_gc_transition = 2, // "gc-transition"
};
/// getMDKindID - Return a unique non-zero ID for the specified metadata kind.
@@ -93,7 +99,6 @@ public:
/// tag registered with an LLVMContext has an unique ID.
uint32_t getOperandBundleTagID(StringRef Tag) const;
-
/// Define the GC for a function
void setGC(const Function &Fn, std::string GCName);
@@ -103,6 +108,21 @@ public:
/// Remove the GC for a function
void deleteGC(const Function &Fn);
+ /// Return true if the Context runtime configuration is set to discard all
+ /// value names. When true, only GlobalValue names will be available in the
+ /// IR.
+ bool shouldDiscardValueNames() const;
+
+ /// Set the Context runtime configuration to discard all value name (but
+ /// GlobalValue). Clients can use this flag to save memory and runtime,
+ /// especially in release mode.
+ void setDiscardValueNames(bool Discard);
+
+ /// Whether there is a string map for uniquing debug info
+ /// identifiers across the context. Off by default.
+ bool isODRUniquingDebugTypes() const;
+ void enableDebugTypeODRUniquing();
+ void disableDebugTypeODRUniquing();
typedef void (*InlineAsmDiagHandlerTy)(const SMDiagnostic&, void *Context,
unsigned LocCookie);
@@ -154,6 +174,17 @@ public:
/// setDiagnosticContext.
void *getDiagnosticContext() const;
+ /// \brief Return if a code hotness metric should be included in optimization
+ /// diagnostics.
+ bool getDiagnosticHotnessRequested() const;
+ /// \brief Set if a code hotness metric should be included in optimization
+ /// diagnostics.
+ void setDiagnosticHotnessRequested(bool Requested);
+
+ /// \brief Get the prefix that should be printed in front of a diagnostic of
+ /// the given \p Severity
+ static const char *getDiagnosticMessagePrefix(DiagnosticSeverity Severity);
+
/// \brief Report a message to the currently installed diagnostic handler.
///
/// This function returns, in particular in the case of error reporting
@@ -209,6 +240,9 @@ public:
return OptionRegistry::instance().template get<ValT, Base, Mem>();
}
+ /// \brief Access the object which manages optimization bisection for failure
+ /// analysis.
+ OptBisect &getOptBisect();
private:
LLVMContext(LLVMContext&) = delete;
void operator=(LLVMContext&) = delete;
@@ -224,10 +258,6 @@ private:
friend class Module;
};
-/// getGlobalContext - Returns a global context. This is for LLVM clients that
-/// only care about operating on a single thread.
-extern LLVMContext &getGlobalContext();
-
// Create wrappers for C Binding types (see CBindingWrapping.h).
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLVMContext, LLVMContextRef)
diff --git a/include/llvm/IR/LegacyPassManagers.h b/include/llvm/IR/LegacyPassManagers.h
index b8e33478d6a9..530fd7166498 100644
--- a/include/llvm/IR/LegacyPassManagers.h
+++ b/include/llvm/IR/LegacyPassManagers.h
@@ -14,13 +14,11 @@
#ifndef LLVM_IR_LEGACYPASSMANAGERS_H
#define LLVM_IR_LEGACYPASSMANAGERS_H
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Pass.h"
-#include <map>
#include <vector>
//===----------------------------------------------------------------------===//
@@ -93,12 +91,13 @@
#include "llvm/Support/PrettyStackTrace.h"
namespace llvm {
- class Module;
- class Pass;
- class StringRef;
- class Value;
- class Timer;
- class PMDataManager;
+template <typename T> class ArrayRef;
+class Module;
+class Pass;
+class StringRef;
+class Value;
+class Timer;
+class PMDataManager;
// enums for debugging strings
enum PassDebuggingString {
diff --git a/include/llvm/IR/Mangler.h b/include/llvm/IR/Mangler.h
index ea2f0c3f09f3..349218e33817 100644
--- a/include/llvm/IR/Mangler.h
+++ b/include/llvm/IR/Mangler.h
@@ -16,13 +16,13 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/IR/GlobalValue.h"
-#include "llvm/Support/raw_ostream.h"
namespace llvm {
class DataLayout;
template <typename T> class SmallVectorImpl;
class Twine;
+class raw_ostream;
class Mangler {
/// We need to give global values the same name every time they are mangled.
diff --git a/include/llvm/IR/Metadata.def b/include/llvm/IR/Metadata.def
index b1d22178e262..607f5ef125c9 100644
--- a/include/llvm/IR/Metadata.def
+++ b/include/llvm/IR/Metadata.def
@@ -77,6 +77,7 @@ HANDLE_METADATA_LEAF(MDString)
HANDLE_METADATA_BRANCH(ValueAsMetadata)
HANDLE_METADATA_LEAF(ConstantAsMetadata)
HANDLE_METADATA_LEAF(LocalAsMetadata)
+HANDLE_METADATA_LEAF(DistinctMDOperandPlaceholder)
HANDLE_MDNODE_BRANCH(MDNode)
HANDLE_MDNODE_LEAF_UNIQUABLE(MDTuple)
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILocation)
diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h
index df8ce354bb7f..91f43d342d27 100644
--- a/include/llvm/IR/Metadata.h
+++ b/include/llvm/IR/Metadata.h
@@ -19,6 +19,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ilist_node.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/IR/Constant.h"
@@ -51,7 +52,7 @@ protected:
enum StorageType { Uniqued, Distinct, Temporary };
/// \brief Storage flag for non-uniqued, otherwise unowned, metadata.
- unsigned Storage : 2;
+ unsigned char Storage;
// TODO: expose remaining bits to subclasses.
unsigned short SubclassData16;
@@ -59,39 +60,14 @@ protected:
public:
enum MetadataKind {
- MDTupleKind,
- DILocationKind,
- GenericDINodeKind,
- DISubrangeKind,
- DIEnumeratorKind,
- DIBasicTypeKind,
- DIDerivedTypeKind,
- DICompositeTypeKind,
- DISubroutineTypeKind,
- DIFileKind,
- DICompileUnitKind,
- DISubprogramKind,
- DILexicalBlockKind,
- DILexicalBlockFileKind,
- DINamespaceKind,
- DIModuleKind,
- DITemplateTypeParameterKind,
- DITemplateValueParameterKind,
- DIGlobalVariableKind,
- DILocalVariableKind,
- DIExpressionKind,
- DIObjCPropertyKind,
- DIImportedEntityKind,
- ConstantAsMetadataKind,
- LocalAsMetadataKind,
- MDStringKind,
- DIMacroKind,
- DIMacroFileKind
+#define HANDLE_METADATA_LEAF(CLASS) CLASS##Kind,
+#include "llvm/IR/Metadata.def"
};
protected:
Metadata(unsigned ID, StorageType Storage)
: SubclassID(ID), Storage(Storage), SubclassData16(0), SubclassData32(0) {
+ static_assert(sizeof(*this) == 8, "Metdata fields poorly packed");
}
~Metadata() = default;
@@ -283,20 +259,14 @@ private:
LLVMContext &Context;
uint64_t NextIndex;
SmallDenseMap<void *, std::pair<OwnerTy, uint64_t>, 4> UseMap;
- /// Flag that can be set to false if this metadata should not be
- /// RAUW'ed, e.g. if it is used as the key of a map.
- bool CanReplace;
public:
ReplaceableMetadataImpl(LLVMContext &Context)
- : Context(Context), NextIndex(0), CanReplace(true) {}
+ : Context(Context), NextIndex(0) {}
~ReplaceableMetadataImpl() {
assert(UseMap.empty() && "Cannot destroy in-use replaceable metadata");
}
- /// Set the CanReplace flag to the given value.
- void setCanReplace(bool Replaceable) { CanReplace = Replaceable; }
-
LLVMContext &getContext() const { return Context; }
/// \brief Replace all uses of this with MD.
@@ -316,7 +286,19 @@ private:
void dropRef(void *Ref);
void moveRef(void *Ref, void *New, const Metadata &MD);
- static ReplaceableMetadataImpl *get(Metadata &MD);
+ /// Lazily construct RAUW support on MD.
+ ///
+ /// If this is an unresolved MDNode, RAUW support will be created on-demand.
+ /// ValueAsMetadata always has RAUW support.
+ static ReplaceableMetadataImpl *getOrCreate(Metadata &MD);
+
+ /// Get RAUW support on MD, if it exists.
+ static ReplaceableMetadataImpl *getIfExists(Metadata &MD);
+
+ /// Check whether this node will support RAUW.
+ ///
+ /// Returns \c true unless getOrCreate() would return null.
+ static bool isReplaceable(const Metadata &MD);
};
/// \brief Value wrapper in the Metadata hierarchy.
@@ -592,7 +574,6 @@ class MDString : public Metadata {
StringMapEntry<MDString> *Entry;
MDString() : Metadata(MDStringKind, Uniqued), Entry(nullptr) {}
- MDString(MDString &&) : Metadata(MDStringKind, Uniqued) {}
public:
static MDString *get(LLVMContext &Context, StringRef Str);
@@ -767,6 +748,13 @@ public:
return nullptr;
}
+ /// Ensure that this has RAUW support, and then return it.
+ ReplaceableMetadataImpl *getOrCreateReplaceableUses() {
+ if (!hasReplaceableUses())
+ makeReplaceable(llvm::make_unique<ReplaceableMetadataImpl>(getContext()));
+ return getReplaceableUses();
+ }
+
/// \brief Assign RAUW support to this.
///
/// Make this replaceable, taking ownership of \c ReplaceableUses (which must
@@ -828,9 +816,9 @@ class MDNode : public Metadata {
unsigned NumOperands;
unsigned NumUnresolved;
-protected:
ContextAndReplaceableUses Context;
+protected:
void *operator new(size_t Size, unsigned NumOps);
void operator delete(void *Mem);
@@ -892,7 +880,7 @@ public:
/// As forward declarations are resolved, their containers should get
/// resolved automatically. However, if this (or one of its operands) is
/// involved in a cycle, \a resolveCycles() needs to be called explicitly.
- bool isResolved() const { return !Context.hasReplaceableUses(); }
+ bool isResolved() const { return !isTemporary() && !NumUnresolved; }
bool isUniqued() const { return Storage == Uniqued; }
bool isDistinct() const { return Storage == Distinct; }
@@ -903,33 +891,17 @@ public:
/// \pre \a isTemporary() must be \c true.
void replaceAllUsesWith(Metadata *MD) {
assert(isTemporary() && "Expected temporary node");
- assert(!isResolved() && "Expected RAUW support");
- Context.getReplaceableUses()->replaceAllUsesWith(MD);
- }
-
- /// Set the CanReplace flag to the given value.
- void setCanReplace(bool Replaceable) {
- Context.getReplaceableUses()->setCanReplace(Replaceable);
+ if (Context.hasReplaceableUses())
+ Context.getReplaceableUses()->replaceAllUsesWith(MD);
}
/// \brief Resolve cycles.
///
/// Once all forward declarations have been resolved, force cycles to be
- /// resolved. This interface is used when there are no more temporaries,
- /// and thus unresolved nodes are part of cycles and no longer need RAUW
- /// support.
+ /// resolved.
///
/// \pre No operands (or operands' operands, etc.) have \a isTemporary().
- void resolveCycles() { resolveRecursivelyImpl(/* AllowTemps */ false); }
-
- /// \brief Resolve cycles while ignoring temporaries.
- ///
- /// This drops RAUW support for any temporaries, which can no longer
- /// be uniqued.
- ///
- void resolveNonTemporaries() {
- resolveRecursivelyImpl(/* AllowTemps */ true);
- }
+ void resolveCycles();
/// \brief Replace a temporary node with a permanent one.
///
@@ -982,15 +954,15 @@ protected:
private:
void handleChangedOperand(void *Ref, Metadata *New);
+ /// Resolve a unique, unresolved node.
void resolve();
+
+ /// Drop RAUW support, if any.
+ void dropReplaceableUses();
+
void resolveAfterOperandChange(Metadata *Old, Metadata *New);
void decrementUnresolvedOperandCount();
- unsigned countUnresolvedOperands();
-
- /// Resolve cycles recursively. If \p AllowTemps is true, then any temporary
- /// metadata is ignored, otherwise it asserts when encountering temporary
- /// metadata.
- void resolveRecursivelyImpl(bool AllowTemps);
+ void countUnresolvedOperands();
/// \brief Mutate this to be "uniqued".
///
@@ -1221,6 +1193,52 @@ public:
typedef MDTupleTypedArrayWrapper<CLASS> CLASS##Array;
#include "llvm/IR/Metadata.def"
+/// Placeholder metadata for operands of distinct MDNodes.
+///
+/// This is a lightweight placeholder for an operand of a distinct node. It's
+/// purpose is to help track forward references when creating a distinct node.
+/// This allows distinct nodes involved in a cycle to be constructed before
+/// their operands without requiring a heavyweight temporary node with
+/// full-blown RAUW support.
+///
+/// Each placeholder supports only a single MDNode user. Clients should pass
+/// an ID, retrieved via \a getID(), to indicate the "real" operand that this
+/// should be replaced with.
+///
+/// While it would be possible to implement move operators, they would be
+/// fairly expensive. Leave them unimplemented to discourage their use
+/// (clients can use std::deque, std::list, BumpPtrAllocator, etc.).
+class DistinctMDOperandPlaceholder : public Metadata {
+ friend class MetadataTracking;
+
+ Metadata **Use = nullptr;
+
+ DistinctMDOperandPlaceholder() = delete;
+ DistinctMDOperandPlaceholder(DistinctMDOperandPlaceholder &&) = delete;
+ DistinctMDOperandPlaceholder(const DistinctMDOperandPlaceholder &) = delete;
+
+public:
+ explicit DistinctMDOperandPlaceholder(unsigned ID)
+ : Metadata(DistinctMDOperandPlaceholderKind, Distinct) {
+ SubclassData32 = ID;
+ }
+
+ ~DistinctMDOperandPlaceholder() {
+ if (Use)
+ *Use = nullptr;
+ }
+
+ unsigned getID() const { return SubclassData32; }
+
+ /// Replace the use of this with MD.
+ void replaceUseWith(Metadata *MD) {
+ if (!Use)
+ return;
+ *Use = MD;
+ Use = nullptr;
+ }
+};
+
//===----------------------------------------------------------------------===//
/// \brief A tuple of MDNodes.
///
@@ -1297,6 +1315,8 @@ public:
void setOperand(unsigned I, MDNode *New);
StringRef getName() const;
void print(raw_ostream &ROS, bool IsForDebug = false) const;
+ void print(raw_ostream &ROS, ModuleSlotTracker &MST,
+ bool IsForDebug = false) const;
void dump() const;
// ---------------------------------------------------------------------------
diff --git a/include/llvm/IR/Module.h b/include/llvm/IR/Module.h
index 942f68543cb6..632b27e2d0dd 100644
--- a/include/llvm/IR/Module.h
+++ b/include/llvm/IR/Module.h
@@ -15,12 +15,12 @@
#ifndef LLVM_IR_MODULE_H
#define LLVM_IR_MODULE_H
-#include "llvm/ADT/Optional.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/IR/Comdat.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalAlias.h"
+#include "llvm/IR/GlobalIFunc.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Metadata.h"
#include "llvm/Support/CBindingWrapping.h"
@@ -29,11 +29,13 @@
#include <system_error>
namespace llvm {
+template <typename T> class Optional;
class FunctionType;
class GVMaterializer;
class LLVMContext;
class RandomNumberGenerator;
class StructType;
+template <class PtrType> class SmallPtrSetImpl;
template<> struct ilist_traits<NamedMDNode>
: public ilist_default_traits<NamedMDNode> {
@@ -75,6 +77,8 @@ public:
typedef SymbolTableList<Function> FunctionListType;
/// The type for the list of aliases.
typedef SymbolTableList<GlobalAlias> AliasListType;
+ /// The type for the list of ifuncs.
+ typedef SymbolTableList<GlobalIFunc> IFuncListType;
/// The type for the list of named metadata.
typedef ilist<NamedMDNode> NamedMDListType;
/// The type of the comdat "symbol" table.
@@ -100,6 +104,11 @@ public:
/// The Global Alias constant iterator
typedef AliasListType::const_iterator const_alias_iterator;
+ /// The Global IFunc iterators.
+ typedef IFuncListType::iterator ifunc_iterator;
+ /// The Global IFunc constant iterator
+ typedef IFuncListType::const_iterator const_ifunc_iterator;
+
/// The named metadata iterators.
typedef NamedMDListType::iterator named_metadata_iterator;
/// The named metadata constant iterators.
@@ -163,6 +172,7 @@ private:
GlobalListType GlobalList; ///< The Global Variables in the module
FunctionListType FunctionList; ///< The Functions in the module
AliasListType AliasList; ///< The Aliases in the module
+ IFuncListType IFuncList; ///< The IFuncs in the module
NamedMDListType NamedMDList; ///< The named metadata in the module
std::string GlobalScopeAsm; ///< Inline Asm at global scope.
ValueSymbolTable *ValSymTab; ///< Symbol table for values
@@ -170,6 +180,8 @@ private:
std::unique_ptr<GVMaterializer>
Materializer; ///< Used to materialize GlobalValues
std::string ModuleID; ///< Human readable identifier for the module
+ std::string SourceFileName; ///< Original source file name for module,
+ ///< recorded in bitcode.
std::string TargetTriple; ///< Platform target triple Module compiled on
///< Format: (arch)(sub)-(vendor)-(sys0-(abi)
void *NamedMDSymTab; ///< NamedMDNode names.
@@ -195,6 +207,12 @@ public:
/// @returns the module identifier as a string
const std::string &getModuleIdentifier() const { return ModuleID; }
+ /// Get the module's original source file name. When compiling from
+ /// bitcode, this is taken from a bitcode record where it was recorded.
+ /// For other compiles it is the same as the ModuleID, which would
+ /// contain the source file name.
+ const std::string &getSourceFileName() const { return SourceFileName; }
+
/// \brief Get a short "name" for the module.
///
/// This is useful for debugging or logging. It is essentially a convenience
@@ -240,6 +258,9 @@ public:
/// Set the module identifier.
void setModuleIdentifier(StringRef ID) { ModuleID = ID; }
+ /// Set the module's original source file name.
+ void setSourceFileName(StringRef Name) { SourceFileName = Name; }
+
/// Set the data layout
void setDataLayout(StringRef Desc);
void setDataLayout(const DataLayout &Other);
@@ -251,8 +272,7 @@ public:
/// A trailing newline is added if the input doesn't have one.
void setModuleInlineAsm(StringRef Asm) {
GlobalScopeAsm = Asm;
- if (!GlobalScopeAsm.empty() &&
- GlobalScopeAsm[GlobalScopeAsm.size()-1] != '\n')
+ if (!GlobalScopeAsm.empty() && GlobalScopeAsm.back() != '\n')
GlobalScopeAsm += '\n';
}
@@ -260,8 +280,7 @@ public:
/// A trailing newline is added if the input doesn't have one.
void appendModuleInlineAsm(StringRef Asm) {
GlobalScopeAsm += Asm;
- if (!GlobalScopeAsm.empty() &&
- GlobalScopeAsm[GlobalScopeAsm.size()-1] != '\n')
+ if (!GlobalScopeAsm.empty() && GlobalScopeAsm.back() != '\n')
GlobalScopeAsm += '\n';
}
@@ -375,6 +394,15 @@ public:
GlobalAlias *getNamedAlias(StringRef Name) const;
/// @}
+/// @name Global IFunc Accessors
+/// @{
+
+ /// Return the global ifunc in the module with the specified name, of
+ /// arbitrary type. This method returns null if a global with the specified
+ /// name is not found.
+ GlobalIFunc *getNamedIFunc(StringRef Name) const;
+
+/// @}
/// @name Named Metadata Accessors
/// @{
@@ -477,6 +505,13 @@ public:
static AliasListType Module::*getSublistAccess(GlobalAlias*) {
return &Module::AliasList;
}
+ /// Get the Module's list of ifuncs (constant).
+ const IFuncListType &getIFuncList() const { return IFuncList; }
+ /// Get the Module's list of ifuncs.
+ IFuncListType &getIFuncList() { return IFuncList; }
+ static IFuncListType Module::*getSublistAccess(GlobalIFunc*) {
+ return &Module::IFuncList;
+ }
/// Get the Module's list of named metadata (constant).
const NamedMDListType &getNamedMDList() const { return NamedMDList; }
/// Get the Module's list of named metadata.
@@ -551,9 +586,96 @@ public:
}
/// @}
-/// @name Named Metadata Iteration
+/// @name IFunc Iteration
/// @{
+ ifunc_iterator ifunc_begin() { return IFuncList.begin(); }
+ const_ifunc_iterator ifunc_begin() const { return IFuncList.begin(); }
+ ifunc_iterator ifunc_end () { return IFuncList.end(); }
+ const_ifunc_iterator ifunc_end () const { return IFuncList.end(); }
+ size_t ifunc_size () const { return IFuncList.size(); }
+ bool ifunc_empty() const { return IFuncList.empty(); }
+
+ iterator_range<ifunc_iterator> ifuncs() {
+ return make_range(ifunc_begin(), ifunc_end());
+ }
+ iterator_range<const_ifunc_iterator> ifuncs() const {
+ return make_range(ifunc_begin(), ifunc_end());
+ }
+
+/// @}
+/// @name Convenience iterators
+/// @{
+
+ template <bool IsConst> class global_object_iterator_t {
+ friend Module;
+
+ typename std::conditional<IsConst, const_iterator, iterator>::type
+ function_i,
+ function_e;
+ typename std::conditional<IsConst, const_global_iterator,
+ global_iterator>::type global_i;
+
+ typedef
+ typename std::conditional<IsConst, const Module, Module>::type ModuleTy;
+
+ global_object_iterator_t(ModuleTy &M)
+ : function_i(M.begin()), function_e(M.end()),
+ global_i(M.global_begin()) {}
+ global_object_iterator_t(ModuleTy &M, int)
+ : function_i(M.end()), function_e(M.end()), global_i(M.global_end()) {}
+
+ public:
+ global_object_iterator_t &operator++() {
+ if (function_i != function_e)
+ ++function_i;
+ else
+ ++global_i;
+ return *this;
+ }
+
+ typename std::conditional<IsConst, const GlobalObject, GlobalObject>::type &
+ operator*() const {
+ if (function_i != function_e)
+ return *function_i;
+ else
+ return *global_i;
+ }
+
+ bool operator!=(const global_object_iterator_t &other) const {
+ return function_i != other.function_i || global_i != other.global_i;
+ }
+ };
+
+ typedef global_object_iterator_t</*IsConst=*/false> global_object_iterator;
+ typedef global_object_iterator_t</*IsConst=*/true>
+ const_global_object_iterator;
+
+ global_object_iterator global_object_begin() {
+ return global_object_iterator(*this);
+ }
+ global_object_iterator global_object_end() {
+ return global_object_iterator(*this, 0);
+ }
+
+ const_global_object_iterator global_object_begin() const {
+ return const_global_object_iterator(*this);
+ }
+ const_global_object_iterator global_object_end() const {
+ return const_global_object_iterator(*this, 0);
+ }
+
+ iterator_range<global_object_iterator> global_objects() {
+ return make_range(global_object_begin(), global_object_end());
+ }
+ iterator_range<const_global_object_iterator> global_objects() const {
+ return make_range(global_object_begin(), global_object_end());
+ }
+
+ /// @}
+ /// @name Named Metadata Iteration
+ /// @{
+
named_metadata_iterator named_metadata_begin() { return NamedMDList.begin(); }
const_named_metadata_iterator named_metadata_begin() const {
return NamedMDList.begin();
@@ -574,6 +696,58 @@ public:
return make_range(named_metadata_begin(), named_metadata_end());
}
+ /// An iterator for DICompileUnits that skips those marked NoDebug.
+ class debug_compile_units_iterator
+ : public std::iterator<std::input_iterator_tag, DICompileUnit *> {
+ NamedMDNode *CUs;
+ unsigned Idx;
+ void SkipNoDebugCUs();
+ public:
+ explicit debug_compile_units_iterator(NamedMDNode *CUs, unsigned Idx)
+ : CUs(CUs), Idx(Idx) {
+ SkipNoDebugCUs();
+ }
+ debug_compile_units_iterator &operator++() {
+ ++Idx;
+ SkipNoDebugCUs();
+ return *this;
+ }
+ debug_compile_units_iterator operator++(int) {
+ debug_compile_units_iterator T(*this);
+ ++Idx;
+ return T;
+ }
+ bool operator==(const debug_compile_units_iterator &I) const {
+ return Idx == I.Idx;
+ }
+ bool operator!=(const debug_compile_units_iterator &I) const {
+ return Idx != I.Idx;
+ }
+ DICompileUnit *operator*() const;
+ DICompileUnit *operator->() const;
+ };
+
+ debug_compile_units_iterator debug_compile_units_begin() const {
+ auto *CUs = getNamedMetadata("llvm.dbg.cu");
+ return debug_compile_units_iterator(CUs, 0);
+ }
+
+ debug_compile_units_iterator debug_compile_units_end() const {
+ auto *CUs = getNamedMetadata("llvm.dbg.cu");
+ return debug_compile_units_iterator(CUs, CUs ? CUs->getNumOperands() : 0);
+ }
+
+ /// Return an iterator for all DICompileUnits listed in this Module's
+ /// llvm.dbg.cu named metadata node and aren't explicitly marked as
+ /// NoDebug.
+ iterator_range<debug_compile_units_iterator> debug_compile_units() const {
+ auto *CUs = getNamedMetadata("llvm.dbg.cu");
+ return make_range(
+ debug_compile_units_iterator(CUs, 0),
+ debug_compile_units_iterator(CUs, CUs ? CUs->getNumOperands() : 0));
+ }
+/// @}
+
/// Destroy ConstantArrays in LLVMContext if they are not used.
/// ConstantArrays constructed during linking can cause quadratic memory
/// explosion. Releasing all unused constants can cause a 20% LTO compile-time
@@ -583,7 +757,6 @@ public:
/// be called where all uses of the LLVMContext are understood.
void dropTriviallyDeadConstantArrays();
-/// @}
/// @name Utility functions for printing and dumping Module objects
/// @{
@@ -628,17 +801,34 @@ public:
void setPICLevel(PICLevel::Level PL);
/// @}
- /// @name Utility functions for querying and setting PGO counts
+/// @}
+/// @name Utility functions for querying and setting PIE level
+/// @{
+
+ /// \brief Returns the PIE level (small or large model)
+ PIELevel::Level getPIELevel() const;
+
+ /// \brief Set the PIE level (small or large model)
+ void setPIELevel(PIELevel::Level PL);
+/// @}
+
+ /// @name Utility functions for querying and setting PGO summary
/// @{
- /// \brief Set maximum function count in PGO mode
- void setMaximumFunctionCount(uint64_t);
+ /// \brief Attach profile summary metadata to this module.
+ void setProfileSummary(Metadata *M);
- /// \brief Returns maximum function count in PGO mode
- Optional<uint64_t> getMaximumFunctionCount();
+ /// \brief Returns profile summary metadata
+ Metadata *getProfileSummary();
/// @}
};
+/// \brief Given "llvm.used" or "llvm.compiler.used" as a global name, collect
+/// the initializer elements of that global in Set and return the global itself.
+GlobalVariable *collectUsedGlobalVariables(const Module &M,
+ SmallPtrSetImpl<GlobalValue *> &Set,
+ bool CompilerUsed);
+
/// An raw_ostream inserter for modules.
inline raw_ostream &operator<<(raw_ostream &O, const Module &M) {
M.print(O, nullptr);
diff --git a/include/llvm/IR/ModuleSlotTracker.h b/include/llvm/IR/ModuleSlotTracker.h
index 49730a66bdf6..eb26fba906ea 100644
--- a/include/llvm/IR/ModuleSlotTracker.h
+++ b/include/llvm/IR/ModuleSlotTracker.h
@@ -30,6 +30,8 @@ class Value;
class ModuleSlotTracker {
/// Storage for a slot tracker.
std::unique_ptr<SlotTracker> MachineStorage;
+ bool ShouldCreateStorage = false;
+ bool ShouldInitializeAllMetadata = false;
const Module *M = nullptr;
const Function *F = nullptr;
@@ -53,7 +55,9 @@ public:
/// Destructor to clean up storage.
~ModuleSlotTracker();
- SlotTracker *getMachine() const { return Machine; }
+ /// Lazily creates a slot tracker.
+ SlotTracker *getMachine();
+
const Module *getModule() const { return M; }
const Function *getCurrentFunction() const { return F; }
diff --git a/include/llvm/IR/ModuleSummaryIndex.h b/include/llvm/IR/ModuleSummaryIndex.h
new file mode 100644
index 000000000000..45d9bf7af706
--- /dev/null
+++ b/include/llvm/IR/ModuleSummaryIndex.h
@@ -0,0 +1,508 @@
+//===-- llvm/ModuleSummaryIndex.h - Module Summary Index --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// @file
+/// ModuleSummaryIndex.h This file contains the declarations the classes that
+/// hold the module index and summary for function importing.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_MODULESUMMARYINDEX_H
+#define LLVM_IR_MODULESUMMARYINDEX_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/IR/Module.h"
+
+#include <array>
+
+namespace llvm {
+
+/// \brief Class to accumulate and hold information about a callee.
+struct CalleeInfo {
+ /// The static number of callsites calling corresponding function.
+ unsigned CallsiteCount;
+ /// The cumulative profile count of calls to corresponding function
+ /// (if using PGO, otherwise 0).
+ uint64_t ProfileCount;
+ CalleeInfo() : CallsiteCount(0), ProfileCount(0) {}
+ CalleeInfo(unsigned CallsiteCount, uint64_t ProfileCount)
+ : CallsiteCount(CallsiteCount), ProfileCount(ProfileCount) {}
+ CalleeInfo &operator+=(uint64_t RHSProfileCount) {
+ CallsiteCount++;
+ ProfileCount += RHSProfileCount;
+ return *this;
+ }
+};
+
+/// Struct to hold value either by GUID or Value*, depending on whether this
+/// is a combined or per-module index, respectively.
+struct ValueInfo {
+ /// The value representation used in this instance.
+ enum ValueInfoKind {
+ VI_GUID,
+ VI_Value,
+ };
+
+ /// Union of the two possible value types.
+ union ValueUnion {
+ GlobalValue::GUID Id;
+ const Value *V;
+ ValueUnion(GlobalValue::GUID Id) : Id(Id) {}
+ ValueUnion(const Value *V) : V(V) {}
+ };
+
+ /// The value being represented.
+ ValueUnion TheValue;
+ /// The value representation.
+ ValueInfoKind Kind;
+ /// Constructor for a GUID value
+ ValueInfo(GlobalValue::GUID Id = 0) : TheValue(Id), Kind(VI_GUID) {}
+ /// Constructor for a Value* value
+ ValueInfo(const Value *V) : TheValue(V), Kind(VI_Value) {}
+ /// Accessor for GUID value
+ GlobalValue::GUID getGUID() const {
+ assert(Kind == VI_GUID && "Not a GUID type");
+ return TheValue.Id;
+ }
+ /// Accessor for Value* value
+ const Value *getValue() const {
+ assert(Kind == VI_Value && "Not a Value type");
+ return TheValue.V;
+ }
+ bool isGUID() const { return Kind == VI_GUID; }
+};
+
+/// \brief Function and variable summary information to aid decisions and
+/// implementation of importing.
+class GlobalValueSummary {
+public:
+ /// \brief Sububclass discriminator (for dyn_cast<> et al.)
+ enum SummaryKind { AliasKind, FunctionKind, GlobalVarKind };
+
+ /// Group flags (Linkage, hasSection, isOptSize, etc.) as a bitfield.
+ struct GVFlags {
+ /// \brief The linkage type of the associated global value.
+ ///
+ /// One use is to flag values that have local linkage types and need to
+ /// have module identifier appended before placing into the combined
+ /// index, to disambiguate from other values with the same name.
+ /// In the future this will be used to update and optimize linkage
+ /// types based on global summary-based analysis.
+ unsigned Linkage : 4;
+
+ /// Indicate if the global value is located in a specific section.
+ unsigned HasSection : 1;
+
+ /// Convenience Constructors
+ explicit GVFlags(GlobalValue::LinkageTypes Linkage, bool HasSection)
+ : Linkage(Linkage), HasSection(HasSection) {}
+ GVFlags(const GlobalValue &GV)
+ : Linkage(GV.getLinkage()), HasSection(GV.hasSection()) {}
+ };
+
+private:
+ /// Kind of summary for use in dyn_cast<> et al.
+ SummaryKind Kind;
+
+ /// This is the hash of the name of the symbol in the original file. It is
+ /// identical to the GUID for global symbols, but differs for local since the
+ /// GUID includes the module level id in the hash.
+ GlobalValue::GUID OriginalName;
+
+ /// \brief Path of module IR containing value's definition, used to locate
+ /// module during importing.
+ ///
+ /// This is only used during parsing of the combined index, or when
+ /// parsing the per-module index for creation of the combined summary index,
+ /// not during writing of the per-module index which doesn't contain a
+ /// module path string table.
+ StringRef ModulePath;
+
+ GVFlags Flags;
+
+ /// List of values referenced by this global value's definition
+ /// (either by the initializer of a global variable, or referenced
+ /// from within a function). This does not include functions called, which
+ /// are listed in the derived FunctionSummary object.
+ std::vector<ValueInfo> RefEdgeList;
+
+protected:
+ /// GlobalValueSummary constructor.
+ GlobalValueSummary(SummaryKind K, GVFlags Flags) : Kind(K), Flags(Flags) {}
+
+public:
+ virtual ~GlobalValueSummary() = default;
+
+ /// Returns the hash of the original name, it is identical to the GUID for
+ /// externally visible symbols, but not for local ones.
+ GlobalValue::GUID getOriginalName() { return OriginalName; }
+
+ /// Initialize the original name hash in this summary.
+ void setOriginalName(GlobalValue::GUID Name) { OriginalName = Name; }
+
+ /// Which kind of summary subclass this is.
+ SummaryKind getSummaryKind() const { return Kind; }
+
+ /// Set the path to the module containing this function, for use in
+ /// the combined index.
+ void setModulePath(StringRef ModPath) { ModulePath = ModPath; }
+
+ /// Get the path to the module containing this function.
+ StringRef modulePath() const { return ModulePath; }
+
+ /// Get the flags for this GlobalValue (see \p struct GVFlags).
+ GVFlags flags() { return Flags; }
+
+ /// Return linkage type recorded for this global value.
+ GlobalValue::LinkageTypes linkage() const {
+ return static_cast<GlobalValue::LinkageTypes>(Flags.Linkage);
+ }
+
+ /// Sets the linkage to the value determined by global summary-based
+ /// optimization. Will be applied in the ThinLTO backends.
+ void setLinkage(GlobalValue::LinkageTypes Linkage) {
+ Flags.Linkage = Linkage;
+ }
+
+ /// Return true if this summary is for a GlobalValue that needs promotion
+ /// to be referenced from another module.
+ bool needsRenaming() const { return GlobalValue::isLocalLinkage(linkage()); }
+
+ /// Return true if this global value is located in a specific section.
+ bool hasSection() const { return Flags.HasSection; }
+
+ /// Record a reference from this global value to the global value identified
+ /// by \p RefGUID.
+ void addRefEdge(GlobalValue::GUID RefGUID) { RefEdgeList.push_back(RefGUID); }
+
+ /// Record a reference from this global value to the global value identified
+ /// by \p RefV.
+ void addRefEdge(const Value *RefV) { RefEdgeList.push_back(RefV); }
+
+ /// Record a reference from this global value to each global value identified
+ /// in \p RefEdges.
+ void addRefEdges(DenseSet<const Value *> &RefEdges) {
+ for (auto &RI : RefEdges)
+ addRefEdge(RI);
+ }
+
+ /// Return the list of values referenced by this global value definition.
+ std::vector<ValueInfo> &refs() { return RefEdgeList; }
+ const std::vector<ValueInfo> &refs() const { return RefEdgeList; }
+};
+
+/// \brief Alias summary information.
+class AliasSummary : public GlobalValueSummary {
+ GlobalValueSummary *AliaseeSummary;
+
+public:
+ /// Summary constructors.
+ AliasSummary(GVFlags Flags) : GlobalValueSummary(AliasKind, Flags) {}
+
+ /// Check if this is an alias summary.
+ static bool classof(const GlobalValueSummary *GVS) {
+ return GVS->getSummaryKind() == AliasKind;
+ }
+
+ void setAliasee(GlobalValueSummary *Aliasee) { AliaseeSummary = Aliasee; }
+
+ const GlobalValueSummary &getAliasee() const {
+ return const_cast<AliasSummary *>(this)->getAliasee();
+ }
+
+ GlobalValueSummary &getAliasee() {
+ assert(AliaseeSummary && "Unexpected missing aliasee summary");
+ return *AliaseeSummary;
+ }
+};
+
+/// \brief Function summary information to aid decisions and implementation of
+/// importing.
+class FunctionSummary : public GlobalValueSummary {
+public:
+ /// <CalleeValueInfo, CalleeInfo> call edge pair.
+ typedef std::pair<ValueInfo, CalleeInfo> EdgeTy;
+
+private:
+ /// Number of instructions (ignoring debug instructions, e.g.) computed
+ /// during the initial compile step when the summary index is first built.
+ unsigned InstCount;
+
+ /// List of <CalleeValueInfo, CalleeInfo> call edge pairs from this function.
+ std::vector<EdgeTy> CallGraphEdgeList;
+
+public:
+ /// Summary constructors.
+ FunctionSummary(GVFlags Flags, unsigned NumInsts)
+ : GlobalValueSummary(FunctionKind, Flags), InstCount(NumInsts) {}
+
+ /// Check if this is a function summary.
+ static bool classof(const GlobalValueSummary *GVS) {
+ return GVS->getSummaryKind() == FunctionKind;
+ }
+
+ /// Get the instruction count recorded for this function.
+ unsigned instCount() const { return InstCount; }
+
+ /// Record a call graph edge from this function to the function identified
+ /// by \p CalleeGUID, with \p CalleeInfo including the cumulative profile
+ /// count (across all calls from this function) or 0 if no PGO.
+ void addCallGraphEdge(GlobalValue::GUID CalleeGUID, CalleeInfo Info) {
+ CallGraphEdgeList.push_back(std::make_pair(CalleeGUID, Info));
+ }
+
+ /// Record a call graph edge from this function to each function GUID recorded
+ /// in \p CallGraphEdges.
+ void
+ addCallGraphEdges(DenseMap<GlobalValue::GUID, CalleeInfo> &CallGraphEdges) {
+ for (auto &EI : CallGraphEdges)
+ addCallGraphEdge(EI.first, EI.second);
+ }
+
+ /// Record a call graph edge from this function to the function identified
+ /// by \p CalleeV, with \p CalleeInfo including the cumulative profile
+ /// count (across all calls from this function) or 0 if no PGO.
+ void addCallGraphEdge(const Value *CalleeV, CalleeInfo Info) {
+ CallGraphEdgeList.push_back(std::make_pair(CalleeV, Info));
+ }
+
+ /// Record a call graph edge from this function to each function recorded
+ /// in \p CallGraphEdges.
+ void addCallGraphEdges(DenseMap<const Value *, CalleeInfo> &CallGraphEdges) {
+ for (auto &EI : CallGraphEdges)
+ addCallGraphEdge(EI.first, EI.second);
+ }
+
+ /// Return the list of <CalleeValueInfo, CalleeInfo> pairs.
+ std::vector<EdgeTy> &calls() { return CallGraphEdgeList; }
+ const std::vector<EdgeTy> &calls() const { return CallGraphEdgeList; }
+};
+
+/// \brief Global variable summary information to aid decisions and
+/// implementation of importing.
+///
+/// Currently this doesn't add anything to the base \p GlobalValueSummary,
+/// but is a placeholder as additional info may be added to the summary
+/// for variables.
+class GlobalVarSummary : public GlobalValueSummary {
+
+public:
+ /// Summary constructors.
+ GlobalVarSummary(GVFlags Flags) : GlobalValueSummary(GlobalVarKind, Flags) {}
+
+ /// Check if this is a global variable summary.
+ static bool classof(const GlobalValueSummary *GVS) {
+ return GVS->getSummaryKind() == GlobalVarKind;
+ }
+};
+
+/// 160 bits SHA1
+typedef std::array<uint32_t, 5> ModuleHash;
+
+/// List of global value summary structures for a particular value held
+/// in the GlobalValueMap. Requires a vector in the case of multiple
+/// COMDAT values of the same name.
+typedef std::vector<std::unique_ptr<GlobalValueSummary>> GlobalValueSummaryList;
+
+/// Map from global value GUID to corresponding summary structures.
+/// Use a std::map rather than a DenseMap since it will likely incur
+/// less overhead, as the value type is not very small and the size
+/// of the map is unknown, resulting in inefficiencies due to repeated
+/// insertions and resizing.
+typedef std::map<GlobalValue::GUID, GlobalValueSummaryList>
+ GlobalValueSummaryMapTy;
+
+/// Type used for iterating through the global value summary map.
+typedef GlobalValueSummaryMapTy::const_iterator const_gvsummary_iterator;
+typedef GlobalValueSummaryMapTy::iterator gvsummary_iterator;
+
+/// String table to hold/own module path strings, which additionally holds the
+/// module ID assigned to each module during the plugin step, as well as a hash
+/// of the module. The StringMap makes a copy of and owns inserted strings.
+typedef StringMap<std::pair<uint64_t, ModuleHash>> ModulePathStringTableTy;
+
+/// Map of global value GUID to its summary, used to identify values defined in
+/// a particular module, and provide efficient access to their summary.
+typedef std::map<GlobalValue::GUID, GlobalValueSummary *> GVSummaryMapTy;
+
+/// Class to hold module path string table and global value map,
+/// and encapsulate methods for operating on them.
+class ModuleSummaryIndex {
+private:
+ /// Map from value name to list of summary instances for values of that
+ /// name (may be duplicates in the COMDAT case, e.g.).
+ GlobalValueSummaryMapTy GlobalValueMap;
+
+ /// Holds strings for combined index, mapping to the corresponding module ID.
+ ModulePathStringTableTy ModulePathStringTable;
+
+public:
+ ModuleSummaryIndex() = default;
+
+ // Disable the copy constructor and assignment operators, so
+ // no unexpected copying/moving occurs.
+ ModuleSummaryIndex(const ModuleSummaryIndex &) = delete;
+ void operator=(const ModuleSummaryIndex &) = delete;
+
+ gvsummary_iterator begin() { return GlobalValueMap.begin(); }
+ const_gvsummary_iterator begin() const { return GlobalValueMap.begin(); }
+ gvsummary_iterator end() { return GlobalValueMap.end(); }
+ const_gvsummary_iterator end() const { return GlobalValueMap.end(); }
+
+ /// Get the list of global value summary objects for a given value name.
+ const GlobalValueSummaryList &getGlobalValueSummaryList(StringRef ValueName) {
+ return GlobalValueMap[GlobalValue::getGUID(ValueName)];
+ }
+
+ /// Get the list of global value summary objects for a given value name.
+ const const_gvsummary_iterator
+ findGlobalValueSummaryList(StringRef ValueName) const {
+ return GlobalValueMap.find(GlobalValue::getGUID(ValueName));
+ }
+
+ /// Get the list of global value summary objects for a given value GUID.
+ const const_gvsummary_iterator
+ findGlobalValueSummaryList(GlobalValue::GUID ValueGUID) const {
+ return GlobalValueMap.find(ValueGUID);
+ }
+
+ /// Add a global value summary for a value of the given name.
+ void addGlobalValueSummary(StringRef ValueName,
+ std::unique_ptr<GlobalValueSummary> Summary) {
+ GlobalValueMap[GlobalValue::getGUID(ValueName)].push_back(
+ std::move(Summary));
+ }
+
+ /// Add a global value summary for a value of the given GUID.
+ void addGlobalValueSummary(GlobalValue::GUID ValueGUID,
+ std::unique_ptr<GlobalValueSummary> Summary) {
+ GlobalValueMap[ValueGUID].push_back(std::move(Summary));
+ }
+
+ /// Find the summary for global \p GUID in module \p ModuleId, or nullptr if
+ /// not found.
+ GlobalValueSummary *findSummaryInModule(GlobalValue::GUID ValueGUID,
+ StringRef ModuleId) const {
+ auto CalleeInfoList = findGlobalValueSummaryList(ValueGUID);
+ if (CalleeInfoList == end()) {
+ return nullptr; // This function does not have a summary
+ }
+ auto Summary =
+ llvm::find_if(CalleeInfoList->second,
+ [&](const std::unique_ptr<GlobalValueSummary> &Summary) {
+ return Summary->modulePath() == ModuleId;
+ });
+ if (Summary == CalleeInfoList->second.end())
+ return nullptr;
+ return Summary->get();
+ }
+
+ /// Returns the first GlobalValueSummary for \p GV, asserting that there
+ /// is only one if \p PerModuleIndex.
+ GlobalValueSummary *getGlobalValueSummary(const GlobalValue &GV,
+ bool PerModuleIndex = true) const {
+ assert(GV.hasName() && "Can't get GlobalValueSummary for GV with no name");
+ return getGlobalValueSummary(GlobalValue::getGUID(GV.getName()),
+ PerModuleIndex);
+ }
+
+ /// Returns the first GlobalValueSummary for \p ValueGUID, asserting that
+ /// there
+ /// is only one if \p PerModuleIndex.
+ GlobalValueSummary *getGlobalValueSummary(GlobalValue::GUID ValueGUID,
+ bool PerModuleIndex = true) const;
+
+ /// Table of modules, containing module hash and id.
+ const StringMap<std::pair<uint64_t, ModuleHash>> &modulePaths() const {
+ return ModulePathStringTable;
+ }
+
+ /// Table of modules, containing hash and id.
+ StringMap<std::pair<uint64_t, ModuleHash>> &modulePaths() {
+ return ModulePathStringTable;
+ }
+
+ /// Get the module ID recorded for the given module path.
+ uint64_t getModuleId(const StringRef ModPath) const {
+ return ModulePathStringTable.lookup(ModPath).first;
+ }
+
+ /// Get the module SHA1 hash recorded for the given module path.
+ const ModuleHash &getModuleHash(const StringRef ModPath) const {
+ auto It = ModulePathStringTable.find(ModPath);
+ assert(It != ModulePathStringTable.end() && "Module not registered");
+ return It->second.second;
+ }
+
+ /// Add the given per-module index into this module index/summary,
+ /// assigning it the given module ID. Each module merged in should have
+ /// a unique ID, necessary for consistent renaming of promoted
+ /// static (local) variables.
+ void mergeFrom(std::unique_ptr<ModuleSummaryIndex> Other,
+ uint64_t NextModuleId);
+
+ /// Convenience method for creating a promoted global name
+ /// for the given value name of a local, and its original module's ID.
+ static std::string getGlobalNameForLocal(StringRef Name, ModuleHash ModHash) {
+ SmallString<256> NewName(Name);
+ NewName += ".llvm.";
+ NewName += utohexstr(ModHash[0]); // Take the first 32 bits
+ return NewName.str();
+ }
+
+ /// Helper to obtain the unpromoted name for a global value (or the original
+ /// name if not promoted).
+ static StringRef getOriginalNameBeforePromote(StringRef Name) {
+ std::pair<StringRef, StringRef> Pair = Name.split(".llvm.");
+ return Pair.first;
+ }
+
+ /// Add a new module path with the given \p Hash, mapped to the given \p
+ /// ModID, and return an iterator to the entry in the index.
+ ModulePathStringTableTy::iterator
+ addModulePath(StringRef ModPath, uint64_t ModId,
+ ModuleHash Hash = ModuleHash{{0}}) {
+ return ModulePathStringTable.insert(std::make_pair(
+ ModPath,
+ std::make_pair(ModId, Hash))).first;
+ }
+
+ /// Check if the given Module has any functions available for exporting
+ /// in the index. We consider any module present in the ModulePathStringTable
+ /// to have exported functions.
+ bool hasExportedFunctions(const Module &M) const {
+ return ModulePathStringTable.count(M.getModuleIdentifier());
+ }
+
+ /// Remove entries in the GlobalValueMap that have empty summaries due to the
+ /// eager nature of map entry creation during VST parsing. These would
+ /// also be suppressed during combined index generation in mergeFrom(),
+ /// but if there was only one module or this was the first module we might
+ /// not invoke mergeFrom.
+ void removeEmptySummaryEntries();
+
+ /// Collect for the given module the list of function it defines
+ /// (GUID -> Summary).
+ void collectDefinedFunctionsForModule(StringRef ModulePath,
+ GVSummaryMapTy &GVSummaryMap) const;
+
+ /// Collect for each module the list of Summaries it defines (GUID ->
+ /// Summary).
+ void collectDefinedGVSummariesPerModule(
+ StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries) const;
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/include/llvm/IR/Operator.h b/include/llvm/IR/Operator.h
index 372b254ab183..5880290f3d99 100644
--- a/include/llvm/IR/Operator.h
+++ b/include/llvm/IR/Operator.h
@@ -79,7 +79,7 @@ public:
};
private:
- friend class BinaryOperator;
+ friend class Instruction;
friend class ConstantExpr;
void setHasNoUnsignedWrap(bool B) {
SubclassOptionalData =
@@ -130,7 +130,7 @@ public:
};
private:
- friend class BinaryOperator;
+ friend class Instruction;
friend class ConstantExpr;
void setIsExact(bool B) {
SubclassOptionalData = (SubclassOptionalData & ~IsExact) | (B * IsExact);
@@ -401,6 +401,7 @@ public:
}
Type *getSourceElementType() const;
+ Type *getResultElementType() const;
/// Method to return the address space of the pointer operand.
unsigned getPointerAddressSpace() const {
diff --git a/include/llvm/IR/OptBisect.h b/include/llvm/IR/OptBisect.h
new file mode 100644
index 000000000000..9eee65e93e52
--- /dev/null
+++ b/include/llvm/IR/OptBisect.h
@@ -0,0 +1,81 @@
+//===----------- llvm/IR/OptBisect.h - LLVM Bisect support -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file declares the interface for bisecting optimizations.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_OPTBISECT_H
+#define LLVM_IR_OPTBISECT_H
+
+namespace llvm {
+
+class Pass;
+class StringRef;
+class Twine;
+
+/// This class implements a mechanism to disable passes and individual
+/// optimizations at compile time based on a command line option
+/// (-opt-bisect-limit) in order to perform a bisecting search for
+/// optimization-related problems.
+class OptBisect {
+public:
+ /// \brief Default constructor, initializes the OptBisect state based on the
+ /// -opt-bisect-limit command line argument.
+ ///
+ /// By default, bisection is disabled.
+ ///
+ /// Clients should not instantiate this class directly. All access should go
+ /// through LLVMContext.
+ OptBisect();
+
+ /// Checks the bisect limit to determine if the specified pass should run.
+ ///
+ /// This function will immediate return true if bisection is disabled. If the
+ /// bisect limit is set to -1, the function will print a message describing
+ /// the pass and the bisect number assigned to it and return true. Otherwise,
+ /// the function will print a message with the bisect number assigned to the
+ /// pass and indicating whether or not the pass will be run and return true if
+ /// the bisect limit has not yet been exceded or false if it has.
+ ///
+ /// Most passes should not call this routine directly. Instead, it is called
+ /// through a helper routine provided by the pass base class. For instance,
+ /// function passes should call FunctionPass::skipFunction().
+ template <class UnitT>
+ bool shouldRunPass(const Pass *P, const UnitT &U);
+
+ /// Checks the bisect limit to determine if the optimization described by the
+ /// /p Desc argument should run.
+ ///
+ /// This function will immediate return true if bisection is disabled. If the
+ /// bisect limit is set to -1, the function will print a message with the
+ /// bisect number assigned to the optimization along with the /p Desc
+ /// description and return true. Otherwise, the function will print a message
+ /// with the bisect number assigned to the optimization and indicating whether
+ /// or not the pass will be run and return true if the bisect limit has not
+ /// yet been exceded or false if it has.
+ ///
+ /// Passes may call this function to provide more fine grained control over
+ /// individual optimizations performed by the pass. Passes which cannot be
+ /// skipped entirely (such as non-optional code generation passes) may still
+ /// call this function to control whether or not individual optional
+ /// transformations are performed.
+ bool shouldRunCase(const Twine &Desc);
+
+private:
+ bool checkPass(const StringRef PassName, const StringRef TargetDesc);
+
+ bool BisectEnabled = false;
+ unsigned LastBisectNum = 0;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_IR_OPTBISECT_H
diff --git a/include/llvm/IR/PassManager.h b/include/llvm/IR/PassManager.h
index 2ceb53d21b7a..402d04a54a41 100644
--- a/include/llvm/IR/PassManager.h
+++ b/include/llvm/IR/PassManager.h
@@ -44,8 +44,8 @@
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManagerInternal.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/TypeName.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/type_traits.h"
#include <list>
@@ -54,9 +54,6 @@
namespace llvm {
-class Module;
-class Function;
-
/// \brief An abstract set of preserved analyses following a transformation pass
/// run.
///
@@ -147,6 +144,16 @@ public:
PreservedPassIDs.count(PassID);
}
+ /// \brief Query whether all of the analyses in the set are preserved.
+ bool preserved(PreservedAnalyses Arg) {
+ if (Arg.areAllPreserved())
+ return areAllPreserved();
+ for (void *P : Arg.PreservedPassIDs)
+ if (!preserved(P))
+ return false;
+ return true;
+ }
+
/// \brief Test whether all passes are preserved.
///
/// This is used primarily to optimize for the case of no changes which will
@@ -166,6 +173,44 @@ private:
// Forward declare the analysis manager template.
template <typename IRUnitT> class AnalysisManager;
+/// A CRTP mix-in to automatically provide informational APIs needed for
+/// passes.
+///
+/// This provides some boiler plate for types that are passes.
+template <typename DerivedT> struct PassInfoMixin {
+ /// Returns the name of the derived pass type.
+ static StringRef name() {
+ StringRef Name = getTypeName<DerivedT>();
+ if (Name.startswith("llvm::"))
+ Name = Name.drop_front(strlen("llvm::"));
+ return Name;
+ }
+};
+
+/// A CRTP mix-in to automatically provide informational APIs needed for
+/// analysis passes.
+///
+/// This provides some boiler plate for types that are analysis passes. It
+/// automatically mixes in \c PassInfoMixin and adds informational APIs
+/// specifically used for analyses.
+template <typename DerivedT>
+struct AnalysisInfoMixin : PassInfoMixin<DerivedT> {
+ /// Returns an opaque, unique ID for this pass type.
+ ///
+ /// Note that this requires the derived type provide a static member whose
+ /// address can be converted to a void pointer.
+ ///
+ /// FIXME: The only reason the derived type needs to provide this rather than
+ /// this mixin providing it is due to broken implementations which cannot
+ /// correctly unique a templated static so that they have the same addresses
+ /// for each instantiation and are definitively emitted once for each
+ /// instantiation. The only currently known platform with this limitation are
+ /// Windows DLL builds, specifically building each part of LLVM as a DLL. If
+ /// we ever remove that build configuration, this mixin can provide the
+ /// static PassID as well.
+ static void *ID() { return (void *)&DerivedT::PassID; }
+};
+
/// \brief Manages a sequence of passes over units of IR.
///
/// A pass manager contains a sequence of passes to run over units of IR. It is
@@ -177,7 +222,8 @@ template <typename IRUnitT> class AnalysisManager;
/// that analysis manager to each pass it runs, as well as calling the analysis
/// manager's invalidation routine with the PreservedAnalyses of each pass it
/// runs.
-template <typename IRUnitT> class PassManager {
+template <typename IRUnitT>
+class PassManager : public PassInfoMixin<PassManager<IRUnitT>> {
public:
/// \brief Construct a pass manager.
///
@@ -195,11 +241,11 @@ public:
}
/// \brief Run all of the passes in this manager over the IR.
- PreservedAnalyses run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM = nullptr) {
+ PreservedAnalyses run(IRUnitT &IR, AnalysisManager<IRUnitT> &AM) {
PreservedAnalyses PA = PreservedAnalyses::all();
if (DebugLogging)
- dbgs() << "Starting pass manager run.\n";
+ dbgs() << "Starting " << getTypeName<IRUnitT>() << " pass manager run.\n";
for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx) {
if (DebugLogging)
@@ -208,13 +254,11 @@ public:
PreservedAnalyses PassPA = Passes[Idx]->run(IR, AM);
- // If we have an active analysis manager at this level we want to ensure
- // we update it as each pass runs and potentially invalidates analyses.
- // We also update the preserved set of analyses based on what analyses we
- // have already handled the invalidation for here and don't need to
- // invalidate when finished.
- if (AM)
- PassPA = AM->invalidate(IR, std::move(PassPA));
+ // Update the analysis manager as each pass runs and potentially
+ // invalidates analyses. We also update the preserved set of analyses
+ // based on what analyses we have already handled the invalidation for
+ // here and don't need to invalidate when finished.
+ PassPA = AM.invalidate(IR, std::move(PassPA));
// Finally, we intersect the final preserved analyses to compute the
// aggregate preserved set for this pass manager.
@@ -228,7 +272,7 @@ public:
}
if (DebugLogging)
- dbgs() << "Finished pass manager run.\n";
+ dbgs() << "Finished " << getTypeName<IRUnitT>() << " pass manager run.\n";
return PA;
}
@@ -238,8 +282,6 @@ public:
Passes.emplace_back(new PassModelT(std::move(Pass)));
}
- static StringRef name() { return "PassManager"; }
-
private:
typedef detail::PassConcept<IRUnitT> PassConceptT;
@@ -252,9 +294,11 @@ private:
bool DebugLogging;
};
+extern template class PassManager<Module>;
/// \brief Convenience typedef for a pass manager over modules.
typedef PassManager<Module> ModulePassManager;
+extern template class PassManager<Function>;
/// \brief Convenience typedef for a pass manager over functions.
typedef PassManager<Function> FunctionPassManager;
@@ -284,8 +328,7 @@ template <typename DerivedT, typename IRUnitT> class AnalysisManagerBase {
}
AnalysisManagerBase(const AnalysisManagerBase &) = delete;
- AnalysisManagerBase &
- operator=(const AnalysisManagerBase &) = delete;
+ AnalysisManagerBase &operator=(const AnalysisManagerBase &) = delete;
protected:
typedef detail::AnalysisResultConcept<IRUnitT> ResultConceptT;
@@ -342,14 +385,34 @@ public:
/// \brief Register an analysis pass with the manager.
///
- /// This provides an initialized and set-up analysis pass to the analysis
- /// manager. Whomever is setting up analysis passes must use this to populate
- /// the manager with all of the analysis passes available.
- template <typename PassT> void registerPass(PassT Pass) {
- assert(!AnalysisPasses.count(PassT::ID()) &&
- "Registered the same analysis pass twice!");
+ /// The argument is a callable whose result is a pass. This allows passing in
+ /// a lambda to construct the pass.
+ ///
+ /// The pass type registered is the result type of calling the argument. If
+ /// that pass has already been registered, then the argument will not be
+ /// called and this function will return false. Otherwise, the pass type
+ /// becomes registered, with the instance provided by calling the argument
+ /// once, and this function returns true.
+ ///
+ /// While this returns whether or not the pass type was already registered,
+ /// there in't an independent way to query that as that would be prone to
+ /// risky use when *querying* the analysis manager. Instead, the only
+ /// supported use case is avoiding duplicate registry of an analysis. This
+ /// interface also lends itself to minimizing the number of times we have to
+ /// do lookups for analyses or construct complex passes only to throw them
+ /// away.
+ template <typename PassBuilderT> bool registerPass(PassBuilderT PassBuilder) {
+ typedef decltype(PassBuilder()) PassT;
typedef detail::AnalysisPassModel<IRUnitT, PassT> PassModelT;
- AnalysisPasses[PassT::ID()].reset(new PassModelT(std::move(Pass)));
+
+ auto &PassPtr = AnalysisPasses[PassT::ID()];
+ if (PassPtr)
+ // Already registered this pass type!
+ return false;
+
+ // Construct a new model around the instance returned by the builder.
+ PassPtr.reset(new PassModelT(PassBuilder()));
+ return true;
}
/// \brief Invalidate a specific analysis pass for an IR module.
@@ -472,7 +535,7 @@ private:
if (DebugLogging)
dbgs() << "Running analysis: " << P.name() << "\n";
AnalysisResultListT &ResultList = AnalysisResultLists[&IR];
- ResultList.emplace_back(PassID, P.run(IR, this));
+ ResultList.emplace_back(PassID, P.run(IR, *this));
// P.run may have inserted elements into AnalysisResults and invalidated
// RI.
@@ -513,8 +576,8 @@ private:
return PA;
if (DebugLogging)
- dbgs() << "Invalidating all non-preserved analyses for: "
- << IR.getName() << "\n";
+ dbgs() << "Invalidating all non-preserved analyses for: " << IR.getName()
+ << "\n";
// Clear all the invalidated results associated specifically with this
// function.
@@ -574,7 +637,8 @@ private:
/// \brief Map type from a pair of analysis ID and function pointer to an
/// iterator into a particular result list.
typedef DenseMap<std::pair<void *, IRUnitT *>,
- typename AnalysisResultListT::iterator> AnalysisResultMapT;
+ typename AnalysisResultListT::iterator>
+ AnalysisResultMapT;
/// \brief Map from an analysis ID and function to a particular cached
/// analysis result.
@@ -584,9 +648,11 @@ private:
bool DebugLogging;
};
+extern template class AnalysisManager<Module>;
/// \brief Convenience typedef for the Module analysis manager.
typedef AnalysisManager<Module> ModuleAnalysisManager;
+extern template class AnalysisManager<Function>;
/// \brief Convenience typedef for the Function analysis manager.
typedef AnalysisManager<Function> FunctionAnalysisManager;
@@ -598,26 +664,80 @@ typedef AnalysisManager<Function> FunctionAnalysisManager;
/// never use a function analysis manager from within (transitively) a module
/// pass manager unless your parent module pass has received a proxy result
/// object for it.
-class FunctionAnalysisManagerModuleProxy {
+///
+/// Note that the proxy's result is a move-only object and represents ownership
+/// of the validity of the analyses in the \c FunctionAnalysisManager it
+/// provides.
+template <typename AnalysisManagerT, typename IRUnitT>
+class InnerAnalysisManagerProxy
+ : public AnalysisInfoMixin<
+ InnerAnalysisManagerProxy<AnalysisManagerT, IRUnitT>> {
public:
- class Result;
+ class Result {
+ public:
+ explicit Result(AnalysisManagerT &AM) : AM(&AM) {}
+ Result(Result &&Arg) : AM(std::move(Arg.AM)) {
+ // We have to null out the analysis manager in the moved-from state
+ // because we are taking ownership of the responsibilty to clear the
+ // analysis state.
+ Arg.AM = nullptr;
+ }
+ Result &operator=(Result &&RHS) {
+ AM = RHS.AM;
+ // We have to null out the analysis manager in the moved-from state
+ // because we are taking ownership of the responsibilty to clear the
+ // analysis state.
+ RHS.AM = nullptr;
+ return *this;
+ }
+ ~Result() {
+ // AM is cleared in a moved from state where there is nothing to do.
+ if (!AM)
+ return;
+
+ // Clear out the analysis manager if we're being destroyed -- it means we
+ // didn't even see an invalidate call when we got invalidated.
+ AM->clear();
+ }
- static void *ID() { return (void *)&PassID; }
+ /// \brief Accessor for the analysis manager.
+ AnalysisManagerT &getManager() { return *AM; }
+
+ /// \brief Handler for invalidation of the module.
+ ///
+ /// If this analysis itself is preserved, then we assume that the set of \c
+ /// Function objects in the \c Module hasn't changed and thus we don't need
+ /// to invalidate *all* cached data associated with a \c Function* in the \c
+ /// FunctionAnalysisManager.
+ ///
+ /// Regardless of whether this analysis is marked as preserved, all of the
+ /// analyses in the \c FunctionAnalysisManager are potentially invalidated
+ /// based on the set of preserved analyses.
+ bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA) {
+ // If this proxy isn't marked as preserved, then we can't even invalidate
+ // individual function analyses, there may be an invalid set of Function
+ // objects in the cache making it impossible to incrementally preserve
+ // them. Just clear the entire manager.
+ if (!PA.preserved(InnerAnalysisManagerProxy::ID()))
+ AM->clear();
+
+ // Return false to indicate that this result is still a valid proxy.
+ return false;
+ }
- static StringRef name() { return "FunctionAnalysisManagerModuleProxy"; }
+ private:
+ AnalysisManagerT *AM;
+ };
- explicit FunctionAnalysisManagerModuleProxy(FunctionAnalysisManager &FAM)
- : FAM(&FAM) {}
+ explicit InnerAnalysisManagerProxy(AnalysisManagerT &AM) : AM(&AM) {}
// We have to explicitly define all the special member functions because MSVC
// refuses to generate them.
- FunctionAnalysisManagerModuleProxy(
- const FunctionAnalysisManagerModuleProxy &Arg)
- : FAM(Arg.FAM) {}
- FunctionAnalysisManagerModuleProxy(FunctionAnalysisManagerModuleProxy &&Arg)
- : FAM(std::move(Arg.FAM)) {}
- FunctionAnalysisManagerModuleProxy &
- operator=(FunctionAnalysisManagerModuleProxy RHS) {
- std::swap(FAM, RHS.FAM);
+ InnerAnalysisManagerProxy(const InnerAnalysisManagerProxy &Arg)
+ : AM(Arg.AM) {}
+ InnerAnalysisManagerProxy(InnerAnalysisManagerProxy &&Arg)
+ : AM(std::move(Arg.AM)) {}
+ InnerAnalysisManagerProxy &operator=(InnerAnalysisManagerProxy RHS) {
+ std::swap(AM, RHS.AM);
return *this;
}
@@ -630,49 +750,24 @@ public:
/// In debug builds, it will also assert that the analysis manager is empty
/// as no queries should arrive at the function analysis manager prior to
/// this analysis being requested.
- Result run(Module &M);
+ Result run(IRUnitT &IR, AnalysisManager<IRUnitT> &) { return Result(*AM); }
private:
+ friend AnalysisInfoMixin<
+ InnerAnalysisManagerProxy<AnalysisManagerT, IRUnitT>>;
static char PassID;
- FunctionAnalysisManager *FAM;
+ AnalysisManagerT *AM;
};
-/// \brief The result proxy object for the
-/// \c FunctionAnalysisManagerModuleProxy.
-///
-/// See its documentation for more information.
-class FunctionAnalysisManagerModuleProxy::Result {
-public:
- explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {}
- // We have to explicitly define all the special member functions because MSVC
- // refuses to generate them.
- Result(const Result &Arg) : FAM(Arg.FAM) {}
- Result(Result &&Arg) : FAM(std::move(Arg.FAM)) {}
- Result &operator=(Result RHS) {
- std::swap(FAM, RHS.FAM);
- return *this;
- }
- ~Result();
-
- /// \brief Accessor for the \c FunctionAnalysisManager.
- FunctionAnalysisManager &getManager() { return *FAM; }
-
- /// \brief Handler for invalidation of the module.
- ///
- /// If this analysis itself is preserved, then we assume that the set of \c
- /// Function objects in the \c Module hasn't changed and thus we don't need
- /// to invalidate *all* cached data associated with a \c Function* in the \c
- /// FunctionAnalysisManager.
- ///
- /// Regardless of whether this analysis is marked as preserved, all of the
- /// analyses in the \c FunctionAnalysisManager are potentially invalidated
- /// based on the set of preserved analyses.
- bool invalidate(Module &M, const PreservedAnalyses &PA);
+template <typename AnalysisManagerT, typename IRUnitT>
+char InnerAnalysisManagerProxy<AnalysisManagerT, IRUnitT>::PassID;
-private:
- FunctionAnalysisManager *FAM;
-};
+extern template class InnerAnalysisManagerProxy<FunctionAnalysisManager,
+ Module>;
+/// Provide the \c FunctionAnalysisManager to \c Module proxy.
+typedef InnerAnalysisManagerProxy<FunctionAnalysisManager, Module>
+ FunctionAnalysisManagerModuleProxy;
/// \brief A function analysis which acts as a proxy for a module analysis
/// manager.
@@ -686,60 +781,67 @@ private:
/// This proxy *doesn't* manage the invalidation in any way. That is handled by
/// the recursive return path of each layer of the pass manager and the
/// returned PreservedAnalysis set.
-class ModuleAnalysisManagerFunctionProxy {
+template <typename AnalysisManagerT, typename IRUnitT>
+class OuterAnalysisManagerProxy
+ : public AnalysisInfoMixin<
+ OuterAnalysisManagerProxy<AnalysisManagerT, IRUnitT>> {
public:
- /// \brief Result proxy object for \c ModuleAnalysisManagerFunctionProxy.
+ /// \brief Result proxy object for \c OuterAnalysisManagerProxy.
class Result {
public:
- explicit Result(const ModuleAnalysisManager &MAM) : MAM(&MAM) {}
+ explicit Result(const AnalysisManagerT &AM) : AM(&AM) {}
// We have to explicitly define all the special member functions because
// MSVC refuses to generate them.
- Result(const Result &Arg) : MAM(Arg.MAM) {}
- Result(Result &&Arg) : MAM(std::move(Arg.MAM)) {}
+ Result(const Result &Arg) : AM(Arg.AM) {}
+ Result(Result &&Arg) : AM(std::move(Arg.AM)) {}
Result &operator=(Result RHS) {
- std::swap(MAM, RHS.MAM);
+ std::swap(AM, RHS.AM);
return *this;
}
- const ModuleAnalysisManager &getManager() const { return *MAM; }
+ const AnalysisManagerT &getManager() const { return *AM; }
/// \brief Handle invalidation by ignoring it, this pass is immutable.
- bool invalidate(Function &) { return false; }
+ bool invalidate(IRUnitT &) { return false; }
private:
- const ModuleAnalysisManager *MAM;
+ const AnalysisManagerT *AM;
};
- static void *ID() { return (void *)&PassID; }
-
- static StringRef name() { return "ModuleAnalysisManagerFunctionProxy"; }
-
- ModuleAnalysisManagerFunctionProxy(const ModuleAnalysisManager &MAM)
- : MAM(&MAM) {}
+ OuterAnalysisManagerProxy(const AnalysisManagerT &AM) : AM(&AM) {}
// We have to explicitly define all the special member functions because MSVC
// refuses to generate them.
- ModuleAnalysisManagerFunctionProxy(
- const ModuleAnalysisManagerFunctionProxy &Arg)
- : MAM(Arg.MAM) {}
- ModuleAnalysisManagerFunctionProxy(ModuleAnalysisManagerFunctionProxy &&Arg)
- : MAM(std::move(Arg.MAM)) {}
- ModuleAnalysisManagerFunctionProxy &
- operator=(ModuleAnalysisManagerFunctionProxy RHS) {
- std::swap(MAM, RHS.MAM);
+ OuterAnalysisManagerProxy(const OuterAnalysisManagerProxy &Arg)
+ : AM(Arg.AM) {}
+ OuterAnalysisManagerProxy(OuterAnalysisManagerProxy &&Arg)
+ : AM(std::move(Arg.AM)) {}
+ OuterAnalysisManagerProxy &operator=(OuterAnalysisManagerProxy RHS) {
+ std::swap(AM, RHS.AM);
return *this;
}
/// \brief Run the analysis pass and create our proxy result object.
- /// Nothing to see here, it just forwards the \c MAM reference into the
+ /// Nothing to see here, it just forwards the \c AM reference into the
/// result.
- Result run(Function &) { return Result(*MAM); }
+ Result run(IRUnitT &, AnalysisManager<IRUnitT> &) { return Result(*AM); }
private:
+ friend AnalysisInfoMixin<
+ OuterAnalysisManagerProxy<AnalysisManagerT, IRUnitT>>;
static char PassID;
- const ModuleAnalysisManager *MAM;
+ const AnalysisManagerT *AM;
};
+template <typename AnalysisManagerT, typename IRUnitT>
+char OuterAnalysisManagerProxy<AnalysisManagerT, IRUnitT>::PassID;
+
+extern template class OuterAnalysisManagerProxy<ModuleAnalysisManager,
+ Function>;
+/// Provide the \c ModuleAnalysisManager to \c Fucntion proxy.
+typedef OuterAnalysisManagerProxy<ModuleAnalysisManager, Function>
+ ModuleAnalysisManagerFunctionProxy;
+
/// \brief Trivial adaptor that maps from a module to its functions.
///
/// Designed to allow composition of a FunctionPass(Manager) and
@@ -762,7 +864,9 @@ private:
/// module.
/// FIXME: Make the above true for all of LLVM's actual passes, some still
/// violate this principle.
-template <typename FunctionPassT> class ModuleToFunctionPassAdaptor {
+template <typename FunctionPassT>
+class ModuleToFunctionPassAdaptor
+ : public PassInfoMixin<ModuleToFunctionPassAdaptor<FunctionPassT>> {
public:
explicit ModuleToFunctionPassAdaptor(FunctionPassT Pass)
: Pass(std::move(Pass)) {}
@@ -783,11 +887,10 @@ public:
}
/// \brief Runs the function pass across every function in the module.
- PreservedAnalyses run(Module &M, ModuleAnalysisManager *AM) {
- FunctionAnalysisManager *FAM = nullptr;
- if (AM)
- // Setup the function analysis manager from its proxy.
- FAM = &AM->getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
+ PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) {
+ // Setup the function analysis manager from its proxy.
+ FunctionAnalysisManager &FAM =
+ AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
PreservedAnalyses PA = PreservedAnalyses::all();
for (Function &F : M) {
@@ -801,8 +904,7 @@ public:
// directly handle the function analysis manager's invalidation here and
// update our preserved set to reflect that these have already been
// handled.
- if (FAM)
- PassPA = FAM->invalidate(F, std::move(PassPA));
+ PassPA = FAM.invalidate(F, std::move(PassPA));
// Then intersect the preserved set so that invalidation of module
// analyses will eventually occur when the module pass completes.
@@ -817,8 +919,6 @@ public:
return PA;
}
- static StringRef name() { return "ModuleToFunctionPassAdaptor"; }
-
private:
FunctionPassT Pass;
};
@@ -835,7 +935,8 @@ createModuleToFunctionPassAdaptor(FunctionPassT Pass) {
///
/// This is a no-op pass which simply forces a specific analysis pass's result
/// to be available when it is run.
-template <typename AnalysisT> struct RequireAnalysisPass {
+template <typename AnalysisT>
+struct RequireAnalysisPass : PassInfoMixin<RequireAnalysisPass<AnalysisT>> {
/// \brief Run this pass over some unit of IR.
///
/// This pass can be run over any unit of IR and use any analysis manager
@@ -843,14 +944,11 @@ template <typename AnalysisT> struct RequireAnalysisPass {
/// created, these methods can be instantiated to satisfy whatever the
/// context requires.
template <typename IRUnitT>
- PreservedAnalyses run(IRUnitT &Arg, AnalysisManager<IRUnitT> *AM) {
- if (AM)
- (void)AM->template getResult<AnalysisT>(Arg);
+ PreservedAnalyses run(IRUnitT &Arg, AnalysisManager<IRUnitT> &AM) {
+ (void)AM.template getResult<AnalysisT>(Arg);
return PreservedAnalyses::all();
}
-
- static StringRef name() { return "RequireAnalysisPass"; }
};
/// \brief A template utility pass to force an analysis result to be
@@ -858,7 +956,9 @@ template <typename AnalysisT> struct RequireAnalysisPass {
///
/// This is a no-op pass which simply forces a specific analysis result to be
/// invalidated when it is run.
-template <typename AnalysisT> struct InvalidateAnalysisPass {
+template <typename AnalysisT>
+struct InvalidateAnalysisPass
+ : PassInfoMixin<InvalidateAnalysisPass<AnalysisT>> {
/// \brief Run this pass over some unit of IR.
///
/// This pass can be run over any unit of IR and use any analysis manager
@@ -866,29 +966,25 @@ template <typename AnalysisT> struct InvalidateAnalysisPass {
/// created, these methods can be instantiated to satisfy whatever the
/// context requires.
template <typename IRUnitT>
- PreservedAnalyses run(IRUnitT &Arg, AnalysisManager<IRUnitT> *AM) {
- if (AM)
- // We have to directly invalidate the analysis result as we can't
- // enumerate all other analyses and use the preserved set to control it.
- (void)AM->template invalidate<AnalysisT>(Arg);
+ PreservedAnalyses run(IRUnitT &Arg, AnalysisManager<IRUnitT> &AM) {
+ // We have to directly invalidate the analysis result as we can't
+ // enumerate all other analyses and use the preserved set to control it.
+ AM.template invalidate<AnalysisT>(Arg);
return PreservedAnalyses::all();
}
-
- static StringRef name() { return "InvalidateAnalysisPass"; }
};
/// \brief A utility pass that does nothing but preserves no analyses.
///
/// As a consequence fo not preserving any analyses, this pass will force all
/// analysis passes to be re-run to produce fresh results if any are needed.
-struct InvalidateAllAnalysesPass {
+struct InvalidateAllAnalysesPass : PassInfoMixin<InvalidateAllAnalysesPass> {
/// \brief Run this pass over some unit of IR.
- template <typename IRUnitT> PreservedAnalyses run(IRUnitT &Arg) {
+ template <typename IRUnitT>
+ PreservedAnalyses run(IRUnitT &, AnalysisManager<IRUnitT> &) {
return PreservedAnalyses::none();
}
-
- static StringRef name() { return "InvalidateAllAnalysesPass"; }
};
}
diff --git a/include/llvm/IR/PassManagerInternal.h b/include/llvm/IR/PassManagerInternal.h
index 92de10bcd75b..4351b5888283 100644
--- a/include/llvm/IR/PassManagerInternal.h
+++ b/include/llvm/IR/PassManagerInternal.h
@@ -18,8 +18,8 @@
#ifndef LLVM_IR_PASSMANAGERINTERNAL_H
#define LLVM_IR_PASSMANAGERINTERNAL_H
-#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
namespace llvm {
@@ -40,48 +40,20 @@ template <typename IRUnitT> struct PassConcept {
/// Note that actual pass object can omit the analysis manager argument if
/// desired. Also that the analysis manager may be null if there is no
/// analysis manager in the pass pipeline.
- virtual PreservedAnalyses run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM) = 0;
+ virtual PreservedAnalyses run(IRUnitT &IR, AnalysisManager<IRUnitT> &AM) = 0;
/// \brief Polymorphic method to access the name of a pass.
virtual StringRef name() = 0;
};
-/// \brief SFINAE metafunction for computing whether \c PassT has a run method
-/// accepting an \c AnalysisManager<IRUnitT>.
-template <typename IRUnitT, typename PassT, typename ResultT>
-class PassRunAcceptsAnalysisManager {
- typedef char SmallType;
- struct BigType {
- char a, b;
- };
-
- template <typename T, ResultT (T::*)(IRUnitT &, AnalysisManager<IRUnitT> *)>
- struct Checker;
-
- template <typename T> static SmallType f(Checker<T, &T::run> *);
- template <typename T> static BigType f(...);
-
-public:
- enum { Value = sizeof(f<PassT>(nullptr)) == sizeof(SmallType) };
-};
-
/// \brief A template wrapper used to implement the polymorphic API.
///
/// Can be instantiated for any object which provides a \c run method accepting
-/// an \c IRUnitT. It requires the pass to be a copyable object. When the
-/// \c run method also accepts an \c AnalysisManager<IRUnitT>*, we pass it
-/// along.
+/// an \c IRUnitT& and an \c AnalysisManager<IRUnit>&. It requires the pass to
+/// be a copyable object. When the
template <typename IRUnitT, typename PassT,
- typename PreservedAnalysesT = PreservedAnalyses,
- bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager<
- IRUnitT, PassT, PreservedAnalysesT>::Value>
-struct PassModel;
-
-/// \brief Specialization of \c PassModel for passes that accept an analyis
-/// manager.
-template <typename IRUnitT, typename PassT, typename PreservedAnalysesT>
-struct PassModel<IRUnitT, PassT, PreservedAnalysesT, true>
- : PassConcept<IRUnitT> {
+ typename PreservedAnalysesT = PreservedAnalyses>
+struct PassModel : PassConcept<IRUnitT> {
explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {}
// We have to explicitly define all the special member functions because MSVC
// refuses to generate them.
@@ -96,39 +68,13 @@ struct PassModel<IRUnitT, PassT, PreservedAnalysesT, true>
return *this;
}
- PreservedAnalysesT run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM) override {
+ PreservedAnalysesT run(IRUnitT &IR, AnalysisManager<IRUnitT> &AM) override {
return Pass.run(IR, AM);
}
StringRef name() override { return PassT::name(); }
PassT Pass;
};
-/// \brief Specialization of \c PassModel for passes that accept an analyis
-/// manager.
-template <typename IRUnitT, typename PassT, typename PreservedAnalysesT>
-struct PassModel<IRUnitT, PassT, PreservedAnalysesT, false>
- : PassConcept<IRUnitT> {
- explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {}
- // We have to explicitly define all the special member functions because MSVC
- // refuses to generate them.
- PassModel(const PassModel &Arg) : Pass(Arg.Pass) {}
- PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
- friend void swap(PassModel &LHS, PassModel &RHS) {
- using std::swap;
- swap(LHS.Pass, RHS.Pass);
- }
- PassModel &operator=(PassModel RHS) {
- swap(*this, RHS);
- return *this;
- }
-
- PreservedAnalysesT run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM) override {
- return Pass.run(IR);
- }
- StringRef name() override { return PassT::name(); }
- PassT Pass;
-};
-
/// \brief Abstract concept of an analysis result.
///
/// This concept is parameterized over the IR unit that this result pertains
@@ -252,7 +198,7 @@ template <typename IRUnitT> struct AnalysisPassConcept {
/// \returns A unique_ptr to the analysis result object to be queried by
/// users.
virtual std::unique_ptr<AnalysisResultConcept<IRUnitT>>
- run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM) = 0;
+ run(IRUnitT &IR, AnalysisManager<IRUnitT> &AM) = 0;
/// \brief Polymorphic method to access the name of a pass.
virtual StringRef name() = 0;
@@ -261,17 +207,10 @@ template <typename IRUnitT> struct AnalysisPassConcept {
/// \brief Wrapper to model the analysis pass concept.
///
/// Can wrap any type which implements a suitable \c run method. The method
-/// must accept the IRUnitT as an argument and produce an object which can be
-/// wrapped in a \c AnalysisResultModel.
-template <typename IRUnitT, typename PassT,
- bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager<
- IRUnitT, PassT, typename PassT::Result>::Value>
-struct AnalysisPassModel;
-
-/// \brief Specialization of \c AnalysisPassModel which passes an
-/// \c AnalysisManager to PassT's run method.
+/// must accept an \c IRUnitT& and an \c AnalysisManager<IRUnitT>& as arguments
+/// and produce an object which can be wrapped in a \c AnalysisResultModel.
template <typename IRUnitT, typename PassT>
-struct AnalysisPassModel<IRUnitT, PassT, true> : AnalysisPassConcept<IRUnitT> {
+struct AnalysisPassModel : AnalysisPassConcept<IRUnitT> {
explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {}
// We have to explicitly define all the special member functions because MSVC
// refuses to generate them.
@@ -294,7 +233,7 @@ struct AnalysisPassModel<IRUnitT, PassT, true> : AnalysisPassConcept<IRUnitT> {
///
/// The return is wrapped in an \c AnalysisResultModel.
std::unique_ptr<AnalysisResultConcept<IRUnitT>>
- run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM) override {
+ run(IRUnitT &IR, AnalysisManager<IRUnitT> &AM) override {
return make_unique<ResultModelT>(Pass.run(IR, AM));
}
@@ -306,44 +245,6 @@ struct AnalysisPassModel<IRUnitT, PassT, true> : AnalysisPassConcept<IRUnitT> {
PassT Pass;
};
-/// \brief Specialization of \c AnalysisPassModel which does not pass an
-/// \c AnalysisManager to PassT's run method.
-template <typename IRUnitT, typename PassT>
-struct AnalysisPassModel<IRUnitT, PassT, false> : AnalysisPassConcept<IRUnitT> {
- explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {}
- // We have to explicitly define all the special member functions because MSVC
- // refuses to generate them.
- AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {}
- AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
- friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) {
- using std::swap;
- swap(LHS.Pass, RHS.Pass);
- }
- AnalysisPassModel &operator=(AnalysisPassModel RHS) {
- swap(*this, RHS);
- return *this;
- }
-
- // FIXME: Replace PassT::Result with type traits when we use C++11.
- typedef AnalysisResultModel<IRUnitT, PassT, typename PassT::Result>
- ResultModelT;
-
- /// \brief The model delegates to the \c PassT::run method.
- ///
- /// The return is wrapped in an \c AnalysisResultModel.
- std::unique_ptr<AnalysisResultConcept<IRUnitT>>
- run(IRUnitT &IR, AnalysisManager<IRUnitT> *) override {
- return make_unique<ResultModelT>(Pass.run(IR));
- }
-
- /// \brief The model delegates to a static \c PassT::name method.
- ///
- /// The returned string ref must point to constant immutable data!
- StringRef name() override { return PassT::name(); }
-
- PassT Pass;
-};
-
} // End namespace detail
}
diff --git a/include/llvm/IR/PatternMatch.h b/include/llvm/IR/PatternMatch.h
index f4d7d8c44416..7da9afcf9463 100644
--- a/include/llvm/IR/PatternMatch.h
+++ b/include/llvm/IR/PatternMatch.h
@@ -1312,6 +1312,43 @@ template <typename Val_t> inline Signum_match<Val_t> m_Signum(const Val_t &V) {
return Signum_match<Val_t>(V);
}
+//===----------------------------------------------------------------------===//
+// Matchers for two-operands operators with the operators in either order
+//
+
+/// \brief Matches an ICmp with a predicate over LHS and RHS in either order.
+/// Does not swap the predicate.
+template<typename LHS, typename RHS>
+inline match_combine_or<CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>,
+ CmpClass_match<RHS, LHS, ICmpInst, ICmpInst::Predicate>>
+m_c_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
+ return m_CombineOr(m_ICmp(Pred, L, R), m_ICmp(Pred, R, L));
+}
+
+/// \brief Matches an And with LHS and RHS in either order.
+template<typename LHS, typename RHS>
+inline match_combine_or<BinaryOp_match<LHS, RHS, Instruction::And>,
+ BinaryOp_match<RHS, LHS, Instruction::And>>
+m_c_And(const LHS &L, const RHS &R) {
+ return m_CombineOr(m_And(L, R), m_And(R, L));
+}
+
+/// \brief Matches an Or with LHS and RHS in either order.
+template<typename LHS, typename RHS>
+inline match_combine_or<BinaryOp_match<LHS, RHS, Instruction::Or>,
+ BinaryOp_match<RHS, LHS, Instruction::Or>>
+m_c_Or(const LHS &L, const RHS &R) {
+ return m_CombineOr(m_Or(L, R), m_Or(R, L));
+}
+
+/// \brief Matches an Xor with LHS and RHS in either order.
+template<typename LHS, typename RHS>
+inline match_combine_or<BinaryOp_match<LHS, RHS, Instruction::Xor>,
+ BinaryOp_match<RHS, LHS, Instruction::Xor>>
+m_c_Xor(const LHS &L, const RHS &R) {
+ return m_CombineOr(m_Xor(L, R), m_Xor(R, L));
+}
+
} // end namespace PatternMatch
} // end namespace llvm
diff --git a/include/llvm/IR/ProfileSummary.h b/include/llvm/IR/ProfileSummary.h
new file mode 100644
index 000000000000..f4248014c6e1
--- /dev/null
+++ b/include/llvm/IR/ProfileSummary.h
@@ -0,0 +1,85 @@
+//===-- ProfileSummary.h - Profile summary data structure. ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the profile summary data structure.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_PROFILE_SUMMARY_H
+#define LLVM_SUPPORT_PROFILE_SUMMARY_H
+
+#include <cstdint>
+#include <utility>
+#include <vector>
+
+#include "llvm/Support/Casting.h"
+
+namespace llvm {
+
+class LLVMContext;
+class Metadata;
+class MDTuple;
+class MDNode;
+
+// The profile summary is one or more (Cutoff, MinCount, NumCounts) triplets.
+// The semantics of counts depend on the type of profile. For instrumentation
+// profile, counts are block counts and for sample profile, counts are
+// per-line samples. Given a target counts percentile, we compute the minimum
+// number of counts needed to reach this target and the minimum among these
+// counts.
+struct ProfileSummaryEntry {
+ uint32_t Cutoff; ///< The required percentile of counts.
+ uint64_t MinCount; ///< The minimum count for this percentile.
+ uint64_t NumCounts; ///< Number of counts >= the minimum count.
+ ProfileSummaryEntry(uint32_t TheCutoff, uint64_t TheMinCount,
+ uint64_t TheNumCounts)
+ : Cutoff(TheCutoff), MinCount(TheMinCount), NumCounts(TheNumCounts) {}
+};
+
+typedef std::vector<ProfileSummaryEntry> SummaryEntryVector;
+
+class ProfileSummary {
+public:
+ enum Kind { PSK_Instr, PSK_Sample };
+
+private:
+ const Kind PSK;
+ static const char *KindStr[2];
+ SummaryEntryVector DetailedSummary;
+ uint64_t TotalCount, MaxCount, MaxInternalCount, MaxFunctionCount;
+ uint32_t NumCounts, NumFunctions;
+ /// \brief Return detailed summary as metadata.
+ Metadata *getDetailedSummaryMD(LLVMContext &Context);
+
+public:
+ static const int Scale = 1000000;
+ ProfileSummary(Kind K, SummaryEntryVector DetailedSummary,
+ uint64_t TotalCount, uint64_t MaxCount,
+ uint64_t MaxInternalCount, uint64_t MaxFunctionCount,
+ uint32_t NumCounts, uint32_t NumFunctions)
+ : PSK(K), DetailedSummary(std::move(DetailedSummary)),
+ TotalCount(TotalCount), MaxCount(MaxCount),
+ MaxInternalCount(MaxInternalCount), MaxFunctionCount(MaxFunctionCount),
+ NumCounts(NumCounts), NumFunctions(NumFunctions) {}
+ Kind getKind() const { return PSK; }
+ /// \brief Return summary information as metadata.
+ Metadata *getMD(LLVMContext &Context);
+ /// \brief Construct profile summary from metdata.
+ static ProfileSummary *getFromMD(Metadata *MD);
+ SummaryEntryVector &getDetailedSummary() { return DetailedSummary; }
+ uint32_t getNumFunctions() { return NumFunctions; }
+ uint64_t getMaxFunctionCount() { return MaxFunctionCount; }
+ uint32_t getNumCounts() { return NumCounts; }
+ uint64_t getTotalCount() { return TotalCount; }
+ uint64_t getMaxCount() { return MaxCount; }
+ uint64_t getMaxInternalCount() { return MaxInternalCount; }
+};
+
+} // end namespace llvm
+#endif
diff --git a/include/llvm/IR/Statepoint.h b/include/llvm/IR/Statepoint.h
index 51a0951a9798..5cd7fe1b576c 100644
--- a/include/llvm/IR/Statepoint.h
+++ b/include/llvm/IR/Statepoint.h
@@ -8,8 +8,9 @@
//===----------------------------------------------------------------------===//
//
// This file contains utility functions and a wrapper class analogous to
-// CallSite for accessing the fields of gc.statepoint, gc.relocate, and
-// gc.result intrinsics
+// CallSite for accessing the fields of gc.statepoint, gc.relocate,
+// gc.result intrinsics; and some general utilities helpful when dealing with
+// gc.statepoint.
//
//===----------------------------------------------------------------------===//
@@ -17,6 +18,7 @@
#define LLVM_IR_STATEPOINT_H
#include "llvm/ADT/iterator_range.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Constants.h"
@@ -24,7 +26,6 @@
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
-#include "llvm/Support/Compiler.h"
namespace llvm {
/// The statepoint intrinsic accepts a set of flags as its third argument.
@@ -38,23 +39,22 @@ enum class StatepointFlags {
};
class GCRelocateInst;
+class GCResultInst;
class ImmutableStatepoint;
-bool isStatepoint(const ImmutableCallSite &CS);
+bool isStatepoint(ImmutableCallSite CS);
bool isStatepoint(const Value *V);
bool isStatepoint(const Value &V);
-bool isGCRelocate(const ImmutableCallSite &CS);
-
-bool isGCResult(const Value *V);
-bool isGCResult(const ImmutableCallSite &CS);
+bool isGCRelocate(ImmutableCallSite CS);
+bool isGCResult(ImmutableCallSite CS);
/// Analogous to CallSiteBase, this provides most of the actual
/// functionality for Statepoint and ImmutableStatepoint. It is
/// templatized to allow easily specializing of const and non-const
/// concrete subtypes. This is structured analogous to CallSite
-/// rather than the IntrinsicInst.h helpers since we want to support
-/// invokable statepoints in the near future.
+/// rather than the IntrinsicInst.h helpers since we need to support
+/// invokable statepoints.
template <typename FunTy, typename InstructionTy, typename ValueTy,
typename CallSiteTy>
class StatepointBase {
@@ -252,11 +252,10 @@ public:
/// Get the experimental_gc_result call tied to this statepoint. Can be
/// nullptr if there isn't a gc_result tied to this statepoint. Guaranteed to
/// be a CallInst if non-null.
- InstructionTy *getGCResult() const {
+ const GCResultInst *getGCResult() const {
for (auto *U : getInstruction()->users())
- if (isGCResult(U))
- return cast<CallInst>(U);
-
+ if (auto *GRI = dyn_cast<GCResultInst>(U))
+ return GRI;
return nullptr;
}
@@ -305,11 +304,13 @@ public:
explicit Statepoint(CallSite CS) : Base(CS) {}
};
-/// This represents the gc.relocate intrinsic.
-class GCRelocateInst : public IntrinsicInst {
+/// Common base class for representing values projected from a statepoint.
+/// Currently, the only projections available are gc.result and gc.relocate.
+class GCProjectionInst : public IntrinsicInst {
public:
static inline bool classof(const IntrinsicInst *I) {
- return I->getIntrinsicID() == Intrinsic::experimental_gc_relocate;
+ return I->getIntrinsicID() == Intrinsic::experimental_gc_relocate ||
+ I->getIntrinsicID() == Intrinsic::experimental_gc_result;
}
static inline bool classof(const Value *V) {
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
@@ -330,6 +331,7 @@ public:
// This takes care both of relocates for call statepoints and relocates
// on normal path of invoke statepoint.
if (!isa<LandingPadInst>(Token)) {
+ assert(isStatepoint(Token));
return cast<Instruction>(Token);
}
@@ -344,6 +346,17 @@ public:
return InvokeBB->getTerminator();
}
+};
+
+/// Represents calls to the gc.relocate intrinsic.
+class GCRelocateInst : public GCProjectionInst {
+public:
+ static inline bool classof(const IntrinsicInst *I) {
+ return I->getIntrinsicID() == Intrinsic::experimental_gc_relocate;
+ }
+ static inline bool classof(const Value *V) {
+ return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
+ }
/// The index into the associate statepoint's argument list
/// which contains the base pointer of the pointer whose
@@ -369,6 +382,17 @@ public:
}
};
+/// Represents calls to the gc.result intrinsic.
+class GCResultInst : public GCProjectionInst {
+public:
+ static inline bool classof(const IntrinsicInst *I) {
+ return I->getIntrinsicID() == Intrinsic::experimental_gc_result;
+ }
+ static inline bool classof(const Value *V) {
+ return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
+ }
+};
+
template <typename FunTy, typename InstructionTy, typename ValueTy,
typename CallSiteTy>
std::vector<const GCRelocateInst *>
@@ -400,6 +424,26 @@ StatepointBase<FunTy, InstructionTy, ValueTy, CallSiteTy>::getRelocates()
}
return Result;
}
+
+/// Call sites that get wrapped by a gc.statepoint (currently only in
+/// RewriteStatepointsForGC and potentially in other passes in the future) can
+/// have attributes that describe properties of gc.statepoint call they will be
+/// eventually be wrapped in. This struct is used represent such directives.
+struct StatepointDirectives {
+ Optional<uint32_t> NumPatchBytes;
+ Optional<uint64_t> StatepointID;
+
+ static const uint64_t DefaultStatepointID = 0xABCDEF00;
+ static const uint64_t DeoptBundleStatepointID = 0xABCDEF0F;
+};
+
+/// Parse out statepoint directives from the function attributes present in \p
+/// AS.
+StatepointDirectives parseStatepointDirectivesFromAttrs(AttributeSet AS);
+
+/// Return \c true if the the \p Attr is an attribute that is a statepoint
+/// directive.
+bool isStatepointDirectiveAttr(Attribute Attr);
}
#endif
diff --git a/include/llvm/IR/SymbolTableListTraits.h b/include/llvm/IR/SymbolTableListTraits.h
index 5fc48d10d63f..60e04e2f9eca 100644
--- a/include/llvm/IR/SymbolTableListTraits.h
+++ b/include/llvm/IR/SymbolTableListTraits.h
@@ -49,6 +49,7 @@ class Function;
class Instruction;
class GlobalVariable;
class GlobalAlias;
+class GlobalIFunc;
class Module;
#define DEFINE_SYMBOL_TABLE_PARENT_TYPE(NODE, PARENT) \
template <> struct SymbolTableListParentType<NODE> { typedef PARENT type; };
@@ -58,6 +59,7 @@ DEFINE_SYMBOL_TABLE_PARENT_TYPE(Argument, Function)
DEFINE_SYMBOL_TABLE_PARENT_TYPE(Function, Module)
DEFINE_SYMBOL_TABLE_PARENT_TYPE(GlobalVariable, Module)
DEFINE_SYMBOL_TABLE_PARENT_TYPE(GlobalAlias, Module)
+DEFINE_SYMBOL_TABLE_PARENT_TYPE(GlobalIFunc, Module)
#undef DEFINE_SYMBOL_TABLE_PARENT_TYPE
template <typename NodeTy> class SymbolTableList;
diff --git a/include/llvm/IR/TrackingMDRef.h b/include/llvm/IR/TrackingMDRef.h
index 97efaff7a377..fe513a8f9795 100644
--- a/include/llvm/IR/TrackingMDRef.h
+++ b/include/llvm/IR/TrackingMDRef.h
@@ -15,7 +15,6 @@
#define LLVM_IR_TRACKINGMDREF_H
#include "llvm/IR/Metadata.h"
-#include "llvm/Support/Casting.h"
namespace llvm {
diff --git a/include/llvm/IR/Type.h b/include/llvm/IR/Type.h
index b2920dd3de63..ef7ad733f47a 100644
--- a/include/llvm/IR/Type.h
+++ b/include/llvm/IR/Type.h
@@ -16,6 +16,7 @@
#define LLVM_IR_TYPE_H
#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/CBindingWrapping.h"
#include "llvm/Support/Casting.h"
@@ -75,7 +76,7 @@ public:
};
private:
- /// Context - This refers to the LLVMContext in which this type was uniqued.
+ /// This refers to the LLVMContext in which this type was uniqued.
LLVMContext &Context;
TypeID ID : 8; // The current base type of this type.
@@ -96,56 +97,64 @@ protected:
assert(getSubclassData() == val && "Subclass data too large for field");
}
- /// NumContainedTys - Keeps track of how many Type*'s there are in the
- /// ContainedTys list.
+ /// Keeps track of how many Type*'s there are in the ContainedTys list.
unsigned NumContainedTys;
- /// ContainedTys - A pointer to the array of Types contained by this Type.
- /// For example, this includes the arguments of a function type, the elements
- /// of a structure, the pointee of a pointer, the element type of an array,
- /// etc. This pointer may be 0 for types that don't contain other types
- /// (Integer, Double, Float).
+ /// A pointer to the array of Types contained by this Type. For example, this
+ /// includes the arguments of a function type, the elements of a structure,
+ /// the pointee of a pointer, the element type of an array, etc. This pointer
+ /// may be 0 for types that don't contain other types (Integer, Double,
+ /// Float).
Type * const *ContainedTys;
+ static bool isSequentialType(TypeID TyID) {
+ return TyID == ArrayTyID || TyID == PointerTyID || TyID == VectorTyID;
+ }
+
public:
- void print(raw_ostream &O, bool IsForDebug = false) const;
+ /// Print the current type.
+ /// Omit the type details if \p NoDetails == true.
+ /// E.g., let %st = type { i32, i16 }
+ /// When \p NoDetails is true, we only print %st.
+ /// Put differently, \p NoDetails prints the type as if
+ /// inlined with the operands when printing an instruction.
+ void print(raw_ostream &O, bool IsForDebug = false,
+ bool NoDetails = false) const;
void dump() const;
- /// getContext - Return the LLVMContext in which this type was uniqued.
+ /// Return the LLVMContext in which this type was uniqued.
LLVMContext &getContext() const { return Context; }
//===--------------------------------------------------------------------===//
// Accessors for working with types.
//
- /// getTypeID - Return the type id for the type. This will return one
- /// of the TypeID enum elements defined above.
- ///
+ /// Return the type id for the type. This will return one of the TypeID enum
+ /// elements defined above.
TypeID getTypeID() const { return ID; }
- /// isVoidTy - Return true if this is 'void'.
+ /// Return true if this is 'void'.
bool isVoidTy() const { return getTypeID() == VoidTyID; }
- /// isHalfTy - Return true if this is 'half', a 16-bit IEEE fp type.
+ /// Return true if this is 'half', a 16-bit IEEE fp type.
bool isHalfTy() const { return getTypeID() == HalfTyID; }
- /// isFloatTy - Return true if this is 'float', a 32-bit IEEE fp type.
+ /// Return true if this is 'float', a 32-bit IEEE fp type.
bool isFloatTy() const { return getTypeID() == FloatTyID; }
- /// isDoubleTy - Return true if this is 'double', a 64-bit IEEE fp type.
+ /// Return true if this is 'double', a 64-bit IEEE fp type.
bool isDoubleTy() const { return getTypeID() == DoubleTyID; }
- /// isX86_FP80Ty - Return true if this is x86 long double.
+ /// Return true if this is x86 long double.
bool isX86_FP80Ty() const { return getTypeID() == X86_FP80TyID; }
- /// isFP128Ty - Return true if this is 'fp128'.
+ /// Return true if this is 'fp128'.
bool isFP128Ty() const { return getTypeID() == FP128TyID; }
- /// isPPC_FP128Ty - Return true if this is powerpc long double.
+ /// Return true if this is powerpc long double.
bool isPPC_FP128Ty() const { return getTypeID() == PPC_FP128TyID; }
- /// isFloatingPointTy - Return true if this is one of the six floating point
- /// types
+ /// Return true if this is one of the six floating-point types
bool isFloatingPointTy() const {
return getTypeID() == HalfTyID || getTypeID() == FloatTyID ||
getTypeID() == DoubleTyID ||
@@ -165,99 +174,81 @@ public:
}
}
- /// isX86_MMXTy - Return true if this is X86 MMX.
+ /// Return true if this is X86 MMX.
bool isX86_MMXTy() const { return getTypeID() == X86_MMXTyID; }
- /// isFPOrFPVectorTy - Return true if this is a FP type or a vector of FP.
- ///
+ /// Return true if this is a FP type or a vector of FP.
bool isFPOrFPVectorTy() const { return getScalarType()->isFloatingPointTy(); }
- /// isLabelTy - Return true if this is 'label'.
+ /// Return true if this is 'label'.
bool isLabelTy() const { return getTypeID() == LabelTyID; }
- /// isMetadataTy - Return true if this is 'metadata'.
+ /// Return true if this is 'metadata'.
bool isMetadataTy() const { return getTypeID() == MetadataTyID; }
- /// isTokenTy - Return true if this is 'token'.
+ /// Return true if this is 'token'.
bool isTokenTy() const { return getTypeID() == TokenTyID; }
- /// isIntegerTy - True if this is an instance of IntegerType.
- ///
+ /// True if this is an instance of IntegerType.
bool isIntegerTy() const { return getTypeID() == IntegerTyID; }
- /// isIntegerTy - Return true if this is an IntegerType of the given width.
+ /// Return true if this is an IntegerType of the given width.
bool isIntegerTy(unsigned Bitwidth) const;
- /// isIntOrIntVectorTy - Return true if this is an integer type or a vector of
- /// integer types.
- ///
+ /// Return true if this is an integer type or a vector of integer types.
bool isIntOrIntVectorTy() const { return getScalarType()->isIntegerTy(); }
- /// isFunctionTy - True if this is an instance of FunctionType.
- ///
+ /// True if this is an instance of FunctionType.
bool isFunctionTy() const { return getTypeID() == FunctionTyID; }
- /// isStructTy - True if this is an instance of StructType.
- ///
+ /// True if this is an instance of StructType.
bool isStructTy() const { return getTypeID() == StructTyID; }
- /// isArrayTy - True if this is an instance of ArrayType.
- ///
+ /// True if this is an instance of ArrayType.
bool isArrayTy() const { return getTypeID() == ArrayTyID; }
- /// isPointerTy - True if this is an instance of PointerType.
- ///
+ /// True if this is an instance of PointerType.
bool isPointerTy() const { return getTypeID() == PointerTyID; }
- /// isPtrOrPtrVectorTy - Return true if this is a pointer type or a vector of
- /// pointer types.
- ///
+ /// Return true if this is a pointer type or a vector of pointer types.
bool isPtrOrPtrVectorTy() const { return getScalarType()->isPointerTy(); }
- /// isVectorTy - True if this is an instance of VectorType.
- ///
+ /// True if this is an instance of VectorType.
bool isVectorTy() const { return getTypeID() == VectorTyID; }
- /// canLosslesslyBitCastTo - Return true if this type could be converted
- /// with a lossless BitCast to type 'Ty'. For example, i8* to i32*. BitCasts
- /// are valid for types of the same size only where no re-interpretation of
- /// the bits is done.
+ /// Return true if this type could be converted with a lossless BitCast to
+ /// type 'Ty'. For example, i8* to i32*. BitCasts are valid for types of the
+ /// same size only where no re-interpretation of the bits is done.
/// @brief Determine if this type could be losslessly bitcast to Ty
bool canLosslesslyBitCastTo(Type *Ty) const;
- /// isEmptyTy - Return true if this type is empty, that is, it has no
- /// elements or all its elements are empty.
+ /// Return true if this type is empty, that is, it has no elements or all of
+ /// its elements are empty.
bool isEmptyTy() const;
- /// isFirstClassType - Return true if the type is "first class", meaning it
- /// is a valid type for a Value.
- ///
+ /// Return true if the type is "first class", meaning it is a valid type for a
+ /// Value.
bool isFirstClassType() const {
return getTypeID() != FunctionTyID && getTypeID() != VoidTyID;
}
- /// isSingleValueType - Return true if the type is a valid type for a
- /// register in codegen. This includes all first-class types except struct
- /// and array types.
- ///
+ /// Return true if the type is a valid type for a register in codegen. This
+ /// includes all first-class types except struct and array types.
bool isSingleValueType() const {
return isFloatingPointTy() || isX86_MMXTy() || isIntegerTy() ||
isPointerTy() || isVectorTy();
}
- /// isAggregateType - Return true if the type is an aggregate type. This
- /// means it is valid as the first operand of an insertvalue or
- /// extractvalue instruction. This includes struct and array types, but
- /// does not include vector types.
- ///
+ /// Return true if the type is an aggregate type. This means it is valid as
+ /// the first operand of an insertvalue or extractvalue instruction. This
+ /// includes struct and array types, but does not include vector types.
bool isAggregateType() const {
return getTypeID() == StructTyID || getTypeID() == ArrayTyID;
}
- /// isSized - Return true if it makes sense to take the size of this type. To
- /// get the actual size for a particular target, it is reasonable to use the
+ /// Return true if it makes sense to take the size of this type. To get the
+ /// actual size for a particular target, it is reasonable to use the
/// DataLayout subsystem to do this.
- ///
bool isSized(SmallPtrSetImpl<Type*> *Visited = nullptr) const {
// If it's a primitive, it is always sized.
if (getTypeID() == IntegerTyID || isFloatingPointTy() ||
@@ -273,8 +264,8 @@ public:
return isSizedDerivedType(Visited);
}
- /// getPrimitiveSizeInBits - Return the basic size of this type if it is a
- /// primitive type. These are fixed by LLVM and are not target dependent.
+ /// Return the basic size of this type if it is a primitive type. These are
+ /// fixed by LLVM and are not target-dependent.
/// This will return zero if the type does not have a size or is not a
/// primitive type.
///
@@ -285,18 +276,18 @@ public:
///
unsigned getPrimitiveSizeInBits() const LLVM_READONLY;
- /// getScalarSizeInBits - If this is a vector type, return the
- /// getPrimitiveSizeInBits value for the element type. Otherwise return the
- /// getPrimitiveSizeInBits value for this type.
+ /// If this is a vector type, return the getPrimitiveSizeInBits value for the
+ /// element type. Otherwise return the getPrimitiveSizeInBits value for this
+ /// type.
unsigned getScalarSizeInBits() const LLVM_READONLY;
- /// getFPMantissaWidth - Return the width of the mantissa of this type. This
- /// is only valid on floating point types. If the FP type does not
- /// have a stable mantissa (e.g. ppc long double), this method returns -1.
+ /// Return the width of the mantissa of this type. This is only valid on
+ /// floating-point types. If the FP type does not have a stable mantissa (e.g.
+ /// ppc long double), this method returns -1.
int getFPMantissaWidth() const;
- /// getScalarType - If this is a vector type, return the element type,
- /// otherwise return 'this'.
+ /// If this is a vector type, return the element type, otherwise return
+ /// 'this'.
Type *getScalarType() const LLVM_READONLY;
//===--------------------------------------------------------------------===//
@@ -317,17 +308,15 @@ public:
return subtype_reverse_iterator(subtype_begin());
}
- /// getContainedType - This method is used to implement the type iterator
- /// (defined at the end of the file). For derived types, this returns the
- /// types 'contained' in the derived type.
- ///
+ /// This method is used to implement the type iterator (defined at the end of
+ /// the file). For derived types, this returns the types 'contained' in the
+ /// derived type.
Type *getContainedType(unsigned i) const {
assert(i < NumContainedTys && "Index out of range!");
return ContainedTys[i];
}
- /// getNumContainedTypes - Return the number of types in the derived type.
- ///
+ /// Return the number of types in the derived type.
unsigned getNumContainedTypes() const { return NumContainedTys; }
//===--------------------------------------------------------------------===//
@@ -347,7 +336,10 @@ public:
inline unsigned getStructNumElements() const;
inline Type *getStructElementType(unsigned N) const;
- inline Type *getSequentialElementType() const;
+ inline Type *getSequentialElementType() const {
+ assert(isSequentialType(getTypeID()) && "Not a sequential type!");
+ return ContainedTys[0];
+ }
inline uint64_t getArrayNumElements() const;
Type *getArrayElementType() const { return getSequentialElementType(); }
@@ -357,7 +349,7 @@ public:
Type *getPointerElementType() const { return getSequentialElementType(); }
- /// \brief Get the address space of this pointer or pointer vector type.
+ /// Get the address space of this pointer or pointer vector type.
inline unsigned getPointerAddressSpace() const;
//===--------------------------------------------------------------------===//
@@ -365,7 +357,7 @@ public:
// instances of Type.
//
- /// getPrimitiveType - Return a type based on an identifier.
+ /// Return a type based on an identifier.
static Type *getPrimitiveType(LLVMContext &C, TypeID IDNumber);
//===--------------------------------------------------------------------===//
@@ -408,14 +400,14 @@ public:
static PointerType *getInt32PtrTy(LLVMContext &C, unsigned AS = 0);
static PointerType *getInt64PtrTy(LLVMContext &C, unsigned AS = 0);
- /// getPointerTo - Return a pointer to the current type. This is equivalent
- /// to PointerType::get(Foo, AddrSpace).
+ /// Return a pointer to the current type. This is equivalent to
+ /// PointerType::get(Foo, AddrSpace).
PointerType *getPointerTo(unsigned AddrSpace = 0) const;
private:
- /// isSizedDerivedType - Derived types like structures and arrays are sized
- /// iff all of the members of the type are sized as well. Since asking for
- /// their size is relatively uncommon, move this operation out of line.
+ /// Derived types like structures and arrays are sized iff all of the members
+ /// of the type are sized as well. Since asking for their size is relatively
+ /// uncommon, move this operation out-of-line.
bool isSizedDerivedType(SmallPtrSetImpl<Type*> *Visited = nullptr) const;
};
diff --git a/include/llvm/IR/TypeFinder.h b/include/llvm/IR/TypeFinder.h
index 5f3854377c16..d5baf7ab0b9e 100644
--- a/include/llvm/IR/TypeFinder.h
+++ b/include/llvm/IR/TypeFinder.h
@@ -15,6 +15,8 @@
#define LLVM_IR_TYPEFINDER_H
#include "llvm/ADT/DenseSet.h"
+#include "llvm/IR/Metadata.h"
+#include "llvm/IR/Type.h"
#include <vector>
namespace llvm {
@@ -22,7 +24,6 @@ namespace llvm {
class MDNode;
class Module;
class StructType;
-class Type;
class Value;
/// TypeFinder - Walk over a module, identifying all of the types that are
diff --git a/include/llvm/IR/Use.h b/include/llvm/IR/Use.h
index a738677f8e5b..e62eab56b1f1 100644
--- a/include/llvm/IR/Use.h
+++ b/include/llvm/IR/Use.h
@@ -27,9 +27,7 @@
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/Support/CBindingWrapping.h"
-#include "llvm/Support/Compiler.h"
#include <cstddef>
-#include <iterator>
namespace llvm {
@@ -101,14 +99,8 @@ public:
inline void set(Value *Val);
- Value *operator=(Value *RHS) {
- set(RHS);
- return RHS;
- }
- const Use &operator=(const Use &RHS) {
- set(RHS.Val);
- return *this;
- }
+ inline Value *operator=(Value *RHS);
+ inline const Use &operator=(const Use &RHS);
Value *operator->() { return Val; }
const Value *operator->() const { return Val; }
diff --git a/include/llvm/IR/UseListOrder.h b/include/llvm/IR/UseListOrder.h
index 1cabf03d1b00..b86425b6a697 100644
--- a/include/llvm/IR/UseListOrder.h
+++ b/include/llvm/IR/UseListOrder.h
@@ -15,8 +15,7 @@
#ifndef LLVM_IR_USELISTORDER_H
#define LLVM_IR_USELISTORDER_H
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/SmallVector.h"
+#include <cstddef>
#include <vector>
namespace llvm {
diff --git a/include/llvm/IR/User.h b/include/llvm/IR/User.h
index 885ae197d228..4d6b30cd1124 100644
--- a/include/llvm/IR/User.h
+++ b/include/llvm/IR/User.h
@@ -19,7 +19,6 @@
#ifndef LLVM_IR_USER_H
#define LLVM_IR_USER_H
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/IR/Value.h"
@@ -28,6 +27,9 @@
namespace llvm {
+template <typename T> class ArrayRef;
+template <typename T> class MutableArrayRef;
+
/// \brief Compile-time customization of User operands.
///
/// Customizes operand-related allocators and accessors.
diff --git a/include/llvm/IR/Value.def b/include/llvm/IR/Value.def
index 4c5d452fc3c3..48842d7f9cd5 100644
--- a/include/llvm/IR/Value.def
+++ b/include/llvm/IR/Value.def
@@ -54,21 +54,29 @@
HANDLE_VALUE(Argument)
HANDLE_VALUE(BasicBlock)
+HANDLE_VALUE(MemoryUse)
+HANDLE_VALUE(MemoryDef)
+HANDLE_VALUE(MemoryPhi)
HANDLE_GLOBAL_VALUE(Function)
HANDLE_GLOBAL_VALUE(GlobalAlias)
+HANDLE_GLOBAL_VALUE(GlobalIFunc)
HANDLE_GLOBAL_VALUE(GlobalVariable)
-HANDLE_CONSTANT(UndefValue)
HANDLE_CONSTANT(BlockAddress)
HANDLE_CONSTANT(ConstantExpr)
+
+// ConstantAggregate.
+HANDLE_CONSTANT(ConstantArray)
+HANDLE_CONSTANT(ConstantStruct)
+HANDLE_CONSTANT(ConstantVector)
+
+// ConstantData.
+HANDLE_CONSTANT(UndefValue)
HANDLE_CONSTANT(ConstantAggregateZero)
HANDLE_CONSTANT(ConstantDataArray)
HANDLE_CONSTANT(ConstantDataVector)
HANDLE_CONSTANT(ConstantInt)
HANDLE_CONSTANT(ConstantFP)
-HANDLE_CONSTANT(ConstantArray)
-HANDLE_CONSTANT(ConstantStruct)
-HANDLE_CONSTANT(ConstantVector)
HANDLE_CONSTANT(ConstantPointerNull)
HANDLE_CONSTANT(ConstantTokenNone)
@@ -81,6 +89,10 @@ HANDLE_INSTRUCTION(Instruction)
HANDLE_CONSTANT_MARKER(ConstantFirstVal, Function)
HANDLE_CONSTANT_MARKER(ConstantLastVal, ConstantTokenNone)
+HANDLE_CONSTANT_MARKER(ConstantDataFirstVal, UndefValue)
+HANDLE_CONSTANT_MARKER(ConstantDataLastVal, ConstantTokenNone)
+HANDLE_CONSTANT_MARKER(ConstantAggregateFirstVal, ConstantArray)
+HANDLE_CONSTANT_MARKER(ConstantAggregateLastVal, ConstantVector)
#undef HANDLE_GLOBAL_VALUE
#undef HANDLE_CONSTANT
diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h
index 8918dcd38c93..f3a342dadf73 100644
--- a/include/llvm/IR/Value.h
+++ b/include/llvm/IR/Value.h
@@ -18,7 +18,6 @@
#include "llvm/IR/Use.h"
#include "llvm/Support/CBindingWrapping.h"
#include "llvm/Support/Casting.h"
-#include "llvm/Support/Compiler.h"
namespace llvm {
@@ -27,9 +26,13 @@ class Argument;
class AssemblyAnnotationWriter;
class BasicBlock;
class Constant;
+class ConstantData;
+class ConstantAggregate;
class DataLayout;
class Function;
class GlobalAlias;
+class GlobalIFunc;
+class GlobalIndirectSymbol;
class GlobalObject;
class GlobalValue;
class GlobalVariable;
@@ -106,10 +109,11 @@ protected:
enum : unsigned { NumUserOperandsBits = 28 };
unsigned NumUserOperands : NumUserOperandsBits;
- bool IsUsedByMD : 1;
- bool HasName : 1;
- bool HasHungOffUses : 1;
- bool HasDescriptor : 1;
+ // Use the same type as the bitfield above so that MSVC will pack them.
+ unsigned IsUsedByMD : 1;
+ unsigned HasName : 1;
+ unsigned HasHungOffUses : 1;
+ unsigned HasDescriptor : 1;
private:
template <typename UseT> // UseT == 'Use' or 'const Use'
@@ -347,13 +351,19 @@ public:
assertModuleIsMaterialized();
return *materialized_user_begin();
}
+ iterator_range<user_iterator> materialized_users() {
+ return make_range(materialized_user_begin(), user_end());
+ }
+ iterator_range<const_user_iterator> materialized_users() const {
+ return make_range(materialized_user_begin(), user_end());
+ }
iterator_range<user_iterator> users() {
assertModuleIsMaterialized();
- return make_range(materialized_user_begin(), user_end());
+ return materialized_users();
}
iterator_range<const_user_iterator> users() const {
assertModuleIsMaterialized();
- return make_range(materialized_user_begin(), user_end());
+ return materialized_users();
}
/// \brief Return true if there is exactly one user of this value.
@@ -494,6 +504,20 @@ public:
return const_cast<Value*>(this)->stripInBoundsOffsets();
}
+ /// \brief Returns the number of bytes known to be dereferenceable for the
+ /// pointer value.
+ ///
+ /// If CanBeNull is set by this function the pointer can either be null or be
+ /// dereferenceable up to the returned number of bytes.
+ unsigned getPointerDereferenceableBytes(const DataLayout &DL,
+ bool &CanBeNull) const;
+
+ /// \brief Returns an alignment of the pointer value.
+ ///
+ /// Returns an alignment which is either specified explicitly, e.g. via
+ /// align attribute of a function argument, or guaranteed by DataLayout.
+ unsigned getPointerAlignment(const DataLayout &DL) const;
+
/// \brief Translate PHI node to its predecessor from the given basic block.
///
/// If this value is a PHI node with CurBB as its parent, return the value in
@@ -592,6 +616,16 @@ void Use::set(Value *V) {
if (V) V->addUse(*this);
}
+Value *Use::operator=(Value *RHS) {
+ set(RHS);
+ return RHS;
+}
+
+const Use &Use::operator=(const Use &RHS) {
+ set(RHS.Val);
+ return *this;
+}
+
template <class Compare> void Value::sortUseList(Compare Cmp) {
if (!UseList || !UseList->Next)
// No need to sort 0 or 1 uses.
@@ -669,6 +703,20 @@ template <> struct isa_impl<Constant, Value> {
}
};
+template <> struct isa_impl<ConstantData, Value> {
+ static inline bool doit(const Value &Val) {
+ return Val.getValueID() >= Value::ConstantDataFirstVal &&
+ Val.getValueID() <= Value::ConstantDataLastVal;
+ }
+};
+
+template <> struct isa_impl<ConstantAggregate, Value> {
+ static inline bool doit(const Value &Val) {
+ return Val.getValueID() >= Value::ConstantAggregateFirstVal &&
+ Val.getValueID() <= Value::ConstantAggregateLastVal;
+ }
+};
+
template <> struct isa_impl<Argument, Value> {
static inline bool doit (const Value &Val) {
return Val.getValueID() == Value::ArgumentVal;
@@ -711,9 +759,21 @@ template <> struct isa_impl<GlobalAlias, Value> {
}
};
+template <> struct isa_impl<GlobalIFunc, Value> {
+ static inline bool doit(const Value &Val) {
+ return Val.getValueID() == Value::GlobalIFuncVal;
+ }
+};
+
+template <> struct isa_impl<GlobalIndirectSymbol, Value> {
+ static inline bool doit(const Value &Val) {
+ return isa<GlobalAlias>(Val) || isa<GlobalIFunc>(Val);
+ }
+};
+
template <> struct isa_impl<GlobalValue, Value> {
static inline bool doit(const Value &Val) {
- return isa<GlobalObject>(Val) || isa<GlobalAlias>(Val);
+ return isa<GlobalObject>(Val) || isa<GlobalIndirectSymbol>(Val);
}
};
@@ -738,8 +798,7 @@ public:
// Create wrappers for C Binding types (see CBindingWrapping.h).
DEFINE_ISA_CONVERSION_FUNCTIONS(Value, LLVMValueRef)
-/* Specialized opaque value conversions.
- */
+// Specialized opaque value conversions.
inline Value **unwrap(LLVMValueRef *Vals) {
return reinterpret_cast<Value**>(Vals);
}
diff --git a/include/llvm/IR/ValueMap.h b/include/llvm/IR/ValueMap.h
index ad518ac053b2..85379ad468c4 100644
--- a/include/llvm/IR/ValueMap.h
+++ b/include/llvm/IR/ValueMap.h
@@ -27,6 +27,7 @@
#define LLVM_IR_VALUEMAP_H
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/IR/TrackingMDRef.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Support/Mutex.h"
@@ -84,8 +85,11 @@ class ValueMap {
typedef DenseMap<const Metadata *, TrackingMDRef> MDMapT;
typedef typename Config::ExtraData ExtraData;
MapT Map;
- std::unique_ptr<MDMapT> MDMap;
+ Optional<MDMapT> MDMap;
ExtraData Data;
+
+ bool MayMapMetadata = true;
+
ValueMap(const ValueMap&) = delete;
ValueMap& operator=(const ValueMap&) = delete;
public:
@@ -99,12 +103,27 @@ public:
explicit ValueMap(const ExtraData &Data, unsigned NumInitBuckets = 64)
: Map(NumInitBuckets), Data(Data) {}
- bool hasMD() const { return MDMap; }
+ bool hasMD() const { return bool(MDMap); }
MDMapT &MD() {
if (!MDMap)
- MDMap.reset(new MDMapT);
+ MDMap.emplace();
return *MDMap;
}
+ Optional<MDMapT> &getMDMap() { return MDMap; }
+
+ bool mayMapMetadata() const { return MayMapMetadata; }
+ void enableMapMetadata() { MayMapMetadata = true; }
+ void disableMapMetadata() { MayMapMetadata = false; }
+
+ /// Get the mapped metadata, if it's in the map.
+ Optional<Metadata *> getMappedMD(const Metadata *MD) const {
+ if (!MDMap)
+ return None;
+ auto Where = MDMap->find(MD);
+ if (Where == MDMap->end())
+ return None;
+ return Where->second.get();
+ }
typedef ValueMapIterator<MapT, KeyT> iterator;
typedef ValueMapConstIterator<MapT, KeyT> const_iterator;
diff --git a/include/llvm/IR/ValueSymbolTable.h b/include/llvm/IR/ValueSymbolTable.h
index 65bd7fc2fec1..61a12db403ea 100644
--- a/include/llvm/IR/ValueSymbolTable.h
+++ b/include/llvm/IR/ValueSymbolTable.h
@@ -14,13 +14,13 @@
#ifndef LLVM_IR_VALUESYMBOLTABLE_H
#define LLVM_IR_VALUESYMBOLTABLE_H
-#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
template <typename ValueSubClass> class SymbolTableListTraits;
+ template <unsigned InternalLen> class SmallString;
class BasicBlock;
class Function;
class NamedMDNode;
@@ -39,6 +39,7 @@ class ValueSymbolTable {
friend class SymbolTableListTraits<Function>;
friend class SymbolTableListTraits<GlobalVariable>;
friend class SymbolTableListTraits<GlobalAlias>;
+ friend class SymbolTableListTraits<GlobalIFunc>;
/// @name Types
/// @{
public:
diff --git a/include/llvm/IR/Verifier.h b/include/llvm/IR/Verifier.h
index 89039d24195e..fdb6ce400a8d 100644
--- a/include/llvm/IR/Verifier.h
+++ b/include/llvm/IR/Verifier.h
@@ -21,8 +21,7 @@
#ifndef LLVM_IR_VERIFIER_H
#define LLVM_IR_VERIFIER_H
-#include "llvm/ADT/StringRef.h"
-#include <string>
+#include "llvm/IR/PassManager.h"
namespace llvm {
@@ -30,7 +29,6 @@ class Function;
class FunctionPass;
class ModulePass;
class Module;
-class PreservedAnalyses;
class raw_ostream;
/// \brief Check a function for errors, useful for use when debugging a
@@ -43,10 +41,38 @@ bool verifyFunction(const Function &F, raw_ostream *OS = nullptr);
/// \brief Check a module for errors.
///
-/// If there are no errors, the function returns false. If an error is found,
-/// a message describing the error is written to OS (if non-null) and true is
-/// returned.
-bool verifyModule(const Module &M, raw_ostream *OS = nullptr);
+/// If there are no errors, the function returns false. If an error is
+/// found, a message describing the error is written to OS (if
+/// non-null) and true is returned.
+///
+/// \return true if the module is broken. If BrokenDebugInfo is
+/// supplied, DebugInfo verification failures won't be considered as
+/// error and instead *BrokenDebugInfo will be set to true. Debug
+/// info errors can be "recovered" from by stripping the debug info.
+bool verifyModule(const Module &M, raw_ostream *OS = nullptr,
+ bool *BrokenDebugInfo = nullptr);
+
+FunctionPass *createVerifierPass(bool FatalErrors = true);
+
+/// Check a module for errors, and report separate error states for IR
+/// and debug info errors.
+class VerifierAnalysis : public AnalysisInfoMixin<VerifierAnalysis> {
+ friend AnalysisInfoMixin<VerifierAnalysis>;
+ static char PassID;
+
+public:
+ struct Result {
+ bool IRBroken, DebugInfoBroken;
+ };
+ static void *ID() { return (void *)&PassID; }
+ Result run(Module &M, ModuleAnalysisManager &);
+ Result run(Function &F, FunctionAnalysisManager &);
+};
+
+/// Check a module for errors, but report debug info errors separately.
+/// Otherwise behaves as the normal verifyModule. Debug info errors can be
+/// "recovered" from by stripping the debug info.
+bool verifyModule(bool &BrokenDebugInfo, const Module &M, raw_ostream *OS);
/// \brief Create a verifier pass.
///
@@ -58,20 +84,17 @@ bool verifyModule(const Module &M, raw_ostream *OS = nullptr);
///
/// Note that this creates a pass suitable for the legacy pass manager. It has
/// nothing to do with \c VerifierPass.
-FunctionPass *createVerifierPass(bool FatalErrors = true);
-
-class VerifierPass {
+class VerifierPass : public PassInfoMixin<VerifierPass> {
bool FatalErrors;
public:
explicit VerifierPass(bool FatalErrors = true) : FatalErrors(FatalErrors) {}
- PreservedAnalyses run(Module &M);
- PreservedAnalyses run(Function &F);
-
- static StringRef name() { return "VerifierPass"; }
+ PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
+
} // End llvm namespace
#endif
diff --git a/include/llvm/IRReader/IRReader.h b/include/llvm/IRReader/IRReader.h
index 523cd3d6df72..7b24ec11fb64 100644
--- a/include/llvm/IRReader/IRReader.h
+++ b/include/llvm/IRReader/IRReader.h
@@ -15,11 +15,12 @@
#ifndef LLVM_IRREADER_IRREADER_H
#define LLVM_IRREADER_IRREADER_H
-#include "llvm/Support/MemoryBuffer.h"
-#include <string>
+#include <memory>
namespace llvm {
+class StringRef;
+class MemoryBufferRef;
class Module;
class SMDiagnostic;
class LLVMContext;
diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h
index 90fbc1d891b7..90ff82fe86d4 100644
--- a/include/llvm/InitializePasses.h
+++ b/include/llvm/InitializePasses.h
@@ -19,250 +19,298 @@ namespace llvm {
class PassRegistry;
-/// initializeCore - Initialize all passes linked into the
-/// TransformUtils library.
+/// Initialize all passes linked into the TransformUtils library.
void initializeCore(PassRegistry&);
-/// initializeTransformUtils - Initialize all passes linked into the
-/// TransformUtils library.
+/// Initialize all passes linked into the TransformUtils library.
void initializeTransformUtils(PassRegistry&);
-/// initializeScalarOpts - Initialize all passes linked into the
-/// ScalarOpts library.
+/// Initialize all passes linked into the ScalarOpts library.
void initializeScalarOpts(PassRegistry&);
-/// initializeObjCARCOpts - Initialize all passes linked into the ObjCARCOpts
-/// library.
+/// Initialize all passes linked into the ObjCARCOpts library.
void initializeObjCARCOpts(PassRegistry&);
-/// initializeVectorization - Initialize all passes linked into the
-/// Vectorize library.
+/// Initialize all passes linked into the Vectorize library.
void initializeVectorization(PassRegistry&);
-/// initializeInstCombine - Initialize all passes linked into the
-/// InstCombine library.
+/// Initialize all passes linked into the InstCombine library.
void initializeInstCombine(PassRegistry&);
-/// initializeIPO - Initialize all passes linked into the IPO library.
+/// Initialize all passes linked into the IPO library.
void initializeIPO(PassRegistry&);
-/// initializeInstrumentation - Initialize all passes linked into the
-/// Instrumentation library.
+/// Initialize all passes linked into the Instrumentation library.
void initializeInstrumentation(PassRegistry&);
-/// initializeAnalysis - Initialize all passes linked into the Analysis library.
+/// Initialize all passes linked into the Analysis library.
void initializeAnalysis(PassRegistry&);
-/// initializeCodeGen - Initialize all passes linked into the CodeGen library.
+/// Initialize all passes linked into the CodeGen library.
void initializeCodeGen(PassRegistry&);
-/// initializeCodeGen - Initialize all passes linked into the CodeGen library.
+/// Initialize all passes linked into the GlobalISel library.
+void initializeGlobalISel(PassRegistry &Registry);
+
+/// Initialize all passes linked into the CodeGen library.
void initializeTarget(PassRegistry&);
-void initializeAAEvalPass(PassRegistry&);
-void initializeAddDiscriminatorsPass(PassRegistry&);
+void initializeAAEvalLegacyPassPass(PassRegistry&);
+void initializeAAResultsWrapperPassPass(PassRegistry &);
void initializeADCELegacyPassPass(PassRegistry&);
-void initializeBDCEPass(PassRegistry&);
+void initializeAddDiscriminatorsLegacyPassPass(PassRegistry&);
+void initializeAddressSanitizerModulePass(PassRegistry&);
+void initializeAddressSanitizerPass(PassRegistry&);
void initializeAliasSetPrinterPass(PassRegistry&);
+void initializeAlignmentFromAssumptionsPass(PassRegistry&);
void initializeAlwaysInlinerPass(PassRegistry&);
void initializeArgPromotionPass(PassRegistry&);
+void initializeAssumptionCacheTrackerPass(PassRegistry &);
void initializeAtomicExpandPass(PassRegistry&);
-void initializeSampleProfileLoaderPass(PassRegistry&);
-void initializeAlignmentFromAssumptionsPass(PassRegistry&);
+void initializeBBVectorizePass(PassRegistry&);
+void initializeBDCELegacyPassPass(PassRegistry &);
void initializeBarrierNoopPass(PassRegistry&);
void initializeBasicAAWrapperPassPass(PassRegistry&);
-void initializeCallGraphWrapperPassPass(PassRegistry &);
void initializeBlockExtractorPassPass(PassRegistry&);
void initializeBlockFrequencyInfoWrapperPassPass(PassRegistry&);
void initializeBoundsCheckingPass(PassRegistry&);
void initializeBranchFolderPassPass(PassRegistry&);
void initializeBranchProbabilityInfoWrapperPassPass(PassRegistry&);
void initializeBreakCriticalEdgesPass(PassRegistry&);
-void initializeCallGraphPrinterPass(PassRegistry&);
-void initializeCallGraphViewerPass(PassRegistry&);
void initializeCFGOnlyPrinterPass(PassRegistry&);
void initializeCFGOnlyViewerPass(PassRegistry&);
void initializeCFGPrinterPass(PassRegistry&);
void initializeCFGSimplifyPassPass(PassRegistry&);
-void initializeCFLAAWrapperPassPass(PassRegistry&);
-void initializeExternalAAWrapperPassPass(PassRegistry&);
-void initializeForwardControlFlowIntegrityPass(PassRegistry&);
-void initializeFlattenCFGPassPass(PassRegistry&);
-void initializeStructurizeCFGPass(PassRegistry&);
void initializeCFGViewerPass(PassRegistry&);
-void initializeConstantHoistingPass(PassRegistry&);
+void initializeCFLAndersAAWrapperPassPass(PassRegistry&);
+void initializeCFLSteensAAWrapperPassPass(PassRegistry&);
+void initializeCallGraphDOTPrinterPass(PassRegistry&);
+void initializeCallGraphPrinterLegacyPassPass(PassRegistry&);
+void initializeCallGraphViewerPass(PassRegistry&);
+void initializeCallGraphWrapperPassPass(PassRegistry &);
void initializeCodeGenPreparePass(PassRegistry&);
-void initializeConstantMergePass(PassRegistry&);
+void initializeConstantHoistingLegacyPassPass(PassRegistry&);
+void initializeConstantMergeLegacyPassPass(PassRegistry &);
void initializeConstantPropagationPass(PassRegistry&);
-void initializeMachineCopyPropagationPass(PassRegistry&);
-void initializeCostModelAnalysisPass(PassRegistry&);
void initializeCorrelatedValuePropagationPass(PassRegistry&);
+void initializeCostModelAnalysisPass(PassRegistry&);
void initializeCrossDSOCFIPass(PassRegistry&);
void initializeDAEPass(PassRegistry&);
void initializeDAHPass(PassRegistry&);
-void initializeDCEPass(PassRegistry&);
-void initializeDSEPass(PassRegistry&);
+void initializeDCELegacyPassPass(PassRegistry&);
+void initializeDSELegacyPassPass(PassRegistry&);
+void initializeDataFlowSanitizerPass(PassRegistry&);
void initializeDeadInstEliminationPass(PassRegistry&);
void initializeDeadMachineInstructionElimPass(PassRegistry&);
void initializeDelinearizationPass(PassRegistry &);
+void initializeDemandedBitsWrapperPassPass(PassRegistry&);
void initializeDependenceAnalysisPass(PassRegistry&);
+void initializeDependenceAnalysisWrapperPassPass(PassRegistry&);
+void initializeDetectDeadLanesPass(PassRegistry&);
void initializeDivergenceAnalysisPass(PassRegistry&);
void initializeDomOnlyPrinterPass(PassRegistry&);
void initializeDomOnlyViewerPass(PassRegistry&);
void initializeDomPrinterPass(PassRegistry&);
void initializeDomViewerPass(PassRegistry&);
-void initializeDominanceFrontierPass(PassRegistry&);
+void initializeDominanceFrontierWrapperPassPass(PassRegistry&);
void initializeDominatorTreeWrapperPassPass(PassRegistry&);
+void initializeDwarfEHPreparePass(PassRegistry&);
+void initializeEarlyCSELegacyPassPass(PassRegistry &);
void initializeEarlyIfConverterPass(PassRegistry&);
void initializeEdgeBundlesPass(PassRegistry&);
-void initializeExpandPostRAPass(PassRegistry&);
-void initializeAAResultsWrapperPassPass(PassRegistry &);
-void initializeGCOVProfilerPass(PassRegistry&);
-void initializePGOInstrumentationGenPass(PassRegistry&);
-void initializePGOInstrumentationUsePass(PassRegistry&);
-void initializeInstrProfilingPass(PassRegistry&);
-void initializeAddressSanitizerPass(PassRegistry&);
-void initializeAddressSanitizerModulePass(PassRegistry&);
-void initializeMemorySanitizerPass(PassRegistry&);
-void initializeThreadSanitizerPass(PassRegistry&);
-void initializeSanitizerCoverageModulePass(PassRegistry&);
-void initializeDataFlowSanitizerPass(PassRegistry&);
-void initializeScalarizerPass(PassRegistry&);
-void initializeEarlyCSELegacyPassPass(PassRegistry &);
-void initializeEliminateAvailableExternallyPass(PassRegistry&);
+void initializeEfficiencySanitizerPass(PassRegistry&);
+void initializeEliminateAvailableExternallyLegacyPassPass(PassRegistry &);
+void initializeGVNHoistLegacyPassPass(PassRegistry &);
void initializeExpandISelPseudosPass(PassRegistry&);
+void initializeExpandPostRAPass(PassRegistry&);
+void initializeExternalAAWrapperPassPass(PassRegistry&);
+void initializeFinalizeMachineBundlesPass(PassRegistry&);
+void initializeFlattenCFGPassPass(PassRegistry&);
+void initializeFloat2IntLegacyPassPass(PassRegistry&);
void initializeForceFunctionAttrsLegacyPassPass(PassRegistry&);
+void initializeForwardControlFlowIntegrityPass(PassRegistry&);
+void initializeFuncletLayoutPass(PassRegistry &);
+void initializeFunctionImportPassPass(PassRegistry &);
void initializeGCMachineCodeAnalysisPass(PassRegistry&);
void initializeGCModuleInfoPass(PassRegistry&);
-void initializeGVNPass(PassRegistry&);
-void initializeGlobalDCEPass(PassRegistry&);
-void initializeGlobalOptPass(PassRegistry&);
+void initializeGCOVProfilerLegacyPassPass(PassRegistry&);
+void initializeGVNLegacyPassPass(PassRegistry&);
+void initializeGlobalDCELegacyPassPass(PassRegistry&);
+void initializeGlobalMergePass(PassRegistry&);
+void initializeGlobalOptLegacyPassPass(PassRegistry&);
void initializeGlobalsAAWrapperPassPass(PassRegistry&);
+void initializeGuardWideningLegacyPassPass(PassRegistry&);
void initializeIPCPPass(PassRegistry&);
-void initializeIPSCCPPass(PassRegistry&);
-void initializeIVUsersPass(PassRegistry&);
+void initializeIPSCCPLegacyPassPass(PassRegistry &);
+void initializeIRTranslatorPass(PassRegistry &);
+void initializeIVUsersWrapperPassPass(PassRegistry&);
void initializeIfConverterPass(PassRegistry&);
+void initializeImplicitNullChecksPass(PassRegistry&);
+void initializeIndVarSimplifyLegacyPassPass(PassRegistry&);
void initializeInductiveRangeCheckEliminationPass(PassRegistry&);
-void initializeIndVarSimplifyPass(PassRegistry&);
void initializeInferFunctionAttrsLegacyPassPass(PassRegistry&);
void initializeInlineCostAnalysisPass(PassRegistry&);
-void initializeInstructionCombiningPassPass(PassRegistry&);
void initializeInstCountPass(PassRegistry&);
void initializeInstNamerPass(PassRegistry&);
-void initializeInternalizePassPass(PassRegistry&);
+void initializeInstSimplifierPass(PassRegistry&);
+void initializeInstrProfilingLegacyPassPass(PassRegistry &);
+void initializeInstructionCombiningPassPass(PassRegistry&);
+void initializeInterleavedAccessPass(PassRegistry &);
+void initializeInternalizeLegacyPassPass(PassRegistry&);
void initializeIntervalPartitionPass(PassRegistry&);
void initializeJumpThreadingPass(PassRegistry&);
-void initializeLCSSAPass(PassRegistry&);
-void initializeLICMPass(PassRegistry&);
-void initializeLazyValueInfoPass(PassRegistry&);
+void initializeLCSSAWrapperPassPass(PassRegistry &);
+void initializeLegacyLICMPassPass(PassRegistry&);
+void initializeLazyBlockFrequencyInfoPassPass(PassRegistry&);
+void initializeLazyValueInfoWrapperPassPass(PassRegistry&);
void initializeLintPass(PassRegistry&);
+void initializeLiveDebugValuesPass(PassRegistry&);
void initializeLiveDebugVariablesPass(PassRegistry&);
void initializeLiveIntervalsPass(PassRegistry&);
void initializeLiveRegMatrixPass(PassRegistry&);
void initializeLiveStacksPass(PassRegistry&);
void initializeLiveVariablesPass(PassRegistry&);
+void initializeLoadCombinePass(PassRegistry&);
void initializeLoaderPassPass(PassRegistry&);
+void initializeLoadStoreVectorizerPass(PassRegistry&);
void initializeLocalStackSlotPassPass(PassRegistry&);
-void initializeLoopDeletionPass(PassRegistry&);
+void initializeLoopAccessLegacyAnalysisPass(PassRegistry&);
+void initializeLoopDataPrefetchPass(PassRegistry&);
+void initializeLoopDeletionLegacyPassPass(PassRegistry&);
+void initializeLoopDistributeLegacyPass(PassRegistry&);
void initializeLoopExtractorPass(PassRegistry&);
+void initializeLoopIdiomRecognizeLegacyPassPass(PassRegistry&);
void initializeLoopInfoWrapperPassPass(PassRegistry&);
+void initializeLoopInstSimplifyLegacyPassPass(PassRegistry&);
void initializeLoopInterchangePass(PassRegistry &);
-void initializeLoopInstSimplifyPass(PassRegistry&);
-void initializeLoopRotatePass(PassRegistry&);
+void initializeLoopLoadEliminationPass(PassRegistry&);
+void initializeLoopPassPass(PassRegistry&);
+void initializeLoopRerollPass(PassRegistry&);
+void initializeLoopRotateLegacyPassPass(PassRegistry&);
+void initializeLoopSimplifyCFGLegacyPassPass(PassRegistry&);
void initializeLoopSimplifyPass(PassRegistry&);
void initializeLoopStrengthReducePass(PassRegistry&);
-void initializeGlobalMergePass(PassRegistry&);
-void initializeLoopRerollPass(PassRegistry&);
void initializeLoopUnrollPass(PassRegistry&);
void initializeLoopUnswitchPass(PassRegistry&);
-void initializeLoopIdiomRecognizePass(PassRegistry&);
-void initializeLowerAtomicPass(PassRegistry&);
-void initializeLowerBitSetsPass(PassRegistry&);
+void initializeLoopVectorizePass(PassRegistry&);
+void initializeLoopVersioningLICMPass(PassRegistry&);
+void initializeLoopVersioningPassPass(PassRegistry &);
+void initializeLowerAtomicLegacyPassPass(PassRegistry &);
+void initializeLowerEmuTLSPass(PassRegistry&);
void initializeLowerExpectIntrinsicPass(PassRegistry&);
+void initializeLowerGuardIntrinsicPass(PassRegistry&);
void initializeLowerIntrinsicsPass(PassRegistry&);
void initializeLowerInvokePass(PassRegistry&);
void initializeLowerSwitchPass(PassRegistry&);
+void initializeLowerTypeTestsPass(PassRegistry&);
+void initializeMIRPrintingPassPass(PassRegistry&);
void initializeMachineBlockFrequencyInfoPass(PassRegistry&);
void initializeMachineBlockPlacementPass(PassRegistry&);
void initializeMachineBlockPlacementStatsPass(PassRegistry&);
void initializeMachineBranchProbabilityInfoPass(PassRegistry&);
void initializeMachineCSEPass(PassRegistry&);
-void initializeImplicitNullChecksPass(PassRegistry&);
-void initializeMachineDominatorTreePass(PassRegistry&);
+void initializeMachineCombinerPass(PassRegistry &);
+void initializeMachineCopyPropagationPass(PassRegistry&);
void initializeMachineDominanceFrontierPass(PassRegistry&);
-void initializeMachinePostDominatorTreePass(PassRegistry&);
+void initializeMachineDominatorTreePass(PassRegistry&);
+void initializeMachineFunctionPrinterPassPass(PassRegistry&);
void initializeMachineLICMPass(PassRegistry&);
void initializeMachineLoopInfoPass(PassRegistry&);
void initializeMachineModuleInfoPass(PassRegistry&);
+void initializeMachinePostDominatorTreePass(PassRegistry&);
void initializeMachineRegionInfoPassPass(PassRegistry&);
void initializeMachineSchedulerPass(PassRegistry&);
void initializeMachineSinkingPass(PassRegistry&);
void initializeMachineTraceMetricsPass(PassRegistry&);
void initializeMachineVerifierPassPass(PassRegistry&);
-void initializeMemCpyOptPass(PassRegistry&);
+void initializeMemCpyOptLegacyPassPass(PassRegistry&);
void initializeMemDepPrinterPass(PassRegistry&);
void initializeMemDerefPrinterPass(PassRegistry&);
-void initializeMemoryDependenceAnalysisPass(PassRegistry&);
-void initializeMergedLoadStoreMotionPass(PassRegistry &);
-void initializeMetaRenamerPass(PassRegistry&);
+void initializeMemoryDependenceWrapperPassPass(PassRegistry&);
+void initializeMemorySSAWrapperPassPass(PassRegistry&);
+void initializeMemorySSAPrinterLegacyPassPass(PassRegistry &);
+void initializeMemorySanitizerPass(PassRegistry&);
void initializeMergeFunctionsPass(PassRegistry&);
+void initializeMergedLoadStoreMotionLegacyPassPass(PassRegistry &);
+void initializeMetaRenamerPass(PassRegistry&);
void initializeModuleDebugInfoPrinterPass(PassRegistry&);
+void initializeModuleSummaryIndexWrapperPassPass(PassRegistry &);
+void initializeNameAnonFunctionPass(PassRegistry &);
void initializeNaryReassociatePass(PassRegistry&);
void initializeNoAAPass(PassRegistry&);
void initializeObjCARCAAWrapperPassPass(PassRegistry&);
void initializeObjCARCAPElimPass(PassRegistry&);
-void initializeObjCARCExpandPass(PassRegistry&);
void initializeObjCARCContractPass(PassRegistry&);
+void initializeObjCARCExpandPass(PassRegistry&);
void initializeObjCARCOptPass(PassRegistry&);
-void initializePAEvalPass(PassRegistry &);
+void initializeOptimizationRemarkEmitterWrapperPassPass(PassRegistry&);
void initializeOptimizePHIsPass(PassRegistry&);
-void initializePartiallyInlineLibCallsPass(PassRegistry&);
+void initializePAEvalPass(PassRegistry &);
void initializePEIPass(PassRegistry&);
+void initializePGOIndirectCallPromotionLegacyPassPass(PassRegistry&);
+void initializePGOInstrumentationGenLegacyPassPass(PassRegistry&);
+void initializePGOInstrumentationUseLegacyPassPass(PassRegistry&);
void initializePHIEliminationPass(PassRegistry&);
-void initializePartialInlinerPass(PassRegistry&);
+void initializePhysicalRegisterUsageInfoPass(PassRegistry &);
+void initializePartialInlinerLegacyPassPass(PassRegistry &);
+void initializePartiallyInlineLibCallsLegacyPassPass(PassRegistry &);
+void initializePatchableFunctionPass(PassRegistry &);
void initializePeepholeOptimizerPass(PassRegistry&);
+void initializePlaceBackedgeSafepointsImplPass(PassRegistry&);
+void initializePlaceSafepointsPass(PassRegistry&);
void initializePostDomOnlyPrinterPass(PassRegistry&);
void initializePostDomOnlyViewerPass(PassRegistry&);
void initializePostDomPrinterPass(PassRegistry&);
void initializePostDomViewerPass(PassRegistry&);
-void initializePostDominatorTreePass(PassRegistry&);
-void initializePostOrderFunctionAttrsPass(PassRegistry&);
-void initializePostRASchedulerPass(PassRegistry&);
+void initializePostDominatorTreeWrapperPassPass(PassRegistry&);
void initializePostMachineSchedulerPass(PassRegistry&);
+void initializePostOrderFunctionAttrsLegacyPassPass(PassRegistry&);
+void initializePostRAHazardRecognizerPass(PassRegistry&);
+void initializePostRASchedulerPass(PassRegistry&);
+void initializePreISelIntrinsicLoweringLegacyPassPass(PassRegistry&);
+void initializePrintBasicBlockPassPass(PassRegistry&);
void initializePrintFunctionPassWrapperPass(PassRegistry&);
void initializePrintModulePassWrapperPass(PassRegistry&);
-void initializePrintBasicBlockPassPass(PassRegistry&);
void initializeProcessImplicitDefsPass(PassRegistry&);
-void initializePromotePassPass(PassRegistry&);
+void initializeProfileSummaryInfoWrapperPassPass(PassRegistry &);
+void initializePromoteLegacyPassPass(PassRegistry &);
void initializePruneEHPass(PassRegistry&);
-void initializeReassociatePass(PassRegistry&);
+void initializeReassociateLegacyPassPass(PassRegistry&);
+void initializeRegBankSelectPass(PassRegistry &);
void initializeRegToMemPass(PassRegistry&);
void initializeRegionInfoPassPass(PassRegistry&);
void initializeRegionOnlyPrinterPass(PassRegistry&);
void initializeRegionOnlyViewerPass(PassRegistry&);
void initializeRegionPrinterPass(PassRegistry&);
void initializeRegionViewerPass(PassRegistry&);
-void initializeReversePostOrderFunctionAttrsPass(PassRegistry&);
+void initializeRegisterCoalescerPass(PassRegistry&);
+void initializeRenameIndependentSubregsPass(PassRegistry&);
+void initializeReversePostOrderFunctionAttrsLegacyPassPass(PassRegistry&);
void initializeRewriteStatepointsForGCPass(PassRegistry&);
-void initializeSafeStackPass(PassRegistry&);
-void initializeSCCPPass(PassRegistry&);
-void initializeSROALegacyPassPass(PassRegistry&);
-void initializeSROA_DTPass(PassRegistry&);
-void initializeSROA_SSAUpPass(PassRegistry&);
+void initializeRewriteSymbolsPass(PassRegistry&);
+void initializeSCCPLegacyPassPass(PassRegistry &);
void initializeSCEVAAWrapperPassPass(PassRegistry&);
+void initializeSLPVectorizerPass(PassRegistry&);
+void initializeSROALegacyPassPass(PassRegistry&);
+void initializeSafeStackPass(PassRegistry&);
+void initializeSampleProfileLoaderLegacyPassPass(PassRegistry&);
+void initializeSanitizerCoverageModulePass(PassRegistry&);
void initializeScalarEvolutionWrapperPassPass(PassRegistry&);
+void initializeScalarizerPass(PassRegistry&);
+void initializeScopedNoAliasAAWrapperPassPass(PassRegistry&);
+void initializeSeparateConstOffsetFromGEPPass(PassRegistry &);
+void initializeShadowStackGCLoweringPass(PassRegistry&);
void initializeShrinkWrapPass(PassRegistry &);
void initializeSimpleInlinerPass(PassRegistry&);
-void initializeShadowStackGCLoweringPass(PassRegistry&);
-void initializeRegisterCoalescerPass(PassRegistry&);
void initializeSingleLoopExtractorPass(PassRegistry&);
-void initializeSinkingPass(PassRegistry&);
-void initializeSeparateConstOffsetFromGEPPass(PassRegistry &);
+void initializeSinkingLegacyPassPass(PassRegistry&);
+void initializeSjLjEHPreparePass(PassRegistry&);
void initializeSlotIndexesPass(PassRegistry&);
-void initializeSpillPlacementPass(PassRegistry&);
void initializeSpeculativeExecutionPass(PassRegistry&);
-void initializeStackProtectorPass(PassRegistry&);
+void initializeSpillPlacementPass(PassRegistry&);
void initializeStackColoringPass(PassRegistry&);
+void initializeStackMapLivenessPass(PassRegistry&);
+void initializeStackProtectorPass(PassRegistry&);
void initializeStackSlotColoringPass(PassRegistry&);
void initializeStraightLineStrengthReducePass(PassRegistry &);
void initializeStripDeadDebugInfoPass(PassRegistry&);
@@ -270,46 +318,26 @@ void initializeStripDeadPrototypesLegacyPassPass(PassRegistry&);
void initializeStripDebugDeclarePass(PassRegistry&);
void initializeStripNonDebugSymbolsPass(PassRegistry&);
void initializeStripSymbolsPass(PassRegistry&);
+void initializeStructurizeCFGPass(PassRegistry&);
void initializeTailCallElimPass(PassRegistry&);
void initializeTailDuplicatePassPass(PassRegistry&);
+void initializeTargetLibraryInfoWrapperPassPass(PassRegistry &);
void initializeTargetPassConfigPass(PassRegistry&);
void initializeTargetTransformInfoWrapperPassPass(PassRegistry &);
-void initializeTargetLibraryInfoWrapperPassPass(PassRegistry &);
-void initializeAssumptionCacheTrackerPass(PassRegistry &);
+void initializeThreadSanitizerPass(PassRegistry&);
void initializeTwoAddressInstructionPassPass(PassRegistry&);
void initializeTypeBasedAAWrapperPassPass(PassRegistry&);
-void initializeScopedNoAliasAAWrapperPassPass(PassRegistry&);
void initializeUnifyFunctionExitNodesPass(PassRegistry&);
-void initializeUnreachableBlockElimPass(PassRegistry&);
+void initializeUnpackMachineBundlesPass(PassRegistry&);
+void initializeUnreachableBlockElimLegacyPassPass(PassRegistry&);
void initializeUnreachableMachineBlockElimPass(PassRegistry&);
void initializeVerifierLegacyPassPass(PassRegistry&);
void initializeVirtRegMapPass(PassRegistry&);
void initializeVirtRegRewriterPass(PassRegistry&);
-void initializeInstSimplifierPass(PassRegistry&);
-void initializeUnpackMachineBundlesPass(PassRegistry&);
-void initializeFinalizeMachineBundlesPass(PassRegistry&);
-void initializeLoopAccessAnalysisPass(PassRegistry&);
-void initializeLoopVectorizePass(PassRegistry&);
-void initializeSLPVectorizerPass(PassRegistry&);
-void initializeBBVectorizePass(PassRegistry&);
-void initializeMachineFunctionPrinterPassPass(PassRegistry&);
-void initializeMIRPrintingPassPass(PassRegistry&);
-void initializeStackMapLivenessPass(PassRegistry&);
-void initializeLiveDebugValuesPass(PassRegistry&);
-void initializeMachineCombinerPass(PassRegistry &);
-void initializeLoadCombinePass(PassRegistry&);
-void initializeRewriteSymbolsPass(PassRegistry&);
+void initializeWholeProgramDevirtPass(PassRegistry &);
void initializeWinEHPreparePass(PassRegistry&);
-void initializePlaceBackedgeSafepointsImplPass(PassRegistry&);
-void initializePlaceSafepointsPass(PassRegistry&);
-void initializeDwarfEHPreparePass(PassRegistry&);
-void initializeFloat2IntPass(PassRegistry&);
-void initializeLoopDistributePass(PassRegistry&);
-void initializeSjLjEHPreparePass(PassRegistry&);
-void initializeDemandedBitsPass(PassRegistry&);
-void initializeFuncletLayoutPass(PassRegistry &);
-void initializeLoopLoadEliminationPass(PassRegistry&);
-void initializeFunctionImportPassPass(PassRegistry &);
+void initializeWriteBitcodePassPass(PassRegistry &);
+void initializeXRayInstrumentationPass(PassRegistry &);
}
#endif
diff --git a/include/llvm/LTO/LTO.h b/include/llvm/LTO/LTO.h
new file mode 100644
index 000000000000..5154c0007aaa
--- /dev/null
+++ b/include/llvm/LTO/LTO.h
@@ -0,0 +1,74 @@
+//===-LTO.h - LLVM Link Time Optimizer ------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares functions and classes used to support LTO. It is intended
+// to be used both by LTO classes as well as by clients (gold-plugin) that
+// don't utilize the LTO code generator interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LTO_LTO_H
+#define LLVM_LTO_LTO_H
+
+#include "llvm/ADT/StringMap.h"
+#include "llvm/IR/ModuleSummaryIndex.h"
+
+namespace llvm {
+
+class LLVMContext;
+class MemoryBufferRef;
+class Module;
+
+/// Helper to load a module from bitcode.
+std::unique_ptr<Module> loadModuleFromBuffer(const MemoryBufferRef &Buffer,
+ LLVMContext &Context, bool Lazy);
+
+/// Provide a "loader" for the FunctionImporter to access function from other
+/// modules.
+class ModuleLoader {
+ /// The context that will be used for importing.
+ LLVMContext &Context;
+
+ /// Map from Module identifier to MemoryBuffer. Used by clients like the
+ /// FunctionImported to request loading a Module.
+ StringMap<MemoryBufferRef> &ModuleMap;
+
+public:
+ ModuleLoader(LLVMContext &Context, StringMap<MemoryBufferRef> &ModuleMap)
+ : Context(Context), ModuleMap(ModuleMap) {}
+
+ /// Load a module on demand.
+ std::unique_ptr<Module> operator()(StringRef Identifier) {
+ return loadModuleFromBuffer(ModuleMap[Identifier], Context, /*Lazy*/ true);
+ }
+};
+
+
+/// Resolve Weak and LinkOnce values in the \p Index. Linkage changes recorded
+/// in the index and the ThinLTO backends must apply the changes to the Module
+/// via thinLTOResolveWeakForLinkerModule.
+///
+/// This is done for correctness (if value exported, ensure we always
+/// emit a copy), and compile-time optimization (allow drop of duplicates).
+void thinLTOResolveWeakForLinkerInIndex(
+ ModuleSummaryIndex &Index,
+ function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)>
+ isPrevailing,
+ function_ref<void(StringRef, GlobalValue::GUID, GlobalValue::LinkageTypes)>
+ recordNewLinkage);
+
+/// Update the linkages in the given \p Index to mark exported values
+/// as external and non-exported values as internal. The ThinLTO backends
+/// must apply the changes to the Module via thinLTOInternalizeModule.
+void thinLTOInternalizeAndPromoteInIndex(
+ ModuleSummaryIndex &Index,
+ function_ref<bool(StringRef, GlobalValue::GUID)> isExported);
+}
+
+#endif
diff --git a/include/llvm/LTO/LTOCodeGenerator.h b/include/llvm/LTO/legacy/LTOCodeGenerator.h
index 3820b211a381..d083e37d75b8 100644
--- a/include/llvm/LTO/LTOCodeGenerator.h
+++ b/include/llvm/LTO/legacy/LTOCodeGenerator.h
@@ -36,18 +36,20 @@
#define LLVM_LTO_LTOCODEGENERATOR_H
#include "llvm-c/lto.h"
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/IR/GlobalValue.h"
+#include "llvm/IR/Module.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include <string>
#include <vector>
namespace llvm {
+template <typename T> class ArrayRef;
class LLVMContext;
class DiagnosticInfo;
- class GlobalValue;
class Linker;
class Mangler;
class MemoryBuffer;
@@ -66,17 +68,21 @@ struct LTOCodeGenerator {
~LTOCodeGenerator();
/// Merge given module. Return true on success.
+ ///
+ /// Resets \a HasVerifiedInput.
bool addModule(struct LTOModule *);
/// Set the destination module.
+ ///
+ /// Resets \a HasVerifiedInput.
void setModule(std::unique_ptr<LTOModule> M);
- void setTargetOptions(TargetOptions Options);
+ void setTargetOptions(const TargetOptions &Options);
void setDebugInfo(lto_debug_model);
- void setCodePICModel(Reloc::Model Model) { RelocModel = Model; }
-
+ void setCodePICModel(Optional<Reloc::Model> Model) { RelocModel = Model; }
+
/// Set the file type to be emitted (assembly or object code).
- /// The default is TargetMachine::CGFT_ObjectFile.
+ /// The default is TargetMachine::CGFT_ObjectFile.
void setFileType(TargetMachine::CodeGenFileType FT) { FileType = FT; }
void setCpu(const char *MCpu) { this->MCpu = MCpu; }
@@ -86,6 +92,22 @@ struct LTOCodeGenerator {
void setShouldInternalize(bool Value) { ShouldInternalize = Value; }
void setShouldEmbedUselists(bool Value) { ShouldEmbedUselists = Value; }
+ /// Restore linkage of globals
+ ///
+ /// When set, the linkage of globals will be restored prior to code
+ /// generation. That is, a global symbol that had external linkage prior to
+ /// LTO will be emitted with external linkage again; and a local will remain
+ /// local. Note that this option only affects the end result - globals may
+ /// still be internalized in the process of LTO and may be modified and/or
+ /// deleted where legal.
+ ///
+ /// The default behavior will internalize globals (unless on the preserve
+ /// list) and, if parallel code generation is enabled, will externalize
+ /// all locals.
+ void setShouldRestoreGlobalsLinkage(bool Value) {
+ ShouldRestoreGlobalsLinkage = Value;
+ }
+
void addMustPreserveSymbol(StringRef Sym) { MustPreserveSymbols[Sym] = 1; }
/// Pass options to the driver and optimization passes.
@@ -105,6 +127,8 @@ struct LTOCodeGenerator {
/// Write the merged module to the file specified by the given path. Return
/// true on success.
+ ///
+ /// Calls \a verifyMergedModuleOnce().
bool writeMergedModules(const char *Path);
/// Compile the merged module into a *single* output file; the path to output
@@ -129,6 +153,8 @@ struct LTOCodeGenerator {
bool DisableVectorization);
/// Optimizes the merged module. Returns true on success.
+ ///
+ /// Calls \a verifyMergedModuleOnce().
bool optimize(bool DisableVerify, bool DisableInline, bool DisableGVNLoadPRE,
bool DisableVectorization);
@@ -142,6 +168,8 @@ struct LTOCodeGenerator {
/// than one element, code generation is done in parallel with out.size()
/// threads. Output files will be written to members of out. Returns true on
/// success.
+ ///
+ /// Calls \a verifyMergedModuleOnce().
bool compileOptimized(ArrayRef<raw_pwrite_stream *> Out);
void setDiagnosticHandler(lto_diagnostic_handler_t, void *);
@@ -153,21 +181,28 @@ struct LTOCodeGenerator {
private:
void initializeLTOPasses();
+ /// Verify the merged module on first call.
+ ///
+ /// Sets \a HasVerifiedInput on first call and doesn't run again on the same
+ /// input.
+ void verifyMergedModuleOnce();
+
bool compileOptimizedToFile(const char **Name);
+ void restoreLinkageForExternals();
void applyScopeRestrictions();
- void applyRestriction(GlobalValue &GV, ArrayRef<StringRef> Libcalls,
- std::vector<const char *> &MustPreserveList,
- SmallPtrSetImpl<GlobalValue *> &AsmUsed,
- Mangler &Mangler);
+ void preserveDiscardableGVs(
+ Module &TheModule,
+ llvm::function_ref<bool(const GlobalValue &)> mustPreserveGV);
+
bool determineTarget();
+ std::unique_ptr<TargetMachine> createTargetMachine();
static void DiagnosticHandler(const DiagnosticInfo &DI, void *Context);
void DiagnosticHandler2(const DiagnosticInfo &DI);
void emitError(const std::string &ErrMsg);
-
- typedef StringMap<uint8_t> StringSet;
+ void emitWarning(const std::string &ErrMsg);
LLVMContext &Context;
std::unique_ptr<Module> MergedModule;
@@ -175,9 +210,11 @@ private:
std::unique_ptr<TargetMachine> TargetMach;
bool EmitDwarfDebugInfo = false;
bool ScopeRestrictionsDone = false;
- Reloc::Model RelocModel = Reloc::Default;
- StringSet MustPreserveSymbols;
- StringSet AsmUndefinedRefs;
+ bool HasVerifiedInput = false;
+ Optional<Reloc::Model> RelocModel;
+ StringSet<> MustPreserveSymbols;
+ StringSet<> AsmUndefinedRefs;
+ StringMap<GlobalValue::LinkageTypes> ExternalSymbols;
std::vector<std::string> CodegenOptions;
std::string FeatureStr;
std::string MCpu;
@@ -185,11 +222,14 @@ private:
std::string NativeObjectPath;
TargetOptions Options;
CodeGenOpt::Level CGOptLevel = CodeGenOpt::Default;
+ const Target *MArch = nullptr;
+ std::string TripleStr;
unsigned OptLevel = 2;
lto_diagnostic_handler_t DiagHandler = nullptr;
void *DiagContext = nullptr;
bool ShouldInternalize = true;
bool ShouldEmbedUselists = false;
+ bool ShouldRestoreGlobalsLinkage = false;
TargetMachine::CodeGenFileType FileType = TargetMachine::CGFT_ObjectFile;
};
}
diff --git a/include/llvm/LTO/LTOModule.h b/include/llvm/LTO/legacy/LTOModule.h
index 97b5865bd47f..2e46219be19e 100644
--- a/include/llvm/LTO/LTOModule.h
+++ b/include/llvm/LTO/legacy/LTOModule.h
@@ -18,8 +18,6 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/IR/Module.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/Object/IRObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include <string>
@@ -59,8 +57,6 @@ private:
std::vector<const char*> _asm_undefines;
LTOModule(std::unique_ptr<object::IRObjectFile> Obj, TargetMachine *TM);
- LTOModule(std::unique_ptr<object::IRObjectFile> Obj, TargetMachine *TM,
- std::unique_ptr<LLVMContext> Context);
public:
~LTOModule();
@@ -69,6 +65,9 @@ public:
static bool isBitcodeFile(const void *mem, size_t length);
static bool isBitcodeFile(const char *path);
+ /// Returns 'true' if the Module is produced for ThinLTO.
+ bool isThinLTO();
+
/// Returns 'true' if the memory buffer is LLVM bitcode for the specified
/// triple.
static bool isBitcodeForTarget(MemoryBuffer *memBuffer,
@@ -92,23 +91,22 @@ public:
/// InitializeAllAsmPrinters();
/// InitializeAllAsmParsers();
static ErrorOr<std::unique_ptr<LTOModule>>
- createFromFile(LLVMContext &Context, const char *path, TargetOptions options);
+ createFromFile(LLVMContext &Context, const char *path,
+ const TargetOptions &options);
static ErrorOr<std::unique_ptr<LTOModule>>
createFromOpenFile(LLVMContext &Context, int fd, const char *path,
- size_t size, TargetOptions options);
+ size_t size, const TargetOptions &options);
static ErrorOr<std::unique_ptr<LTOModule>>
createFromOpenFileSlice(LLVMContext &Context, int fd, const char *path,
- size_t map_size, off_t offset, TargetOptions options);
+ size_t map_size, off_t offset,
+ const TargetOptions &options);
static ErrorOr<std::unique_ptr<LTOModule>>
createFromBuffer(LLVMContext &Context, const void *mem, size_t length,
- TargetOptions options, StringRef path = "");
-
+ const TargetOptions &options, StringRef path = "");
static ErrorOr<std::unique_ptr<LTOModule>>
- createInLocalContext(const void *mem, size_t length, TargetOptions options,
+ createInLocalContext(std::unique_ptr<LLVMContext> Context, const void *mem,
+ size_t length, const TargetOptions &options,
StringRef path);
- static ErrorOr<std::unique_ptr<LTOModule>>
- createInContext(const void *mem, size_t length, TargetOptions options,
- StringRef path, LLVMContext *Context);
const Module &getModule() const {
return const_cast<LTOModule*>(this)->getModule();
@@ -207,8 +205,8 @@ private:
/// Create an LTOModule (private version).
static ErrorOr<std::unique_ptr<LTOModule>>
- makeLTOModule(MemoryBufferRef Buffer, TargetOptions options,
- LLVMContext *Context);
+ makeLTOModule(MemoryBufferRef Buffer, const TargetOptions &options,
+ LLVMContext &Context, bool ShouldBeLazy);
};
}
#endif
diff --git a/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h b/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h
new file mode 100644
index 000000000000..539880e8d3a7
--- /dev/null
+++ b/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h
@@ -0,0 +1,276 @@
+//===-ThinLTOCodeGenerator.h - LLVM Link Time Optimizer -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the ThinLTOCodeGenerator class, similar to the
+// LTOCodeGenerator but for the ThinLTO scheme. It provides an interface for
+// linker plugin.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LTO_THINLTOCODEGENERATOR_H
+#define LLVM_LTO_THINLTOCODEGENERATOR_H
+
+#include "llvm-c/lto.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/IR/ModuleSummaryIndex.h"
+#include "llvm/Support/CodeGen.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Target/TargetOptions.h"
+
+#include <string>
+
+namespace llvm {
+class StringRef;
+class LLVMContext;
+class TargetMachine;
+
+/// Helper to gather options relevant to the target machine creation
+struct TargetMachineBuilder {
+ Triple TheTriple;
+ std::string MCpu;
+ std::string MAttr;
+ TargetOptions Options;
+ Optional<Reloc::Model> RelocModel;
+ CodeGenOpt::Level CGOptLevel = CodeGenOpt::Default;
+
+ std::unique_ptr<TargetMachine> create() const;
+};
+
+/// This class define an interface similar to the LTOCodeGenerator, but adapted
+/// for ThinLTO processing.
+/// The ThinLTOCodeGenerator is not intended to be reuse for multiple
+/// compilation: the model is that the client adds modules to the generator and
+/// ask to perform the ThinLTO optimizations / codegen, and finally destroys the
+/// codegenerator.
+class ThinLTOCodeGenerator {
+public:
+ /// Add given module to the code generator.
+ void addModule(StringRef Identifier, StringRef Data);
+
+ /**
+ * Adds to a list of all global symbols that must exist in the final generated
+ * code. If a symbol is not listed there, it will be optimized away if it is
+ * inlined into every usage.
+ */
+ void preserveSymbol(StringRef Name);
+
+ /**
+ * Adds to a list of all global symbols that are cross-referenced between
+ * ThinLTO files. If the ThinLTO CodeGenerator can ensure that every
+ * references from a ThinLTO module to this symbol is optimized away, then
+ * the symbol can be discarded.
+ */
+ void crossReferenceSymbol(StringRef Name);
+
+ /**
+ * Process all the modules that were added to the code generator in parallel.
+ *
+ * Client can access the resulting object files using getProducedBinaries()
+ */
+ void run();
+
+ /**
+ * Return the "in memory" binaries produced by the code generator.
+ */
+ std::vector<std::unique_ptr<MemoryBuffer>> &getProducedBinaries() {
+ return ProducedBinaries;
+ }
+
+ /**
+ * \defgroup Options setters
+ * @{
+ */
+
+ /**
+ * \defgroup Cache controlling options
+ *
+ * These entry points control the ThinLTO cache. The cache is intended to
+ * support incremental build, and thus needs to be persistent accross build.
+ * The client enabled the cache by supplying a path to an existing directory.
+ * The code generator will use this to store objects files that may be reused
+ * during a subsequent build.
+ * To avoid filling the disk space, a few knobs are provided:
+ * - The pruning interval limit the frequency at which the garbage collector
+ * will try to scan the cache directory to prune it from expired entries.
+ * Setting to -1 disable the pruning (default).
+ * - The pruning expiration time indicates to the garbage collector how old
+ * an entry needs to be to be removed.
+ * - Finally, the garbage collector can be instructed to prune the cache till
+ * the occupied space goes below a threshold.
+ * @{
+ */
+
+ struct CachingOptions {
+ std::string Path; // Path to the cache, empty to disable.
+ int PruningInterval = 1200; // seconds, -1 to disable pruning.
+ unsigned int Expiration = 7 * 24 * 3600; // seconds (1w default).
+ unsigned MaxPercentageOfAvailableSpace = 75; // percentage.
+ };
+
+ /// Provide a path to a directory where to store the cached files for
+ /// incremental build.
+ void setCacheDir(std::string Path) { CacheOptions.Path = std::move(Path); }
+
+ /// Cache policy: interval (seconds) between two prune of the cache. Set to a
+ /// negative value (default) to disable pruning. A value of 0 will be ignored.
+ void setCachePruningInterval(int Interval) {
+ if (Interval)
+ CacheOptions.PruningInterval = Interval;
+ }
+
+ /// Cache policy: expiration (in seconds) for an entry.
+ /// A value of 0 will be ignored.
+ void setCacheEntryExpiration(unsigned Expiration) {
+ if (Expiration)
+ CacheOptions.Expiration = Expiration;
+ }
+
+ /**
+ * Sets the maximum cache size that can be persistent across build, in terms
+ * of percentage of the available space on the the disk. Set to 100 to
+ * indicate no limit, 50 to indicate that the cache size will not be left over
+ * half the available space. A value over 100 will be reduced to 100, and a
+ * value of 0 will be ignored.
+ *
+ *
+ * The formula looks like:
+ * AvailableSpace = FreeSpace + ExistingCacheSize
+ * NewCacheSize = AvailableSpace * P/100
+ *
+ */
+ void setMaxCacheSizeRelativeToAvailableSpace(unsigned Percentage) {
+ if (Percentage)
+ CacheOptions.MaxPercentageOfAvailableSpace = Percentage;
+ }
+
+ /**@}*/
+
+ /// Set the path to a directory where to save temporaries at various stages of
+ /// the processing.
+ void setSaveTempsDir(std::string Path) { SaveTempsDir = std::move(Path); }
+
+ /// CPU to use to initialize the TargetMachine
+ void setCpu(std::string Cpu) { TMBuilder.MCpu = std::move(Cpu); }
+
+ /// Subtarget attributes
+ void setAttr(std::string MAttr) { TMBuilder.MAttr = std::move(MAttr); }
+
+ /// TargetMachine options
+ void setTargetOptions(TargetOptions Options) {
+ TMBuilder.Options = std::move(Options);
+ }
+
+ /// CodeModel
+ void setCodePICModel(Optional<Reloc::Model> Model) {
+ TMBuilder.RelocModel = Model;
+ }
+
+ /// CodeGen optimization level
+ void setCodeGenOptLevel(CodeGenOpt::Level CGOptLevel) {
+ TMBuilder.CGOptLevel = CGOptLevel;
+ }
+
+ /// Disable CodeGen, only run the stages till codegen and stop. The output
+ /// will be bitcode.
+ void disableCodeGen(bool Disable) { DisableCodeGen = Disable; }
+
+ /// Perform CodeGen only: disable all other stages.
+ void setCodeGenOnly(bool CGOnly) { CodeGenOnly = CGOnly; }
+
+ /**@}*/
+
+ /**
+ * \defgroup Set of APIs to run individual stages in isolation.
+ * @{
+ */
+
+ /**
+ * Produce the combined summary index from all the bitcode files:
+ * "thin-link".
+ */
+ std::unique_ptr<ModuleSummaryIndex> linkCombinedIndex();
+
+ /**
+ * Perform promotion and renaming of exported internal functions,
+ * and additionally resolve weak and linkonce symbols.
+ * Index is updated to reflect linkage changes from weak resolution.
+ */
+ void promote(Module &Module, ModuleSummaryIndex &Index);
+
+ /**
+ * Compute and emit the imported files for module at \p ModulePath.
+ */
+ static void emitImports(StringRef ModulePath, StringRef OutputName,
+ ModuleSummaryIndex &Index);
+
+ /**
+ * Perform cross-module importing for the module identified by
+ * ModuleIdentifier.
+ */
+ void crossModuleImport(Module &Module, ModuleSummaryIndex &Index);
+
+ /**
+ * Compute the list of summaries needed for importing into module.
+ */
+ static void gatherImportedSummariesForModule(
+ StringRef ModulePath, ModuleSummaryIndex &Index,
+ std::map<std::string, GVSummaryMapTy> &ModuleToSummariesForIndex);
+
+ /**
+ * Perform internalization. Index is updated to reflect linkage changes.
+ */
+ void internalize(Module &Module, ModuleSummaryIndex &Index);
+
+ /**
+ * Perform post-importing ThinLTO optimizations.
+ */
+ void optimize(Module &Module);
+
+ /**
+ * Perform ThinLTO CodeGen.
+ */
+ std::unique_ptr<MemoryBuffer> codegen(Module &Module);
+
+ /**@}*/
+
+private:
+ /// Helper factory to build a TargetMachine
+ TargetMachineBuilder TMBuilder;
+
+ /// Vector holding the in-memory buffer containing the produced binaries.
+ std::vector<std::unique_ptr<MemoryBuffer>> ProducedBinaries;
+
+ /// Vector holding the input buffers containing the bitcode modules to
+ /// process.
+ std::vector<MemoryBufferRef> Modules;
+
+ /// Set of symbols that need to be preserved outside of the set of bitcode
+ /// files.
+ StringSet<> PreservedSymbols;
+
+ /// Set of symbols that are cross-referenced between bitcode files.
+ StringSet<> CrossReferencedSymbols;
+
+ /// Control the caching behavior.
+ CachingOptions CacheOptions;
+
+ /// Path to a directory to save the temporary bitcode files.
+ std::string SaveTempsDir;
+
+ /// Flag to enable/disable CodeGen. When set to true, the process stops after
+ /// optimizations and a bitcode is produced.
+ bool DisableCodeGen = false;
+
+ /// Flag to indicate that only the CodeGen will be performed, no cross-module
+ /// importing or optimization.
+ bool CodeGenOnly = false;
+};
+}
+#endif
diff --git a/include/llvm/LTO/legacy/UpdateCompilerUsed.h b/include/llvm/LTO/legacy/UpdateCompilerUsed.h
new file mode 100644
index 000000000000..4be0027e97d7
--- /dev/null
+++ b/include/llvm/LTO/legacy/UpdateCompilerUsed.h
@@ -0,0 +1,32 @@
+//==------ UpdateCompilerUsed.h - LLVM Link Time Optimizer Utility --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares a helper class to update llvm.compiler_used metadata.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LTO_UPDATE_COMPILER_USED_H
+#define LLVM_LTO_UPDATE_COMPILER_USED_H
+
+#include "llvm/ADT/StringSet.h"
+#include "llvm/IR/GlobalValue.h"
+
+namespace llvm {
+class Module;
+class TargetMachine;
+
+/// Find all globals in \p TheModule that are referenced in
+/// \p AsmUndefinedRefs, as well as the user-supplied functions definitions that
+/// are also libcalls, and create or update the magic "llvm.compiler_used"
+/// global in \p TheModule.
+void updateCompilerUsed(Module &TheModule, const TargetMachine &TM,
+ const StringSet<> &AsmUndefinedRefs);
+}
+
+#endif // LLVM_LTO_UPDATE_COMPILER_USED_H
diff --git a/include/llvm/LibDriver/LibDriver.h b/include/llvm/LibDriver/LibDriver.h
index 09495650c1b9..95feb60be403 100644
--- a/include/llvm/LibDriver/LibDriver.h
+++ b/include/llvm/LibDriver/LibDriver.h
@@ -15,12 +15,10 @@
#ifndef LLVM_LIBDRIVER_LIBDRIVER_H
#define LLVM_LIBDRIVER_LIBDRIVER_H
-#include "llvm/ADT/ArrayRef.h"
-
namespace llvm {
+template <typename T> class ArrayRef;
-int libDriverMain(llvm::ArrayRef<const char*> ARgs);
-
+int libDriverMain(ArrayRef<const char *> ARgs);
}
#endif
diff --git a/include/llvm/LineEditor/LineEditor.h b/include/llvm/LineEditor/LineEditor.h
index bb106f87ca48..68995d0633ad 100644
--- a/include/llvm/LineEditor/LineEditor.h
+++ b/include/llvm/LineEditor/LineEditor.h
@@ -15,6 +15,7 @@
#include <cstdio>
#include <memory>
#include <string>
+#include <utility>
#include <vector>
namespace llvm {
@@ -137,7 +138,7 @@ private:
template <typename T>
struct ListCompleterModel : ListCompleterConcept {
- ListCompleterModel(T Value) : Value(Value) {}
+ ListCompleterModel(T Value) : Value(std::move(Value)) {}
std::vector<Completion> getCompletions(StringRef Buffer,
size_t Pos) const override {
return Value(Buffer, Pos);
diff --git a/include/llvm/LinkAllIR.h b/include/llvm/LinkAllIR.h
index 2b0604aee067..77e19ce900e3 100644
--- a/include/llvm/LinkAllIR.h
+++ b/include/llvm/LinkAllIR.h
@@ -43,8 +43,9 @@ namespace {
// to know that getenv() never returns -1, this will do the job.
if (std::getenv("bar") != (char*) -1)
return;
- (void)new llvm::Module("", llvm::getGlobalContext());
- (void)new llvm::UnreachableInst(llvm::getGlobalContext());
+ llvm::LLVMContext Context;
+ (void)new llvm::Module("", Context);
+ (void)new llvm::UnreachableInst(Context);
(void) llvm::createVerifierPass();
}
} ForceVMCoreLinking;
diff --git a/include/llvm/LinkAllPasses.h b/include/llvm/LinkAllPasses.h
index 327faac33206..b2721d0a1fd9 100644
--- a/include/llvm/LinkAllPasses.h
+++ b/include/llvm/LinkAllPasses.h
@@ -17,8 +17,10 @@
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AliasSetTracker.h"
+#include "llvm/Analysis/AliasAnalysisEvaluator.h"
#include "llvm/Analysis/BasicAliasAnalysis.h"
-#include "llvm/Analysis/CFLAliasAnalysis.h"
+#include "llvm/Analysis/CFLAndersAliasAnalysis.h"
+#include "llvm/Analysis/CFLSteensAliasAnalysis.h"
#include "llvm/Analysis/CallPrinter.h"
#include "llvm/Analysis/DomPrinter.h"
#include "llvm/Analysis/GlobalsModRef.h"
@@ -31,14 +33,17 @@
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
#include "llvm/Analysis/ScopedNoAliasAA.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TypeBasedAliasAnalysis.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/Transforms/IPO.h"
+#include "llvm/Transforms/IPO/FunctionAttrs.h"
#include "llvm/Transforms/Instrumentation.h"
#include "llvm/Transforms/ObjCARC.h"
#include "llvm/Transforms/Scalar.h"
+#include "llvm/Transforms/Scalar/GVN.h"
#include "llvm/Transforms/Utils/SymbolRewriter.h"
#include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h"
#include "llvm/Transforms/Vectorize.h"
@@ -66,10 +71,11 @@ namespace {
(void) llvm::createScopedNoAliasAAWrapperPass();
(void) llvm::createBoundsCheckingPass();
(void) llvm::createBreakCriticalEdgesPass();
- (void) llvm::createCallGraphPrinterPass();
+ (void) llvm::createCallGraphDOTPrinterPass();
(void) llvm::createCallGraphViewerPass();
(void) llvm::createCFGSimplificationPass();
- (void) llvm::createCFLAAWrapperPass();
+ (void) llvm::createCFLAndersAAWrapperPass();
+ (void) llvm::createCFLSteensAAWrapperPass();
(void) llvm::createStructurizeCFGPass();
(void) llvm::createConstantMergePass();
(void) llvm::createConstantPropagationPass();
@@ -78,22 +84,24 @@ namespace {
(void) llvm::createDeadCodeEliminationPass();
(void) llvm::createDeadInstEliminationPass();
(void) llvm::createDeadStoreEliminationPass();
- (void) llvm::createDependenceAnalysisPass();
+ (void) llvm::createDependenceAnalysisWrapperPass();
(void) llvm::createDivergenceAnalysisPass();
(void) llvm::createDomOnlyPrinterPass();
(void) llvm::createDomPrinterPass();
(void) llvm::createDomOnlyViewerPass();
(void) llvm::createDomViewerPass();
(void) llvm::createGCOVProfilerPass();
- (void) llvm::createPGOInstrumentationGenPass();
- (void) llvm::createPGOInstrumentationUsePass();
- (void) llvm::createInstrProfilingPass();
+ (void) llvm::createPGOInstrumentationGenLegacyPass();
+ (void) llvm::createPGOInstrumentationUseLegacyPass();
+ (void) llvm::createPGOIndirectCallPromotionLegacyPass();
+ (void) llvm::createInstrProfilingLegacyPass();
(void) llvm::createFunctionImportPass();
(void) llvm::createFunctionInliningPass();
(void) llvm::createAlwaysInlinerPass();
(void) llvm::createGlobalDCEPass();
(void) llvm::createGlobalOptimizerPass();
(void) llvm::createGlobalsAAWrapperPass();
+ (void) llvm::createGuardWideningPass();
(void) llvm::createIPConstantPropagationPass();
(void) llvm::createIPSCCPPass();
(void) llvm::createInductiveRangeCheckEliminationPass();
@@ -106,10 +114,12 @@ namespace {
(void) llvm::createLoopExtractorPass();
(void) llvm::createLoopInterchangePass();
(void) llvm::createLoopSimplifyPass();
+ (void) llvm::createLoopSimplifyCFGPass();
(void) llvm::createLoopStrengthReducePass();
(void) llvm::createLoopRerollPass();
(void) llvm::createLoopUnrollPass();
(void) llvm::createLoopUnswitchPass();
+ (void) llvm::createLoopVersioningLICMPass();
(void) llvm::createLoopIdiomPass();
(void) llvm::createLoopRotatePass();
(void) llvm::createLowerExpectIntrinsicPass();
@@ -137,7 +147,7 @@ namespace {
(void) llvm::createRegionViewerPass();
(void) llvm::createSCCPPass();
(void) llvm::createSafeStackPass();
- (void) llvm::createScalarReplAggregatesPass();
+ (void) llvm::createSROAPass();
(void) llvm::createSingleLoopExtractorPass();
(void) llvm::createStripSymbolsPass();
(void) llvm::createStripNonDebugSymbolsPass();
@@ -150,6 +160,7 @@ namespace {
(void) llvm::createConstantHoistingPass();
(void) llvm::createCodeGenPreparePass();
(void) llvm::createEarlyCSEPass();
+ (void) llvm::createGVNHoistPass();
(void) llvm::createMergedLoadStoreMotionPass();
(void) llvm::createGVNPass();
(void) llvm::createMemCpyOptPass();
@@ -157,7 +168,7 @@ namespace {
(void) llvm::createPostDomTree();
(void) llvm::createInstructionNamerPass();
(void) llvm::createMetaRenamerPass();
- (void) llvm::createPostOrderFunctionAttrsPass();
+ (void) llvm::createPostOrderFunctionAttrsLegacyPass();
(void) llvm::createReversePostOrderFunctionAttrsPass();
(void) llvm::createMergeFunctionsPass();
std::string buf;
@@ -175,11 +186,13 @@ namespace {
(void) llvm::createInstructionSimplifierPass();
(void) llvm::createLoopVectorizePass();
(void) llvm::createSLPVectorizerPass();
+ (void) llvm::createLoadStoreVectorizerPass();
(void) llvm::createBBVectorizePass();
(void) llvm::createPartiallyInlineLibCallsPass();
(void) llvm::createScalarizerPass();
(void) llvm::createSeparateConstOffsetFromGEPPass();
(void) llvm::createSpeculativeExecutionPass();
+ (void) llvm::createSpeculativeExecutionIfHasBranchDivergencePass();
(void) llvm::createRewriteSymbolsPass();
(void) llvm::createStraightLineStrengthReducePass();
(void) llvm::createMemDerefPrinter();
@@ -190,7 +203,9 @@ namespace {
(void)new llvm::ScalarEvolutionWrapperPass();
llvm::Function::Create(nullptr, llvm::GlobalValue::ExternalLinkage)->viewCFGOnly();
llvm::RGPassManager RGM;
- llvm::AliasAnalysis AA;
+ llvm::TargetLibraryInfoImpl TLII;
+ llvm::TargetLibraryInfo TLI(TLII);
+ llvm::AliasAnalysis AA(TLI);
llvm::AliasSetTracker X(AA);
X.add(nullptr, 0, llvm::AAMDNodes()); // for -print-alias-sets
(void) llvm::AreStatisticsEnabled();
diff --git a/include/llvm/Linker/IRMover.h b/include/llvm/Linker/IRMover.h
index a964cc4b72c5..578940ed4069 100644
--- a/include/llvm/Linker/IRMover.h
+++ b/include/llvm/Linker/IRMover.h
@@ -15,10 +15,12 @@
#include <functional>
namespace llvm {
+class Error;
class GlobalValue;
-class MDNode;
+class Metadata;
class Module;
class StructType;
+class TrackingMDRef;
class Type;
class IRMover {
@@ -39,6 +41,9 @@ class IRMover {
static bool isEqual(const StructType *LHS, const StructType *RHS);
};
+ /// Type of the Metadata map in \a ValueToValueMapTy.
+ typedef DenseMap<const Metadata *, TrackingMDRef> MDMapT;
+
public:
class IdentifiedStructTypeSet {
// The set of opaque types is the composite module.
@@ -58,17 +63,22 @@ public:
IRMover(Module &M);
typedef std::function<void(GlobalValue &)> ValueAdder;
- /// Move in the provide values. The source is destroyed.
- /// Returns true on error.
- bool move(Module &Src, ArrayRef<GlobalValue *> ValuesToLink,
- std::function<void(GlobalValue &GV, ValueAdder Add)> AddLazyFor,
- DenseMap<unsigned, MDNode *> *ValIDToTempMDMap = nullptr,
- bool IsMetadataLinkingPostpass = false);
+
+ /// Move in the provide values in \p ValuesToLink from \p Src.
+ ///
+ /// - \p AddLazyFor is a call back that the IRMover will call when a global
+ /// value is referenced by one of the ValuesToLink (transitively) but was
+ /// not present in ValuesToLink. The GlobalValue and a ValueAdder callback
+ /// are passed as an argument, and the callback is expected to be called
+ /// if the GlobalValue needs to be added to the \p ValuesToLink and linked.
+ Error move(std::unique_ptr<Module> Src, ArrayRef<GlobalValue *> ValuesToLink,
+ std::function<void(GlobalValue &GV, ValueAdder Add)> AddLazyFor);
Module &getModule() { return Composite; }
private:
Module &Composite;
IdentifiedStructTypeSet IdentifiedStructTypes;
+ MDMapT SharedMDs; ///< A Metadata map to use for all calls to \a move().
};
} // End llvm namespace
diff --git a/include/llvm/Linker/Linker.h b/include/llvm/Linker/Linker.h
index 2b051e6d15c9..b077c373326f 100644
--- a/include/llvm/Linker/Linker.h
+++ b/include/llvm/Linker/Linker.h
@@ -10,7 +10,6 @@
#ifndef LLVM_LINKER_LINKER_H
#define LLVM_LINKER_LINKER_H
-#include "llvm/IR/FunctionInfo.h"
#include "llvm/Linker/IRMover.h"
namespace llvm {
@@ -30,7 +29,10 @@ public:
None = 0,
OverrideFromSrc = (1 << 0),
LinkOnlyNeeded = (1 << 1),
- InternalizeLinkedSymbols = (1 << 2)
+ InternalizeLinkedSymbols = (1 << 2),
+ /// Don't force link referenced linkonce definitions, import declaration.
+ DontForceLinkLinkonceODR = (1 << 3)
+
};
Linker(Module &M);
@@ -39,38 +41,18 @@ public:
///
/// Passing OverrideSymbols as true will have symbols from Src
/// shadow those in the Dest.
- /// For ThinLTO function importing/exporting the \p FunctionInfoIndex
- /// is passed. If \p FunctionsToImport is provided, only the functions that
+ /// For ThinLTO function importing/exporting the \p ModuleSummaryIndex
+ /// is passed. If \p GlobalsToImport is provided, only the globals that
/// are part of the set will be imported from the source module.
- /// The \p ValIDToTempMDMap is populated by the linker when function
- /// importing is performed.
///
/// Returns true on error.
bool linkInModule(std::unique_ptr<Module> Src, unsigned Flags = Flags::None,
- const FunctionInfoIndex *Index = nullptr,
- DenseSet<const GlobalValue *> *FunctionsToImport = nullptr,
- DenseMap<unsigned, MDNode *> *ValIDToTempMDMap = nullptr);
-
- /// This exists to implement the deprecated LLVMLinkModules C api. Don't use
- /// for anything else.
- bool linkInModuleForCAPI(Module &Src);
+ DenseSet<const GlobalValue *> *GlobalsToImport = nullptr);
static bool linkModules(Module &Dest, std::unique_ptr<Module> Src,
unsigned Flags = Flags::None);
-
- /// \brief Link metadata from \p Src into the composite. The source is
- /// destroyed.
- ///
- /// The \p ValIDToTempMDMap sound have been populated earlier during function
- /// importing from \p Src.
- bool linkInMetadata(Module &Src,
- DenseMap<unsigned, MDNode *> *ValIDToTempMDMap);
};
-/// Perform in-place global value handling on the given Module for
-/// exported local functions renamed and promoted for ThinLTO.
-bool renameModuleForThinLTO(Module &M, const FunctionInfoIndex *Index);
-
} // End llvm namespace
#endif
diff --git a/include/llvm/MC/MCAsmBackend.h b/include/llvm/MC/MCAsmBackend.h
index 51312ff80447..ce17a2a06758 100644
--- a/include/llvm/MC/MCAsmBackend.h
+++ b/include/llvm/MC/MCAsmBackend.h
@@ -11,6 +11,7 @@
#define LLVM_MC_MCASMBACKEND_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/MC/MCDirectives.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCFixup.h"
@@ -28,7 +29,7 @@ class MCRelaxableFragment;
class MCObjectWriter;
class MCSection;
class MCValue;
-class raw_ostream;
+class raw_pwrite_stream;
/// Generic interface to target specific assembler backends.
class MCAsmBackend {
@@ -38,8 +39,6 @@ class MCAsmBackend {
protected: // Can only create subclasses.
MCAsmBackend();
- unsigned HasDataInCodeSupport : 1;
-
public:
virtual ~MCAsmBackend();
@@ -50,17 +49,6 @@ public:
/// emit the final object file.
virtual MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const = 0;
- /// Create a new ELFObjectTargetWriter to enable non-standard
- /// ELFObjectWriters.
- virtual MCELFObjectTargetWriter *createELFObjectTargetWriter() const {
- llvm_unreachable("createELFObjectTargetWriter is not supported by asm "
- "backend");
- }
-
- /// Check whether this target implements data-in-code markers. If not, data
- /// region directives will be ignored.
- bool hasDataInCodeSupport() const { return HasDataInCodeSupport; }
-
/// \name Target Fixup Interfaces
/// @{
@@ -68,9 +56,7 @@ public:
virtual unsigned getNumFixupKinds() const = 0;
/// Map a relocation name used in .reloc to a fixup kind.
- /// Returns true and sets MappedKind if Name is successfully mapped.
- /// Otherwise returns false and leaves MappedKind unchanged.
- virtual bool getFixupKind(StringRef Name, MCFixupKind &MappedKind) const;
+ virtual Optional<MCFixupKind> getFixupKind(StringRef Name) const;
/// Get information on a fixup kind.
virtual const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const;
@@ -116,8 +102,10 @@ public:
///
/// \param Inst The instruction to relax, which may be the same as the
/// output.
+ /// \param STI the subtarget information for the associated instruction.
/// \param [out] Res On return, the relaxed instruction.
- virtual void relaxInstruction(const MCInst &Inst, MCInst &Res) const = 0;
+ virtual void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
+ MCInst &Res) const = 0;
/// @}
@@ -133,6 +121,10 @@ public:
/// \return - True on success.
virtual bool writeNopData(uint64_t Count, MCObjectWriter *OW) const = 0;
+ /// Give backend an opportunity to finish layout after relaxation
+ virtual void finishLayout(MCAssembler const &Asm,
+ MCAsmLayout &Layout) const {}
+
/// Handle any target-specific assembler flags. By default, do nothing.
virtual void handleAssemblerFlag(MCAssemblerFlag Flag) {}
diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h
index 384584ef4ef0..e6ed5688d18d 100644
--- a/include/llvm/MC/MCAsmInfo.h
+++ b/include/llvm/MC/MCAsmInfo.h
@@ -53,6 +53,12 @@ namespace LCOMM {
enum LCOMMType { NoAlignment, ByteAlignment, Log2Alignment };
}
+enum class DebugCompressionType {
+ DCT_None, // no compression
+ DCT_Zlib, // zlib style complession
+ DCT_ZlibGnu // zlib-gnu style compression
+};
+
/// This class is intended to be used as a base class for asm
/// properties and features specific to the target.
class MCAsmInfo {
@@ -280,6 +286,10 @@ protected:
/// to false.
bool HasNoDeadStrip;
+ /// True if this target supports the MachO .alt_entry directive. Defaults to
+ /// false.
+ bool HasAltEntry;
+
/// Used to declare a global as being a weak symbol. Defaults to ".weak".
const char *WeakDirective;
@@ -352,13 +362,20 @@ protected:
/// construction (see LLVMTargetMachine::initAsmInfo()).
bool UseIntegratedAssembler;
- /// Compress DWARF debug sections. Defaults to false.
- bool CompressDebugSections;
+ /// Preserve Comments in assembly
+ bool PreserveAsmComments;
+
+ /// Compress DWARF debug sections. Defaults to no compression.
+ DebugCompressionType CompressDebugSections;
/// True if the integrated assembler should interpret 'a >> b' constant
/// expressions as logical rather than arithmetic.
bool UseLogicalShr;
+ // If true, emit GOTPCRELX/REX_GOTPCRELX instead of GOTPCREL, on
+ // X86_64 ELF.
+ bool RelaxELFRelocations = true;
+
public:
explicit MCAsmInfo();
virtual ~MCAsmInfo();
@@ -483,7 +500,7 @@ public:
bool getAlignmentIsInBytes() const { return AlignmentIsInBytes; }
unsigned getTextAlignFillValue() const { return TextAlignFillValue; }
const char *getGlobalDirective() const { return GlobalDirective; }
- bool doesSetDirectiveSuppressesReloc() const {
+ bool doesSetDirectiveSuppressReloc() const {
return SetDirectiveSuppressesReloc;
}
bool hasAggressiveSymbolFolding() const { return HasAggressiveSymbolFolding; }
@@ -498,6 +515,7 @@ public:
bool hasSingleParameterDotFile() const { return HasSingleParameterDotFile; }
bool hasIdentDirective() const { return HasIdentDirective; }
bool hasNoDeadStrip() const { return HasNoDeadStrip; }
+ bool hasAltEntry() const { return HasAltEntry; }
const char *getWeakDirective() const { return WeakDirective; }
const char *getWeakRefDirective() const { return WeakRefDirective; }
bool hasWeakDefDirective() const { return HasWeakDefDirective; }
@@ -520,6 +538,10 @@ public:
ExceptionHandling getExceptionHandlingType() const { return ExceptionsType; }
WinEH::EncodingType getWinEHEncodingType() const { return WinEHEncodingType; }
+ void setExceptionsType(ExceptionHandling EH) {
+ ExceptionsType = EH;
+ }
+
/// Returns true if the exception handling method for the platform uses call
/// frame information to unwind.
bool usesCFIForEH() const {
@@ -556,13 +578,26 @@ public:
UseIntegratedAssembler = Value;
}
- bool compressDebugSections() const { return CompressDebugSections; }
+ /// Return true if assembly (inline or otherwise) should be parsed.
+ bool preserveAsmComments() const { return PreserveAsmComments; }
+
+ /// Set whether assembly (inline or otherwise) should be parsed.
+ virtual void setPreserveAsmComments(bool Value) {
+ PreserveAsmComments = Value;
+ }
- void setCompressDebugSections(bool CompressDebugSections) {
+ DebugCompressionType compressDebugSections() const {
+ return CompressDebugSections;
+ }
+
+ void setCompressDebugSections(DebugCompressionType CompressDebugSections) {
this->CompressDebugSections = CompressDebugSections;
}
bool shouldUseLogicalShr() const { return UseLogicalShr; }
+
+ bool canRelaxRelocations() const { return RelaxELFRelocations; }
+ void setRelaxELFRelocations(bool V) { RelaxELFRelocations = V; }
};
}
diff --git a/include/llvm/MC/MCAsmInfoELF.h b/include/llvm/MC/MCAsmInfoELF.h
index 7125f5c7ad7a..f8bb943aac4e 100644
--- a/include/llvm/MC/MCAsmInfoELF.h
+++ b/include/llvm/MC/MCAsmInfoELF.h
@@ -18,6 +18,10 @@ class MCAsmInfoELF : public MCAsmInfo {
MCSection *getNonexecutableStackSection(MCContext &Ctx) const final;
protected:
+ /// Targets which have non-executable stacks by default can set this to false
+ /// to disable the special section which requests a non-executable stack.
+ bool UsesNonexecutableStackSection;
+
MCAsmInfoELF();
};
}
diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h
index c0bd12875839..aa3b451152df 100644
--- a/include/llvm/MC/MCAssembler.h
+++ b/include/llvm/MC/MCAssembler.h
@@ -123,7 +123,7 @@ private:
// here. Maybe when the relocation stuff moves to target specific,
// this can go with it? The streamer would need some target specific
// refactoring too.
- mutable SmallPtrSet<const MCSymbol *, 64> ThumbFuncs;
+ mutable SmallPtrSet<const MCSymbol *, 32> ThumbFuncs;
/// \brief The bundle alignment size currently set in the assembler.
///
@@ -189,6 +189,9 @@ private:
bool relaxDwarfLineAddr(MCAsmLayout &Layout, MCDwarfLineAddrFragment &DF);
bool relaxDwarfCallFrameFragment(MCAsmLayout &Layout,
MCDwarfCallFrameFragment &DF);
+ bool relaxCVInlineLineTable(MCAsmLayout &Layout,
+ MCCVInlineLineTableFragment &DF);
+ bool relaxCVDefRange(MCAsmLayout &Layout, MCCVDefRangeFragment &DF);
/// finishLayout - Finalize a layout, including fragment lowering.
void finishLayout(MCAsmLayout &Layout);
@@ -243,8 +246,8 @@ public:
// concrete and require clients to pass in a target like object. The other
// option is to make this abstract, and have targets provide concrete
// implementations as we do with AsmParser.
- MCAssembler(MCContext &Context_, MCAsmBackend &Backend_,
- MCCodeEmitter &Emitter_, MCObjectWriter &Writer_);
+ MCAssembler(MCContext &Context, MCAsmBackend &Backend,
+ MCCodeEmitter &Emitter, MCObjectWriter &Writer);
~MCAssembler();
/// Reuse an assembler instance
diff --git a/include/llvm/MC/MCCodeGenInfo.h b/include/llvm/MC/MCCodeGenInfo.h
deleted file mode 100644
index 0a4744f1d0f7..000000000000
--- a/include/llvm/MC/MCCodeGenInfo.h
+++ /dev/null
@@ -1,51 +0,0 @@
-//===-- llvm/MC/MCCodeGenInfo.h - Target CodeGen Info -----------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file tracks information about the target which can affect codegen,
-// asm parsing, and asm printing. For example, relocation model.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_MC_MCCODEGENINFO_H
-#define LLVM_MC_MCCODEGENINFO_H
-
-#include "llvm/Support/CodeGen.h"
-
-namespace llvm {
-
-class MCCodeGenInfo {
- /// RelocationModel - Relocation model: static, pic, etc.
- ///
- Reloc::Model RelocationModel;
-
- /// CMModel - Code model.
- ///
- CodeModel::Model CMModel;
-
- /// OptLevel - Optimization level.
- ///
- CodeGenOpt::Level OptLevel;
-
-public:
- void initMCCodeGenInfo(Reloc::Model RM = Reloc::Default,
- CodeModel::Model CM = CodeModel::Default,
- CodeGenOpt::Level OL = CodeGenOpt::Default);
-
- Reloc::Model getRelocationModel() const { return RelocationModel; }
-
- CodeModel::Model getCodeModel() const { return CMModel; }
-
- CodeGenOpt::Level getOptLevel() const { return OptLevel; }
-
- // Allow overriding OptLevel on a per-function basis.
- void setOptLevel(CodeGenOpt::Level Level) { OptLevel = Level; }
-};
-} // namespace llvm
-
-#endif
diff --git a/include/llvm/MC/MCCodeView.h b/include/llvm/MC/MCCodeView.h
new file mode 100644
index 000000000000..d999ff555997
--- /dev/null
+++ b/include/llvm/MC/MCCodeView.h
@@ -0,0 +1,210 @@
+//===- MCCodeView.h - Machine Code CodeView support -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Holds state from .cv_file and .cv_loc directives for later emission.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_MC_MCCODEVIEW_H
+#define LLVM_MC_MCCODEVIEW_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/MC/MCObjectStreamer.h"
+#include "llvm/MC/MCFragment.h"
+#include <map>
+#include <vector>
+
+namespace llvm {
+class MCContext;
+class MCObjectStreamer;
+class MCStreamer;
+
+/// \brief Instances of this class represent the information from a
+/// .cv_loc directive.
+class MCCVLoc {
+ uint32_t FunctionId;
+ uint32_t FileNum;
+ uint32_t Line;
+ uint16_t Column;
+ uint16_t PrologueEnd : 1;
+ uint16_t IsStmt : 1;
+
+private: // MCContext manages these
+ friend class MCContext;
+ MCCVLoc(unsigned functionid, unsigned fileNum, unsigned line, unsigned column,
+ bool prologueend, bool isstmt)
+ : FunctionId(functionid), FileNum(fileNum), Line(line), Column(column),
+ PrologueEnd(prologueend), IsStmt(isstmt) {}
+
+ // Allow the default copy constructor and assignment operator to be used
+ // for an MCCVLoc object.
+
+public:
+ unsigned getFunctionId() const { return FunctionId; }
+
+ /// \brief Get the FileNum of this MCCVLoc.
+ unsigned getFileNum() const { return FileNum; }
+
+ /// \brief Get the Line of this MCCVLoc.
+ unsigned getLine() const { return Line; }
+
+ /// \brief Get the Column of this MCCVLoc.
+ unsigned getColumn() const { return Column; }
+
+ bool isPrologueEnd() const { return PrologueEnd; }
+ bool isStmt() const { return IsStmt; }
+
+ void setFunctionId(unsigned FID) { FunctionId = FID; }
+
+ /// \brief Set the FileNum of this MCCVLoc.
+ void setFileNum(unsigned fileNum) { FileNum = fileNum; }
+
+ /// \brief Set the Line of this MCCVLoc.
+ void setLine(unsigned line) { Line = line; }
+
+ /// \brief Set the Column of this MCCVLoc.
+ void setColumn(unsigned column) {
+ assert(column <= UINT16_MAX);
+ Column = column;
+ }
+
+ void setPrologueEnd(bool PE) { PrologueEnd = PE; }
+ void setIsStmt(bool IS) { IsStmt = IS; }
+};
+
+/// \brief Instances of this class represent the line information for
+/// the CodeView line table entries. Which is created after a machine
+/// instruction is assembled and uses an address from a temporary label
+/// created at the current address in the current section and the info from
+/// the last .cv_loc directive seen as stored in the context.
+class MCCVLineEntry : public MCCVLoc {
+ const MCSymbol *Label;
+
+private:
+ // Allow the default copy constructor and assignment operator to be used
+ // for an MCCVLineEntry object.
+
+public:
+ // Constructor to create an MCCVLineEntry given a symbol and the dwarf loc.
+ MCCVLineEntry(const MCSymbol *Label, const MCCVLoc loc)
+ : MCCVLoc(loc), Label(Label) {}
+
+ const MCSymbol *getLabel() const { return Label; }
+
+ // This is called when an instruction is assembled into the specified
+ // section and if there is information from the last .cv_loc directive that
+ // has yet to have a line entry made for it is made.
+ static void Make(MCObjectStreamer *MCOS);
+};
+
+/// Holds state from .cv_file and .cv_loc directives for later emission.
+class CodeViewContext {
+public:
+ CodeViewContext();
+ ~CodeViewContext();
+
+ bool isValidFileNumber(unsigned FileNumber) const;
+ bool addFile(unsigned FileNumber, StringRef Filename);
+ ArrayRef<StringRef> getFilenames() { return Filenames; }
+
+ /// \brief Add a line entry.
+ void addLineEntry(const MCCVLineEntry &LineEntry) {
+ size_t Offset = MCCVLines.size();
+ auto I = MCCVLineStartStop.insert(
+ {LineEntry.getFunctionId(), {Offset, Offset + 1}});
+ if (!I.second)
+ I.first->second.second = Offset + 1;
+ MCCVLines.push_back(LineEntry);
+ }
+
+ std::vector<MCCVLineEntry> getFunctionLineEntries(unsigned FuncId) {
+ std::vector<MCCVLineEntry> FilteredLines;
+
+ auto I = MCCVLineStartStop.find(FuncId);
+ if (I != MCCVLineStartStop.end())
+ for (size_t Idx = I->second.first, End = I->second.second; Idx != End;
+ ++Idx)
+ if (MCCVLines[Idx].getFunctionId() == FuncId)
+ FilteredLines.push_back(MCCVLines[Idx]);
+ return FilteredLines;
+ }
+
+ std::pair<size_t, size_t> getLineExtent(unsigned FuncId) {
+ auto I = MCCVLineStartStop.find(FuncId);
+ // Return an empty extent if there are no cv_locs for this function id.
+ if (I == MCCVLineStartStop.end())
+ return {~0ULL, 0};
+ return I->second;
+ }
+
+ ArrayRef<MCCVLineEntry> getLinesForExtent(size_t L, size_t R) {
+ if (R <= L)
+ return None;
+ if (L >= MCCVLines.size())
+ return None;
+ return makeArrayRef(&MCCVLines[L], R - L);
+ }
+
+ /// Emits a line table substream.
+ void emitLineTableForFunction(MCObjectStreamer &OS, unsigned FuncId,
+ const MCSymbol *FuncBegin,
+ const MCSymbol *FuncEnd);
+
+ void emitInlineLineTableForFunction(
+ MCObjectStreamer &OS, unsigned PrimaryFunctionId, unsigned SourceFileId,
+ unsigned SourceLineNum, const MCSymbol *FnStartSym,
+ const MCSymbol *FnEndSym, ArrayRef<unsigned> SecondaryFunctionIds);
+
+ /// Encodes the binary annotations once we have a layout.
+ void encodeInlineLineTable(MCAsmLayout &Layout,
+ MCCVInlineLineTableFragment &F);
+
+ void
+ emitDefRange(MCObjectStreamer &OS,
+ ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
+ StringRef FixedSizePortion);
+
+ void encodeDefRange(MCAsmLayout &Layout, MCCVDefRangeFragment &F);
+
+ /// Emits the string table substream.
+ void emitStringTable(MCObjectStreamer &OS);
+
+ /// Emits the file checksum substream.
+ void emitFileChecksums(MCObjectStreamer &OS);
+
+private:
+ /// Map from string to string table offset.
+ StringMap<unsigned> StringTable;
+
+ /// The fragment that ultimately holds our strings.
+ MCDataFragment *StrTabFragment = nullptr;
+ bool InsertedStrTabFragment = false;
+
+ MCDataFragment *getStringTableFragment();
+
+ /// Add something to the string table.
+ StringRef addToStringTable(StringRef S);
+
+ /// Get a string table offset.
+ unsigned getStringTableOffset(StringRef S);
+
+ /// An array of absolute paths. Eventually this may include the file checksum.
+ SmallVector<StringRef, 4> Filenames;
+
+ /// The offset of the first and last .cv_loc directive for a given function
+ /// id.
+ std::map<unsigned, std::pair<size_t, size_t>> MCCVLineStartStop;
+
+ /// A collection of MCCVLineEntry for each section.
+ std::vector<MCCVLineEntry> MCCVLines;
+};
+
+} // end namespace llvm
+#endif
diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h
index e5a9afd9968c..fe1377e054e8 100644
--- a/include/llvm/MC/MCContext.h
+++ b/include/llvm/MC/MCContext.h
@@ -16,6 +16,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/MC/MCCodeView.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/SectionKind.h"
@@ -42,6 +43,7 @@ namespace llvm {
class MCSectionMachO;
class MCSectionELF;
class MCSectionCOFF;
+ class CodeViewContext;
/// Context object for machine code objects. This class owns all of the
/// sections that it creates.
@@ -66,6 +68,8 @@ namespace llvm {
/// The MCObjectFileInfo for this target.
const MCObjectFileInfo *MOFI;
+ std::unique_ptr<CodeViewContext> CVContext;
+
/// Allocator object used for creating machine code objects.
///
/// We use a bump pointer allocator to avoid the need to track all allocated
@@ -92,7 +96,9 @@ namespace llvm {
DenseMap<std::pair<unsigned, unsigned>, MCSymbol *> LocalSymbols;
/// Keeps tracks of names that were used both for used declared and
- /// artificial symbols.
+ /// artificial symbols. The value is "true" if the name has been used for a
+ /// non-section symbol (there can be at most one of those, plus an unlimited
+ /// number of section symbols with the same name).
StringMap<bool, BumpPtrAllocator &> UsedNames;
/// The next ID to dole out to an unnamed assembler temporary symbol with
@@ -135,6 +141,10 @@ namespace llvm {
MCDwarfLoc CurrentDwarfLoc;
bool DwarfLocSeen;
+ /// The current CodeView line information from the last .cv_loc directive.
+ MCCVLoc CurrentCVLoc = MCCVLoc(0, 0, 0, 0, false, true);
+ bool CVLocSeen = false;
+
/// Generate dwarf debugging info for assembly source files.
bool GenDwarfForAssembly;
@@ -190,16 +200,19 @@ namespace llvm {
std::string SectionName;
StringRef GroupName;
int SelectionKey;
+ unsigned UniqueID;
COFFSectionKey(StringRef SectionName, StringRef GroupName,
- int SelectionKey)
+ int SelectionKey, unsigned UniqueID)
: SectionName(SectionName), GroupName(GroupName),
- SelectionKey(SelectionKey) {}
+ SelectionKey(SelectionKey), UniqueID(UniqueID) {}
bool operator<(const COFFSectionKey &Other) const {
if (SectionName != Other.SectionName)
return SectionName < Other.SectionName;
if (GroupName != Other.GroupName)
return GroupName < Other.GroupName;
- return SelectionKey < Other.SelectionKey;
+ if (SelectionKey != Other.SelectionKey)
+ return SelectionKey < Other.SelectionKey;
+ return UniqueID < Other.UniqueID;
}
};
@@ -237,6 +250,8 @@ namespace llvm {
const MCObjectFileInfo *getObjectFileInfo() const { return MOFI; }
+ CodeViewContext &getCVContext();
+
void setAllowTemporaryLabels(bool Value) { AllowTemporaryLabels = Value; }
void setUseNamesOnTempLabels(bool Value) { UseNamesOnTempLabels = Value; }
@@ -303,6 +318,13 @@ namespace llvm {
/// \name Section Management
/// @{
+ enum : unsigned {
+ /// Pass this value as the UniqueID during section creation to get the
+ /// generic section with the given name and characteristics. The usual
+ /// sections such as .text use this ID.
+ GenericSectionID = ~0U
+ };
+
/// Return the MCSection for the specified mach-o section. This requires
/// the operands to be valid.
MCSectionMachO *getMachOSection(StringRef Segment, StringRef Section,
@@ -317,48 +339,56 @@ namespace llvm {
BeginSymName);
}
- MCSectionELF *getELFSection(StringRef Section, unsigned Type,
+ MCSectionELF *getELFSection(const Twine &Section, unsigned Type,
unsigned Flags) {
return getELFSection(Section, Type, Flags, nullptr);
}
- MCSectionELF *getELFSection(StringRef Section, unsigned Type,
+ MCSectionELF *getELFSection(const Twine &Section, unsigned Type,
unsigned Flags, const char *BeginSymName) {
return getELFSection(Section, Type, Flags, 0, "", BeginSymName);
}
- MCSectionELF *getELFSection(StringRef Section, unsigned Type,
+ MCSectionELF *getELFSection(const Twine &Section, unsigned Type,
unsigned Flags, unsigned EntrySize,
- StringRef Group) {
+ const Twine &Group) {
return getELFSection(Section, Type, Flags, EntrySize, Group, nullptr);
}
- MCSectionELF *getELFSection(StringRef Section, unsigned Type,
+ MCSectionELF *getELFSection(const Twine &Section, unsigned Type,
unsigned Flags, unsigned EntrySize,
- StringRef Group, const char *BeginSymName) {
+ const Twine &Group, const char *BeginSymName) {
return getELFSection(Section, Type, Flags, EntrySize, Group, ~0,
BeginSymName);
}
- MCSectionELF *getELFSection(StringRef Section, unsigned Type,
+ MCSectionELF *getELFSection(const Twine &Section, unsigned Type,
unsigned Flags, unsigned EntrySize,
- StringRef Group, unsigned UniqueID) {
+ const Twine &Group, unsigned UniqueID) {
return getELFSection(Section, Type, Flags, EntrySize, Group, UniqueID,
nullptr);
}
- MCSectionELF *getELFSection(StringRef Section, unsigned Type,
+ MCSectionELF *getELFSection(const Twine &Section, unsigned Type,
unsigned Flags, unsigned EntrySize,
- StringRef Group, unsigned UniqueID,
+ const Twine &Group, unsigned UniqueID,
const char *BeginSymName);
- MCSectionELF *getELFSection(StringRef Section, unsigned Type,
+ MCSectionELF *getELFSection(const Twine &Section, unsigned Type,
unsigned Flags, unsigned EntrySize,
const MCSymbolELF *Group, unsigned UniqueID,
const char *BeginSymName,
const MCSectionELF *Associated);
- MCSectionELF *createELFRelSection(StringRef Name, unsigned Type,
+ /// Get a section with the provided group identifier. This section is
+ /// named by concatenating \p Prefix with '.' then \p Suffix. The \p Type
+ /// describes the type of the section and \p Flags are used to further
+ /// configure this named section.
+ MCSectionELF *getELFNamedSection(const Twine &Prefix, const Twine &Suffix,
+ unsigned Type, unsigned Flags,
+ unsigned EntrySize = 0);
+
+ MCSectionELF *createELFRelSection(const Twine &Name, unsigned Type,
unsigned Flags, unsigned EntrySize,
const MCSymbolELF *Group,
const MCSectionELF *Associated);
@@ -370,6 +400,7 @@ namespace llvm {
MCSectionCOFF *getCOFFSection(StringRef Section, unsigned Characteristics,
SectionKind Kind, StringRef COMDATSymName,
int Selection,
+ unsigned UniqueID = GenericSectionID,
const char *BeginSymName = nullptr);
MCSectionCOFF *getCOFFSection(StringRef Section, unsigned Characteristics,
@@ -382,8 +413,9 @@ namespace llvm {
/// section containing KeySym. For example, to create a debug info section
/// associated with an inline function, pass the normal debug info section
/// as Sec and the function symbol as KeySym.
- MCSectionCOFF *getAssociativeCOFFSection(MCSectionCOFF *Sec,
- const MCSymbol *KeySym);
+ MCSectionCOFF *
+ getAssociativeCOFFSection(MCSectionCOFF *Sec, const MCSymbol *KeySym,
+ unsigned UniqueID = GenericSectionID);
// Create and save a copy of STI and return a reference to the copy.
MCSubtargetInfo &getSubtargetCopy(const MCSubtargetInfo &STI);
@@ -394,14 +426,11 @@ namespace llvm {
/// @{
/// \brief Get the compilation directory for DW_AT_comp_dir
- /// This can be overridden by clients which want to control the reported
- /// compilation directory and have it be something other than the current
- /// working directory.
- /// Returns an empty string if the current directory cannot be determined.
+ /// The compilation directory should be set with \c setCompilationDir before
+ /// calling this function. If it is unset, an empty string will be returned.
StringRef getCompilationDir() const { return CompilationDir; }
/// \brief Set the compilation directory for DW_AT_comp_dir
- /// Override the default (CWD) compilation directory.
void setCompilationDir(StringRef S) { CompilationDir = S.str(); }
/// \brief Get the main file name for use in error messages and debug
@@ -505,6 +534,35 @@ namespace llvm {
/// @}
+
+ /// \name CodeView Management
+ /// @{
+
+ /// Creates an entry in the cv file table.
+ unsigned getCVFile(StringRef FileName, unsigned FileNumber);
+
+ /// Saves the information from the currently parsed .cv_loc directive
+ /// and sets CVLocSeen. When the next instruction is assembled an entry
+ /// in the line number table with this information and the address of the
+ /// instruction will be created.
+ void setCurrentCVLoc(unsigned FunctionId, unsigned FileNo, unsigned Line,
+ unsigned Column, bool PrologueEnd, bool IsStmt) {
+ CurrentCVLoc.setFunctionId(FunctionId);
+ CurrentCVLoc.setFileNum(FileNo);
+ CurrentCVLoc.setLine(Line);
+ CurrentCVLoc.setColumn(Column);
+ CurrentCVLoc.setPrologueEnd(PrologueEnd);
+ CurrentCVLoc.setIsStmt(IsStmt);
+ CVLocSeen = true;
+ }
+ void clearCVLocSeen() { CVLocSeen = false; }
+
+ bool getCVLocSeen() { return CVLocSeen; }
+ const MCCVLoc &getCurrentCVLoc() { return CurrentCVLoc; }
+
+ bool isValidCVFileNumber(unsigned FileNumber);
+ /// @}
+
char *getSecureLogFile() { return SecureLogFile; }
raw_fd_ostream *getSecureLog() { return SecureLog.get(); }
bool getSecureLogUsed() { return SecureLogUsed; }
diff --git a/include/llvm/MC/MCDirectives.h b/include/llvm/MC/MCDirectives.h
index 326b2a1ac061..8c74b169135b 100644
--- a/include/llvm/MC/MCDirectives.h
+++ b/include/llvm/MC/MCDirectives.h
@@ -35,6 +35,7 @@ enum MCSymbolAttr {
MCSA_Local, ///< .local (ELF)
MCSA_NoDeadStrip, ///< .no_dead_strip (MachO)
MCSA_SymbolResolver, ///< .symbol_resolver (MachO)
+ MCSA_AltEntry, ///< .alt_entry (MachO)
MCSA_PrivateExtern, ///< .private_extern (MachO)
MCSA_Protected, ///< .protected (ELF)
MCSA_Reference, ///< .reference (MachO)
diff --git a/include/llvm/MC/MCDisassembler.h b/include/llvm/MC/MCDisassembler/MCDisassembler.h
index 57c40d660f64..9006d87abb43 100644
--- a/include/llvm/MC/MCDisassembler.h
+++ b/include/llvm/MC/MCDisassembler/MCDisassembler.h
@@ -6,16 +6,16 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_MC_MCDISASSEMBLER_H
-#define LLVM_MC_MCDISASSEMBLER_H
+#ifndef LLVM_MC_MCDISASSEMBLER_MCDISASSEMBLER_H
+#define LLVM_MC_MCDISASSEMBLER_MCDISASSEMBLER_H
#include "llvm-c/Disassembler.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/MC/MCSymbolizer.h"
+#include "llvm/MC/MCDisassembler/MCSymbolizer.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
+template <typename T> class ArrayRef;
class MCInst;
class MCSubtargetInfo;
class raw_ostream;
diff --git a/include/llvm/MC/MCExternalSymbolizer.h b/include/llvm/MC/MCDisassembler/MCExternalSymbolizer.h
index 2c7d23707c95..bd3e5d4638e5 100644
--- a/include/llvm/MC/MCExternalSymbolizer.h
+++ b/include/llvm/MC/MCDisassembler/MCExternalSymbolizer.h
@@ -13,11 +13,11 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_MC_MCEXTERNALSYMBOLIZER_H
-#define LLVM_MC_MCEXTERNALSYMBOLIZER_H
+#ifndef LLVM_MC_MCDISASSEMBLER_MCEXTERNALSYMBOLIZER_H
+#define LLVM_MC_MCDISASSEMBLER_MCEXTERNALSYMBOLIZER_H
#include "llvm-c/Disassembler.h"
-#include "llvm/MC/MCSymbolizer.h"
+#include "llvm/MC/MCDisassembler/MCSymbolizer.h"
#include <memory>
namespace llvm {
diff --git a/include/llvm/MC/MCRelocationInfo.h b/include/llvm/MC/MCDisassembler/MCRelocationInfo.h
index 40e0217b8d83..25334f755ee6 100644
--- a/include/llvm/MC/MCRelocationInfo.h
+++ b/include/llvm/MC/MCDisassembler/MCRelocationInfo.h
@@ -13,8 +13,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_MC_MCRELOCATIONINFO_H
-#define LLVM_MC_MCRELOCATIONINFO_H
+#ifndef LLVM_MC_MCDISASSEMBLER_MCRELOCATIONINFO_H
+#define LLVM_MC_MCDISASSEMBLER_MCRELOCATIONINFO_H
#include "llvm/Support/Compiler.h"
@@ -38,10 +38,6 @@ public:
MCRelocationInfo(MCContext &Ctx);
virtual ~MCRelocationInfo();
- /// \brief Create an MCExpr for the relocation \p Rel.
- /// \returns If possible, an MCExpr corresponding to Rel, else 0.
- virtual const MCExpr *createExprForRelocation(object::RelocationRef Rel);
-
/// \brief Create an MCExpr for the target-specific \p VariantKind.
/// The VariantKinds are defined in llvm-c/Disassembler.h.
/// Used by MCExternalSymbolizer.
diff --git a/include/llvm/MC/MCSymbolizer.h b/include/llvm/MC/MCDisassembler/MCSymbolizer.h
index 2ef17673f091..713467c0a3e7 100644
--- a/include/llvm/MC/MCSymbolizer.h
+++ b/include/llvm/MC/MCDisassembler/MCSymbolizer.h
@@ -13,10 +13,10 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_MC_MCSYMBOLIZER_H
-#define LLVM_MC_MCSYMBOLIZER_H
+#ifndef LLVM_MC_MCDISASSEMBLER_MCSYMBOLIZER_H
+#define LLVM_MC_MCDISASSEMBLER_MCSYMBOLIZER_H
-#include "llvm/MC/MCRelocationInfo.h"
+#include "llvm/MC/MCDisassembler/MCRelocationInfo.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/DataTypes.h"
#include <cassert>
diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h
index 8a50863a0c39..0c555d377d8b 100644
--- a/include/llvm/MC/MCDwarf.h
+++ b/include/llvm/MC/MCDwarf.h
@@ -15,20 +15,18 @@
#ifndef LLVM_MC_MCDWARF_H
#define LLVM_MC_MCDWARF_H
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCSection.h"
-#include "llvm/Support/Compiler.h"
#include "llvm/Support/Dwarf.h"
-#include "llvm/Support/raw_ostream.h"
-#include <map>
#include <string>
#include <utility>
#include <vector>
namespace llvm {
+template <typename T> class ArrayRef;
+class raw_ostream;
class MCAsmBackend;
class MCContext;
class MCObjectStreamer;
@@ -72,7 +70,7 @@ class MCDwarfLoc {
private: // MCContext manages these
friend class MCContext;
- friend class MCLineEntry;
+ friend class MCDwarfLineEntry;
MCDwarfLoc(unsigned fileNum, unsigned line, unsigned column, unsigned flags,
unsigned isa, unsigned discriminator)
: FileNum(fileNum), Line(line), Column(column), Flags(flags), Isa(isa),
@@ -135,16 +133,16 @@ public:
/// instruction is assembled and uses an address from a temporary label
/// created at the current address in the current section and the info from
/// the last .loc directive seen as stored in the context.
-class MCLineEntry : public MCDwarfLoc {
+class MCDwarfLineEntry : public MCDwarfLoc {
MCSymbol *Label;
private:
// Allow the default copy constructor and assignment operator to be used
- // for an MCLineEntry object.
+ // for an MCDwarfLineEntry object.
public:
- // Constructor to create an MCLineEntry given a symbol and the dwarf loc.
- MCLineEntry(MCSymbol *label, const MCDwarfLoc loc)
+ // Constructor to create an MCDwarfLineEntry given a symbol and the dwarf loc.
+ MCDwarfLineEntry(MCSymbol *label, const MCDwarfLoc loc)
: MCDwarfLoc(loc), Label(label) {}
MCSymbol *getLabel() const { return Label; }
@@ -162,21 +160,21 @@ public:
class MCLineSection {
public:
// \brief Add an entry to this MCLineSection's line entries.
- void addLineEntry(const MCLineEntry &LineEntry, MCSection *Sec) {
+ void addLineEntry(const MCDwarfLineEntry &LineEntry, MCSection *Sec) {
MCLineDivisions[Sec].push_back(LineEntry);
}
- typedef std::vector<MCLineEntry> MCLineEntryCollection;
- typedef MCLineEntryCollection::iterator iterator;
- typedef MCLineEntryCollection::const_iterator const_iterator;
- typedef MapVector<MCSection *, MCLineEntryCollection> MCLineDivisionMap;
+ typedef std::vector<MCDwarfLineEntry> MCDwarfLineEntryCollection;
+ typedef MCDwarfLineEntryCollection::iterator iterator;
+ typedef MCDwarfLineEntryCollection::const_iterator const_iterator;
+ typedef MapVector<MCSection *, MCDwarfLineEntryCollection> MCLineDivisionMap;
private:
- // A collection of MCLineEntry for each section.
+ // A collection of MCDwarfLineEntry for each section.
MCLineDivisionMap MCLineDivisions;
public:
- // Returns the collection of MCLineEntry for a given Compile Unit ID.
+ // Returns the collection of MCDwarfLineEntry for a given Compile Unit ID.
const MCLineDivisionMap &getMCLineEntries() const {
return MCLineDivisions;
}
diff --git a/include/llvm/MC/MCELFObjectWriter.h b/include/llvm/MC/MCELFObjectWriter.h
index 193dac018b2b..376e21821316 100644
--- a/include/llvm/MC/MCELFObjectWriter.h
+++ b/include/llvm/MC/MCELFObjectWriter.h
@@ -11,12 +11,15 @@
#define LLVM_MC_MCELFOBJECTWRITER_H
#include "llvm/ADT/Triple.h"
+#include "llvm/MC/MCValue.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/ELF.h"
+#include "llvm/Support/raw_ostream.h"
#include <vector>
namespace llvm {
class MCAssembler;
+class MCContext;
class MCFixup;
class MCFragment;
class MCObjectWriter;
@@ -30,10 +33,21 @@ struct ELFRelocationEntry {
const MCSymbolELF *Symbol; // The symbol to relocate with.
unsigned Type; // The type of the relocation.
uint64_t Addend; // The addend to use.
+ const MCSymbolELF *OriginalSymbol; // The original value of Symbol if we changed it.
+ uint64_t OriginalAddend; // The original value of addend.
ELFRelocationEntry(uint64_t Offset, const MCSymbolELF *Symbol, unsigned Type,
- uint64_t Addend)
- : Offset(Offset), Symbol(Symbol), Type(Type), Addend(Addend) {}
+ uint64_t Addend, const MCSymbolELF *OriginalSymbol,
+ uint64_t OriginalAddend)
+ : Offset(Offset), Symbol(Symbol), Type(Type), Addend(Addend),
+ OriginalSymbol(OriginalSymbol), OriginalAddend(OriginalAddend) {}
+
+ void print(raw_ostream &Out) const {
+ Out << "Off=" << Offset << ", Sym=" << Symbol << ", Type=" << Type
+ << ", Addend=" << Addend << ", OriginalSymbol=" << OriginalSymbol
+ << ", OriginalAddend=" << OriginalAddend;
+ }
+ void dump() const { print(errs()); }
};
class MCELFObjectTargetWriter {
@@ -64,8 +78,8 @@ public:
virtual ~MCELFObjectTargetWriter() {}
- virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
- bool IsPCRel) const = 0;
+ virtual unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
+ const MCFixup &Fixup, bool IsPCRel) const = 0;
virtual bool needsRelocateWithSymbol(const MCSymbol &Sym,
unsigned Type) const;
diff --git a/include/llvm/MC/MCELFStreamer.h b/include/llvm/MC/MCELFStreamer.h
index 6eb2c2c343ff..b108f0df52b6 100644
--- a/include/llvm/MC/MCELFStreamer.h
+++ b/include/llvm/MC/MCELFStreamer.h
@@ -15,7 +15,6 @@
#include "llvm/MC/MCObjectStreamer.h"
#include "llvm/MC/SectionKind.h"
#include "llvm/Support/DataTypes.h"
-#include <vector>
namespace llvm {
class MCAsmBackend;
diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h
index f6ccdc095551..b0e4736565b0 100644
--- a/include/llvm/MC/MCExpr.h
+++ b/include/llvm/MC/MCExpr.h
@@ -73,7 +73,8 @@ public:
/// \name Utility Methods
/// @{
- void print(raw_ostream &OS, const MCAsmInfo *MAI) const;
+ void print(raw_ostream &OS, const MCAsmInfo *MAI,
+ bool InParens = false) const;
void dump() const;
/// @}
@@ -165,6 +166,7 @@ public:
VK_GOT,
VK_GOTOFF,
+ VK_GOTREL,
VK_GOTPCREL,
VK_GOTTPOFF,
VK_INDNTPOFF,
@@ -176,6 +178,8 @@ public:
VK_TLSLDM,
VK_TPOFF,
VK_DTPOFF,
+ VK_TLSCALL, // symbol(tlscall)
+ VK_TLSDESC, // symbol(tlsdesc)
VK_TLVP, // Mach-O thread local variable relocations
VK_TLVPPAGE,
VK_TLVPPAGEOFF,
@@ -194,8 +198,6 @@ public:
VK_ARM_PREL31,
VK_ARM_SBREL, // symbol(sbrel)
VK_ARM_TLSLDO, // symbol(tlsldo)
- VK_ARM_TLSCALL, // symbol(tlscall)
- VK_ARM_TLSDESC, // symbol(tlsdesc)
VK_ARM_TLSDESCSEQ,
VK_PPC_LO, // symbol@l
@@ -214,7 +216,6 @@ public:
VK_PPC_TOC_HI, // symbol@toc@h
VK_PPC_TOC_HA, // symbol@toc@ha
VK_PPC_DTPMOD, // symbol@dtpmod
- VK_PPC_TPREL, // symbol@tprel
VK_PPC_TPREL_LO, // symbol@tprel@l
VK_PPC_TPREL_HI, // symbol@tprel@h
VK_PPC_TPREL_HA, // symbol@tprel@ha
@@ -222,7 +223,6 @@ public:
VK_PPC_TPREL_HIGHERA, // symbol@tprel@highera
VK_PPC_TPREL_HIGHEST, // symbol@tprel@highest
VK_PPC_TPREL_HIGHESTA, // symbol@tprel@highesta
- VK_PPC_DTPREL, // symbol@dtprel
VK_PPC_DTPREL_LO, // symbol@dtprel@l
VK_PPC_DTPREL_HI, // symbol@dtprel@h
VK_PPC_DTPREL_HA, // symbol@dtprel@ha
@@ -251,33 +251,6 @@ public:
VK_PPC_TLSLD, // symbol@tlsld
VK_PPC_LOCAL, // symbol@local
- VK_Mips_GPREL,
- VK_Mips_GOT_CALL,
- VK_Mips_GOT16,
- VK_Mips_GOT,
- VK_Mips_ABS_HI,
- VK_Mips_ABS_LO,
- VK_Mips_TLSGD,
- VK_Mips_TLSLDM,
- VK_Mips_DTPREL_HI,
- VK_Mips_DTPREL_LO,
- VK_Mips_GOTTPREL,
- VK_Mips_TPREL_HI,
- VK_Mips_TPREL_LO,
- VK_Mips_GPOFF_HI,
- VK_Mips_GPOFF_LO,
- VK_Mips_GOT_DISP,
- VK_Mips_GOT_PAGE,
- VK_Mips_GOT_OFST,
- VK_Mips_HIGHER,
- VK_Mips_HIGHEST,
- VK_Mips_GOT_HI16,
- VK_Mips_GOT_LO16,
- VK_Mips_CALL_HI16,
- VK_Mips_CALL_LO16,
- VK_Mips_PCREL_HI16,
- VK_Mips_PCREL_LO16,
-
VK_COFF_IMGREL32, // symbol@imgrel (image-relative)
VK_Hexagon_PCREL,
diff --git a/include/llvm/MC/MCFragment.h b/include/llvm/MC/MCFragment.h
index 7d6db525ce61..e0a2bfc23747 100644
--- a/include/llvm/MC/MCFragment.h
+++ b/include/llvm/MC/MCFragment.h
@@ -40,6 +40,8 @@ public:
FT_DwarfFrame,
FT_LEB,
FT_SafeSEH,
+ FT_CVInlineLines,
+ FT_CVDefRange,
FT_Dummy
};
@@ -210,7 +212,8 @@ public:
static bool classof(const MCFragment *F) {
MCFragment::FragmentType Kind = F->getKind();
- return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data;
+ return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data ||
+ Kind == MCFragment::FT_CVDefRange;
}
};
@@ -321,36 +324,19 @@ public:
class MCFillFragment : public MCFragment {
- /// Value - Value to use for filling bytes.
- int64_t Value;
-
- /// ValueSize - The size (in bytes) of \p Value to use when filling, or 0 if
- /// this is a virtual fill fragment.
- unsigned ValueSize;
+ /// Value to use for filling bytes.
+ uint8_t Value;
- /// Size - The number of bytes to insert.
+ /// The number of bytes to insert.
uint64_t Size;
public:
- MCFillFragment(int64_t Value, unsigned ValueSize, uint64_t Size,
- MCSection *Sec = nullptr)
- : MCFragment(FT_Fill, false, 0, Sec), Value(Value), ValueSize(ValueSize),
- Size(Size) {
- assert((!ValueSize || (Size % ValueSize) == 0) &&
- "Fill size must be a multiple of the value size!");
- }
-
- /// \name Accessors
- /// @{
-
- int64_t getValue() const { return Value; }
-
- unsigned getValueSize() const { return ValueSize; }
+ MCFillFragment(uint8_t Value, uint64_t Size, MCSection *Sec = nullptr)
+ : MCFragment(FT_Fill, false, 0, Sec), Value(Value), Size(Size) {}
+ uint8_t getValue() const { return Value; }
uint64_t getSize() const { return Size; }
- /// @}
-
static bool classof(const MCFragment *F) {
return F->getKind() == MCFragment::FT_Fill;
}
@@ -501,6 +487,79 @@ public:
}
};
+/// Fragment representing the binary annotations produced by the
+/// .cv_inline_linetable directive.
+class MCCVInlineLineTableFragment : public MCFragment {
+ unsigned SiteFuncId;
+ unsigned StartFileId;
+ unsigned StartLineNum;
+ const MCSymbol *FnStartSym;
+ const MCSymbol *FnEndSym;
+ SmallVector<unsigned, 3> SecondaryFuncs;
+ SmallString<8> Contents;
+
+ /// CodeViewContext has the real knowledge about this format, so let it access
+ /// our members.
+ friend class CodeViewContext;
+
+public:
+ MCCVInlineLineTableFragment(unsigned SiteFuncId, unsigned StartFileId,
+ unsigned StartLineNum, const MCSymbol *FnStartSym,
+ const MCSymbol *FnEndSym,
+ ArrayRef<unsigned> SecondaryFuncs,
+ MCSection *Sec = nullptr)
+ : MCFragment(FT_CVInlineLines, false, 0, Sec), SiteFuncId(SiteFuncId),
+ StartFileId(StartFileId), StartLineNum(StartLineNum),
+ FnStartSym(FnStartSym), FnEndSym(FnEndSym),
+ SecondaryFuncs(SecondaryFuncs.begin(), SecondaryFuncs.end()) {}
+
+ /// \name Accessors
+ /// @{
+
+ const MCSymbol *getFnStartSym() const { return FnStartSym; }
+ const MCSymbol *getFnEndSym() const { return FnEndSym; }
+
+ SmallString<8> &getContents() { return Contents; }
+ const SmallString<8> &getContents() const { return Contents; }
+
+ /// @}
+
+ static bool classof(const MCFragment *F) {
+ return F->getKind() == MCFragment::FT_CVInlineLines;
+ }
+};
+
+/// Fragment representing the .cv_def_range directive.
+class MCCVDefRangeFragment : public MCEncodedFragmentWithFixups<32, 4> {
+ SmallVector<std::pair<const MCSymbol *, const MCSymbol *>, 2> Ranges;
+ SmallString<32> FixedSizePortion;
+
+ /// CodeViewContext has the real knowledge about this format, so let it access
+ /// our members.
+ friend class CodeViewContext;
+
+public:
+ MCCVDefRangeFragment(
+ ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
+ StringRef FixedSizePortion, MCSection *Sec = nullptr)
+ : MCEncodedFragmentWithFixups<32, 4>(FT_CVDefRange, false, Sec),
+ Ranges(Ranges.begin(), Ranges.end()),
+ FixedSizePortion(FixedSizePortion) {}
+
+ /// \name Accessors
+ /// @{
+ ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> getRanges() const {
+ return Ranges;
+ }
+
+ StringRef getFixedSizePortion() const { return FixedSizePortion; }
+ /// @}
+
+ static bool classof(const MCFragment *F) {
+ return F->getKind() == MCFragment::FT_CVDefRange;
+ }
+};
+
} // end namespace llvm
#endif
diff --git a/include/llvm/MC/MCInstPrinter.h b/include/llvm/MC/MCInstPrinter.h
index 0eafd02c51c6..2119c5a633b4 100644
--- a/include/llvm/MC/MCInstPrinter.h
+++ b/include/llvm/MC/MCInstPrinter.h
@@ -10,11 +10,11 @@
#ifndef LLVM_MC_MCINSTPRINTER_H
#define LLVM_MC_MCINSTPRINTER_H
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Format.h"
namespace llvm {
+template <typename T> class ArrayRef;
class MCInst;
class raw_ostream;
class MCAsmInfo;
diff --git a/include/llvm/MC/MCLinkerOptimizationHint.h b/include/llvm/MC/MCLinkerOptimizationHint.h
index a519c4b71b03..200bb93f64c8 100644
--- a/include/llvm/MC/MCLinkerOptimizationHint.h
+++ b/include/llvm/MC/MCLinkerOptimizationHint.h
@@ -20,7 +20,6 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
-#include "llvm/MC/MCMachObjectWriter.h"
#include "llvm/Support/raw_ostream.h"
namespace llvm {
@@ -28,6 +27,7 @@ namespace llvm {
// Forward declarations.
class MCAsmLayout;
class MCSymbol;
+class MachObjectWriter;
/// Linker Optimization Hint Type.
enum MCLOHType {
@@ -123,31 +123,12 @@ public:
/// Emit this directive as:
/// <kind, numArgs, addr1, ..., addrN>
- void emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const {
- raw_ostream &OutStream = ObjWriter.getStream();
- emit_impl(OutStream, ObjWriter, Layout);
- }
+ void emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const;
/// Get the size in bytes of this directive if emitted in \p ObjWriter with
/// the given \p Layout.
uint64_t getEmitSize(const MachObjectWriter &ObjWriter,
- const MCAsmLayout &Layout) const {
- class raw_counting_ostream : public raw_ostream {
- uint64_t Count;
-
- void write_impl(const char *, size_t size) override { Count += size; }
-
- uint64_t current_pos() const override { return Count; }
-
- public:
- raw_counting_ostream() : Count(0) {}
- ~raw_counting_ostream() override { flush(); }
- };
-
- raw_counting_ostream OutStream;
- emit_impl(OutStream, ObjWriter, Layout);
- return OutStream.tell();
- }
+ const MCAsmLayout &Layout) const;
};
class MCLOHContainer {
diff --git a/include/llvm/MC/MCMachObjectWriter.h b/include/llvm/MC/MCMachObjectWriter.h
index cd3db957afc1..1a685dbd608e 100644
--- a/include/llvm/MC/MCMachObjectWriter.h
+++ b/include/llvm/MC/MCMachObjectWriter.h
@@ -11,7 +11,6 @@
#define LLVM_MC_MCMACHOBJECTWRITER_H
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCObjectWriter.h"
diff --git a/include/llvm/MC/MCObjectFileInfo.h b/include/llvm/MC/MCObjectFileInfo.h
index 8a3a6af3bf79..cef4e5b3eb93 100644
--- a/include/llvm/MC/MCObjectFileInfo.h
+++ b/include/llvm/MC/MCObjectFileInfo.h
@@ -127,6 +127,7 @@ protected:
MCSection *DwarfGnuPubTypesSection;
MCSection *COFFDebugSymbolsSection;
+ MCSection *COFFDebugTypesSection;
/// Extra TLS Variable Data section.
///
@@ -158,6 +159,7 @@ protected:
MCSection *MergeableConst4Section;
MCSection *MergeableConst8Section;
MCSection *MergeableConst16Section;
+ MCSection *MergeableConst32Section;
// MachO specific sections.
@@ -183,6 +185,7 @@ protected:
MCSection *SixteenByteConstantSection;
MCSection *LazySymbolPointerSection;
MCSection *NonLazySymbolPointerSection;
+ MCSection *ThreadLocalPointerSection;
/// COFF specific sections.
MCSection *DrectveSection;
@@ -191,12 +194,8 @@ protected:
MCSection *SXDataSection;
public:
- void InitMCObjectFileInfo(const Triple &TT, Reloc::Model RM,
- CodeModel::Model CM, MCContext &ctx);
- LLVM_ATTRIBUTE_DEPRECATED(
- void InitMCObjectFileInfo(StringRef TT, Reloc::Model RM,
- CodeModel::Model CM, MCContext &ctx),
- "StringRef GNU Triple argument replaced by a llvm::Triple object");
+ void InitMCObjectFileInfo(const Triple &TT, bool PIC, CodeModel::Model CM,
+ MCContext &ctx);
bool getSupportsWeakOmittedEHFrame() const {
return SupportsWeakOmittedEHFrame;
@@ -274,6 +273,10 @@ public:
MCSection *getCOFFDebugSymbolsSection() const {
return COFFDebugSymbolsSection;
}
+ MCSection *getCOFFDebugTypesSection() const {
+ return COFFDebugTypesSection;
+ }
+
MCSection *getTLSExtraDataSection() const { return TLSExtraDataSection; }
const MCSection *getTLSDataSection() const { return TLSDataSection; }
@@ -293,6 +296,9 @@ public:
const MCSection *getMergeableConst16Section() const {
return MergeableConst16Section;
}
+ const MCSection *getMergeableConst32Section() const {
+ return MergeableConst32Section;
+ }
// MachO specific sections.
const MCSection *getTLSTLVSection() const { return TLSTLVSection; }
@@ -324,6 +330,9 @@ public:
MCSection *getNonLazySymbolPointerSection() const {
return NonLazySymbolPointerSection;
}
+ MCSection *getThreadLocalPointerSection() const {
+ return ThreadLocalPointerSection;
+ }
// COFF specific sections.
MCSection *getDrectveSection() const { return DrectveSection; }
@@ -338,18 +347,18 @@ public:
enum Environment { IsMachO, IsELF, IsCOFF };
Environment getObjectFileType() const { return Env; }
- Reloc::Model getRelocM() const { return RelocM; }
+ bool isPositionIndependent() const { return PositionIndependent; }
private:
Environment Env;
- Reloc::Model RelocM;
+ bool PositionIndependent;
CodeModel::Model CMModel;
MCContext *Ctx;
Triple TT;
- void initMachOMCObjectFileInfo(Triple T);
- void initELFMCObjectFileInfo(Triple T);
- void initCOFFMCObjectFileInfo(Triple T);
+ void initMachOMCObjectFileInfo(const Triple &T);
+ void initELFMCObjectFileInfo(const Triple &T);
+ void initCOFFMCObjectFileInfo(const Triple &T);
public:
const Triple &getTargetTriple() const { return TT; }
diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h
index 9fe2fda21353..d7775f27868c 100644
--- a/include/llvm/MC/MCObjectStreamer.h
+++ b/include/llvm/MC/MCObjectStreamer.h
@@ -59,7 +59,6 @@ public:
void EmitFrames(MCAsmBackend *MAB);
void EmitCFISections(bool EH, bool Debug) override;
-protected:
MCFragment *getCurrentFragment() const;
void insert(MCFragment *F) {
@@ -73,6 +72,7 @@ protected:
/// fragment is not a data fragment.
MCDataFragment *getOrCreateDataFragment();
+protected:
bool changeSectionImpl(MCSection *Section, const MCExpr *Subsection);
/// If any labels have been emitted but not assigned fragments, ensure that
@@ -122,11 +122,31 @@ public:
unsigned PointerSize);
void EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
const MCSymbol *Label);
+ void EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line,
+ unsigned Column, bool PrologueEnd, bool IsStmt,
+ StringRef FileName) override;
+ void EmitCVLinetableDirective(unsigned FunctionId, const MCSymbol *Begin,
+ const MCSymbol *End) override;
+ void EmitCVInlineLinetableDirective(
+ unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,
+ const MCSymbol *FnStartSym, const MCSymbol *FnEndSym,
+ ArrayRef<unsigned> SecondaryFunctionIds) override;
+ void EmitCVDefRangeDirective(
+ ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
+ StringRef FixedSizePortion) override;
+ void EmitCVStringTableDirective() override;
+ void EmitCVFileChecksumsDirective() override;
void EmitGPRel32Value(const MCExpr *Value) override;
void EmitGPRel64Value(const MCExpr *Value) override;
bool EmitRelocDirective(const MCExpr &Offset, StringRef Name,
const MCExpr *Expr, SMLoc Loc) override;
- void EmitFill(uint64_t NumBytes, uint8_t FillValue) override;
+ using MCStreamer::emitFill;
+ void emitFill(uint64_t NumBytes, uint8_t FillValue) override;
+ void emitFill(const MCExpr &NumBytes, uint64_t FillValue,
+ SMLoc Loc = SMLoc()) override;
+ void emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr,
+ SMLoc Loc = SMLoc()) override;
+
void FinishImpl() override;
/// Emit the absolute difference between two symbols if possible.
diff --git a/include/llvm/MC/MCObjectWriter.h b/include/llvm/MC/MCObjectWriter.h
index 63c833ac20d6..0ecebe42a0b9 100644
--- a/include/llvm/MC/MCObjectWriter.h
+++ b/include/llvm/MC/MCObjectWriter.h
@@ -22,6 +22,7 @@ class MCAsmLayout;
class MCAssembler;
class MCFixup;
class MCFragment;
+class MCSymbol;
class MCSymbolRefExpr;
class MCValue;
diff --git a/include/llvm/MC/MCParser/AsmLexer.h b/include/llvm/MC/MCParser/AsmLexer.h
index 1bb6d212784e..c779121b6cf0 100644
--- a/include/llvm/MC/MCParser/AsmLexer.h
+++ b/include/llvm/MC/MCParser/AsmLexer.h
@@ -29,7 +29,8 @@ class AsmLexer : public MCAsmLexer {
const char *CurPtr;
StringRef CurBuf;
- bool isAtStartOfLine;
+ bool IsAtStartOfLine;
+ bool IsAtStartOfStatement;
void operator=(const AsmLexer&) = delete;
AsmLexer(const AsmLexer&) = delete;
@@ -45,17 +46,15 @@ public:
void setBuffer(StringRef Buf, const char *ptr = nullptr);
StringRef LexUntilEndOfStatement() override;
- StringRef LexUntilEndOfLine();
size_t peekTokens(MutableArrayRef<AsmToken> Buf,
bool ShouldSkipSpace = true) override;
- bool isAtStartOfComment(const char *Ptr);
- bool isAtStatementSeparator(const char *Ptr);
-
const MCAsmInfo &getMAI() const { return MAI; }
private:
+ bool isAtStartOfComment(const char *Ptr);
+ bool isAtStatementSeparator(const char *Ptr);
int getNextChar();
AsmToken ReturnError(const char *Loc, const std::string &Msg);
@@ -67,6 +66,8 @@ private:
AsmToken LexQuote();
AsmToken LexFloatLiteral();
AsmToken LexHexFloatLiteral(bool NoIntDigits);
+
+ StringRef LexUntilEndOfLine();
};
} // end namespace llvm
diff --git a/include/llvm/MC/MCParser/MCAsmLexer.h b/include/llvm/MC/MCParser/MCAsmLexer.h
index 55279f49529a..3dd22c93d363 100644
--- a/include/llvm/MC/MCParser/MCAsmLexer.h
+++ b/include/llvm/MC/MCParser/MCAsmLexer.h
@@ -11,10 +11,13 @@
#define LLVM_MC_MCPARSER_MCASMLEXER_H
#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/SMLoc.h"
+#include <utility>
namespace llvm {
@@ -36,12 +39,15 @@ public:
// Real values.
Real,
+ // Comments
+ Comment,
+ HashDirective,
// No-value.
EndOfStatement,
Colon,
Space,
Plus, Minus, Tilde,
- Slash, // '/'
+ Slash, // '/'
BackSlash, // '\'
LParen, RParen, LBrac, RBrac, LCurly, RCurly,
Star, Dot, Comma, Dollar, Equal, EqualEqual,
@@ -64,7 +70,7 @@ private:
public:
AsmToken() {}
AsmToken(TokenKind Kind, StringRef Str, APInt IntVal)
- : Kind(Kind), Str(Str), IntVal(IntVal) {}
+ : Kind(Kind), Str(Str), IntVal(std::move(IntVal)) {}
AsmToken(TokenKind Kind, StringRef Str, int64_t IntVal = 0)
: Kind(Kind), Str(Str), IntVal(64, IntVal, true) {}
@@ -150,8 +156,12 @@ public:
const AsmToken &Lex() {
assert(!CurTok.empty());
CurTok.erase(CurTok.begin());
- if (CurTok.empty())
- CurTok.emplace_back(LexToken());
+ // LexToken may generate multiple tokens via UnLex but will always return
+ // the first one. Place returned value at head of CurTok vector.
+ if (CurTok.empty()) {
+ AsmToken T = LexToken();
+ CurTok.insert(CurTok.begin(), T);
+ }
return CurTok.front();
}
diff --git a/include/llvm/MC/MCTargetAsmParser.h b/include/llvm/MC/MCParser/MCTargetAsmParser.h
index 03b2dc9a282c..28a7b9664882 100644
--- a/include/llvm/MC/MCTargetAsmParser.h
+++ b/include/llvm/MC/MCParser/MCTargetAsmParser.h
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_MC_MCTARGETASMPARSER_H
-#define LLVM_MC_MCTARGETASMPARSER_H
+#ifndef LLVM_MC_MCPARSER_MCTARGETASMPARSER_H
+#define LLVM_MC_MCPARSER_MCTARGETASMPARSER_H
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCParser/MCAsmParserExtension.h"
@@ -40,6 +40,7 @@ enum AsmRewriteKind {
AOK_Output, // Rewrite in terms of $N.
AOK_SizeDirective, // Add a sizing directive (e.g., dword ptr).
AOK_Label, // Rewrite local labels.
+ AOK_EndOfStatement, // Add EndOfStatement (e.g., "\n\t").
AOK_Skip // Skip emission (e.g., offset/type operators).
};
@@ -55,6 +56,7 @@ const char AsmRewritePrecedence [] = {
3, // AOK_Output
5, // AOK_SizeDirective
1, // AOK_Label
+ 5, // AOK_EndOfStatement
2 // AOK_Skip
};
diff --git a/include/llvm/MC/MCRegisterInfo.h b/include/llvm/MC/MCRegisterInfo.h
index a4d5e0867232..548280614e92 100644
--- a/include/llvm/MC/MCRegisterInfo.h
+++ b/include/llvm/MC/MCRegisterInfo.h
@@ -182,6 +182,7 @@ private:
const DwarfLLVMRegPair *Dwarf2LRegs; // Dwarf to LLVM regs mapping
const DwarfLLVMRegPair *EHDwarf2LRegs; // Dwarf to LLVM regs mapping EH
DenseMap<unsigned, int> L2SEHRegs; // LLVM to SEH regs mapping
+ DenseMap<unsigned, int> L2CVRegs; // LLVM to CV regs mapping
public:
/// DiffListIterator - Base iterator class that can traverse the
@@ -309,6 +310,10 @@ public:
L2SEHRegs[LLVMReg] = SEHReg;
}
+ void mapLLVMRegToCVReg(unsigned LLVMReg, int CVReg) {
+ L2CVRegs[LLVMReg] = CVReg;
+ }
+
/// \brief This method should return the register where the return
/// address can be found.
unsigned getRARegister() const {
@@ -396,6 +401,10 @@ public:
/// number. Returns LLVM register number if there is no equivalent value.
int getSEHRegNum(unsigned RegNum) const;
+ /// \brief Map a target register to an equivalent CodeView register
+ /// number.
+ int getCodeViewRegNum(unsigned RegNum) const;
+
regclass_iterator regclass_begin() const { return Classes; }
regclass_iterator regclass_end() const { return Classes+NumClasses; }
@@ -440,6 +449,11 @@ public:
return RegA == RegB || isSuperRegister(RegA, RegB);
}
+ /// \brief Returns true if RegB is a super-register or sub-register of RegA
+ /// or if RegB == RegA.
+ bool isSuperOrSubRegisterEq(unsigned RegA, unsigned RegB) const {
+ return isSubRegisterEq(RegA, RegB) || isSuperRegister(RegA, RegB);
+ }
};
//===----------------------------------------------------------------------===//
diff --git a/include/llvm/MC/MCSchedule.h b/include/llvm/MC/MCSchedule.h
index d7f9b69a9a2c..37728797f626 100644
--- a/include/llvm/MC/MCSchedule.h
+++ b/include/llvm/MC/MCSchedule.h
@@ -165,9 +165,6 @@ struct MCSchedModel {
static const unsigned DefaultLoopMicroOpBufferSize = 0;
// LoadLatency is the expected latency of load instructions.
- //
- // If MinLatency >= 0, this may be overriden for individual load opcodes by
- // InstrItinerary OperandCycles.
unsigned LoadLatency;
static const unsigned DefaultLoadLatency = 4;
@@ -175,7 +172,6 @@ struct MCSchedModel {
// See TargetInstrInfo::isHighLatencyDef().
// By default, this is set to an arbitrarily high number of cycles
// likely to have some impact on scheduling heuristics.
- // If MinLatency >= 0, this may be overriden by InstrItinData OperandCycles.
unsigned HighLatency;
static const unsigned DefaultHighLatency = 10;
diff --git a/include/llvm/MC/MCSection.h b/include/llvm/MC/MCSection.h
index 09a98929113a..a8d7af9bd651 100644
--- a/include/llvm/MC/MCSection.h
+++ b/include/llvm/MC/MCSection.h
@@ -15,7 +15,6 @@
#define LLVM_MC_MCSECTION_H
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/ilist_node.h"
#include "llvm/MC/MCFragment.h"
diff --git a/include/llvm/MC/MCSectionCOFF.h b/include/llvm/MC/MCSectionCOFF.h
index d94682c8c381..c9fd8ea1605d 100644
--- a/include/llvm/MC/MCSectionCOFF.h
+++ b/include/llvm/MC/MCSectionCOFF.h
@@ -32,6 +32,13 @@ class MCSectionCOFF final : public MCSection {
/// below.
mutable unsigned Characteristics;
+ /// The unique IDs used with the .pdata and .xdata sections created internally
+ /// by the assembler. This ID is used to ensure that for every .text section,
+ /// there is exactly one .pdata and one .xdata section, which is required by
+ /// the Microsoft incremental linker. This data is mutable because this ID is
+ /// not notionally part of the section.
+ mutable unsigned WinCFISectionID = ~0U;
+
/// The COMDAT symbol of this section. Only valid if this is a COMDAT section.
/// Two COMDAT sections are merged if they have the same COMDAT symbol.
MCSymbol *COMDATSymbol;
@@ -71,6 +78,12 @@ public:
bool UseCodeAlign() const override;
bool isVirtualSection() const override;
+ unsigned getOrAssignWinCFISectionID(unsigned *NextID) const {
+ if (WinCFISectionID == ~0U)
+ WinCFISectionID = (*NextID)++;
+ return WinCFISectionID;
+ }
+
static bool classof(const MCSection *S) { return S->getVariant() == SV_COFF; }
};
diff --git a/include/llvm/MC/MCSectionELF.h b/include/llvm/MC/MCSectionELF.h
index b3bb3ad4e02c..dabd787b0d45 100644
--- a/include/llvm/MC/MCSectionELF.h
+++ b/include/llvm/MC/MCSectionELF.h
@@ -75,6 +75,7 @@ public:
unsigned getType() const { return Type; }
unsigned getFlags() const { return Flags; }
unsigned getEntrySize() const { return EntrySize; }
+ void setFlags(unsigned F) { Flags = F; }
const MCSymbolELF *getGroup() const { return Group; }
void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS,
diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h
index 04d143ffef66..cd710ee43425 100644
--- a/include/llvm/MC/MCStreamer.h
+++ b/include/llvm/MC/MCStreamer.h
@@ -183,6 +183,12 @@ class MCStreamer {
/// PushSection.
SmallVector<std::pair<MCSectionSubPair, MCSectionSubPair>, 4> SectionStack;
+ /// The next unique ID to use when creating a WinCFI-related section (.pdata
+ /// or .xdata). This ID ensures that we have a one-to-one mapping from
+ /// code section to unwind info section, which MSVC's incremental linker
+ /// requires.
+ unsigned NextWinCFIID = 0;
+
protected:
MCStreamer(MCContext &Ctx);
@@ -222,6 +228,8 @@ public:
return DwarfFrameInfos;
}
+ bool hasUnfinishedDwarfFrameInfo();
+
unsigned getNumWinFrameInfos() { return WinFrameInfos.size(); }
ArrayRef<WinEH::FrameInfo *> getWinFrameInfos() const {
return WinFrameInfos;
@@ -244,7 +252,7 @@ public:
/// correctly?
virtual bool isIntegratedAssemblerRequired() const { return false; }
- /// \brief Add a textual command.
+ /// \brief Add a textual comment.
///
/// Typically for comments that can be emitted to the generated .s
/// file if applicable as a QoI issue to make the output of the compiler
@@ -266,6 +274,12 @@ public:
/// only prints comments, the object streamer ignores it instead of asserting.
virtual void emitRawComment(const Twine &T, bool TabPrefix = true);
+ /// \brief Add explicit comment T. T is required to be a valid
+ /// comment in the output and does not need to be escaped.
+ virtual void addExplicitComment(const Twine &T);
+ /// \brief Emit added explicit comments.
+ virtual void emitExplicitComments();
+
/// AddBlankLine - Emit a blank line to a .s file to pretty it up.
virtual void AddBlankLine() {}
@@ -515,6 +529,10 @@ public:
/// etc.
virtual void EmitBytes(StringRef Data);
+ /// Functionally identical to EmitBytes. When emitting textual assembly, this
+ /// method uses .byte directives instead of .ascii or .asciz for readability.
+ virtual void EmitBinaryData(StringRef Data);
+
/// \brief Emit the expression \p Value into the output as a native
/// integer of the given \p Size bytes.
///
@@ -567,7 +585,29 @@ public:
/// \brief Emit NumBytes bytes worth of the value specified by FillValue.
/// This implements directives such as '.space'.
- virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue);
+ virtual void emitFill(uint64_t NumBytes, uint8_t FillValue);
+
+ /// \brief Emit \p Size bytes worth of the value specified by \p FillValue.
+ ///
+ /// This is used to implement assembler directives such as .space or .skip.
+ ///
+ /// \param NumBytes - The number of bytes to emit.
+ /// \param FillValue - The value to use when filling bytes.
+ /// \param Loc - The location of the expression for error reporting.
+ virtual void emitFill(const MCExpr &NumBytes, uint64_t FillValue,
+ SMLoc Loc = SMLoc());
+
+ /// \brief Emit \p NumValues copies of \p Size bytes. Each \p Size bytes is
+ /// taken from the lowest order 4 bytes of \p Expr expression.
+ ///
+ /// This is used to implement assembler directives such as .fill.
+ ///
+ /// \param NumValues - The number of copies of \p Size bytes to emit.
+ /// \param Size - The size (in bytes) of each repeated value.
+ /// \param Expr - The expression from which \p Size bytes are used.
+ virtual void emitFill(uint64_t NumValues, int64_t Size, int64_t Expr);
+ virtual void emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr,
+ SMLoc Loc = SMLoc());
/// \brief Emit NumBytes worth of zeros.
/// This function properly handles data in virtual sections.
@@ -640,6 +680,40 @@ public:
unsigned Isa, unsigned Discriminator,
StringRef FileName);
+ /// \brief Associate a filename with a specified logical file number. This
+ /// implements the '.cv_file 4 "foo.c"' assembler directive.
+ virtual unsigned EmitCVFileDirective(unsigned FileNo, StringRef Filename);
+
+ /// \brief This implements the CodeView '.cv_loc' assembler directive.
+ virtual void EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
+ unsigned Line, unsigned Column,
+ bool PrologueEnd, bool IsStmt,
+ StringRef FileName);
+
+ /// \brief This implements the CodeView '.cv_linetable' assembler directive.
+ virtual void EmitCVLinetableDirective(unsigned FunctionId,
+ const MCSymbol *FnStart,
+ const MCSymbol *FnEnd);
+
+ /// \brief This implements the CodeView '.cv_inline_linetable' assembler
+ /// directive.
+ virtual void EmitCVInlineLinetableDirective(
+ unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,
+ const MCSymbol *FnStartSym, const MCSymbol *FnEndSym,
+ ArrayRef<unsigned> SecondaryFunctionIds);
+
+ /// \brief This implements the CodeView '.cv_def_range' assembler
+ /// directive.
+ virtual void EmitCVDefRangeDirective(
+ ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
+ StringRef FixedSizePortion);
+
+ /// \brief This implements the CodeView '.cv_stringtable' assembler directive.
+ virtual void EmitCVStringTableDirective() {}
+
+ /// \brief This implements the CodeView '.cv_filechecksums' assembler directive.
+ virtual void EmitCVFileChecksumsDirective() {}
+
/// Emit the absolute difference between two symbols.
///
/// \pre Offset of \c Hi is greater than the offset \c Lo.
@@ -684,6 +758,14 @@ public:
virtual void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except);
virtual void EmitWinEHHandlerData();
+ /// Get the .pdata section used for the given section. Typically the given
+ /// section is either the main .text section or some other COMDAT .text
+ /// section, but it may be any section containing code.
+ MCSection *getAssociatedPDataSection(const MCSection *TextSec);
+
+ /// Get the .xdata section used for the given section.
+ MCSection *getAssociatedXDataSection(const MCSection *TextSec);
+
virtual void EmitSyntaxDirective();
/// \brief Emit a .reloc directive.
diff --git a/include/llvm/MC/MCSubtargetInfo.h b/include/llvm/MC/MCSubtargetInfo.h
index 446feefc4500..5ede043fa2ee 100644
--- a/include/llvm/MC/MCSubtargetInfo.h
+++ b/include/llvm/MC/MCSubtargetInfo.h
@@ -14,6 +14,7 @@
#ifndef LLVM_MC_MCSUBTARGETINFO_H
#define LLVM_MC_MCSUBTARGETINFO_H
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/MC/MCInstrItineraries.h"
#include "llvm/MC/SubtargetFeature.h"
#include <string>
diff --git a/include/llvm/MC/MCSymbol.h b/include/llvm/MC/MCSymbol.h
index c51ecfcb0c5c..23e34b7869a5 100644
--- a/include/llvm/MC/MCSymbol.h
+++ b/include/llvm/MC/MCSymbol.h
@@ -17,7 +17,7 @@
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/StringMap.h"
-#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCFragment.h"
#include "llvm/Support/Compiler.h"
namespace llvm {
@@ -87,7 +87,7 @@ protected:
/// IsUsed - True if this symbol has been used.
mutable unsigned IsUsed : 1;
- mutable bool IsRegistered : 1;
+ mutable unsigned IsRegistered : 1;
/// This symbol is visible outside this translation unit.
mutable unsigned IsExternal : 1;
diff --git a/include/llvm/MC/MCSymbolMachO.h b/include/llvm/MC/MCSymbolMachO.h
index 5b0321fe9f73..25220e4a8109 100644
--- a/include/llvm/MC/MCSymbolMachO.h
+++ b/include/llvm/MC/MCSymbolMachO.h
@@ -9,6 +9,7 @@
#ifndef LLVM_MC_MCSYMBOLMACHO_H
#define LLVM_MC_MCSYMBOLMACHO_H
+#include "llvm/ADT/Twine.h"
#include "llvm/MC/MCSymbol.h"
namespace llvm {
@@ -33,6 +34,7 @@ class MCSymbolMachO : public MCSymbol {
SF_WeakReference = 0x0040,
SF_WeakDefinition = 0x0080,
SF_SymbolResolver = 0x0100,
+ SF_AltEntry = 0x0200,
// Common alignment
SF_CommonAlignmentMask = 0xF0FF,
@@ -88,6 +90,14 @@ public:
modifyFlags(SF_SymbolResolver, SF_SymbolResolver);
}
+ void setAltEntry() const {
+ modifyFlags(SF_AltEntry, SF_AltEntry);
+ }
+
+ bool isAltEntry() const {
+ return getFlags() & SF_AltEntry;
+ }
+
void setDesc(unsigned Value) const {
assert(Value == (Value & SF_DescFlagsMask) &&
"Invalid .desc value!");
@@ -96,7 +106,7 @@ public:
/// \brief Get the encoded value of the flags as they will be emitted in to
/// the MachO binary
- uint16_t getEncodedFlags() const {
+ uint16_t getEncodedFlags(bool EncodeAsAltEntry) const {
uint16_t Flags = getFlags();
// Common alignment is packed into the 'desc' bits.
@@ -113,6 +123,9 @@ public:
}
}
+ if (EncodeAsAltEntry)
+ Flags |= SF_AltEntry;
+
return Flags;
}
diff --git a/include/llvm/MC/MCTargetOptions.h b/include/llvm/MC/MCTargetOptions.h
index 4b66a750cb7d..1d170b757cb3 100644
--- a/include/llvm/MC/MCTargetOptions.h
+++ b/include/llvm/MC/MCTargetOptions.h
@@ -36,6 +36,10 @@ public:
bool ShowMCEncoding : 1;
bool ShowMCInst : 1;
bool AsmVerbose : 1;
+
+ /// Preserve Comments in Assembly.
+ bool PreserveAsmComments : 1;
+
int DwarfVersion;
/// getABIName - If this returns a non-empty string this represents the
/// textual name of the ABI that we want the backend to use, e.g. o32, or
diff --git a/include/llvm/MC/MCWin64EH.h b/include/llvm/MC/MCWin64EH.h
index 0e81a191cd2c..83ea738de8c3 100644
--- a/include/llvm/MC/MCWin64EH.h
+++ b/include/llvm/MC/MCWin64EH.h
@@ -17,7 +17,6 @@
#include "llvm/MC/MCWinEH.h"
#include "llvm/Support/Win64EH.h"
-#include <vector>
namespace llvm {
class MCStreamer;
diff --git a/include/llvm/MC/MCWinEH.h b/include/llvm/MC/MCWinEH.h
index 723d7a397c49..4ca52a6654eb 100644
--- a/include/llvm/MC/MCWinEH.h
+++ b/include/llvm/MC/MCWinEH.h
@@ -13,11 +13,9 @@
#include <vector>
namespace llvm {
-class MCContext;
class MCSection;
class MCStreamer;
class MCSymbol;
-class StringRef;
namespace WinEH {
struct Instruction {
@@ -31,50 +29,35 @@ struct Instruction {
};
struct FrameInfo {
- const MCSymbol *Begin;
- const MCSymbol *End;
- const MCSymbol *ExceptionHandler;
- const MCSymbol *Function;
- const MCSymbol *PrologEnd;
- const MCSymbol *Symbol;
+ const MCSymbol *Begin = nullptr;
+ const MCSymbol *End = nullptr;
+ const MCSymbol *ExceptionHandler = nullptr;
+ const MCSymbol *Function = nullptr;
+ const MCSymbol *PrologEnd = nullptr;
+ const MCSymbol *Symbol = nullptr;
+ const MCSection *TextSection = nullptr;
- bool HandlesUnwind;
- bool HandlesExceptions;
+ bool HandlesUnwind = false;
+ bool HandlesExceptions = false;
- int LastFrameInst;
- const FrameInfo *ChainedParent;
+ int LastFrameInst = -1;
+ const FrameInfo *ChainedParent = nullptr;
std::vector<Instruction> Instructions;
- FrameInfo()
- : Begin(nullptr), End(nullptr), ExceptionHandler(nullptr),
- Function(nullptr), PrologEnd(nullptr), Symbol(nullptr),
- HandlesUnwind(false), HandlesExceptions(false), LastFrameInst(-1),
- ChainedParent(nullptr), Instructions() {}
+ FrameInfo() = default;
FrameInfo(const MCSymbol *Function, const MCSymbol *BeginFuncEHLabel)
- : Begin(BeginFuncEHLabel), End(nullptr), ExceptionHandler(nullptr),
- Function(Function), PrologEnd(nullptr), Symbol(nullptr),
- HandlesUnwind(false), HandlesExceptions(false), LastFrameInst(-1),
- ChainedParent(nullptr), Instructions() {}
+ : Begin(BeginFuncEHLabel), Function(Function) {}
FrameInfo(const MCSymbol *Function, const MCSymbol *BeginFuncEHLabel,
const FrameInfo *ChainedParent)
- : Begin(BeginFuncEHLabel), End(nullptr), ExceptionHandler(nullptr),
- Function(Function), PrologEnd(nullptr), Symbol(nullptr),
- HandlesUnwind(false), HandlesExceptions(false), LastFrameInst(-1),
- ChainedParent(ChainedParent), Instructions() {}
+ : Begin(BeginFuncEHLabel), Function(Function),
+ ChainedParent(ChainedParent) {}
};
class UnwindEmitter {
public:
- static MCSection *getPDataSection(const MCSymbol *Function,
- MCContext &Context);
- static MCSection *getXDataSection(const MCSymbol *Function,
- MCContext &Context);
+ virtual ~UnwindEmitter();
- virtual ~UnwindEmitter() { }
-
- //
- // This emits the unwind info sections (.pdata and .xdata in PE/COFF).
- //
+ /// This emits the unwind info sections (.pdata and .xdata in PE/COFF).
virtual void Emit(MCStreamer &Streamer) const = 0;
virtual void EmitUnwindInfo(MCStreamer &Streamer, FrameInfo *FI) const = 0;
};
diff --git a/include/llvm/MC/SectionKind.h b/include/llvm/MC/SectionKind.h
index b09b93cfc377..02fb22623cf7 100644
--- a/include/llvm/MC/SectionKind.h
+++ b/include/llvm/MC/SectionKind.h
@@ -63,6 +63,10 @@ class SectionKind {
/// for example, vectors.
MergeableConst16,
+ /// MergeableConst32 - This is a section used by 32-byte constants,
+ /// for example, vectors.
+ MergeableConst32,
+
/// Writeable - This is the base of all segments that need to be written
/// to during program runtime.
@@ -125,11 +129,12 @@ public:
bool isMergeableConst() const {
return K == MergeableConst4 || K == MergeableConst8 ||
- K == MergeableConst16;
+ K == MergeableConst16 || K == MergeableConst32;
}
bool isMergeableConst4() const { return K == MergeableConst4; }
bool isMergeableConst8() const { return K == MergeableConst8; }
bool isMergeableConst16() const { return K == MergeableConst16; }
+ bool isMergeableConst32() const { return K == MergeableConst32; }
bool isWriteable() const {
return isThreadLocal() || isGlobalWriteableData();
@@ -180,6 +185,7 @@ public:
static SectionKind getMergeableConst4() { return get(MergeableConst4); }
static SectionKind getMergeableConst8() { return get(MergeableConst8); }
static SectionKind getMergeableConst16() { return get(MergeableConst16); }
+ static SectionKind getMergeableConst32() { return get(MergeableConst32); }
static SectionKind getThreadBSS() { return get(ThreadBSS); }
static SectionKind getThreadData() { return get(ThreadData); }
static SectionKind getBSS() { return get(BSS); }
diff --git a/include/llvm/MC/StringTableBuilder.h b/include/llvm/MC/StringTableBuilder.h
index adde86b45583..f2b8ecd2d997 100644
--- a/include/llvm/MC/StringTableBuilder.h
+++ b/include/llvm/MC/StringTableBuilder.h
@@ -23,12 +23,15 @@ public:
private:
SmallString<256> StringTable;
- DenseMap<StringRef, size_t> StringIndexMap;
+ DenseMap<CachedHash<StringRef>, size_t> StringIndexMap;
size_t Size = 0;
Kind K;
+ unsigned Alignment;
+
+ void finalizeStringTable(bool Optimize);
public:
- StringTableBuilder(Kind K);
+ StringTableBuilder(Kind K, unsigned Alignment = 1);
/// \brief Add a string to the builder. Returns the position of S in the
/// table. The position will be changed if finalize is used.
@@ -39,6 +42,10 @@ public:
/// be added after this point.
void finalize();
+ /// Finalize the string table without reording it. In this mode, offsets
+ /// returned by add will still be valid.
+ void finalizeInOrder();
+
/// \brief Retrieve the string table data. Can only be used after the table
/// is finalized.
StringRef data() const {
@@ -50,7 +57,10 @@ public:
/// after the table is finalized.
size_t getOffset(StringRef S) const;
- const DenseMap<StringRef, size_t> &getMap() const { return StringIndexMap; }
+ const DenseMap<CachedHash<StringRef>, size_t> &getMap() const {
+ return StringIndexMap;
+ }
+
size_t getSize() const { return Size; }
void clear();
diff --git a/include/llvm/MC/SubtargetFeature.h b/include/llvm/MC/SubtargetFeature.h
index 75d1e7997119..ed4abd772821 100644
--- a/include/llvm/MC/SubtargetFeature.h
+++ b/include/llvm/MC/SubtargetFeature.h
@@ -18,12 +18,13 @@
#ifndef LLVM_MC_SUBTARGETFEATURE_H
#define LLVM_MC_SUBTARGETFEATURE_H
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/DataTypes.h"
#include <bitset>
+#include <vector>
namespace llvm {
+template <typename T> class ArrayRef;
class raw_ostream;
class StringRef;
diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h
index 8dd042a2533f..cfba2567371a 100644
--- a/include/llvm/Object/Archive.h
+++ b/include/llvm/Object/Archive.h
@@ -14,6 +14,7 @@
#ifndef LLVM_OBJECT_ARCHIVE_H
#define LLVM_OBJECT_ARCHIVE_H
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Object/Binary.h"
@@ -42,7 +43,7 @@ struct ArchiveMemberHeader {
sys::fs::perms getAccessMode() const;
sys::TimeValue getLastModified() const;
llvm::StringRef getRawLastModified() const {
- return StringRef(LastModified, sizeof(LastModified)).rtrim(" ");
+ return StringRef(LastModified, sizeof(LastModified)).rtrim(' ');
}
unsigned getUID() const;
unsigned getGID() const;
@@ -78,6 +79,7 @@ public:
ErrorOr<Child> getNext() const;
ErrorOr<StringRef> getName() const;
+ ErrorOr<std::string> getFullName() const;
StringRef getRawName() const { return getHeader()->getName(); }
sys::TimeValue getLastModified() const {
return getHeader()->getLastModified();
@@ -100,26 +102,25 @@ public:
ErrorOr<MemoryBufferRef> getMemoryBufferRef() const;
- ErrorOr<std::unique_ptr<Binary>>
+ Expected<std::unique_ptr<Binary>>
getAsBinary(LLVMContext *Context = nullptr) const;
};
class child_iterator {
- ErrorOr<Child> child;
+ Child C;
+ Error *E;
public:
- child_iterator() : child(Child(nullptr, nullptr, nullptr)) {}
- child_iterator(const Child &c) : child(c) {}
- child_iterator(std::error_code EC) : child(EC) {}
- const ErrorOr<Child> *operator->() const { return &child; }
- const ErrorOr<Child> &operator*() const { return child; }
+ child_iterator() : C(Child(nullptr, nullptr, nullptr)), E(nullptr) {}
+ child_iterator(const Child &C, Error *E) : C(C), E(E) {}
+ const Child *operator->() const { return &C; }
+ const Child &operator*() const { return C; }
bool operator==(const child_iterator &other) const {
- // We ignore error states so that comparisions with end() work, which
- // allows range loops.
- if (child.getError() || other.child.getError())
- return false;
- return *child == *other.child;
+ // Ignore errors here: If an error occurred during increment then getNext
+ // will have been set to child_end(), and the following comparison should
+ // do the right thing.
+ return C == other.C;
}
bool operator!=(const child_iterator &other) const {
@@ -129,8 +130,15 @@ public:
// Code in loops with child_iterators must check for errors on each loop
// iteration. And if there is an error break out of the loop.
child_iterator &operator++() { // Preincrement
- assert(child && "Can't increment iterator with error");
- child = child->getNext();
+ assert(E && "Can't increment iterator with no Error attached");
+ if (auto ChildOrErr = C.getNext())
+ C = *ChildOrErr;
+ else {
+ ErrorAsOutParameter ErrAsOutParam(*E);
+ C = C.getParent()->child_end().C;
+ *E = errorCodeToError(ChildOrErr.getError());
+ E = nullptr;
+ }
return *this;
}
};
@@ -175,23 +183,25 @@ public:
}
};
- Archive(MemoryBufferRef Source, std::error_code &EC);
- static ErrorOr<std::unique_ptr<Archive>> create(MemoryBufferRef Source);
+ Archive(MemoryBufferRef Source, Error &Err);
+ static Expected<std::unique_ptr<Archive>> create(MemoryBufferRef Source);
enum Kind {
K_GNU,
K_MIPS64,
K_BSD,
+ K_DARWIN64,
K_COFF
};
Kind kind() const { return (Kind)Format; }
bool isThin() const { return IsThin; }
- child_iterator child_begin(bool SkipInternal = true) const;
+ child_iterator child_begin(Error &Err, bool SkipInternal = true) const;
child_iterator child_end() const;
- iterator_range<child_iterator> children(bool SkipInternal = true) const {
- return make_range(child_begin(SkipInternal), child_end());
+ iterator_range<child_iterator> children(Error &Err,
+ bool SkipInternal = true) const {
+ return make_range(child_begin(Err, SkipInternal), child_end());
}
symbol_iterator symbol_begin() const;
@@ -206,12 +216,16 @@ public:
}
// check if a symbol is in the archive
- child_iterator findSym(StringRef name) const;
+ Expected<Optional<Child>> findSym(StringRef name) const;
bool hasSymbolTable() const;
StringRef getSymbolTable() const { return SymbolTable; }
uint32_t getNumberOfSymbols() const;
+ std::vector<std::unique_ptr<MemoryBuffer>> takeThinBuffers() {
+ return std::move(ThinBuffers);
+ }
+
private:
StringRef SymbolTable;
StringRef StringTable;
@@ -220,7 +234,7 @@ private:
uint16_t FirstRegularStartOfFile = -1;
void setFirstRegular(const Child &C);
- unsigned Format : 2;
+ unsigned Format : 3;
unsigned IsThin : 1;
mutable std::vector<std::unique_ptr<MemoryBuffer>> ThinBuffers;
};
diff --git a/include/llvm/Object/ArchiveWriter.h b/include/llvm/Object/ArchiveWriter.h
index b5d2ba358080..55b58fac4f66 100644
--- a/include/llvm/Object/ArchiveWriter.h
+++ b/include/llvm/Object/ArchiveWriter.h
@@ -20,29 +20,36 @@
namespace llvm {
-class NewArchiveIterator {
- bool IsNewMember;
- StringRef Name;
-
- object::Archive::Child OldMember;
-
-public:
- NewArchiveIterator(const object::Archive::Child &OldMember, StringRef Name);
- NewArchiveIterator(StringRef FileName);
- bool isNewMember() const;
- StringRef getName() const;
-
- const object::Archive::Child &getOld() const;
-
- StringRef getNew() const;
- llvm::ErrorOr<int> getFD(sys::fs::file_status &NewStatus) const;
- const sys::fs::file_status &getStatus() const;
+struct NewArchiveMember {
+ std::unique_ptr<MemoryBuffer> Buf;
+ sys::TimeValue ModTime = sys::TimeValue::PosixZeroTime();
+ unsigned UID = 0, GID = 0, Perms = 0644;
+
+ NewArchiveMember() = default;
+ NewArchiveMember(NewArchiveMember &&Other)
+ : Buf(std::move(Other.Buf)), ModTime(Other.ModTime), UID(Other.UID),
+ GID(Other.GID), Perms(Other.Perms) {}
+ NewArchiveMember &operator=(NewArchiveMember &&Other) {
+ Buf = std::move(Other.Buf);
+ ModTime = Other.ModTime;
+ UID = Other.UID;
+ GID = Other.GID;
+ Perms = Other.Perms;
+ return *this;
+ }
+ NewArchiveMember(MemoryBufferRef BufRef);
+
+ static Expected<NewArchiveMember>
+ getOldMember(const object::Archive::Child &OldMember, bool Deterministic);
+
+ static Expected<NewArchiveMember> getFile(StringRef FileName,
+ bool Deterministic);
};
std::pair<StringRef, std::error_code>
-writeArchive(StringRef ArcName, std::vector<NewArchiveIterator> &NewMembers,
+writeArchive(StringRef ArcName, std::vector<NewArchiveMember> &NewMembers,
bool WriteSymtab, object::Archive::Kind Kind, bool Deterministic,
- bool Thin);
+ bool Thin, std::unique_ptr<MemoryBuffer> OldArchiveBuf = nullptr);
}
#endif
diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h
index a0d1127781f6..5dff5406fcdd 100644
--- a/include/llvm/Object/Binary.h
+++ b/include/llvm/Object/Binary.h
@@ -42,8 +42,8 @@ protected:
ID_Archive,
ID_MachOUniversalBinary,
ID_COFFImportFile,
- ID_IR, // LLVM IR
- ID_FunctionIndex, // Function summary index
+ ID_IR, // LLVM IR
+ ID_ModuleSummaryIndex, // Module summary index
// Object and children.
ID_StartObjects,
@@ -123,7 +123,7 @@ public:
return TypeID == ID_IR;
}
- bool isFunctionIndex() const { return TypeID == ID_FunctionIndex; }
+ bool isModuleSummaryIndex() const { return TypeID == ID_ModuleSummaryIndex; }
bool isLittleEndian() const {
return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B ||
@@ -134,8 +134,8 @@ public:
/// @brief Create a Binary from Source, autodetecting the file type.
///
/// @param Source The data to create the Binary from.
-ErrorOr<std::unique_ptr<Binary>> createBinary(MemoryBufferRef Source,
- LLVMContext *Context = nullptr);
+Expected<std::unique_ptr<Binary>> createBinary(MemoryBufferRef Source,
+ LLVMContext *Context = nullptr);
template <typename T> class OwningBinary {
std::unique_ptr<T> Bin;
@@ -185,7 +185,7 @@ template <typename T> const T* OwningBinary<T>::getBinary() const {
return Bin.get();
}
-ErrorOr<OwningBinary<Binary>> createBinary(StringRef Path);
+Expected<OwningBinary<Binary>> createBinary(StringRef Path);
}
}
diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h
index 3e69c3e6e5d4..dcc58b06e228 100644
--- a/include/llvm/Object/COFF.h
+++ b/include/llvm/Object/COFF.h
@@ -169,6 +169,26 @@ struct import_directory_table_entry {
support::ulittle32_t ImportAddressTableRVA;
};
+struct debug_directory {
+ support::ulittle32_t Characteristics;
+ support::ulittle32_t TimeDateStamp;
+ support::ulittle16_t MajorVersion;
+ support::ulittle16_t MinorVersion;
+ support::ulittle32_t Type;
+ support::ulittle32_t SizeOfData;
+ support::ulittle32_t AddressOfRawData;
+ support::ulittle32_t PointerToRawData;
+};
+
+/// Information that is resent in debug_directory::AddressOfRawData if Type is
+/// IMAGE_DEBUG_TYPE_CODEVIEW.
+struct debug_pdb_info {
+ support::ulittle32_t Signature;
+ uint8_t Guid[16];
+ support::ulittle32_t Age;
+ // PDBFileName: The null-terminated PDB file name follows.
+};
+
template <typename IntTy>
struct import_lookup_table_entry {
IntTy Data;
@@ -414,6 +434,18 @@ struct coff_section {
return (Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL) &&
NumberOfRelocations == UINT16_MAX;
}
+ uint32_t getAlignment() const {
+ // The IMAGE_SCN_TYPE_NO_PAD bit is a legacy way of getting to
+ // IMAGE_SCN_ALIGN_1BYTES.
+ if (Characteristics & COFF::IMAGE_SCN_TYPE_NO_PAD)
+ return 1;
+
+ // Bit [20:24] contains section alignment. Both 0 and 1 mean alignment 1.
+ uint32_t Shift = (Characteristics >> 20) & 0xF;
+ if (Shift > 0)
+ return 1U << (Shift - 1);
+ return 1;
+ }
};
struct coff_relocation {
@@ -427,20 +459,32 @@ struct coff_aux_function_definition {
support::ulittle32_t TotalSize;
support::ulittle32_t PointerToLinenumber;
support::ulittle32_t PointerToNextFunction;
+ char Unused1[2];
};
+static_assert(sizeof(coff_aux_function_definition) == 18,
+ "auxiliary entry must be 18 bytes");
+
struct coff_aux_bf_and_ef_symbol {
char Unused1[4];
support::ulittle16_t Linenumber;
char Unused2[6];
support::ulittle32_t PointerToNextFunction;
+ char Unused3[2];
};
+static_assert(sizeof(coff_aux_bf_and_ef_symbol) == 18,
+ "auxiliary entry must be 18 bytes");
+
struct coff_aux_weak_external {
support::ulittle32_t TagIndex;
support::ulittle32_t Characteristics;
+ char Unused1[10];
};
+static_assert(sizeof(coff_aux_weak_external) == 18,
+ "auxiliary entry must be 18 bytes");
+
struct coff_aux_section_definition {
support::ulittle32_t Length;
support::ulittle16_t NumberOfRelocations;
@@ -458,12 +502,19 @@ struct coff_aux_section_definition {
}
};
+static_assert(sizeof(coff_aux_section_definition) == 18,
+ "auxiliary entry must be 18 bytes");
+
struct coff_aux_clr_token {
uint8_t AuxType;
uint8_t Reserved;
support::ulittle32_t SymbolTableIndex;
+ char MBZ[12];
};
+static_assert(sizeof(coff_aux_clr_token) == 18,
+ "auxiliary entry must be 18 bytes");
+
struct coff_import_header {
support::ulittle16_t Sig1;
support::ulittle16_t Sig2;
@@ -485,6 +536,26 @@ struct coff_import_directory_table_entry {
support::ulittle32_t ImportAddressTableRVA;
};
+template <typename IntTy>
+struct coff_tls_directory {
+ IntTy StartAddressOfRawData;
+ IntTy EndAddressOfRawData;
+ IntTy AddressOfIndex;
+ IntTy AddressOfCallBacks;
+ support::ulittle32_t SizeOfZeroFill;
+ support::ulittle32_t Characteristics;
+ uint32_t getAlignment() const {
+ // Bit [20:24] contains section alignment.
+ uint32_t Shift = (Characteristics & 0x00F00000) >> 20;
+ if (Shift > 0)
+ return 1U << (Shift - 1);
+ return 0;
+ }
+};
+
+typedef coff_tls_directory<support::little32_t> coff_tls_directory32;
+typedef coff_tls_directory<support::little64_t> coff_tls_directory64;
+
struct coff_load_configuration32 {
support::ulittle32_t Characteristics;
support::ulittle32_t TimeDateStamp;
@@ -563,12 +634,13 @@ private:
const char *StringTable;
uint32_t StringTableSize;
const import_directory_table_entry *ImportDirectory;
- uint32_t NumberOfImportDirectory;
const delay_import_directory_table_entry *DelayImportDirectory;
uint32_t NumberOfDelayImportDirectory;
const export_directory_table_entry *ExportDirectory;
const coff_base_reloc_block_header *BaseRelocHeader;
const coff_base_reloc_block_header *BaseRelocEnd;
+ const debug_directory *DebugDirectoryBegin;
+ const debug_directory *DebugDirectoryEnd;
std::error_code getString(uint32_t offset, StringRef &Res) const;
@@ -582,6 +654,7 @@ private:
std::error_code initDelayImportTablePtr();
std::error_code initExportTablePtr();
std::error_code initBaseRelocPtr();
+ std::error_code initDebugDirectoryPtr();
public:
uintptr_t getSymbolTable() const {
@@ -647,13 +720,13 @@ public:
}
protected:
void moveSymbolNext(DataRefImpl &Symb) const override;
- ErrorOr<StringRef> getSymbolName(DataRefImpl Symb) const override;
- ErrorOr<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
+ Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
+ Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
uint32_t getSymbolFlags(DataRefImpl Symb) const override;
- SymbolRef::Type getSymbolType(DataRefImpl Symb) const override;
- ErrorOr<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
+ Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
+ Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
void moveSectionNext(DataRefImpl &Sec) const override;
std::error_code getSectionName(DataRefImpl Sec,
StringRef &Res) const override;
@@ -662,6 +735,7 @@ protected:
std::error_code getSectionContents(DataRefImpl Sec,
StringRef &Res) const override;
uint64_t getSectionAlignment(DataRefImpl Sec) const override;
+ bool isSectionCompressed(DataRefImpl Sec) const override;
bool isSectionText(DataRefImpl Sec) const override;
bool isSectionData(DataRefImpl Sec) const override;
bool isSectionBSS(DataRefImpl Sec) const override;
@@ -693,6 +767,7 @@ public:
uint8_t getBytesInAddress() const override;
StringRef getFileFormatName() const override;
unsigned getArch() const override;
+ SubtargetFeatures getFeatures() const override { return SubtargetFeatures(); }
import_directory_iterator import_directory_begin() const;
import_directory_iterator import_directory_end() const;
@@ -702,12 +777,21 @@ public:
export_directory_iterator export_directory_end() const;
base_reloc_iterator base_reloc_begin() const;
base_reloc_iterator base_reloc_end() const;
+ const debug_directory *debug_directory_begin() const {
+ return DebugDirectoryBegin;
+ }
+ const debug_directory *debug_directory_end() const {
+ return DebugDirectoryEnd;
+ }
iterator_range<import_directory_iterator> import_directories() const;
iterator_range<delay_import_directory_iterator>
delay_import_directories() const;
iterator_range<export_directory_iterator> export_directories() const;
iterator_range<base_reloc_iterator> base_relocs() const;
+ iterator_range<const debug_directory *> debug_directories() const {
+ return make_range(debug_directory_begin(), debug_directory_end());
+ }
const dos_header *getDOSHeader() const {
if (!PE32Header && !PE32PlusHeader)
@@ -776,9 +860,28 @@ public:
uint64_t getImageBase() const;
std::error_code getVaPtr(uint64_t VA, uintptr_t &Res) const;
std::error_code getRvaPtr(uint32_t Rva, uintptr_t &Res) const;
+
+ /// Given an RVA base and size, returns a valid array of bytes or an error
+ /// code if the RVA and size is not contained completely within a valid
+ /// section.
+ std::error_code getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
+ ArrayRef<uint8_t> &Contents) const;
+
std::error_code getHintName(uint32_t Rva, uint16_t &Hint,
StringRef &Name) const;
+ /// Get PDB information out of a codeview debug directory entry.
+ std::error_code getDebugPDBInfo(const debug_directory *DebugDir,
+ const debug_pdb_info *&Info,
+ StringRef &PDBFileName) const;
+
+ /// Get PDB information from an executable. If the information is not present,
+ /// Info will be set to nullptr and PDBFileName will be empty. An error is
+ /// returned only on corrupt object files. Convenience accessor that can be
+ /// used if the debug directory is not already handy.
+ std::error_code getDebugPDBInfo(const debug_pdb_info *&Info,
+ StringRef &PDBFileName) const;
+
bool isRelocatableObject() const override;
bool is64() const { return PE32PlusHeader; }
@@ -807,9 +910,6 @@ public:
std::error_code
getImportTableEntry(const import_directory_table_entry *&Result) const;
- std::error_code
- getImportLookupEntry(const import_lookup_table_entry32 *&Result) const;
-
private:
const import_directory_table_entry *ImportTable;
uint32_t Index;
@@ -881,7 +981,9 @@ public:
void moveNext();
std::error_code getSymbolName(StringRef &Result) const;
+ std::error_code isOrdinal(bool &Result) const;
std::error_code getOrdinal(uint16_t &Result) const;
+ std::error_code getHintNameRVA(uint32_t &Result) const;
private:
const import_lookup_table_entry32 *Entry32;
@@ -909,6 +1011,30 @@ private:
const COFFObjectFile *OwningObject;
};
+// Corresponds to `_FPO_DATA` structure in the PE/COFF spec.
+struct FpoData {
+ support::ulittle32_t Offset; // ulOffStart: Offset 1st byte of function code
+ support::ulittle32_t Size; // cbProcSize: # bytes in function
+ support::ulittle32_t NumLocals; // cdwLocals: # bytes in locals/4
+ support::ulittle16_t NumParams; // cdwParams: # bytes in params/4
+ support::ulittle16_t Attributes;
+
+ // cbProlog: # bytes in prolog
+ int getPrologSize() const { return Attributes & 0xF; }
+
+ // cbRegs: # regs saved
+ int getNumSavedRegs() const { return (Attributes >> 8) & 0x7; }
+
+ // fHasSEH: true if seh is func
+ bool hasSEH() const { return (Attributes >> 9) & 1; }
+
+ // fUseBP: true if EBP has been allocated
+ bool useBP() const { return (Attributes >> 10) & 1; }
+
+ // cbFrame: frame pointer
+ int getFP() const { return Attributes >> 14; }
+};
+
} // end namespace object
} // end namespace llvm
diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h
index b0eaa3f5ed4d..80b8be03810c 100644
--- a/include/llvm/Object/ELF.h
+++ b/include/llvm/Object/ELF.h
@@ -54,14 +54,19 @@ public:
typedef Elf_Versym_Impl<ELFT> Elf_Versym;
typedef Elf_Hash_Impl<ELFT> Elf_Hash;
typedef Elf_GnuHash_Impl<ELFT> Elf_GnuHash;
- typedef iterator_range<const Elf_Dyn *> Elf_Dyn_Range;
- typedef iterator_range<const Elf_Shdr *> Elf_Shdr_Range;
- typedef iterator_range<const Elf_Sym *> Elf_Sym_Range;
+ typedef typename ELFT::DynRange Elf_Dyn_Range;
+ typedef typename ELFT::ShdrRange Elf_Shdr_Range;
+ typedef typename ELFT::SymRange Elf_Sym_Range;
+ typedef typename ELFT::RelRange Elf_Rel_Range;
+ typedef typename ELFT::RelaRange Elf_Rela_Range;
+ typedef typename ELFT::PhdrRange Elf_Phdr_Range;
const uint8_t *base() const {
return reinterpret_cast<const uint8_t *>(Buf.data());
}
+ size_t getBufSize() const { return Buf.size(); }
+
private:
StringRef Buf;
@@ -104,22 +109,10 @@ public:
Header->getDataEncoding() == ELF::ELFDATA2LSB;
}
- ErrorOr<const Elf_Dyn *> dynamic_table_begin(const Elf_Phdr *Phdr) const;
- ErrorOr<const Elf_Dyn *> dynamic_table_end(const Elf_Phdr *Phdr) const;
- ErrorOr<Elf_Dyn_Range> dynamic_table(const Elf_Phdr *Phdr) const {
- ErrorOr<const Elf_Dyn *> Begin = dynamic_table_begin(Phdr);
- if (std::error_code EC = Begin.getError())
- return EC;
- ErrorOr<const Elf_Dyn *> End = dynamic_table_end(Phdr);
- if (std::error_code EC = End.getError())
- return EC;
- return make_range(*Begin, *End);
- }
-
const Elf_Shdr *section_begin() const;
const Elf_Shdr *section_end() const;
Elf_Shdr_Range sections() const {
- return make_range(section_begin(), section_end());
+ return makeArrayRef(section_begin(), section_end());
}
const Elf_Sym *symbol_begin(const Elf_Shdr *Sec) const {
@@ -138,11 +131,9 @@ public:
return symbol_begin(Sec) + Size / sizeof(Elf_Sym);
}
Elf_Sym_Range symbols(const Elf_Shdr *Sec) const {
- return make_range(symbol_begin(Sec), symbol_end(Sec));
+ return makeArrayRef(symbol_begin(Sec), symbol_end(Sec));
}
- typedef iterator_range<const Elf_Rela *> Elf_Rela_Range;
-
const Elf_Rela *rela_begin(const Elf_Shdr *sec) const {
if (sec->sh_entsize != sizeof(Elf_Rela))
report_fatal_error("Invalid relocation entry size");
@@ -157,7 +148,7 @@ public:
}
Elf_Rela_Range relas(const Elf_Shdr *Sec) const {
- return make_range(rela_begin(Sec), rela_end(Sec));
+ return makeArrayRef(rela_begin(Sec), rela_end(Sec));
}
const Elf_Rel *rel_begin(const Elf_Shdr *sec) const {
@@ -173,9 +164,8 @@ public:
return rel_begin(sec) + Size / sizeof(Elf_Rel);
}
- typedef iterator_range<const Elf_Rel *> Elf_Rel_Range;
Elf_Rel_Range rels(const Elf_Shdr *Sec) const {
- return make_range(rel_begin(Sec), rel_end(Sec));
+ return makeArrayRef(rel_begin(Sec), rel_end(Sec));
}
/// \brief Iterate over program header table.
@@ -189,10 +179,8 @@ public:
return program_header_begin() + Header->e_phnum;
}
- typedef iterator_range<const Elf_Phdr *> Elf_Phdr_Range;
-
const Elf_Phdr_Range program_headers() const {
- return make_range(program_header_begin(), program_header_end());
+ return makeArrayRef(program_header_begin(), program_header_end());
}
uint64_t getNumSections() const;
@@ -200,6 +188,9 @@ public:
uint32_t getExtendedSymbolTableIndex(const Elf_Sym *Sym,
const Elf_Shdr *SymTab,
ArrayRef<Elf_Word> ShndxTable) const;
+ uint32_t getExtendedSymbolTableIndex(const Elf_Sym *Sym,
+ const Elf_Sym *FirstSym,
+ ArrayRef<Elf_Word> ShndxTable) const;
const Elf_Ehdr *getHeader() const { return Header; }
ErrorOr<const Elf_Shdr *> getSection(const Elf_Sym *Sym,
const Elf_Shdr *SymTab,
@@ -225,8 +216,15 @@ template <class ELFT>
uint32_t ELFFile<ELFT>::getExtendedSymbolTableIndex(
const Elf_Sym *Sym, const Elf_Shdr *SymTab,
ArrayRef<Elf_Word> ShndxTable) const {
+ return getExtendedSymbolTableIndex(Sym, symbol_begin(SymTab), ShndxTable);
+}
+
+template <class ELFT>
+uint32_t ELFFile<ELFT>::getExtendedSymbolTableIndex(
+ const Elf_Sym *Sym, const Elf_Sym *FirstSym,
+ ArrayRef<Elf_Word> ShndxTable) const {
assert(Sym->st_shndx == ELF::SHN_XINDEX);
- unsigned Index = Sym - symbol_begin(SymTab);
+ unsigned Index = Sym - FirstSym;
// The size of the table was checked in getSHNDXTable.
return ShndxTable[Index];
@@ -404,34 +402,6 @@ const typename ELFFile<ELFT>::Elf_Shdr *ELFFile<ELFT>::section_end() const {
}
template <class ELFT>
-ErrorOr<const typename ELFFile<ELFT>::Elf_Dyn *>
-ELFFile<ELFT>::dynamic_table_begin(const Elf_Phdr *Phdr) const {
- if (!Phdr)
- return nullptr;
- assert(Phdr->p_type == ELF::PT_DYNAMIC && "Got the wrong program header");
- uintX_t Offset = Phdr->p_offset;
- if (Offset > Buf.size())
- return object_error::parse_failed;
- return reinterpret_cast<const Elf_Dyn *>(base() + Offset);
-}
-
-template <class ELFT>
-ErrorOr<const typename ELFFile<ELFT>::Elf_Dyn *>
-ELFFile<ELFT>::dynamic_table_end(const Elf_Phdr *Phdr) const {
- if (!Phdr)
- return nullptr;
- assert(Phdr->p_type == ELF::PT_DYNAMIC && "Got the wrong program header");
- uintX_t Size = Phdr->p_filesz;
- if (Size % sizeof(Elf_Dyn))
- return object_error::elf_invalid_dynamic_table_size;
- // FIKME: Check for overflow?
- uintX_t End = Phdr->p_offset + Size;
- if (End > Buf.size())
- return object_error::parse_failed;
- return reinterpret_cast<const Elf_Dyn *>(base() + End);
-}
-
-template <class ELFT>
template <typename T>
const T *ELFFile<ELFT>::getEntry(uint32_t Section, uint32_t Entry) const {
ErrorOr<const Elf_Shdr *> Sec = getSection(Section);
diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h
index 5d826da4c2fc..07c6364a6894 100644
--- a/include/llvm/Object/ELFObjectFile.h
+++ b/include/llvm/Object/ELFObjectFile.h
@@ -14,23 +14,28 @@
#ifndef LLVM_OBJECT_ELFOBJECTFILE_H
#define LLVM_OBJECT_ELFOBJECTFILE_H
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/MC/SubtargetFeature.h"
+#include "llvm/Object/Binary.h"
#include "llvm/Object/ELF.h"
+#include "llvm/Object/ELFTypes.h"
+#include "llvm/Object/Error.h"
#include "llvm/Object/ObjectFile.h"
+#include "llvm/Object/SymbolicFile.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cctype>
-#include <limits>
-#include <utility>
+#include <cassert>
+#include <cstdint>
+#include <system_error>
namespace llvm {
namespace object {
@@ -47,6 +52,7 @@ class ELFObjectFileBase : public ObjectFile {
protected:
ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source);
+ virtual uint16_t getEMachine() const = 0;
virtual uint64_t getSymbolSize(DataRefImpl Symb) const = 0;
virtual uint8_t getSymbolOther(DataRefImpl Symb) const = 0;
virtual uint8_t getSymbolELFType(DataRefImpl Symb) const = 0;
@@ -55,14 +61,16 @@ protected:
virtual uint64_t getSectionFlags(DataRefImpl Sec) const = 0;
virtual ErrorOr<int64_t> getRelocationAddend(DataRefImpl Rel) const = 0;
-public:
+public:
typedef iterator_range<elf_symbol_iterator> elf_symbol_iterator_range;
virtual elf_symbol_iterator_range getDynamicSymbolIterators() const = 0;
elf_symbol_iterator_range symbols() const;
static inline bool classof(const Binary *v) { return v->isELF(); }
+
+ SubtargetFeatures getFeatures() const override;
};
class ELFSectionRef : public SectionRef {
@@ -175,6 +183,7 @@ ELFObjectFileBase::symbols() const {
}
template <class ELFT> class ELFObjectFile : public ELFObjectFileBase {
+ uint16_t getEMachine() const override;
uint64_t getSymbolSize(DataRefImpl Sym) const override;
public:
@@ -197,18 +206,18 @@ protected:
ArrayRef<Elf_Word> ShndxTable;
void moveSymbolNext(DataRefImpl &Symb) const override;
- ErrorOr<StringRef> getSymbolName(DataRefImpl Symb) const override;
- ErrorOr<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
+ Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
+ Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
uint32_t getSymbolFlags(DataRefImpl Symb) const override;
uint8_t getSymbolOther(DataRefImpl Symb) const override;
uint8_t getSymbolELFType(DataRefImpl Symb) const override;
- SymbolRef::Type getSymbolType(DataRefImpl Symb) const override;
- ErrorOr<section_iterator> getSymbolSection(const Elf_Sym *Symb,
- const Elf_Shdr *SymTab) const;
- ErrorOr<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
+ Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
+ Expected<section_iterator> getSymbolSection(const Elf_Sym *Symb,
+ const Elf_Shdr *SymTab) const;
+ Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
void moveSectionNext(DataRefImpl &Sec) const override;
std::error_code getSectionName(DataRefImpl Sec,
@@ -218,6 +227,7 @@ protected:
std::error_code getSectionContents(DataRefImpl Sec,
StringRef &Res) const override;
uint64_t getSectionAlignment(DataRefImpl Sec) const override;
+ bool isSectionCompressed(DataRefImpl Sec) const override;
bool isSectionText(DataRefImpl Sec) const override;
bool isSectionData(DataRefImpl Sec) const override;
bool isSectionBSS(DataRefImpl Sec) const override;
@@ -284,11 +294,9 @@ protected:
// A symbol is exported if its binding is either GLOBAL or WEAK, and its
// visibility is either DEFAULT or PROTECTED. All other symbols are not
// exported.
- if ((Binding == ELF::STB_GLOBAL || Binding == ELF::STB_WEAK) &&
- (Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_PROTECTED))
- return true;
-
- return false;
+ return ((Binding == ELF::STB_GLOBAL || Binding == ELF::STB_WEAK) &&
+ (Visibility == ELF::STV_DEFAULT ||
+ Visibility == ELF::STV_PROTECTED));
}
// This flag is used for classof, to distinguish ELFObjectFile from
@@ -354,7 +362,7 @@ void ELFObjectFile<ELFT>::moveSymbolNext(DataRefImpl &Sym) const {
}
template <class ELFT>
-ErrorOr<StringRef> ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Sym) const {
+Expected<StringRef> ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Sym) const {
const Elf_Sym *ESym = getSymbol(Sym);
const Elf_Shdr *SymTableSec = *EF.getSection(Sym.d.a);
const Elf_Shdr *StringTableSec = *EF.getSection(SymTableSec->sh_link);
@@ -389,7 +397,7 @@ uint64_t ELFObjectFile<ELFT>::getSymbolValueImpl(DataRefImpl Symb) const {
}
template <class ELFT>
-ErrorOr<uint64_t>
+Expected<uint64_t>
ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb) const {
uint64_t Result = getSymbolValue(Symb);
const Elf_Sym *ESym = getSymbol(Symb);
@@ -407,7 +415,7 @@ ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb) const {
ErrorOr<const Elf_Shdr *> SectionOrErr =
EF.getSection(ESym, SymTab, ShndxTable);
if (std::error_code EC = SectionOrErr.getError())
- return EC;
+ return errorCodeToError(EC);
const Elf_Shdr *Section = *SectionOrErr;
if (Section)
Result += Section->sh_addr;
@@ -425,6 +433,11 @@ uint32_t ELFObjectFile<ELFT>::getSymbolAlignment(DataRefImpl Symb) const {
}
template <class ELFT>
+uint16_t ELFObjectFile<ELFT>::getEMachine() const {
+ return EF.getHeader()->e_machine;
+}
+
+template <class ELFT>
uint64_t ELFObjectFile<ELFT>::getSymbolSize(DataRefImpl Sym) const {
return getSymbol(Sym)->st_size;
}
@@ -445,7 +458,8 @@ uint8_t ELFObjectFile<ELFT>::getSymbolELFType(DataRefImpl Symb) const {
}
template <class ELFT>
-SymbolRef::Type ELFObjectFile<ELFT>::getSymbolType(DataRefImpl Symb) const {
+Expected<SymbolRef::Type>
+ELFObjectFile<ELFT>::getSymbolType(DataRefImpl Symb) const {
const Elf_Sym *ESym = getSymbol(Symb);
switch (ESym->getType()) {
@@ -487,12 +501,17 @@ uint32_t ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Sym) const {
Result |= SymbolRef::SF_FormatSpecific;
if (EF.getHeader()->e_machine == ELF::EM_ARM) {
- if (ErrorOr<StringRef> NameOrErr = getSymbolName(Sym)) {
+ if (Expected<StringRef> NameOrErr = getSymbolName(Sym)) {
StringRef Name = *NameOrErr;
if (Name.startswith("$d") || Name.startswith("$t") ||
Name.startswith("$a"))
Result |= SymbolRef::SF_FormatSpecific;
+ } else {
+ // TODO: Actually report errors helpfully.
+ consumeError(NameOrErr.takeError());
}
+ if (ESym->getType() == ELF::STT_FUNC && (ESym->st_value & 1) == 1)
+ Result |= SymbolRef::SF_Thumb;
}
if (ESym->st_shndx == ELF::SHN_UNDEF)
@@ -511,12 +530,12 @@ uint32_t ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Sym) const {
}
template <class ELFT>
-ErrorOr<section_iterator>
+Expected<section_iterator>
ELFObjectFile<ELFT>::getSymbolSection(const Elf_Sym *ESym,
const Elf_Shdr *SymTab) const {
ErrorOr<const Elf_Shdr *> ESecOrErr = EF.getSection(ESym, SymTab, ShndxTable);
if (std::error_code EC = ESecOrErr.getError())
- return EC;
+ return errorCodeToError(EC);
const Elf_Shdr *ESec = *ESecOrErr;
if (!ESec)
@@ -528,7 +547,7 @@ ELFObjectFile<ELFT>::getSymbolSection(const Elf_Sym *ESym,
}
template <class ELFT>
-ErrorOr<section_iterator>
+Expected<section_iterator>
ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb) const {
const Elf_Sym *Sym = getSymbol(Symb);
const Elf_Shdr *SymTab = *EF.getSection(Symb.d.a);
@@ -576,6 +595,11 @@ uint64_t ELFObjectFile<ELFT>::getSectionAlignment(DataRefImpl Sec) const {
}
template <class ELFT>
+bool ELFObjectFile<ELFT>::isSectionCompressed(DataRefImpl Sec) const {
+ return getSection(Sec)->sh_flags & ELF::SHF_COMPRESSED;
+}
+
+template <class ELFT>
bool ELFObjectFile<ELFT>::isSectionText(DataRefImpl Sec) const {
return getSection(Sec)->sh_flags & ELF::SHF_EXECINSTR;
}
@@ -606,22 +630,6 @@ ELFObjectFile<ELFT>::section_rel_begin(DataRefImpl Sec) const {
uintptr_t SHT = reinterpret_cast<uintptr_t>(EF.section_begin());
RelData.d.a = (Sec.p - SHT) / EF.getHeader()->e_shentsize;
RelData.d.b = 0;
-
- const Elf_Shdr *S = reinterpret_cast<const Elf_Shdr *>(Sec.p);
- if (S->sh_type != ELF::SHT_RELA && S->sh_type != ELF::SHT_REL)
- return relocation_iterator(RelocationRef(RelData, this));
-
- const Elf_Shdr *RelSec = getRelSection(RelData);
- ErrorOr<const Elf_Shdr *> SymSecOrErr = EF.getSection(RelSec->sh_link);
- if (std::error_code EC = SymSecOrErr.getError())
- report_fatal_error(EC.message());
- const Elf_Shdr *SymSec = *SymSecOrErr;
- uint32_t SymSecType = SymSec->sh_type;
- if (SymSecType != ELF::SHT_SYMTAB && SymSecType != ELF::SHT_DYNSYM)
- report_fatal_error("Invalid symbol table section type!");
- if (SymSecType == ELF::SHT_DYNSYM)
- RelData.d.b = 1;
-
return relocation_iterator(RelocationRef(RelData, this));
}
@@ -633,7 +641,14 @@ ELFObjectFile<ELFT>::section_rel_end(DataRefImpl Sec) const {
if (S->sh_type != ELF::SHT_RELA && S->sh_type != ELF::SHT_REL)
return Begin;
DataRefImpl RelData = Begin->getRawDataRefImpl();
- RelData.d.b += (S->sh_size / S->sh_entsize) << 1;
+ const Elf_Shdr *RelSec = getRelSection(RelData);
+
+ // Error check sh_link here so that getRelocationSymbol can just use it.
+ ErrorOr<const Elf_Shdr *> SymSecOrErr = EF.getSection(RelSec->sh_link);
+ if (std::error_code EC = SymSecOrErr.getError())
+ report_fatal_error(EC.message());
+
+ RelData.d.b += S->sh_size / S->sh_entsize;
return relocation_iterator(RelocationRef(RelData, this));
}
@@ -657,7 +672,7 @@ ELFObjectFile<ELFT>::getRelocatedSection(DataRefImpl Sec) const {
// Relocations
template <class ELFT>
void ELFObjectFile<ELFT>::moveRelocationNext(DataRefImpl &Rel) const {
- Rel.d.b += 2;
+ ++Rel.d.b;
}
template <class ELFT>
@@ -672,12 +687,10 @@ ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const {
if (!symbolIdx)
return symbol_end();
- bool IsDyn = Rel.d.b & 1;
+ // FIXME: error check symbolIdx
DataRefImpl SymbolData;
- if (IsDyn)
- SymbolData = toDRI(DotDynSymSec, symbolIdx);
- else
- SymbolData = toDRI(DotSymtabSec, symbolIdx);
+ SymbolData.d.a = sec->sh_link;
+ SymbolData.d.b = symbolIdx;
return symbol_iterator(SymbolRef(SymbolData, this));
}
@@ -725,14 +738,14 @@ template <class ELFT>
const typename ELFObjectFile<ELFT>::Elf_Rel *
ELFObjectFile<ELFT>::getRel(DataRefImpl Rel) const {
assert(getRelSection(Rel)->sh_type == ELF::SHT_REL);
- return EF.template getEntry<Elf_Rel>(Rel.d.a, Rel.d.b >> 1);
+ return EF.template getEntry<Elf_Rel>(Rel.d.a, Rel.d.b);
}
template <class ELFT>
const typename ELFObjectFile<ELFT>::Elf_Rela *
ELFObjectFile<ELFT>::getRela(DataRefImpl Rela) const {
assert(getRelSection(Rela)->sh_type == ELF::SHT_RELA);
- return EF.template getEntry<Elf_Rela>(Rela.d.a, Rela.d.b >> 1);
+ return EF.template getEntry<Elf_Rela>(Rela.d.a, Rela.d.b);
}
template <class ELFT>
@@ -835,6 +848,8 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const {
return "ELF32-avr";
case ELF::EM_HEXAGON:
return "ELF32-hexagon";
+ case ELF::EM_LANAI:
+ return "ELF32-lanai";
case ELF::EM_MIPS:
return "ELF32-mips";
case ELF::EM_PPC:
@@ -844,6 +859,8 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const {
return "ELF32-sparc";
case ELF::EM_WEBASSEMBLY:
return "ELF32-wasm";
+ case ELF::EM_AMDGPU:
+ return "ELF32-amdgpu";
default:
return "ELF32-unknown";
}
@@ -865,6 +882,12 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const {
return "ELF64-mips";
case ELF::EM_WEBASSEMBLY:
return "ELF64-wasm";
+ case ELF::EM_AMDGPU:
+ return (EF.getHeader()->e_ident[ELF::EI_OSABI] == ELF::ELFOSABI_AMDGPU_HSA
+ && IsLittleEndian) ?
+ "ELF64-amdgpu-hsacobj" : "ELF64-amdgpu";
+ case ELF::EM_BPF:
+ return "ELF64-BPF";
default:
return "ELF64-unknown";
}
@@ -891,6 +914,8 @@ unsigned ELFObjectFile<ELFT>::getArch() const {
return Triple::avr;
case ELF::EM_HEXAGON:
return Triple::hexagon;
+ case ELF::EM_LANAI:
+ return Triple::lanai;
case ELF::EM_MIPS:
switch (EF.getHeader()->e_ident[ELF::EI_CLASS]) {
case ELF::ELFCLASS32:
@@ -919,6 +944,15 @@ unsigned ELFObjectFile<ELFT>::getArch() const {
default: return Triple::UnknownArch;
}
+ case ELF::EM_AMDGPU:
+ return (EF.getHeader()->e_ident[ELF::EI_CLASS] == ELF::ELFCLASS64
+ && EF.getHeader()->e_ident[ELF::EI_OSABI] == ELF::ELFOSABI_AMDGPU_HSA
+ && IsLittleEndian) ?
+ Triple::amdgcn : Triple::UnknownArch;
+
+ case ELF::EM_BPF:
+ return IsLittleEndian ? Triple::bpfel : Triple::bpfeb;
+
default:
return Triple::UnknownArch;
}
@@ -934,7 +968,7 @@ template <class ELFT> bool ELFObjectFile<ELFT>::isRelocatableObject() const {
return EF.getHeader()->e_type == ELF::ET_REL;
}
-}
-}
+} // end namespace object
+} // end namespace llvm
-#endif
+#endif // LLVM_OBJECT_ELFOBJECTFILE_H
diff --git a/include/llvm/Object/ELFTypes.h b/include/llvm/Object/ELFTypes.h
index 07b312a7d77c..55028f360dbf 100644
--- a/include/llvm/Object/ELFTypes.h
+++ b/include/llvm/Object/ELFTypes.h
@@ -21,9 +21,60 @@ namespace object {
using support::endianness;
-template <endianness target_endianness, bool is64Bits> struct ELFType {
- static const endianness TargetEndianness = target_endianness;
- static const bool Is64Bits = is64Bits;
+template <class ELFT> struct Elf_Ehdr_Impl;
+template <class ELFT> struct Elf_Shdr_Impl;
+template <class ELFT> struct Elf_Sym_Impl;
+template <class ELFT> struct Elf_Dyn_Impl;
+template <class ELFT> struct Elf_Phdr_Impl;
+template <class ELFT, bool isRela> struct Elf_Rel_Impl;
+template <class ELFT> struct Elf_Verdef_Impl;
+template <class ELFT> struct Elf_Verdaux_Impl;
+template <class ELFT> struct Elf_Verneed_Impl;
+template <class ELFT> struct Elf_Vernaux_Impl;
+template <class ELFT> struct Elf_Versym_Impl;
+template <class ELFT> struct Elf_Hash_Impl;
+template <class ELFT> struct Elf_GnuHash_Impl;
+template <class ELFT> struct Elf_Chdr_Impl;
+
+template <endianness E, bool Is64> struct ELFType {
+private:
+ template <typename Ty>
+ using packed = support::detail::packed_endian_specific_integral<Ty, E, 2>;
+
+public:
+ static const endianness TargetEndianness = E;
+ static const bool Is64Bits = Is64;
+
+ typedef typename std::conditional<Is64, uint64_t, uint32_t>::type uint;
+ typedef Elf_Ehdr_Impl<ELFType<E, Is64>> Ehdr;
+ typedef Elf_Shdr_Impl<ELFType<E, Is64>> Shdr;
+ typedef Elf_Sym_Impl<ELFType<E, Is64>> Sym;
+ typedef Elf_Dyn_Impl<ELFType<E, Is64>> Dyn;
+ typedef Elf_Phdr_Impl<ELFType<E, Is64>> Phdr;
+ typedef Elf_Rel_Impl<ELFType<E, Is64>, false> Rel;
+ typedef Elf_Rel_Impl<ELFType<E, Is64>, true> Rela;
+ typedef Elf_Verdef_Impl<ELFType<E, Is64>> Verdef;
+ typedef Elf_Verdaux_Impl<ELFType<E, Is64>> Verdaux;
+ typedef Elf_Verneed_Impl<ELFType<E, Is64>> Verneed;
+ typedef Elf_Vernaux_Impl<ELFType<E, Is64>> Vernaux;
+ typedef Elf_Versym_Impl<ELFType<E, Is64>> Versym;
+ typedef Elf_Hash_Impl<ELFType<E, Is64>> Hash;
+ typedef Elf_GnuHash_Impl<ELFType<E, Is64>> GnuHash;
+ typedef Elf_Chdr_Impl<ELFType<E, Is64>> Chdr;
+ typedef ArrayRef<Dyn> DynRange;
+ typedef ArrayRef<Shdr> ShdrRange;
+ typedef ArrayRef<Sym> SymRange;
+ typedef ArrayRef<Rel> RelRange;
+ typedef ArrayRef<Rela> RelaRange;
+ typedef ArrayRef<Phdr> PhdrRange;
+
+ typedef packed<uint16_t> Half;
+ typedef packed<uint32_t> Word;
+ typedef packed<int32_t> Sword;
+ typedef packed<uint64_t> Xword;
+ typedef packed<int64_t> Sxword;
+ typedef packed<uint> Addr;
+ typedef packed<uint> Off;
};
typedef ELFType<support::little, false> ELF32LE;
@@ -208,14 +259,14 @@ struct Elf_Sym_Impl : Elf_Sym_Base<ELFT> {
return getBinding() != ELF::STB_LOCAL;
}
- ErrorOr<StringRef> getName(StringRef StrTab) const;
+ Expected<StringRef> getName(StringRef StrTab) const;
};
template <class ELFT>
-ErrorOr<StringRef> Elf_Sym_Impl<ELFT>::getName(StringRef StrTab) const {
+Expected<StringRef> Elf_Sym_Impl<ELFT>::getName(StringRef StrTab) const {
uint32_t Offset = this->st_name;
if (Offset >= StrTab.size())
- return object_error::parse_failed;
+ return errorCodeToError(object_error::parse_failed);
return StringRef(StrTab.data() + Offset);
}
@@ -320,12 +371,10 @@ struct Elf_Dyn_Impl : Elf_Dyn_Base<ELFT> {
uintX_t getPtr() const { return d_un.d_ptr; }
};
-// Elf_Rel: Elf Relocation
-template <class ELFT, bool isRela> struct Elf_Rel_Impl;
-
template <endianness TargetEndianness>
struct Elf_Rel_Impl<ELFType<TargetEndianness, false>, false> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
+ static const bool IsRela = false;
Elf_Addr r_offset; // Location (file byte offset, or program virtual addr)
Elf_Word r_info; // Symbol table index and type of relocation to apply
@@ -361,12 +410,14 @@ template <endianness TargetEndianness>
struct Elf_Rel_Impl<ELFType<TargetEndianness, false>, true>
: public Elf_Rel_Impl<ELFType<TargetEndianness, false>, false> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
+ static const bool IsRela = true;
Elf_Sword r_addend; // Compute value for relocatable field by adding this
};
template <endianness TargetEndianness>
struct Elf_Rel_Impl<ELFType<TargetEndianness, true>, false> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
+ static const bool IsRela = false;
Elf_Addr r_offset; // Location (file byte offset, or program virtual addr)
Elf_Xword r_info; // Symbol table index and type of relocation to apply
@@ -411,6 +462,7 @@ template <endianness TargetEndianness>
struct Elf_Rel_Impl<ELFType<TargetEndianness, true>, true>
: public Elf_Rel_Impl<ELFType<TargetEndianness, true>, false> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
+ static const bool IsRela = true;
Elf_Sxword r_addend; // Compute value for relocatable field by adding this.
};
@@ -508,6 +560,25 @@ struct Elf_GnuHash_Impl {
}
};
+// Compressed section headers.
+// http://www.sco.com/developers/gabi/latest/ch4.sheader.html#compression_header
+template <endianness TargetEndianness>
+struct Elf_Chdr_Impl<ELFType<TargetEndianness, false>> {
+ LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
+ Elf_Word ch_type;
+ Elf_Word ch_size;
+ Elf_Word ch_addralign;
+};
+
+template <endianness TargetEndianness>
+struct Elf_Chdr_Impl<ELFType<TargetEndianness, true>> {
+ LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
+ Elf_Word ch_type;
+ Elf_Word ch_reserved;
+ Elf_Xword ch_size;
+ Elf_Xword ch_addralign;
+};
+
// MIPS .reginfo section
template <class ELFT>
struct Elf_Mips_RegInfo;
diff --git a/include/llvm/Object/Error.h b/include/llvm/Object/Error.h
index 0f79a6ed0dd8..cd55e5dc26d7 100644
--- a/include/llvm/Object/Error.h
+++ b/include/llvm/Object/Error.h
@@ -14,11 +14,15 @@
#ifndef LLVM_OBJECT_ERROR_H
#define LLVM_OBJECT_ERROR_H
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Error.h"
#include <system_error>
namespace llvm {
namespace object {
+class Binary;
+
const std::error_category &object_category();
enum class object_error {
@@ -30,16 +34,51 @@ enum class object_error {
string_table_non_null_end,
invalid_section_index,
bitcode_section_not_found,
- elf_invalid_dynamic_table_size,
- macho_small_load_command,
- macho_load_segment_too_many_sections,
- macho_load_segment_too_small,
};
inline std::error_code make_error_code(object_error e) {
return std::error_code(static_cast<int>(e), object_category());
}
+/// Base class for all errors indicating malformed binary files.
+///
+/// Having a subclass for all malformed binary files allows archive-walking
+/// code to skip malformed files without having to understand every possible
+/// way that a binary file might be malformed.
+///
+/// Currently inherits from ECError for easy interoperability with
+/// std::error_code, but this will be removed in the future.
+class BinaryError : public ErrorInfo<BinaryError, ECError> {
+public:
+ static char ID;
+ BinaryError() {
+ // Default to parse_failed, can be overridden with setErrorCode.
+ setErrorCode(make_error_code(object_error::parse_failed));
+ }
+};
+
+/// Generic binary error.
+///
+/// For errors that don't require their own specific sub-error (most errors)
+/// this class can be used to describe the error via a string message.
+class GenericBinaryError : public ErrorInfo<GenericBinaryError, BinaryError> {
+public:
+ static char ID;
+ GenericBinaryError(Twine Msg);
+ GenericBinaryError(Twine Msg, object_error ECOverride);
+ const std::string &getMessage() const { return Msg; }
+ void log(raw_ostream &OS) const override;
+private:
+ std::string Msg;
+};
+
+/// isNotObjectErrorInvalidFileType() is used when looping through the children
+/// of an archive after calling getAsBinary() on the child and it returns an
+/// llvm::Error. In the cases we want to loop through the children and ignore the
+/// non-objects in the archive this is used to test the error to see if an
+/// error() function needs to called on the llvm::Error.
+Error isNotObjectErrorInvalidFileType(llvm::Error Err);
+
} // end namespace object.
} // end namespace llvm.
diff --git a/include/llvm/Object/FunctionIndexObjectFile.h b/include/llvm/Object/FunctionIndexObjectFile.h
deleted file mode 100644
index 74b461dc7cc7..000000000000
--- a/include/llvm/Object/FunctionIndexObjectFile.h
+++ /dev/null
@@ -1,110 +0,0 @@
-//===- FunctionIndexObjectFile.h - Function index file implementation -----===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file declares the FunctionIndexObjectFile template class.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_OBJECT_FUNCTIONINDEXOBJECTFILE_H
-#define LLVM_OBJECT_FUNCTIONINDEXOBJECTFILE_H
-
-#include "llvm/IR/DiagnosticInfo.h"
-#include "llvm/Object/SymbolicFile.h"
-
-namespace llvm {
-class FunctionInfoIndex;
-class Module;
-
-namespace object {
-class ObjectFile;
-
-/// This class is used to read just the function summary index related
-/// sections out of the given object (which may contain a single module's
-/// bitcode or be a combined index bitcode file). It builds a FunctionInfoIndex
-/// object.
-class FunctionIndexObjectFile : public SymbolicFile {
- std::unique_ptr<FunctionInfoIndex> Index;
-
-public:
- FunctionIndexObjectFile(MemoryBufferRef Object,
- std::unique_ptr<FunctionInfoIndex> I);
- ~FunctionIndexObjectFile() override;
-
- // TODO: Walk through FunctionMap entries for function symbols.
- // However, currently these interfaces are not used by any consumers.
- void moveSymbolNext(DataRefImpl &Symb) const override {
- llvm_unreachable("not implemented");
- }
- std::error_code printSymbolName(raw_ostream &OS,
- DataRefImpl Symb) const override {
- llvm_unreachable("not implemented");
- return std::error_code();
- }
- uint32_t getSymbolFlags(DataRefImpl Symb) const override {
- llvm_unreachable("not implemented");
- return 0;
- }
- basic_symbol_iterator symbol_begin_impl() const override {
- llvm_unreachable("not implemented");
- return basic_symbol_iterator(BasicSymbolRef());
- }
- basic_symbol_iterator symbol_end_impl() const override {
- llvm_unreachable("not implemented");
- return basic_symbol_iterator(BasicSymbolRef());
- }
-
- const FunctionInfoIndex &getIndex() const {
- return const_cast<FunctionIndexObjectFile *>(this)->getIndex();
- }
- FunctionInfoIndex &getIndex() { return *Index; }
- std::unique_ptr<FunctionInfoIndex> takeIndex();
-
- static inline bool classof(const Binary *v) { return v->isFunctionIndex(); }
-
- /// \brief Finds and returns bitcode embedded in the given object file, or an
- /// error code if not found.
- static ErrorOr<MemoryBufferRef> findBitcodeInObject(const ObjectFile &Obj);
-
- /// \brief Finds and returns bitcode in the given memory buffer (which may
- /// be either a bitcode file or a native object file with embedded bitcode),
- /// or an error code if not found.
- static ErrorOr<MemoryBufferRef>
- findBitcodeInMemBuffer(MemoryBufferRef Object);
-
- /// \brief Looks for function summary in the given memory buffer,
- /// returns true if found, else false.
- static bool
- hasFunctionSummaryInMemBuffer(MemoryBufferRef Object,
- DiagnosticHandlerFunction DiagnosticHandler);
-
- /// \brief Parse function index in the given memory buffer.
- /// Return new FunctionIndexObjectFile instance containing parsed function
- /// summary/index.
- static ErrorOr<std::unique_ptr<FunctionIndexObjectFile>>
- create(MemoryBufferRef Object, DiagnosticHandlerFunction DiagnosticHandler,
- bool IsLazy = false);
-
- /// \brief Parse the function summary information for function with the
- /// given name out of the given buffer. Parsed information is
- /// stored on the index object saved in this object.
- std::error_code
- findFunctionSummaryInMemBuffer(MemoryBufferRef Object,
- DiagnosticHandlerFunction DiagnosticHandler,
- StringRef FunctionName);
-};
-}
-
-/// Parse the function index out of an IR file and return the function
-/// index object if found, or nullptr if not.
-ErrorOr<std::unique_ptr<FunctionInfoIndex>>
-getFunctionIndexForFile(StringRef Path,
- DiagnosticHandlerFunction DiagnosticHandler);
-}
-
-#endif
diff --git a/include/llvm/Object/IRObjectFile.h b/include/llvm/Object/IRObjectFile.h
index ef655287c34c..9fe011e17d62 100644
--- a/include/llvm/Object/IRObjectFile.h
+++ b/include/llvm/Object/IRObjectFile.h
@@ -20,6 +20,7 @@ namespace llvm {
class Mangler;
class Module;
class GlobalValue;
+class Triple;
namespace object {
class ObjectFile;
@@ -59,6 +60,15 @@ public:
/// error code if not found.
static ErrorOr<MemoryBufferRef> findBitcodeInObject(const ObjectFile &Obj);
+ /// Parse inline ASM and collect the symbols that are not defined in
+ /// the current module.
+ ///
+ /// For each found symbol, call \p AsmUndefinedRefs with the name of the
+ /// symbol found and the associated flags.
+ static void CollectAsmUndefinedRefs(
+ const Triple &TheTriple, StringRef InlineAsm,
+ function_ref<void(StringRef, BasicSymbolRef::Flags)> AsmUndefinedRefs);
+
/// \brief Finds and returns bitcode in the given memory buffer (which may
/// be either a bitcode file or a native object file with embedded bitcode),
/// or an error code if not found.
diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h
index e02ce3b21416..7906db1e8a77 100644
--- a/include/llvm/Object/MachO.h
+++ b/include/llvm/Object/MachO.h
@@ -193,24 +193,24 @@ public:
typedef SmallVector<LoadCommandInfo, 4> LoadCommandList;
typedef LoadCommandList::const_iterator load_command_iterator;
- MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits,
- std::error_code &EC);
+ static Expected<std::unique_ptr<MachOObjectFile>>
+ create(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits);
void moveSymbolNext(DataRefImpl &Symb) const override;
uint64_t getNValue(DataRefImpl Sym) const;
- ErrorOr<StringRef> getSymbolName(DataRefImpl Symb) const override;
+ Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
// MachO specific.
std::error_code getIndirectName(DataRefImpl Symb, StringRef &Res) const;
unsigned getSectionType(SectionRef Sec) const;
- ErrorOr<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
+ Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
- SymbolRef::Type getSymbolType(DataRefImpl Symb) const override;
+ Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
uint32_t getSymbolFlags(DataRefImpl Symb) const override;
- ErrorOr<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
+ Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
unsigned getSymbolSectionID(SymbolRef Symb) const;
unsigned getSectionID(SectionRef Sec) const;
@@ -222,10 +222,12 @@ public:
std::error_code getSectionContents(DataRefImpl Sec,
StringRef &Res) const override;
uint64_t getSectionAlignment(DataRefImpl Sec) const override;
+ bool isSectionCompressed(DataRefImpl Sec) const override;
bool isSectionText(DataRefImpl Sec) const override;
bool isSectionData(DataRefImpl Sec) const override;
bool isSectionBSS(DataRefImpl Sec) const override;
bool isSectionVirtual(DataRefImpl Sec) const override;
+ bool isSectionBitcode(DataRefImpl Sec) const override;
relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
relocation_iterator section_rel_end(DataRefImpl Sec) const override;
@@ -251,6 +253,7 @@ public:
// MachO specific.
basic_symbol_iterator getSymbolByIndex(unsigned Index) const;
+ uint64_t getSymbolIndex(DataRefImpl Symb) const;
section_iterator section_begin() const override;
section_iterator section_end() const override;
@@ -259,7 +262,8 @@ public:
StringRef getFileFormatName() const override;
unsigned getArch() const override;
- Triple getArch(const char **McpuDefault, Triple *ThumbTriple) const;
+ SubtargetFeatures getFeatures() const override { return SubtargetFeatures(); }
+ Triple getArchTriple(const char **McpuDefault = nullptr) const;
relocation_iterator section_rel_begin(unsigned Index) const;
relocation_iterator section_rel_end(unsigned Index) const;
@@ -405,12 +409,8 @@ public:
StringRef &Suffix);
static Triple::ArchType getArch(uint32_t CPUType);
- static Triple getArch(uint32_t CPUType, uint32_t CPUSubType,
- const char **McpuDefault = nullptr);
- static Triple getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
- const char **McpuDefault = nullptr);
- static Triple getArch(uint32_t CPUType, uint32_t CPUSubType,
- const char **McpuDefault, Triple *ThumbTriple);
+ static Triple getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
+ const char **McpuDefault = nullptr);
static bool isValidArch(StringRef ArchFlag);
static Triple getHostArch();
@@ -441,6 +441,10 @@ public:
}
private:
+
+ MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits,
+ Error &Err);
+
uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
union {
diff --git a/include/llvm/Object/MachOUniversal.h b/include/llvm/Object/MachOUniversal.h
index a11d381a700a..7eb2af944f3d 100644
--- a/include/llvm/Object/MachOUniversal.h
+++ b/include/llvm/Object/MachOUniversal.h
@@ -14,21 +14,22 @@
#ifndef LLVM_OBJECT_MACHOUNIVERSAL_H
#define LLVM_OBJECT_MACHOUNIVERSAL_H
-#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/MachO.h"
-#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/MachO.h"
namespace llvm {
+class StringRef;
+
namespace object {
class MachOUniversalBinary : public Binary {
virtual void anchor();
+ uint32_t Magic;
uint32_t NumberOfObjects;
public:
class ObjectForArch {
@@ -37,6 +38,7 @@ public:
uint32_t Index;
/// \brief Descriptor of the object.
MachO::fat_arch Header;
+ MachO::fat_arch_64 Header64;
public:
ObjectForArch(const MachOUniversalBinary *Parent, uint32_t Index);
@@ -51,19 +53,58 @@ public:
}
ObjectForArch getNext() const { return ObjectForArch(Parent, Index + 1); }
- uint32_t getCPUType() const { return Header.cputype; }
- uint32_t getCPUSubType() const { return Header.cpusubtype; }
- uint32_t getOffset() const { return Header.offset; }
- uint32_t getSize() const { return Header.size; }
- uint32_t getAlign() const { return Header.align; }
+ uint32_t getCPUType() const {
+ if (Parent->getMagic() == MachO::FAT_MAGIC)
+ return Header.cputype;
+ else // Parent->getMagic() == MachO::FAT_MAGIC_64
+ return Header64.cputype;
+ }
+ uint32_t getCPUSubType() const {
+ if (Parent->getMagic() == MachO::FAT_MAGIC)
+ return Header.cpusubtype;
+ else // Parent->getMagic() == MachO::FAT_MAGIC_64
+ return Header64.cpusubtype;
+ }
+ uint32_t getOffset() const {
+ if (Parent->getMagic() == MachO::FAT_MAGIC)
+ return Header.offset;
+ else // Parent->getMagic() == MachO::FAT_MAGIC_64
+ return Header64.offset;
+ }
+ uint32_t getSize() const {
+ if (Parent->getMagic() == MachO::FAT_MAGIC)
+ return Header.size;
+ else // Parent->getMagic() == MachO::FAT_MAGIC_64
+ return Header64.size;
+ }
+ uint32_t getAlign() const {
+ if (Parent->getMagic() == MachO::FAT_MAGIC)
+ return Header.align;
+ else // Parent->getMagic() == MachO::FAT_MAGIC_64
+ return Header64.align;
+ }
+ uint32_t getReserved() const {
+ if (Parent->getMagic() == MachO::FAT_MAGIC)
+ return 0;
+ else // Parent->getMagic() == MachO::FAT_MAGIC_64
+ return Header64.reserved;
+ }
std::string getArchTypeName() const {
- Triple T = MachOObjectFile::getArch(Header.cputype, Header.cpusubtype);
- return T.getArchName();
+ if (Parent->getMagic() == MachO::FAT_MAGIC) {
+ Triple T =
+ MachOObjectFile::getArchTriple(Header.cputype, Header.cpusubtype);
+ return T.getArchName();
+ } else { // Parent->getMagic() == MachO::FAT_MAGIC_64
+ Triple T =
+ MachOObjectFile::getArchTriple(Header64.cputype,
+ Header64.cpusubtype);
+ return T.getArchName();
+ }
}
- ErrorOr<std::unique_ptr<MachOObjectFile>> getAsObjectFile() const;
+ Expected<std::unique_ptr<MachOObjectFile>> getAsObjectFile() const;
- ErrorOr<std::unique_ptr<Archive>> getAsArchive() const;
+ Expected<std::unique_ptr<Archive>> getAsArchive() const;
};
class object_iterator {
@@ -86,8 +127,8 @@ public:
}
};
- MachOUniversalBinary(MemoryBufferRef Souce, std::error_code &EC);
- static ErrorOr<std::unique_ptr<MachOUniversalBinary>>
+ MachOUniversalBinary(MemoryBufferRef Souce, Error &Err);
+ static Expected<std::unique_ptr<MachOUniversalBinary>>
create(MemoryBufferRef Source);
object_iterator begin_objects() const {
@@ -101,6 +142,7 @@ public:
return make_range(begin_objects(), end_objects());
}
+ uint32_t getMagic() const { return Magic; }
uint32_t getNumberOfObjects() const { return NumberOfObjects; }
// Cast methods.
@@ -108,7 +150,7 @@ public:
return V->isMachOUniversalBinary();
}
- ErrorOr<std::unique_ptr<MachOObjectFile>>
+ Expected<std::unique_ptr<MachOObjectFile>>
getObjectForArch(StringRef ArchName) const;
};
diff --git a/include/llvm/Object/ModuleSummaryIndexObjectFile.h b/include/llvm/Object/ModuleSummaryIndexObjectFile.h
new file mode 100644
index 000000000000..d021fb29427f
--- /dev/null
+++ b/include/llvm/Object/ModuleSummaryIndexObjectFile.h
@@ -0,0 +1,103 @@
+//===- ModuleSummaryIndexObjectFile.h - Summary index file implementation -=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the ModuleSummaryIndexObjectFile template class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECT_MODULESUMMARYINDEXOBJECTFILE_H
+#define LLVM_OBJECT_MODULESUMMARYINDEXOBJECTFILE_H
+
+#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/Object/SymbolicFile.h"
+
+namespace llvm {
+class ModuleSummaryIndex;
+class Module;
+
+namespace object {
+class ObjectFile;
+
+/// This class is used to read just the module summary index related
+/// sections out of the given object (which may contain a single module's
+/// bitcode or be a combined index bitcode file). It builds a ModuleSummaryIndex
+/// object.
+class ModuleSummaryIndexObjectFile : public SymbolicFile {
+ std::unique_ptr<ModuleSummaryIndex> Index;
+
+public:
+ ModuleSummaryIndexObjectFile(MemoryBufferRef Object,
+ std::unique_ptr<ModuleSummaryIndex> I);
+ ~ModuleSummaryIndexObjectFile() override;
+
+ // TODO: Walk through GlobalValueMap entries for symbols.
+ // However, currently these interfaces are not used by any consumers.
+ void moveSymbolNext(DataRefImpl &Symb) const override {
+ llvm_unreachable("not implemented");
+ }
+ std::error_code printSymbolName(raw_ostream &OS,
+ DataRefImpl Symb) const override {
+ llvm_unreachable("not implemented");
+ return std::error_code();
+ }
+ uint32_t getSymbolFlags(DataRefImpl Symb) const override {
+ llvm_unreachable("not implemented");
+ return 0;
+ }
+ basic_symbol_iterator symbol_begin_impl() const override {
+ llvm_unreachable("not implemented");
+ return basic_symbol_iterator(BasicSymbolRef());
+ }
+ basic_symbol_iterator symbol_end_impl() const override {
+ llvm_unreachable("not implemented");
+ return basic_symbol_iterator(BasicSymbolRef());
+ }
+
+ const ModuleSummaryIndex &getIndex() const {
+ return const_cast<ModuleSummaryIndexObjectFile *>(this)->getIndex();
+ }
+ ModuleSummaryIndex &getIndex() { return *Index; }
+ std::unique_ptr<ModuleSummaryIndex> takeIndex();
+
+ static inline bool classof(const Binary *v) {
+ return v->isModuleSummaryIndex();
+ }
+
+ /// \brief Finds and returns bitcode embedded in the given object file, or an
+ /// error code if not found.
+ static ErrorOr<MemoryBufferRef> findBitcodeInObject(const ObjectFile &Obj);
+
+ /// \brief Finds and returns bitcode in the given memory buffer (which may
+ /// be either a bitcode file or a native object file with embedded bitcode),
+ /// or an error code if not found.
+ static ErrorOr<MemoryBufferRef>
+ findBitcodeInMemBuffer(MemoryBufferRef Object);
+
+ /// \brief Looks for summary sections in the given memory buffer,
+ /// returns true if found, else false.
+ static bool hasGlobalValueSummaryInMemBuffer(
+ MemoryBufferRef Object,
+ const DiagnosticHandlerFunction &DiagnosticHandler);
+
+ /// \brief Parse module summary index in the given memory buffer.
+ /// Return new ModuleSummaryIndexObjectFile instance containing parsed module
+ /// summary/index.
+ static ErrorOr<std::unique_ptr<ModuleSummaryIndexObjectFile>>
+ create(MemoryBufferRef Object,
+ const DiagnosticHandlerFunction &DiagnosticHandler);
+};
+}
+
+/// Parse the module summary index out of an IR file and return the module
+/// summary index object if found, or nullptr if not.
+ErrorOr<std::unique_ptr<ModuleSummaryIndex>> getModuleSummaryIndexForFile(
+ StringRef Path, const DiagnosticHandlerFunction &DiagnosticHandler);
+}
+
+#endif
diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h
index ce0c891ee0c2..6272a5f056eb 100644
--- a/include/llvm/Object/ObjectFile.h
+++ b/include/llvm/Object/ObjectFile.h
@@ -15,13 +15,13 @@
#define LLVM_OBJECT_OBJECTFILE_H
#include "llvm/ADT/StringRef.h"
+#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Object/SymbolicFile.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include <cstring>
-#include <vector>
namespace llvm {
namespace object {
@@ -90,10 +90,12 @@ public:
/// @brief Get the alignment of this section as the actual value (not log 2).
uint64_t getAlignment() const;
+ bool isCompressed() const;
bool isText() const;
bool isData() const;
bool isBSS() const;
bool isVirtual() const;
+ bool isBitcode() const;
bool containsSymbol(SymbolRef S) const;
@@ -130,10 +132,10 @@ public:
assert(isa<ObjectFile>(BasicSymbolRef::getObject()));
}
- ErrorOr<StringRef> getName() const;
+ Expected<StringRef> getName() const;
/// Returns the symbol virtual address (i.e. address at which it will be
/// mapped).
- ErrorOr<uint64_t> getAddress() const;
+ Expected<uint64_t> getAddress() const;
/// Return the value of the symbol depending on the object this can be an
/// offset or a virtual address.
@@ -142,11 +144,11 @@ public:
/// @brief Get the alignment of this symbol as the actual value (not log 2).
uint32_t getAlignment() const;
uint64_t getCommonSize() const;
- SymbolRef::Type getType() const;
+ Expected<SymbolRef::Type> getType() const;
/// @brief Get section this symbol is defined in reference to. Result is
/// end_sections() if it is undefined or is an absolute symbol.
- ErrorOr<section_iterator> getSection() const;
+ Expected<section_iterator> getSection() const;
const ObjectFile *getObject() const;
};
@@ -193,15 +195,15 @@ protected:
// Implementations assume that the DataRefImpl is valid and has not been
// modified externally. It's UB otherwise.
friend class SymbolRef;
- virtual ErrorOr<StringRef> getSymbolName(DataRefImpl Symb) const = 0;
+ virtual Expected<StringRef> getSymbolName(DataRefImpl Symb) const = 0;
std::error_code printSymbolName(raw_ostream &OS,
DataRefImpl Symb) const override;
- virtual ErrorOr<uint64_t> getSymbolAddress(DataRefImpl Symb) const = 0;
+ virtual Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const = 0;
virtual uint64_t getSymbolValueImpl(DataRefImpl Symb) const = 0;
virtual uint32_t getSymbolAlignment(DataRefImpl Symb) const;
virtual uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const = 0;
- virtual SymbolRef::Type getSymbolType(DataRefImpl Symb) const = 0;
- virtual ErrorOr<section_iterator>
+ virtual Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const = 0;
+ virtual Expected<section_iterator>
getSymbolSection(DataRefImpl Symb) const = 0;
// Same as above for SectionRef.
@@ -214,11 +216,13 @@ protected:
virtual std::error_code getSectionContents(DataRefImpl Sec,
StringRef &Res) const = 0;
virtual uint64_t getSectionAlignment(DataRefImpl Sec) const = 0;
+ virtual bool isSectionCompressed(DataRefImpl Sec) const = 0;
virtual bool isSectionText(DataRefImpl Sec) const = 0;
virtual bool isSectionData(DataRefImpl Sec) const = 0;
virtual bool isSectionBSS(DataRefImpl Sec) const = 0;
// A section is 'virtual' if its contents aren't present in the object image.
virtual bool isSectionVirtual(DataRefImpl Sec) const = 0;
+ virtual bool isSectionBitcode(DataRefImpl Sec) const;
virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const = 0;
virtual relocation_iterator section_rel_end(DataRefImpl Sec) const = 0;
virtual section_iterator getRelocatedSection(DataRefImpl Sec) const;
@@ -259,6 +263,7 @@ public:
virtual StringRef getFileFormatName() const = 0;
virtual /* Triple::ArchType */ unsigned getArch() const = 0;
+ virtual SubtargetFeatures getFeatures() const = 0;
/// Returns platform-specific object flags, if any.
virtual std::error_code getPlatformFlags(unsigned &Result) const {
@@ -273,12 +278,12 @@ public:
/// @param ObjectPath The path to the object file. ObjectPath.isObject must
/// return true.
/// @brief Create ObjectFile from path.
- static ErrorOr<OwningBinary<ObjectFile>>
+ static Expected<OwningBinary<ObjectFile>>
createObjectFile(StringRef ObjectPath);
- static ErrorOr<std::unique_ptr<ObjectFile>>
+ static Expected<std::unique_ptr<ObjectFile>>
createObjectFile(MemoryBufferRef Object, sys::fs::file_magic Type);
- static ErrorOr<std::unique_ptr<ObjectFile>>
+ static Expected<std::unique_ptr<ObjectFile>>
createObjectFile(MemoryBufferRef Object) {
return createObjectFile(Object, sys::fs::file_magic::unknown);
}
@@ -294,19 +299,20 @@ public:
static ErrorOr<std::unique_ptr<ObjectFile>>
createELFObjectFile(MemoryBufferRef Object);
- static ErrorOr<std::unique_ptr<MachOObjectFile>>
+ static Expected<std::unique_ptr<MachOObjectFile>>
createMachOObjectFile(MemoryBufferRef Object);
+
};
// Inline function definitions.
inline SymbolRef::SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner)
: BasicSymbolRef(SymbolP, Owner) {}
-inline ErrorOr<StringRef> SymbolRef::getName() const {
+inline Expected<StringRef> SymbolRef::getName() const {
return getObject()->getSymbolName(getRawDataRefImpl());
}
-inline ErrorOr<uint64_t> SymbolRef::getAddress() const {
+inline Expected<uint64_t> SymbolRef::getAddress() const {
return getObject()->getSymbolAddress(getRawDataRefImpl());
}
@@ -322,11 +328,11 @@ inline uint64_t SymbolRef::getCommonSize() const {
return getObject()->getCommonSymbolSize(getRawDataRefImpl());
}
-inline ErrorOr<section_iterator> SymbolRef::getSection() const {
+inline Expected<section_iterator> SymbolRef::getSection() const {
return getObject()->getSymbolSection(getRawDataRefImpl());
}
-inline SymbolRef::Type SymbolRef::getType() const {
+inline Expected<SymbolRef::Type> SymbolRef::getType() const {
return getObject()->getSymbolType(getRawDataRefImpl());
}
@@ -378,6 +384,10 @@ inline uint64_t SectionRef::getAlignment() const {
return OwningObject->getSectionAlignment(SectionPimpl);
}
+inline bool SectionRef::isCompressed() const {
+ return OwningObject->isSectionCompressed(SectionPimpl);
+}
+
inline bool SectionRef::isText() const {
return OwningObject->isSectionText(SectionPimpl);
}
@@ -394,6 +404,10 @@ inline bool SectionRef::isVirtual() const {
return OwningObject->isSectionVirtual(SectionPimpl);
}
+inline bool SectionRef::isBitcode() const {
+ return OwningObject->isSectionBitcode(SectionPimpl);
+}
+
inline relocation_iterator SectionRef::relocation_begin() const {
return OwningObject->section_rel_begin(SectionPimpl);
}
diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h
index d5e4258cb0a7..5e0df98d8627 100644
--- a/include/llvm/Object/RelocVisitor.h
+++ b/include/llvm/Object/RelocVisitor.h
@@ -16,7 +16,6 @@
#ifndef LLVM_OBJECT_RELOCVISITOR_H
#define LLVM_OBJECT_RELOCVISITOR_H
-#include "llvm/ADT/StringRef.h"
#include "llvm/Object/COFF.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/MachO.h"
@@ -175,6 +174,14 @@ private:
case llvm::ELF::R_ARM_ABS32:
return visitELF_ARM_ABS32(R, Value);
}
+ case Triple::lanai:
+ switch (RelocType) {
+ case llvm::ELF::R_LANAI_32:
+ return visitELF_Lanai_32(R, Value);
+ default:
+ HasError = true;
+ return RelocToApply();
+ }
case Triple::mipsel:
case Triple::mips:
switch (RelocType) {
@@ -311,6 +318,13 @@ private:
return RelocToApply(Res, 4);
}
+ /// Lanai ELF
+ RelocToApply visitELF_Lanai_32(RelocationRef R, uint64_t Value) {
+ int64_t Addend = getELFAddend(R);
+ uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
+ return RelocToApply(Res, 4);
+ }
+
/// MIPS ELF
RelocToApply visitELF_MIPS_32(RelocationRef R, uint64_t Value) {
uint32_t Res = Value & 0xFFFFFFFF;
diff --git a/include/llvm/Object/StackMapParser.h b/include/llvm/Object/StackMapParser.h
index 276eab6c294e..e58162de1501 100644
--- a/include/llvm/Object/StackMapParser.h
+++ b/include/llvm/Object/StackMapParser.h
@@ -10,9 +10,8 @@
#ifndef LLVM_CODEGEN_STACKMAPPARSER_H
#define LLVM_CODEGEN_STACKMAPPARSER_H
-#include "llvm/Support/Debug.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/Endian.h"
-#include <map>
#include <vector>
namespace llvm {
diff --git a/include/llvm/Object/SymbolicFile.h b/include/llvm/Object/SymbolicFile.h
index 0c5b38111a9c..894c2670f265 100644
--- a/include/llvm/Object/SymbolicFile.h
+++ b/include/llvm/Object/SymbolicFile.h
@@ -16,6 +16,7 @@
#include "llvm/Object/Binary.h"
#include "llvm/Support/Format.h"
+#include <utility>
namespace llvm {
namespace object {
@@ -58,7 +59,7 @@ class content_iterator
content_type Current;
public:
- content_iterator(content_type symb) : Current(symb) {}
+ content_iterator(content_type symb) : Current(std::move(symb)) {}
const content_type *operator->() const { return &Current; }
@@ -153,15 +154,15 @@ public:
}
// construction aux.
- static ErrorOr<std::unique_ptr<SymbolicFile>>
+ static Expected<std::unique_ptr<SymbolicFile>>
createSymbolicFile(MemoryBufferRef Object, sys::fs::file_magic Type,
LLVMContext *Context);
- static ErrorOr<std::unique_ptr<SymbolicFile>>
+ static Expected<std::unique_ptr<SymbolicFile>>
createSymbolicFile(MemoryBufferRef Object) {
return createSymbolicFile(Object, sys::fs::file_magic::unknown, nullptr);
}
- static ErrorOr<OwningBinary<SymbolicFile>>
+ static Expected<OwningBinary<SymbolicFile>>
createSymbolicFile(StringRef ObjectPath);
static inline bool classof(const Binary *v) {
diff --git a/include/llvm/Object/COFFYAML.h b/include/llvm/ObjectYAML/COFFYAML.h
index 12a25223bd37..65ad1dde67f5 100644
--- a/include/llvm/Object/COFFYAML.h
+++ b/include/llvm/ObjectYAML/COFFYAML.h
@@ -11,11 +11,11 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_OBJECT_COFFYAML_H
-#define LLVM_OBJECT_COFFYAML_H
+#ifndef LLVM_OBJECTYAML_COFFYAML_H
+#define LLVM_OBJECTYAML_COFFYAML_H
#include "llvm/ADT/Optional.h"
-#include "llvm/MC/YAML.h"
+#include "llvm/ObjectYAML/YAML.h"
#include "llvm/Support/COFF.h"
namespace llvm {
@@ -54,7 +54,7 @@ namespace COFFYAML {
struct Section {
COFF::section Header;
- unsigned Alignment;
+ unsigned Alignment = 0;
yaml::BinaryRef SectionData;
std::vector<Relocation> Relocations;
StringRef Name;
@@ -63,8 +63,8 @@ namespace COFFYAML {
struct Symbol {
COFF::symbol Header;
- COFF::SymbolBaseType SimpleType;
- COFF::SymbolComplexType ComplexType;
+ COFF::SymbolBaseType SimpleType = COFF::IMAGE_SYM_TYPE_NULL;
+ COFF::SymbolComplexType ComplexType = COFF::IMAGE_SYM_DTYPE_NULL;
Optional<COFF::AuxiliaryFunctionDefinition> FunctionDefinition;
Optional<COFF::AuxiliarybfAndefSymbol> bfAndefSymbol;
Optional<COFF::AuxiliaryWeakExternal> WeakExternal;
diff --git a/include/llvm/Object/ELFYAML.h b/include/llvm/ObjectYAML/ELFYAML.h
index df0aa500c8a2..81a4ec28c94f 100644
--- a/include/llvm/Object/ELFYAML.h
+++ b/include/llvm/ObjectYAML/ELFYAML.h
@@ -13,10 +13,10 @@
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_OBJECT_ELFYAML_H
-#define LLVM_OBJECT_ELFYAML_H
+#ifndef LLVM_OBJECTYAML_ELFYAML_H
+#define LLVM_OBJECTYAML_ELFYAML_H
-#include "llvm/MC/YAML.h"
+#include "llvm/ObjectYAML/YAML.h"
#include "llvm/Support/ELF.h"
namespace llvm {
diff --git a/include/llvm/ObjectYAML/MachOYAML.h b/include/llvm/ObjectYAML/MachOYAML.h
new file mode 100644
index 000000000000..bb15e64789d0
--- /dev/null
+++ b/include/llvm/ObjectYAML/MachOYAML.h
@@ -0,0 +1,296 @@
+//===- MachOYAML.h - Mach-O YAMLIO implementation ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file declares classes for handling the YAML representation
+/// of Mach-O.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECTYAML_MACHOYAML_H
+#define LLVM_OBJECTYAML_MACHOYAML_H
+
+#include "llvm/ObjectYAML/YAML.h"
+#include "llvm/Support/MachO.h"
+
+namespace llvm {
+namespace MachOYAML {
+
+struct Section {
+ char sectname[16];
+ char segname[16];
+ llvm::yaml::Hex64 addr;
+ uint64_t size;
+ llvm::yaml::Hex32 offset;
+ uint32_t align;
+ llvm::yaml::Hex32 reloff;
+ uint32_t nreloc;
+ llvm::yaml::Hex32 flags;
+ llvm::yaml::Hex32 reserved1;
+ llvm::yaml::Hex32 reserved2;
+ llvm::yaml::Hex32 reserved3;
+};
+
+struct FileHeader {
+ llvm::yaml::Hex32 magic;
+ llvm::yaml::Hex32 cputype;
+ llvm::yaml::Hex32 cpusubtype;
+ llvm::yaml::Hex32 filetype;
+ uint32_t ncmds;
+ uint32_t sizeofcmds;
+ llvm::yaml::Hex32 flags;
+ llvm::yaml::Hex32 reserved;
+};
+
+struct LoadCommand {
+ virtual ~LoadCommand();
+ llvm::MachO::macho_load_command Data;
+ std::vector<Section> Sections;
+ std::vector<llvm::yaml::Hex8> PayloadBytes;
+ std::string PayloadString;
+ uint64_t ZeroPadBytes;
+};
+
+struct NListEntry {
+ uint32_t n_strx;
+ uint8_t n_type;
+ uint8_t n_sect;
+ uint16_t n_desc;
+ uint64_t n_value;
+};
+struct RebaseOpcode {
+ MachO::RebaseOpcode Opcode;
+ uint8_t Imm;
+ std::vector<yaml::Hex64> ExtraData;
+};
+
+struct BindOpcode {
+ MachO::BindOpcode Opcode;
+ uint8_t Imm;
+ std::vector<yaml::Hex64> ULEBExtraData;
+ std::vector<int64_t> SLEBExtraData;
+ StringRef Symbol;
+};
+
+struct ExportEntry {
+ ExportEntry()
+ : TerminalSize(0), NodeOffset(0), Name(), Flags(0), Address(0), Other(0),
+ ImportName(), Children() {}
+ uint64_t TerminalSize;
+ uint64_t NodeOffset;
+ std::string Name;
+ llvm::yaml::Hex64 Flags;
+ llvm::yaml::Hex64 Address;
+ llvm::yaml::Hex64 Other;
+ std::string ImportName;
+ std::vector<MachOYAML::ExportEntry> Children;
+};
+
+struct LinkEditData {
+ std::vector<MachOYAML::RebaseOpcode> RebaseOpcodes;
+ std::vector<MachOYAML::BindOpcode> BindOpcodes;
+ std::vector<MachOYAML::BindOpcode> WeakBindOpcodes;
+ std::vector<MachOYAML::BindOpcode> LazyBindOpcodes;
+ MachOYAML::ExportEntry ExportTrie;
+ std::vector<NListEntry> NameList;
+ std::vector<StringRef> StringTable;
+};
+
+struct Object {
+ FileHeader Header;
+ std::vector<LoadCommand> LoadCommands;
+ std::vector<Section> Sections;
+ LinkEditData LinkEdit;
+};
+
+struct FatHeader {
+ llvm::yaml::Hex32 magic;
+ uint32_t nfat_arch;
+};
+
+struct FatArch {
+ llvm::yaml::Hex32 cputype;
+ llvm::yaml::Hex32 cpusubtype;
+ llvm::yaml::Hex64 offset;
+ uint64_t size;
+ uint32_t align;
+ llvm::yaml::Hex32 reserved;
+};
+
+struct UniversalBinary {
+ FatHeader Header;
+ std::vector<FatArch> FatArchs;
+ std::vector<Object> Slices;
+};
+
+} // namespace llvm::MachOYAML
+} // namespace llvm
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::LoadCommand)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::Section)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::Hex8)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::Hex64)
+LLVM_YAML_IS_SEQUENCE_VECTOR(int64_t)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::RebaseOpcode)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::BindOpcode)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::ExportEntry)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::NListEntry)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::StringRef)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::Object)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::FatArch)
+
+namespace llvm {
+namespace yaml {
+
+template <> struct MappingTraits<MachOYAML::FileHeader> {
+ static void mapping(IO &IO, MachOYAML::FileHeader &FileHeader);
+};
+
+template <> struct MappingTraits<MachOYAML::Object> {
+ static void mapping(IO &IO, MachOYAML::Object &Object);
+};
+
+template <> struct MappingTraits<MachOYAML::FatHeader> {
+ static void mapping(IO &IO, MachOYAML::FatHeader &FatHeader);
+};
+
+template <> struct MappingTraits<MachOYAML::FatArch> {
+ static void mapping(IO &IO, MachOYAML::FatArch &FatArch);
+};
+
+template <> struct MappingTraits<MachOYAML::UniversalBinary> {
+ static void mapping(IO &IO, MachOYAML::UniversalBinary &UniversalBinary);
+};
+
+template <> struct MappingTraits<MachOYAML::LoadCommand> {
+ static void mapping(IO &IO, MachOYAML::LoadCommand &LoadCommand);
+};
+
+template <> struct MappingTraits<MachOYAML::LinkEditData> {
+ static void mapping(IO &IO, MachOYAML::LinkEditData &LinkEditData);
+};
+
+template <> struct MappingTraits<MachOYAML::RebaseOpcode> {
+ static void mapping(IO &IO, MachOYAML::RebaseOpcode &RebaseOpcode);
+};
+
+template <> struct MappingTraits<MachOYAML::BindOpcode> {
+ static void mapping(IO &IO, MachOYAML::BindOpcode &BindOpcode);
+};
+
+template <> struct MappingTraits<MachOYAML::ExportEntry> {
+ static void mapping(IO &IO, MachOYAML::ExportEntry &ExportEntry);
+};
+
+template <> struct MappingTraits<MachOYAML::Section> {
+ static void mapping(IO &IO, MachOYAML::Section &Section);
+};
+
+template <> struct MappingTraits<MachOYAML::NListEntry> {
+ static void mapping(IO &IO, MachOYAML::NListEntry &NListEntry);
+};
+
+#define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \
+ io.enumCase(value, #LCName, MachO::LCName);
+
+template <> struct ScalarEnumerationTraits<MachO::LoadCommandType> {
+ static void enumeration(IO &io, MachO::LoadCommandType &value) {
+#include "llvm/Support/MachO.def"
+ io.enumFallback<Hex32>(value);
+ }
+};
+
+#define ENUM_CASE(Enum) io.enumCase(value, #Enum, MachO::Enum);
+
+template <> struct ScalarEnumerationTraits<MachO::RebaseOpcode> {
+ static void enumeration(IO &io, MachO::RebaseOpcode &value) {
+ ENUM_CASE(REBASE_OPCODE_DONE)
+ ENUM_CASE(REBASE_OPCODE_SET_TYPE_IMM)
+ ENUM_CASE(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB)
+ ENUM_CASE(REBASE_OPCODE_ADD_ADDR_ULEB)
+ ENUM_CASE(REBASE_OPCODE_ADD_ADDR_IMM_SCALED)
+ ENUM_CASE(REBASE_OPCODE_DO_REBASE_IMM_TIMES)
+ ENUM_CASE(REBASE_OPCODE_DO_REBASE_ULEB_TIMES)
+ ENUM_CASE(REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB)
+ ENUM_CASE(REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB)
+ io.enumFallback<Hex8>(value);
+ }
+};
+
+template <> struct ScalarEnumerationTraits<MachO::BindOpcode> {
+ static void enumeration(IO &io, MachO::BindOpcode &value) {
+ ENUM_CASE(BIND_OPCODE_DONE)
+ ENUM_CASE(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM)
+ ENUM_CASE(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB)
+ ENUM_CASE(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM)
+ ENUM_CASE(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM)
+ ENUM_CASE(BIND_OPCODE_SET_TYPE_IMM)
+ ENUM_CASE(BIND_OPCODE_SET_ADDEND_SLEB)
+ ENUM_CASE(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB)
+ ENUM_CASE(BIND_OPCODE_ADD_ADDR_ULEB)
+ ENUM_CASE(BIND_OPCODE_DO_BIND)
+ ENUM_CASE(BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB)
+ ENUM_CASE(BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED)
+ ENUM_CASE(BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB)
+ io.enumFallback<Hex8>(value);
+ }
+};
+
+// This trait is used for 16-byte chars in Mach structures used for strings
+typedef char char_16[16];
+
+template <> struct ScalarTraits<char_16> {
+ static void output(const char_16 &Val, void *, llvm::raw_ostream &Out);
+
+ static StringRef input(StringRef Scalar, void *, char_16 &Val);
+ static bool mustQuote(StringRef S);
+};
+
+// This trait is used for UUIDs. It reads and writes them matching otool's
+// formatting style.
+typedef uint8_t uuid_t[16];
+
+template <> struct ScalarTraits<uuid_t> {
+ static void output(const uuid_t &Val, void *, llvm::raw_ostream &Out);
+
+ static StringRef input(StringRef Scalar, void *, uuid_t &Val);
+ static bool mustQuote(StringRef S);
+};
+
+// Load Command struct mapping traits
+
+#define LOAD_COMMAND_STRUCT(LCStruct) \
+ template <> struct MappingTraits<MachO::LCStruct> { \
+ static void mapping(IO &IO, MachO::LCStruct &LoadCommand); \
+ };
+
+#include "llvm/Support/MachO.def"
+
+// Extra structures used by load commands
+template <> struct MappingTraits<MachO::dylib> {
+ static void mapping(IO &IO, MachO::dylib &LoadCommand);
+};
+
+template <> struct MappingTraits<MachO::fvmlib> {
+ static void mapping(IO &IO, MachO::fvmlib &LoadCommand);
+};
+
+template <> struct MappingTraits<MachO::section> {
+ static void mapping(IO &IO, MachO::section &LoadCommand);
+};
+
+template <> struct MappingTraits<MachO::section_64> {
+ static void mapping(IO &IO, MachO::section_64 &LoadCommand);
+};
+
+} // namespace llvm::yaml
+
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/ObjectYAML/ObjectYAML.h b/include/llvm/ObjectYAML/ObjectYAML.h
new file mode 100644
index 000000000000..1d6462347770
--- /dev/null
+++ b/include/llvm/ObjectYAML/ObjectYAML.h
@@ -0,0 +1,35 @@
+//===- ObjectYAML.h ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECTYAML_OBJECTYAML_H
+#define LLVM_OBJECTYAML_OBJECTYAML_H
+
+#include "llvm/Support/YAMLTraits.h"
+#include "llvm/ObjectYAML/ELFYAML.h"
+#include "llvm/ObjectYAML/COFFYAML.h"
+#include "llvm/ObjectYAML/MachOYAML.h"
+
+namespace llvm {
+namespace yaml {
+
+struct YamlObjectFile {
+ std::unique_ptr<ELFYAML::Object> Elf;
+ std::unique_ptr<COFFYAML::Object> Coff;
+ std::unique_ptr<MachOYAML::Object> MachO;
+ std::unique_ptr<MachOYAML::UniversalBinary> FatMachO;
+};
+
+template <> struct MappingTraits<YamlObjectFile> {
+ static void mapping(IO &IO, YamlObjectFile &ObjectFile);
+};
+
+} // namespace yaml
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/MC/YAML.h b/include/llvm/ObjectYAML/YAML.h
index 383cdc6785fa..7f6836809b6d 100644
--- a/include/llvm/MC/YAML.h
+++ b/include/llvm/ObjectYAML/YAML.h
@@ -1,5 +1,14 @@
-#ifndef LLVM_MC_YAML_H
-#define LLVM_MC_YAML_H
+//===- YAML.h ---------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECTYAML_YAML_H
+#define LLVM_OBJECTYAML_YAML_H
#include "llvm/Support/YAMLTraits.h"
diff --git a/include/llvm/Option/OptParser.td b/include/llvm/Option/OptParser.td
index dbf240d74805..4da86f09750d 100644
--- a/include/llvm/Option/OptParser.td
+++ b/include/llvm/Option/OptParser.td
@@ -46,6 +46,9 @@ def KIND_JOINED_OR_SEPARATE : OptionKind<"JoinedOrSeparate">;
def KIND_JOINED_AND_SEPARATE : OptionKind<"JoinedAndSeparate">;
// An option which consumes all remaining arguments if there are any.
def KIND_REMAINING_ARGS : OptionKind<"RemainingArgs">;
+// An option which consumes an optional joined argument and any other remaining
+// arguments.
+def KIND_REMAINING_ARGS_JOINED : OptionKind<"RemainingArgsJoined">;
// Define the option flags.
diff --git a/include/llvm/Option/Option.h b/include/llvm/Option/Option.h
index 494987a135ef..139f281b3c4c 100644
--- a/include/llvm/Option/Option.h
+++ b/include/llvm/Option/Option.h
@@ -51,6 +51,7 @@ public:
JoinedClass,
SeparateClass,
RemainingArgsClass,
+ RemainingArgsJoinedClass,
CommaJoinedClass,
MultiArgClass,
JoinedOrSeparateClass,
@@ -150,6 +151,7 @@ public:
case MultiArgClass:
case JoinedOrSeparateClass:
case RemainingArgsClass:
+ case RemainingArgsJoinedClass:
return RenderSeparateStyle;
}
llvm_unreachable("Unexpected kind!");
diff --git a/include/llvm/Pass.h b/include/llvm/Pass.h
index 99604cdbc9ca..2a21b82876bb 100644
--- a/include/llvm/Pass.h
+++ b/include/llvm/Pass.h
@@ -29,7 +29,6 @@
#ifndef LLVM_PASS_H
#define LLVM_PASS_H
-#include "llvm/Support/Compiler.h"
#include <string>
namespace llvm {
@@ -251,6 +250,11 @@ public:
explicit ModulePass(char &pid) : Pass(PT_Module, pid) {}
// Force out-of-line virtual method.
~ModulePass() override;
+
+protected:
+ /// Optional passes call this function to check whether the pass should be
+ /// skipped. This is the case when optimization bisect is over the limit.
+ bool skipModule(Module &M) const;
};
@@ -310,9 +314,10 @@ public:
PassManagerType getPotentialPassManagerType() const override;
protected:
- /// skipOptnoneFunction - This function has Attribute::OptimizeNone
- /// and most transformation passes should skip it.
- bool skipOptnoneFunction(const Function &F) const;
+ /// Optional passes call this function to check whether the pass should be
+ /// skipped. This is the case when Attribute::OptimizeNone is set or when
+ /// optimization bisect is over the limit.
+ bool skipFunction(const Function &F) const;
};
@@ -359,9 +364,10 @@ public:
PassManagerType getPotentialPassManagerType() const override;
protected:
- /// skipOptnoneFunction - Containing function has Attribute::OptimizeNone
- /// and most transformation passes should skip it.
- bool skipOptnoneFunction(const BasicBlock &BB) const;
+ /// Optional passes call this function to check whether the pass should be
+ /// skipped. This is the case when Attribute::OptimizeNone is set or when
+ /// optimization bisect is over the limit.
+ bool skipBasicBlock(const BasicBlock &BB) const;
};
/// If the user specifies the -time-passes argument on an LLVM tool command line
diff --git a/include/llvm/PassAnalysisSupport.h b/include/llvm/PassAnalysisSupport.h
index 492a4ef464f8..abd992938057 100644
--- a/include/llvm/PassAnalysisSupport.h
+++ b/include/llvm/PassAnalysisSupport.h
@@ -20,11 +20,11 @@
#define LLVM_PASSANALYSISSUPPORT_H
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/Pass.h"
#include <vector>
namespace llvm {
+class StringRef;
//===----------------------------------------------------------------------===//
/// Represent the analysis usage information of a pass. This tracks analyses
@@ -153,9 +153,9 @@ public:
/// Find pass that is implementing PI.
Pass *findImplPass(AnalysisID PI) {
Pass *ResultPass = nullptr;
- for (unsigned i = 0; i < AnalysisImpls.size() ; ++i) {
- if (AnalysisImpls[i].first == PI) {
- ResultPass = AnalysisImpls[i].second;
+ for (const auto &AnalysisImpl : AnalysisImpls) {
+ if (AnalysisImpl.first == PI) {
+ ResultPass = AnalysisImpl.second;
break;
}
}
diff --git a/include/llvm/PassRegistry.h b/include/llvm/PassRegistry.h
index e7fe1f53a4d4..4bb19675585e 100644
--- a/include/llvm/PassRegistry.h
+++ b/include/llvm/PassRegistry.h
@@ -20,7 +20,6 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/PassInfo.h"
#include "llvm/Support/CBindingWrapping.h"
#include "llvm/Support/RWMutex.h"
@@ -28,6 +27,7 @@
namespace llvm {
+class StringRef;
class PassInfo;
struct PassRegistrationListener;
diff --git a/include/llvm/PassSupport.h b/include/llvm/PassSupport.h
index 7c3d49f02e8f..ba6d84f04ba0 100644
--- a/include/llvm/PassSupport.h
+++ b/include/llvm/PassSupport.h
@@ -26,73 +26,57 @@
#include "llvm/PassInfo.h"
#include "llvm/PassRegistry.h"
#include "llvm/Support/Atomic.h"
-#include "llvm/Support/Compiler.h"
-#include <vector>
+#include "llvm/Support/Threading.h"
+#include <functional>
namespace llvm {
class TargetMachine;
-#define CALL_ONCE_INITIALIZATION(function) \
- static volatile sys::cas_flag initialized = 0; \
- sys::cas_flag old_val = sys::CompareAndSwap(&initialized, 1, 0); \
- if (old_val == 0) { \
- function(Registry); \
- sys::MemoryFence(); \
- TsanIgnoreWritesBegin(); \
- TsanHappensBefore(&initialized); \
- initialized = 2; \
- TsanIgnoreWritesEnd(); \
- } else { \
- sys::cas_flag tmp = initialized; \
- sys::MemoryFence(); \
- while (tmp != 2) { \
- tmp = initialized; \
- sys::MemoryFence(); \
- } \
- } \
- TsanHappensAfter(&initialized);
-
-#define INITIALIZE_PASS(passName, arg, name, cfg, analysis) \
- static void* initialize##passName##PassOnce(PassRegistry &Registry) { \
- PassInfo *PI = new PassInfo(name, arg, & passName ::ID, \
- PassInfo::NormalCtor_t(callDefaultCtor< passName >), cfg, analysis); \
- Registry.registerPass(*PI, true); \
- return PI; \
- } \
- void llvm::initialize##passName##Pass(PassRegistry &Registry) { \
- CALL_ONCE_INITIALIZATION(initialize##passName##PassOnce) \
+#define INITIALIZE_PASS(passName, arg, name, cfg, analysis) \
+ static void *initialize##passName##PassOnce(PassRegistry &Registry) { \
+ PassInfo *PI = new PassInfo( \
+ name, arg, &passName::ID, \
+ PassInfo::NormalCtor_t(callDefaultCtor<passName>), cfg, analysis); \
+ Registry.registerPass(*PI, true); \
+ return PI; \
+ } \
+ LLVM_DEFINE_ONCE_FLAG(Initialize##passName##PassFlag); \
+ void llvm::initialize##passName##Pass(PassRegistry &Registry) { \
+ llvm::call_once(Initialize##passName##PassFlag, \
+ initialize##passName##PassOnce, std::ref(Registry)); \
}
-#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis) \
- static void* initialize##passName##PassOnce(PassRegistry &Registry) {
-
-#define INITIALIZE_PASS_DEPENDENCY(depName) \
- initialize##depName##Pass(Registry);
-#define INITIALIZE_AG_DEPENDENCY(depName) \
- initialize##depName##AnalysisGroup(Registry);
-
-#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis) \
- PassInfo *PI = new PassInfo(name, arg, & passName ::ID, \
- PassInfo::NormalCtor_t(callDefaultCtor< passName >), cfg, analysis); \
- Registry.registerPass(*PI, true); \
- return PI; \
- } \
- void llvm::initialize##passName##Pass(PassRegistry &Registry) { \
- CALL_ONCE_INITIALIZATION(initialize##passName##PassOnce) \
+#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis) \
+ static void *initialize##passName##PassOnce(PassRegistry &Registry) {
+
+#define INITIALIZE_PASS_DEPENDENCY(depName) initialize##depName##Pass(Registry);
+#define INITIALIZE_AG_DEPENDENCY(depName) \
+ initialize##depName##AnalysisGroup(Registry);
+
+#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis) \
+ PassInfo *PI = new PassInfo( \
+ name, arg, &passName::ID, \
+ PassInfo::NormalCtor_t(callDefaultCtor<passName>), cfg, analysis); \
+ Registry.registerPass(*PI, true); \
+ return PI; \
+ } \
+ LLVM_DEFINE_ONCE_FLAG(Initialize##passName##PassFlag); \
+ void llvm::initialize##passName##Pass(PassRegistry &Registry) { \
+ llvm::call_once(Initialize##passName##PassFlag, \
+ initialize##passName##PassOnce, std::ref(Registry)); \
}
-#define INITIALIZE_PASS_WITH_OPTIONS(PassName, Arg, Name, Cfg, Analysis) \
- INITIALIZE_PASS_BEGIN(PassName, Arg, Name, Cfg, Analysis) \
- PassName::registerOptions(); \
+#define INITIALIZE_PASS_WITH_OPTIONS(PassName, Arg, Name, Cfg, Analysis) \
+ INITIALIZE_PASS_BEGIN(PassName, Arg, Name, Cfg, Analysis) \
+ PassName::registerOptions(); \
INITIALIZE_PASS_END(PassName, Arg, Name, Cfg, Analysis)
#define INITIALIZE_PASS_WITH_OPTIONS_BEGIN(PassName, Arg, Name, Cfg, Analysis) \
- INITIALIZE_PASS_BEGIN(PassName, Arg, Name, Cfg, Analysis) \
- PassName::registerOptions(); \
+ INITIALIZE_PASS_BEGIN(PassName, Arg, Name, Cfg, Analysis) \
+ PassName::registerOptions();
-template<typename PassName>
-Pass *callDefaultCtor() { return new PassName(); }
+template <typename PassName> Pass *callDefaultCtor() { return new PassName(); }
template <typename PassName> Pass *callTargetMachineCtor(TargetMachine *TM) {
return new PassName(TM);
@@ -115,20 +99,17 @@ template <typename PassName> Pass *callTargetMachineCtor(TargetMachine *TM) {
///
/// static RegisterPass<PassClassName> tmp("passopt", "My Name");
///
-template<typename passName>
-struct RegisterPass : public PassInfo {
-
+template <typename passName> struct RegisterPass : public PassInfo {
// Register Pass using default constructor...
RegisterPass(const char *PassArg, const char *Name, bool CFGOnly = false,
bool is_analysis = false)
- : PassInfo(Name, PassArg, &passName::ID,
- PassInfo::NormalCtor_t(callDefaultCtor<passName>),
- CFGOnly, is_analysis) {
+ : PassInfo(Name, PassArg, &passName::ID,
+ PassInfo::NormalCtor_t(callDefaultCtor<passName>), CFGOnly,
+ is_analysis) {
PassRegistry::getPassRegistry()->registerPass(*this);
}
};
-
/// RegisterAnalysisGroup - Register a Pass as a member of an analysis _group_.
/// Analysis groups are used to define an interface (which need not derive from
/// Pass) that is required by passes to do their job. Analysis Groups differ
@@ -150,70 +131,73 @@ struct RegisterPass : public PassInfo {
///
class RegisterAGBase : public PassInfo {
public:
- RegisterAGBase(const char *Name,
- const void *InterfaceID,
- const void *PassID = nullptr,
- bool isDefault = false);
+ RegisterAGBase(const char *Name, const void *InterfaceID,
+ const void *PassID = nullptr, bool isDefault = false);
};
-template<typename Interface, bool Default = false>
+template <typename Interface, bool Default = false>
struct RegisterAnalysisGroup : public RegisterAGBase {
explicit RegisterAnalysisGroup(PassInfo &RPB)
- : RegisterAGBase(RPB.getPassName(),
- &Interface::ID, RPB.getTypeInfo(),
- Default) {
- }
+ : RegisterAGBase(RPB.getPassName(), &Interface::ID, RPB.getTypeInfo(),
+ Default) {}
explicit RegisterAnalysisGroup(const char *Name)
- : RegisterAGBase(Name, &Interface::ID) {
- }
+ : RegisterAGBase(Name, &Interface::ID) {}
};
-#define INITIALIZE_ANALYSIS_GROUP(agName, name, defaultPass) \
- static void* initialize##agName##AnalysisGroupOnce(PassRegistry &Registry) { \
- initialize##defaultPass##Pass(Registry); \
- PassInfo *AI = new PassInfo(name, & agName :: ID); \
- Registry.registerAnalysisGroup(& agName ::ID, 0, *AI, false, true); \
- return AI; \
- } \
- void llvm::initialize##agName##AnalysisGroup(PassRegistry &Registry) { \
- CALL_ONCE_INITIALIZATION(initialize##agName##AnalysisGroupOnce) \
+#define INITIALIZE_ANALYSIS_GROUP(agName, name, defaultPass) \
+ static void *initialize##agName##AnalysisGroupOnce(PassRegistry &Registry) { \
+ initialize##defaultPass##Pass(Registry); \
+ PassInfo *AI = new PassInfo(name, &agName::ID); \
+ Registry.registerAnalysisGroup(&agName::ID, 0, *AI, false, true); \
+ return AI; \
+ } \
+ LLVM_DEFINE_ONCE_FLAG(Initialize##agName##AnalysisGroupFlag); \
+ void llvm::initialize##agName##AnalysisGroup(PassRegistry &Registry) { \
+ llvm::call_once(Initialize##agName##AnalysisGroupFlag, \
+ initialize##agName##AnalysisGroupOnce, \
+ std::ref(Registry)); \
}
-
-#define INITIALIZE_AG_PASS(passName, agName, arg, name, cfg, analysis, def) \
- static void* initialize##passName##PassOnce(PassRegistry &Registry) { \
- if (!def) initialize##agName##AnalysisGroup(Registry); \
- PassInfo *PI = new PassInfo(name, arg, & passName ::ID, \
- PassInfo::NormalCtor_t(callDefaultCtor< passName >), cfg, analysis); \
- Registry.registerPass(*PI, true); \
- \
- PassInfo *AI = new PassInfo(name, & agName :: ID); \
- Registry.registerAnalysisGroup(& agName ::ID, & passName ::ID, \
- *AI, def, true); \
- return AI; \
- } \
- void llvm::initialize##passName##Pass(PassRegistry &Registry) { \
- CALL_ONCE_INITIALIZATION(initialize##passName##PassOnce) \
+#define INITIALIZE_AG_PASS(passName, agName, arg, name, cfg, analysis, def) \
+ static void *initialize##passName##PassOnce(PassRegistry &Registry) { \
+ if (!def) \
+ initialize##agName##AnalysisGroup(Registry); \
+ PassInfo *PI = new PassInfo( \
+ name, arg, &passName::ID, \
+ PassInfo::NormalCtor_t(callDefaultCtor<passName>), cfg, analysis); \
+ Registry.registerPass(*PI, true); \
+ \
+ PassInfo *AI = new PassInfo(name, &agName::ID); \
+ Registry.registerAnalysisGroup(&agName::ID, &passName::ID, *AI, def, \
+ true); \
+ return AI; \
+ } \
+ LLVM_DEFINE_ONCE_FLAG(Initialize##passName##PassFlag); \
+ void llvm::initialize##passName##Pass(PassRegistry &Registry) { \
+ llvm::call_once(Initialize##passName##PassFlag, \
+ initialize##passName##PassOnce, std::ref(Registry)); \
}
-
#define INITIALIZE_AG_PASS_BEGIN(passName, agName, arg, n, cfg, analysis, def) \
- static void* initialize##passName##PassOnce(PassRegistry &Registry) { \
- if (!def) initialize##agName##AnalysisGroup(Registry);
-
-#define INITIALIZE_AG_PASS_END(passName, agName, arg, n, cfg, analysis, def) \
- PassInfo *PI = new PassInfo(n, arg, & passName ::ID, \
- PassInfo::NormalCtor_t(callDefaultCtor< passName >), cfg, analysis); \
- Registry.registerPass(*PI, true); \
- \
- PassInfo *AI = new PassInfo(n, & agName :: ID); \
- Registry.registerAnalysisGroup(& agName ::ID, & passName ::ID, \
- *AI, def, true); \
- return AI; \
- } \
- void llvm::initialize##passName##Pass(PassRegistry &Registry) { \
- CALL_ONCE_INITIALIZATION(initialize##passName##PassOnce) \
+ static void *initialize##passName##PassOnce(PassRegistry &Registry) { \
+ if (!def) \
+ initialize##agName##AnalysisGroup(Registry);
+
+#define INITIALIZE_AG_PASS_END(passName, agName, arg, n, cfg, analysis, def) \
+ PassInfo *PI = new PassInfo( \
+ n, arg, &passName::ID, \
+ PassInfo::NormalCtor_t(callDefaultCtor<passName>), cfg, analysis); \
+ Registry.registerPass(*PI, true); \
+ \
+ PassInfo *AI = new PassInfo(n, &agName::ID); \
+ Registry.registerAnalysisGroup(&agName::ID, &passName::ID, *AI, def, true); \
+ return AI; \
+ } \
+ LLVM_DEFINE_ONCE_FLAG(Initialize##passName##PassFlag); \
+ void llvm::initialize##passName##Pass(PassRegistry &Registry) { \
+ llvm::call_once(Initialize##passName##PassFlag, \
+ initialize##passName##PassOnce, std::ref(Registry)); \
}
//===---------------------------------------------------------------------------
@@ -224,7 +208,6 @@ struct RegisterAnalysisGroup : public RegisterAGBase {
/// loaded).
///
struct PassRegistrationListener {
-
PassRegistrationListener() {}
virtual ~PassRegistrationListener() {}
@@ -244,7 +227,6 @@ struct PassRegistrationListener {
virtual void passEnumerate(const PassInfo *) {}
};
-
} // End llvm namespace
#endif
diff --git a/include/llvm/Passes/PassBuilder.h b/include/llvm/Passes/PassBuilder.h
index 1e605e374178..9f0a9c6e1380 100644
--- a/include/llvm/Passes/PassBuilder.h
+++ b/include/llvm/Passes/PassBuilder.h
@@ -16,11 +16,13 @@
#ifndef LLVM_PASSES_PASSBUILDER_H
#define LLVM_PASSES_PASSBUILDER_H
-#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/CGSCCPassManager.h"
+#include "llvm/Analysis/LoopPassManager.h"
#include "llvm/IR/PassManager.h"
namespace llvm {
+class StringRef;
+class AAManager;
class TargetMachine;
/// \brief This class provides access to building LLVM's passes.
@@ -33,29 +35,164 @@ class PassBuilder {
TargetMachine *TM;
public:
+ /// \brief LLVM-provided high-level optimization levels.
+ ///
+ /// This enumerates the LLVM-provided high-level optimization levels. Each
+ /// level has a specific goal and rationale.
+ enum OptimizationLevel {
+ /// Disable as many optimizations as possible. This doesn't completely
+ /// disable the optimizer in all cases, for example always_inline functions
+ /// can be required to be inlined for correctness.
+ O0,
+
+ /// Optimize quickly without destroying debuggability.
+ ///
+ /// FIXME: The current and historical behavior of this level does *not*
+ /// agree with this goal, but we would like to move toward this goal in the
+ /// future.
+ ///
+ /// This level is tuned to produce a result from the optimizer as quickly
+ /// as possible and to avoid destroying debuggability. This tends to result
+ /// in a very good development mode where the compiled code will be
+ /// immediately executed as part of testing. As a consequence, where
+ /// possible, we would like to produce efficient-to-execute code, but not
+ /// if it significantly slows down compilation or would prevent even basic
+ /// debugging of the resulting binary.
+ ///
+ /// As an example, complex loop transformations such as versioning,
+ /// vectorization, or fusion might not make sense here due to the degree to
+ /// which the executed code would differ from the source code, and the
+ /// potential compile time cost.
+ O1,
+
+ /// Optimize for fast execution as much as possible without triggering
+ /// significant incremental compile time or code size growth.
+ ///
+ /// The key idea is that optimizations at this level should "pay for
+ /// themselves". So if an optimization increases compile time by 5% or
+ /// increases code size by 5% for a particular benchmark, that benchmark
+ /// should also be one which sees a 5% runtime improvement. If the compile
+ /// time or code size penalties happen on average across a diverse range of
+ /// LLVM users' benchmarks, then the improvements should as well.
+ ///
+ /// And no matter what, the compile time needs to not grow superlinearly
+ /// with the size of input to LLVM so that users can control the runtime of
+ /// the optimizer in this mode.
+ ///
+ /// This is expected to be a good default optimization level for the vast
+ /// majority of users.
+ O2,
+
+ /// Optimize for fast execution as much as possible.
+ ///
+ /// This mode is significantly more aggressive in trading off compile time
+ /// and code size to get execution time improvements. The core idea is that
+ /// this mode should include any optimization that helps execution time on
+ /// balance across a diverse collection of benchmarks, even if it increases
+ /// code size or compile time for some benchmarks without corresponding
+ /// improvements to execution time.
+ ///
+ /// Despite being willing to trade more compile time off to get improved
+ /// execution time, this mode still tries to avoid superlinear growth in
+ /// order to make even significantly slower compile times at least scale
+ /// reasonably. This does not preclude very substantial constant factor
+ /// costs though.
+ O3,
+
+ /// Similar to \c O2 but tries to optimize for small code size instead of
+ /// fast execution without triggering significant incremental execution
+ /// time slowdowns.
+ ///
+ /// The logic here is exactly the same as \c O2, but with code size and
+ /// execution time metrics swapped.
+ ///
+ /// A consequence of the different core goal is that this should in general
+ /// produce substantially smaller executables that still run in
+ /// a reasonable amount of time.
+ Os,
+
+ /// A very specialized mode that will optimize for code size at any and all
+ /// costs.
+ ///
+ /// This is useful primarily when there are absolute size limitations and
+ /// any effort taken to reduce the size is worth it regardless of the
+ /// execution time impact. You should expect this level to produce rather
+ /// slow, but very small, code.
+ Oz
+ };
+
explicit PassBuilder(TargetMachine *TM = nullptr) : TM(TM) {}
+ /// \brief Cross register the analysis managers through their proxies.
+ ///
+ /// This is an interface that can be used to cross register each
+ // AnalysisManager with all the others analysis managers.
+ void crossRegisterProxies(LoopAnalysisManager &LAM,
+ FunctionAnalysisManager &FAM,
+ CGSCCAnalysisManager &CGAM,
+ ModuleAnalysisManager &MAM);
+
/// \brief Registers all available module analysis passes.
///
/// This is an interface that can be used to populate a \c
/// ModuleAnalysisManager with all registered module analyses. Callers can
- /// still manually register any additional analyses.
+ /// still manually register any additional analyses. Callers can also
+ /// pre-register analyses and this will not override those.
void registerModuleAnalyses(ModuleAnalysisManager &MAM);
/// \brief Registers all available CGSCC analysis passes.
///
/// This is an interface that can be used to populate a \c CGSCCAnalysisManager
/// with all registered CGSCC analyses. Callers can still manually register any
- /// additional analyses.
+ /// additional analyses. Callers can also pre-register analyses and this will
+ /// not override those.
void registerCGSCCAnalyses(CGSCCAnalysisManager &CGAM);
/// \brief Registers all available function analysis passes.
///
/// This is an interface that can be used to populate a \c
/// FunctionAnalysisManager with all registered function analyses. Callers can
- /// still manually register any additional analyses.
+ /// still manually register any additional analyses. Callers can also
+ /// pre-register analyses and this will not override those.
void registerFunctionAnalyses(FunctionAnalysisManager &FAM);
+ /// \brief Registers all available loop analysis passes.
+ ///
+ /// This is an interface that can be used to populate a \c LoopAnalysisManager
+ /// with all registered loop analyses. Callers can still manually register any
+ /// additional analyses.
+ void registerLoopAnalyses(LoopAnalysisManager &LAM);
+
+ /// \brief Add a per-module default optimization pipeline to a pass manager.
+ ///
+ /// This provides a good default optimization pipeline for per-module
+ /// optimization and code generation without any link-time optimization. It
+ /// typically correspond to frontend "-O[123]" options for optimization
+ /// levels \c O1, \c O2 and \c O3 resp.
+ void addPerModuleDefaultPipeline(ModulePassManager &MPM,
+ OptimizationLevel Level,
+ bool DebugLogging = false);
+
+ /// \brief Add a pre-link, LTO-targeting default optimization pipeline to
+ /// a pass manager.
+ ///
+ /// This adds the pre-link optimizations tuned to work well with a later LTO
+ /// run. It works to minimize the IR which needs to be analyzed without
+ /// making irreversible decisions which could be made better during the LTO
+ /// run.
+ void addLTOPreLinkDefaultPipeline(ModulePassManager &MPM,
+ OptimizationLevel Level,
+ bool DebugLogging = false);
+
+ /// \brief Add an LTO default optimization pipeline to a pass manager.
+ ///
+ /// This provides a good default optimization pipeline for link-time
+ /// optimization and code generation. It is particularly tuned to fit well
+ /// when IR coming into the LTO phase was first run through \c
+ /// addPreLinkLTODefaultPipeline, and the two coordinate closely.
+ void addLTODefaultPipeline(ModulePassManager &MPM, OptimizationLevel Level,
+ bool DebugLogging = false);
+
/// \brief Parse a textual pass pipeline description into a \c ModulePassManager.
///
/// The format of the textual pass pipeline description looks something like:
@@ -87,10 +224,32 @@ public:
bool parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText,
bool VerifyEachPass = true, bool DebugLogging = false);
+ /// Parse a textual alias analysis pipeline into the provided AA manager.
+ ///
+ /// The format of the textual AA pipeline is a comma separated list of AA
+ /// pass names:
+ ///
+ /// basic-aa,globals-aa,...
+ ///
+ /// The AA manager is set up such that the provided alias analyses are tried
+ /// in the order specified. See the \c AAManaager documentation for details
+ /// about the logic used. This routine just provides the textual mapping
+ /// between AA names and the analyses to register with the manager.
+ ///
+ /// Returns false if the text cannot be parsed cleanly. The specific state of
+ /// the \p AA manager is unspecified if such an error is encountered and this
+ /// returns false.
+ bool parseAAPipeline(AAManager &AA, StringRef PipelineText);
+
private:
- bool parseModulePassName(ModulePassManager &MPM, StringRef Name);
+ bool parseModulePassName(ModulePassManager &MPM, StringRef Name,
+ bool DebugLogging);
bool parseCGSCCPassName(CGSCCPassManager &CGPM, StringRef Name);
bool parseFunctionPassName(FunctionPassManager &FPM, StringRef Name);
+ bool parseLoopPassName(LoopPassManager &LPM, StringRef Name);
+ bool parseAAPassName(AAManager &AA, StringRef Name);
+ bool parseLoopPassPipeline(LoopPassManager &LPM, StringRef &PipelineText,
+ bool VerifyEachPass, bool DebugLogging);
bool parseFunctionPassPipeline(FunctionPassManager &FPM,
StringRef &PipelineText, bool VerifyEachPass,
bool DebugLogging);
@@ -99,7 +258,6 @@ private:
bool parseModulePassPipeline(ModulePassManager &MPM, StringRef &PipelineText,
bool VerifyEachPass, bool DebugLogging);
};
-
}
#endif
diff --git a/include/llvm/ProfileData/CoverageMapping.h b/include/llvm/ProfileData/Coverage/CoverageMapping.h
index 92a991eb39ba..6afde56122f0 100644
--- a/include/llvm/ProfileData/CoverageMapping.h
+++ b/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -23,13 +23,13 @@
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Endian.h"
-#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/raw_ostream.h"
#include <system_error>
#include <tuple>
namespace llvm {
namespace coverage {
+
enum class coveragemap_error {
success = 0,
eof,
@@ -38,14 +38,37 @@ enum class coveragemap_error {
truncated,
malformed
};
-} // end of coverage namespace.
+
+const std::error_category &coveragemap_category();
+
+inline std::error_code make_error_code(coveragemap_error E) {
+ return std::error_code(static_cast<int>(E), coveragemap_category());
}
-namespace std {
-template <>
-struct is_error_code_enum<llvm::coverage::coveragemap_error> : std::true_type {
+class CoverageMapError : public ErrorInfo<CoverageMapError> {
+public:
+ CoverageMapError(coveragemap_error Err) : Err(Err) {
+ assert(Err != coveragemap_error::success && "Not an error");
+ }
+
+ std::string message() const override;
+
+ void log(raw_ostream &OS) const override { OS << message(); }
+
+ std::error_code convertToErrorCode() const override {
+ return make_error_code(Err);
+ }
+
+ coveragemap_error get() const { return Err; }
+
+ static char ID;
+
+private:
+ coveragemap_error Err;
};
-}
+
+} // end of coverage namespace.
+} // end of llvm namespace
namespace llvm {
class IndexedInstrProfReader;
@@ -265,7 +288,7 @@ public:
/// \brief Return the number of times that a region of code associated with
/// this counter was executed.
- ErrorOr<int64_t> evaluate(const Counter &C) const;
+ Expected<int64_t> evaluate(const Counter &C) const;
};
/// \brief Code coverage information for a single function.
@@ -370,13 +393,6 @@ struct CoverageSegment {
return std::tie(L.Line, L.Col, L.Count, L.HasCount, L.IsRegionEntry) ==
std::tie(R.Line, R.Col, R.Count, R.HasCount, R.IsRegionEntry);
}
-
- void setCount(uint64_t NewCount) {
- Count = NewCount;
- HasCount = true;
- }
-
- void addCount(uint64_t NewCount) { setCount(Count + NewCount); }
};
/// \brief Coverage information to be processed or displayed.
@@ -400,14 +416,14 @@ public:
Expansions(std::move(RHS.Expansions)) {}
/// \brief Get the name of the file this data covers.
- StringRef getFilename() { return Filename; }
+ StringRef getFilename() const { return Filename; }
std::vector<CoverageSegment>::iterator begin() { return Segments.begin(); }
std::vector<CoverageSegment>::iterator end() { return Segments.end(); }
bool empty() { return Segments.empty(); }
/// \brief Expansions that can be further processed.
- std::vector<ExpansionRecord> getExpansions() { return Expansions; }
+ ArrayRef<ExpansionRecord> getExpansions() { return Expansions; }
};
/// \brief The mapping of profile information to coverage data.
@@ -422,12 +438,12 @@ class CoverageMapping {
public:
/// \brief Load the coverage mapping using the given readers.
- static ErrorOr<std::unique_ptr<CoverageMapping>>
+ static Expected<std::unique_ptr<CoverageMapping>>
load(CoverageMappingReader &CoverageReader,
IndexedInstrProfReader &ProfileReader);
/// \brief Load the coverage mapping from the given files.
- static ErrorOr<std::unique_ptr<CoverageMapping>>
+ static Expected<std::unique_ptr<CoverageMapping>>
load(StringRef ObjectFilename, StringRef ProfileFilename,
StringRef Arch = StringRef());
@@ -445,7 +461,7 @@ public:
/// The given filename must be the name as recorded in the coverage
/// information. That is, only names returned from getUniqueSourceFiles will
/// yield a result.
- CoverageData getCoverageForFile(StringRef Filename);
+ CoverageData getCoverageForFile(StringRef Filename) const;
/// \brief Gets all of the functions covered by this profile.
iterator_range<FunctionRecordIterator> getCoveredFunctions() const {
@@ -464,21 +480,16 @@ public:
///
/// Functions that are instantiated more than once, such as C++ template
/// specializations, have distinct coverage records for each instantiation.
- std::vector<const FunctionRecord *> getInstantiations(StringRef Filename);
+ std::vector<const FunctionRecord *>
+ getInstantiations(StringRef Filename) const;
/// \brief Get the coverage for a particular function.
- CoverageData getCoverageForFunction(const FunctionRecord &Function);
+ CoverageData getCoverageForFunction(const FunctionRecord &Function) const;
/// \brief Get the coverage for an expansion within a coverage set.
- CoverageData getCoverageForExpansion(const ExpansionRecord &Expansion);
+ CoverageData getCoverageForExpansion(const ExpansionRecord &Expansion) const;
};
-const std::error_category &coveragemap_category();
-
-inline std::error_code make_error_code(coveragemap_error E) {
- return std::error_code(static_cast<int>(E), coveragemap_category());
-}
-
// Profile coverage map has the following layout:
// [CoverageMapFileHeader]
// [ArrayStart]
@@ -488,9 +499,11 @@ inline std::error_code make_error_code(coveragemap_error E) {
// [ArrayEnd]
// [Encoded Region Mapping Data]
LLVM_PACKED_START
-template <class IntPtrT> struct CovMapFunctionRecord {
+template <class IntPtrT> struct CovMapFunctionRecordV1 {
+#define COVMAP_V1
#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name;
#include "llvm/ProfileData/InstrProfData.inc"
+#undef COVMAP_V1
// Return the structural hash associated with the function.
template <support::endianness Endian> uint64_t getFuncHash() const {
@@ -506,16 +519,41 @@ template <class IntPtrT> struct CovMapFunctionRecord {
}
// Return the PGO name of the function */
template <support::endianness Endian>
- std::error_code getFuncName(InstrProfSymtab &ProfileNames,
- StringRef &FuncName) const {
+ Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
IntPtrT NameRef = getFuncNameRef<Endian>();
uint32_t NameS = support::endian::byte_swap<uint32_t, Endian>(NameSize);
FuncName = ProfileNames.getFuncName(NameRef, NameS);
if (NameS && FuncName.empty())
- return coveragemap_error::malformed;
- return std::error_code();
+ return make_error<CoverageMapError>(coveragemap_error::malformed);
+ return Error::success();
+ }
+};
+
+struct CovMapFunctionRecord {
+#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name;
+#include "llvm/ProfileData/InstrProfData.inc"
+
+ // Return the structural hash associated with the function.
+ template <support::endianness Endian> uint64_t getFuncHash() const {
+ return support::endian::byte_swap<uint64_t, Endian>(FuncHash);
+ }
+ // Return the coverage map data size for the funciton.
+ template <support::endianness Endian> uint32_t getDataSize() const {
+ return support::endian::byte_swap<uint32_t, Endian>(DataSize);
+ }
+ // Return function lookup key. The value is consider opaque.
+ template <support::endianness Endian> uint64_t getFuncNameRef() const {
+ return support::endian::byte_swap<uint64_t, Endian>(NameRef);
+ }
+ // Return the PGO name of the function */
+ template <support::endianness Endian>
+ Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
+ uint64_t NameRef = getFuncNameRef<Endian>();
+ FuncName = ProfileNames.getFuncName(NameRef);
+ return Error::success();
}
};
+
// Per module coverage mapping data header, i.e. CoverageMapFileHeader
// documented above.
struct CovMapHeader {
@@ -537,10 +575,24 @@ struct CovMapHeader {
LLVM_PACKED_END
-enum CoverageMappingVersion {
- CoverageMappingVersion1 = 0,
- // The current versin is Version1
- CoverageMappingCurrentVersion = INSTR_PROF_COVMAP_VERSION
+enum CovMapVersion {
+ Version1 = 0,
+ // Function's name reference from CovMapFuncRecord is changed from raw
+ // name string pointer to MD5 to support name section compression. Name
+ // section is also compressed.
+ Version2 = 1,
+ // The current version is Version2
+ CurrentVersion = INSTR_PROF_COVMAP_VERSION
+};
+
+template <int CovMapVersion, class IntPtrT> struct CovMapTraits {
+ typedef CovMapFunctionRecord CovMapFuncRecordType;
+ typedef uint64_t NameRefType;
+};
+
+template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version1, IntPtrT> {
+ typedef CovMapFunctionRecordV1<IntPtrT> CovMapFuncRecordType;
+ typedef IntPtrT NameRefType;
};
} // end namespace coverage
diff --git a/include/llvm/ProfileData/CoverageMappingReader.h b/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
index 38fb4680476b..db907f128d93 100644
--- a/include/llvm/ProfileData/CoverageMappingReader.h
+++ b/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
@@ -19,7 +19,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Object/ObjectFile.h"
-#include "llvm/ProfileData/CoverageMapping.h"
+#include "llvm/ProfileData/Coverage/CoverageMapping.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -69,7 +69,7 @@ public:
class CoverageMappingReader {
public:
- virtual std::error_code readNextRecord(CoverageMappingRecord &Record) = 0;
+ virtual Error readNextRecord(CoverageMappingRecord &Record) = 0;
CoverageMappingIterator begin() { return CoverageMappingIterator(this); }
CoverageMappingIterator end() { return CoverageMappingIterator(); }
virtual ~CoverageMappingReader() {}
@@ -82,10 +82,10 @@ protected:
RawCoverageReader(StringRef Data) : Data(Data) {}
- std::error_code readULEB128(uint64_t &Result);
- std::error_code readIntMax(uint64_t &Result, uint64_t MaxPlus1);
- std::error_code readSize(uint64_t &Result);
- std::error_code readString(StringRef &Result);
+ Error readULEB128(uint64_t &Result);
+ Error readIntMax(uint64_t &Result, uint64_t MaxPlus1);
+ Error readSize(uint64_t &Result);
+ Error readString(StringRef &Result);
};
/// \brief Reader for the raw coverage filenames.
@@ -100,7 +100,17 @@ public:
RawCoverageFilenamesReader(StringRef Data, std::vector<StringRef> &Filenames)
: RawCoverageReader(Data), Filenames(Filenames) {}
- std::error_code read();
+ Error read();
+};
+
+/// \brief Checks if the given coverage mapping data is exported for
+/// an unused function.
+class RawCoverageMappingDummyChecker : public RawCoverageReader {
+public:
+ RawCoverageMappingDummyChecker(StringRef MappingData)
+ : RawCoverageReader(MappingData) {}
+
+ Expected<bool> isDummy();
};
/// \brief Reader for the raw coverage mapping data.
@@ -125,12 +135,12 @@ public:
Filenames(Filenames), Expressions(Expressions),
MappingRegions(MappingRegions) {}
- std::error_code read();
+ Error read();
private:
- std::error_code decodeCounter(unsigned Value, Counter &C);
- std::error_code readCounter(Counter &C);
- std::error_code
+ Error decodeCounter(unsigned Value, Counter &C);
+ Error readCounter(Counter &C);
+ Error
readMappingRegionsSubArray(std::vector<CounterMappingRegion> &MappingRegions,
unsigned InferredFileID, size_t NumFileIDs);
};
@@ -140,14 +150,14 @@ private:
class BinaryCoverageReader : public CoverageMappingReader {
public:
struct ProfileMappingRecord {
- CoverageMappingVersion Version;
+ CovMapVersion Version;
StringRef FunctionName;
uint64_t FunctionHash;
StringRef CoverageMapping;
size_t FilenamesBegin;
size_t FilenamesSize;
- ProfileMappingRecord(CoverageMappingVersion Version, StringRef FunctionName,
+ ProfileMappingRecord(CovMapVersion Version, StringRef FunctionName,
uint64_t FunctionHash, StringRef CoverageMapping,
size_t FilenamesBegin, size_t FilenamesSize)
: Version(Version), FunctionName(FunctionName),
@@ -158,6 +168,7 @@ public:
private:
std::vector<StringRef> Filenames;
std::vector<ProfileMappingRecord> MappingRecords;
+ InstrProfSymtab ProfileNames;
size_t CurrentRecord;
std::vector<StringRef> FunctionsFilenames;
std::vector<CounterExpression> Expressions;
@@ -169,11 +180,11 @@ private:
BinaryCoverageReader() : CurrentRecord(0) {}
public:
- static ErrorOr<std::unique_ptr<BinaryCoverageReader>>
+ static Expected<std::unique_ptr<BinaryCoverageReader>>
create(std::unique_ptr<MemoryBuffer> &ObjectBuffer,
StringRef Arch);
- std::error_code readNextRecord(CoverageMappingRecord &Record) override;
+ Error readNextRecord(CoverageMappingRecord &Record) override;
};
} // end namespace coverage
diff --git a/include/llvm/ProfileData/CoverageMappingWriter.h b/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h
index 2e3b0378d032..10269cc50f35 100644
--- a/include/llvm/ProfileData/CoverageMappingWriter.h
+++ b/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h
@@ -17,7 +17,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringMap.h"
-#include "llvm/ProfileData/CoverageMapping.h"
+#include "llvm/ProfileData/Coverage/CoverageMapping.h"
#include "llvm/Support/raw_ostream.h"
namespace llvm {
diff --git a/include/llvm/ProfileData/InstrProf.h b/include/llvm/ProfileData/InstrProf.h
index c84d8d24f206..75646b761659 100644
--- a/include/llvm/ProfileData/InstrProf.h
+++ b/include/llvm/ProfileData/InstrProf.h
@@ -1,4 +1,4 @@
-//=-- InstrProf.h - Instrumented profiling format support ---------*- C++ -*-=//
+//===-- InstrProf.h - Instrumented profiling format support -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,18 +13,20 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_PROFILEDATA_INSTRPROF_H_
-#define LLVM_PROFILEDATA_INSTRPROF_H_
+#ifndef LLVM_PROFILEDATA_INSTRPROF_H
+#define LLVM_PROFILEDATA_INSTRPROF_H
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/IR/GlobalValue.h"
+#include "llvm/IR/Metadata.h"
#include "llvm/ProfileData/InstrProfData.inc"
+#include "llvm/ProfileData/ProfileCommon.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/MD5.h"
+#include "llvm/Support/MathExtras.h"
#include <cstdint>
#include <list>
#include <system_error>
@@ -56,6 +58,20 @@ inline StringRef getInstrProfDataSectionName(bool AddSegment) {
: INSTR_PROF_DATA_SECT_NAME_STR;
}
+/// Return the name of data section containing pointers to value profile
+/// counters/nodes.
+inline StringRef getInstrProfValuesSectionName(bool AddSegment) {
+ return AddSegment ? "__DATA," INSTR_PROF_VALS_SECT_NAME_STR
+ : INSTR_PROF_VALS_SECT_NAME_STR;
+}
+
+/// Return the name of data section containing nodes holdling value
+/// profiling data.
+inline StringRef getInstrProfVNodesSectionName(bool AddSegment) {
+ return AddSegment ? "__DATA," INSTR_PROF_VNODES_SECT_NAME_STR
+ : INSTR_PROF_VNODES_SECT_NAME_STR;
+}
+
/// Return the name profile runtime entry point to do value profiling
/// for a given site.
inline StringRef getInstrProfValueProfFuncName() {
@@ -78,10 +94,22 @@ inline StringRef getInstrProfDataVarPrefix() { return "__profd_"; }
/// Return the name prefix of profile counter variables.
inline StringRef getInstrProfCountersVarPrefix() { return "__profc_"; }
+/// Return the name prefix of value profile variables.
+inline StringRef getInstrProfValuesVarPrefix() { return "__profvp_"; }
+
+/// Return the name of value profile node array variables:
+inline StringRef getInstrProfVNodesVarName() { return "__llvm_prf_vnodes"; }
+
/// Return the name prefix of the COMDAT group for instrumentation variables
/// associated with a COMDAT function.
inline StringRef getInstrProfComdatPrefix() { return "__profv_"; }
+/// Return the name of the variable holding the strings (possibly compressed)
+/// of all function's PGO names.
+inline StringRef getInstrProfNamesVarName() {
+ return "__llvm_prf_nm";
+}
+
/// Return the name of a covarage mapping variable (internal linkage)
/// for each instrumented source module. Such variables are allocated
/// in the __llvm_covmap section.
@@ -90,10 +118,12 @@ inline StringRef getCoverageMappingVarName() {
}
/// Return the name of the internal variable recording the array
-/// of PGO name vars referenced by the coverage mapping, The owning
+/// of PGO name vars referenced by the coverage mapping. The owning
/// functions of those names are not emitted by FE (e.g, unused inline
/// functions.)
-inline StringRef getCoverageNamesVarName() { return "__llvm_coverage_names"; }
+inline StringRef getCoverageUnusedNamesVarName() {
+ return "__llvm_coverage_names";
+}
/// Return the name of function that registers all the per-function control
/// data at program startup time by calling __llvm_register_function. This
@@ -110,6 +140,11 @@ inline StringRef getInstrProfRegFuncName() {
return "__llvm_profile_register_function";
}
+/// Return the name of the runtime interface that registers the PGO name strings.
+inline StringRef getInstrProfNamesRegFuncName() {
+ return "__llvm_profile_register_names_function";
+}
+
/// Return the name of the runtime initialization method that is generated by
/// the compiler. The function calls __llvm_profile_register_functions and
/// __llvm_profile_override_default_filename functions if needed. This function
@@ -135,9 +170,13 @@ inline StringRef getInstrProfFileOverriderFuncName() {
return "__llvm_profile_override_default_filename";
}
+/// Return the marker used to separate PGO names during serialization.
+inline StringRef getInstrProfNameSeparator() { return "\01"; }
+
/// Return the modified name for function \c F suitable to be
-/// used the key for profile lookup.
-std::string getPGOFuncName(const Function &F,
+/// used the key for profile lookup. Variable \c InLTO indicates if this
+/// is called in LTO optimization passes.
+std::string getPGOFuncName(const Function &F, bool InLTO = false,
uint64_t Version = INSTR_PROF_INDEX_VERSION);
/// Return the modified name for a function suitable to be
@@ -149,10 +188,16 @@ std::string getPGOFuncName(StringRef RawFuncName,
StringRef FileName,
uint64_t Version = INSTR_PROF_INDEX_VERSION);
+/// Return the name of the global variable used to store a function
+/// name in PGO instrumentation. \c FuncName is the name of the function
+/// returned by the \c getPGOFuncName call.
+std::string getPGOFuncNameVarName(StringRef FuncName,
+ GlobalValue::LinkageTypes Linkage);
+
/// Create and return the global variable for function name used in PGO
/// instrumentation. \c FuncName is the name of the function returned
/// by \c getPGOFuncName call.
-GlobalVariable *createPGOFuncNameVar(Function &F, StringRef FuncName);
+GlobalVariable *createPGOFuncNameVar(Function &F, StringRef PGOFuncName);
/// Create and return the global variable for function name used in PGO
/// instrumentation. /// \c FuncName is the name of the function
@@ -160,13 +205,14 @@ GlobalVariable *createPGOFuncNameVar(Function &F, StringRef FuncName);
/// and \c Linkage is the linkage of the instrumented function.
GlobalVariable *createPGOFuncNameVar(Module &M,
GlobalValue::LinkageTypes Linkage,
- StringRef FuncName);
+ StringRef PGOFuncName);
/// Return the initializer in string of the PGO name var \c NameVar.
StringRef getPGOFuncNameVarInitializer(GlobalVariable *NameVar);
/// Given a PGO function name, remove the filename prefix and return
/// the original (static) function name.
-StringRef getFuncNameWithoutPrefix(StringRef PGOFuncName, StringRef FileName);
+StringRef getFuncNameWithoutPrefix(StringRef PGOFuncName,
+ StringRef FileName = "<unknown>");
/// Given a vector of strings (function PGO names) \c NameStrs, the
/// method generates a combined string \c Result thatis ready to be
@@ -174,22 +220,59 @@ StringRef getFuncNameWithoutPrefix(StringRef PGOFuncName, StringRef FileName);
/// The first field is the legnth of the uncompressed strings, and the
/// the second field is the length of the zlib-compressed string.
/// Both fields are encoded in ULEB128. If \c doCompress is false, the
-/// third field is the uncompressed strings; otherwise it is the
-/// compressed string. When the string compression is off, the
+/// third field is the uncompressed strings; otherwise it is the
+/// compressed string. When the string compression is off, the
/// second field will have value zero.
-int collectPGOFuncNameStrings(const std::vector<std::string> &NameStrs,
- bool doCompression, std::string &Result);
+Error collectPGOFuncNameStrings(const std::vector<std::string> &NameStrs,
+ bool doCompression, std::string &Result);
/// Produce \c Result string with the same format described above. The input
/// is vector of PGO function name variables that are referenced.
-int collectPGOFuncNameStrings(const std::vector<GlobalVariable *> &NameVars,
- std::string &Result);
+Error collectPGOFuncNameStrings(const std::vector<GlobalVariable *> &NameVars,
+ std::string &Result, bool doCompression = true);
class InstrProfSymtab;
/// \c NameStrings is a string composed of one of more sub-strings encoded in
-/// the
-/// format described above. The substrings are seperated by 0 or more zero
-/// bytes.
-/// This method decodes the string and populates the \c Symtab.
-int readPGOFuncNameStrings(StringRef NameStrings, InstrProfSymtab &Symtab);
+/// the format described above. The substrings are seperated by 0 or more zero
+/// bytes. This method decodes the string and populates the \c Symtab.
+Error readPGOFuncNameStrings(StringRef NameStrings, InstrProfSymtab &Symtab);
+
+enum InstrProfValueKind : uint32_t {
+#define VALUE_PROF_KIND(Enumerator, Value) Enumerator = Value,
+#include "llvm/ProfileData/InstrProfData.inc"
+};
+
+struct InstrProfRecord;
+
+/// Get the value profile data for value site \p SiteIdx from \p InstrProfR
+/// and annotate the instruction \p Inst with the value profile meta data.
+/// Annotate up to \p MaxMDCount (default 3) number of records per value site.
+void annotateValueSite(Module &M, Instruction &Inst,
+ const InstrProfRecord &InstrProfR,
+ InstrProfValueKind ValueKind, uint32_t SiteIndx,
+ uint32_t MaxMDCount = 3);
+/// Same as the above interface but using an ArrayRef, as well as \p Sum.
+void annotateValueSite(Module &M, Instruction &Inst,
+ ArrayRef<InstrProfValueData> VDs,
+ uint64_t Sum, InstrProfValueKind ValueKind,
+ uint32_t MaxMDCount);
+
+/// Extract the value profile data from \p Inst which is annotated with
+/// value profile meta data. Return false if there is no value data annotated,
+/// otherwise return true.
+bool getValueProfDataFromInst(const Instruction &Inst,
+ InstrProfValueKind ValueKind,
+ uint32_t MaxNumValueData,
+ InstrProfValueData ValueData[],
+ uint32_t &ActualNumValueData, uint64_t &TotalC);
+
+inline StringRef getPGOFuncNameMetadataName() { return "PGOFuncName"; }
+
+/// Return the PGOFuncName meta data associated with a function.
+MDNode *getPGOFuncNameMetadata(const Function &F);
+
+/// Create the PGOFuncName meta data if PGOFuncName is different from
+/// function's raw name. This should only apply to internal linkage functions
+/// declared by users only.
+void createPGOFuncNameMetadata(Function &F, StringRef PGOFuncName);
const std::error_category &instrprof_category();
@@ -208,26 +291,104 @@ enum class instrprof_error {
hash_mismatch,
count_mismatch,
counter_overflow,
- value_site_count_mismatch
+ value_site_count_mismatch,
+ compress_failed,
+ uncompress_failed
};
inline std::error_code make_error_code(instrprof_error E) {
return std::error_code(static_cast<int>(E), instrprof_category());
}
-inline instrprof_error MergeResult(instrprof_error &Accumulator,
- instrprof_error Result) {
- // Prefer first error encountered as later errors may be secondary effects of
- // the initial problem.
- if (Accumulator == instrprof_error::success &&
- Result != instrprof_error::success)
- Accumulator = Result;
- return Accumulator;
-}
+class InstrProfError : public ErrorInfo<InstrProfError> {
+public:
+ InstrProfError(instrprof_error Err) : Err(Err) {
+ assert(Err != instrprof_error::success && "Not an error");
+ }
-enum InstrProfValueKind : uint32_t {
-#define VALUE_PROF_KIND(Enumerator, Value) Enumerator = Value,
-#include "llvm/ProfileData/InstrProfData.inc"
+ std::string message() const override;
+
+ void log(raw_ostream &OS) const override { OS << message(); }
+
+ std::error_code convertToErrorCode() const override {
+ return make_error_code(Err);
+ }
+
+ instrprof_error get() const { return Err; }
+
+ /// Consume an Error and return the raw enum value contained within it. The
+ /// Error must either be a success value, or contain a single InstrProfError.
+ static instrprof_error take(Error E) {
+ auto Err = instrprof_error::success;
+ handleAllErrors(std::move(E), [&Err](const InstrProfError &IPE) {
+ assert(Err == instrprof_error::success && "Multiple errors encountered");
+ Err = IPE.get();
+ });
+ return Err;
+ }
+
+ static char ID;
+
+private:
+ instrprof_error Err;
+};
+
+class SoftInstrProfErrors {
+ /// Count the number of soft instrprof_errors encountered and keep track of
+ /// the first such error for reporting purposes.
+
+ /// The first soft error encountered.
+ instrprof_error FirstError;
+
+ /// The number of hash mismatches.
+ unsigned NumHashMismatches;
+
+ /// The number of count mismatches.
+ unsigned NumCountMismatches;
+
+ /// The number of counter overflows.
+ unsigned NumCounterOverflows;
+
+ /// The number of value site count mismatches.
+ unsigned NumValueSiteCountMismatches;
+
+public:
+ SoftInstrProfErrors()
+ : FirstError(instrprof_error::success), NumHashMismatches(0),
+ NumCountMismatches(0), NumCounterOverflows(0),
+ NumValueSiteCountMismatches(0) {}
+
+ ~SoftInstrProfErrors() {
+ assert(FirstError == instrprof_error::success &&
+ "Unchecked soft error encountered");
+ }
+
+ /// Track a soft error (\p IE) and increment its associated counter.
+ void addError(instrprof_error IE);
+
+ /// Get the number of hash mismatches.
+ unsigned getNumHashMismatches() const { return NumHashMismatches; }
+
+ /// Get the number of count mismatches.
+ unsigned getNumCountMismatches() const { return NumCountMismatches; }
+
+ /// Get the number of counter overflows.
+ unsigned getNumCounterOverflows() const { return NumCounterOverflows; }
+
+ /// Get the number of value site count mismatches.
+ unsigned getNumValueSiteCountMismatches() const {
+ return NumValueSiteCountMismatches;
+ }
+
+ /// Return the first encountered error and reset FirstError to a success
+ /// value.
+ Error takeError() {
+ if (FirstError == instrprof_error::success)
+ return Error::success();
+ auto E = make_error<InstrProfError>(FirstError);
+ FirstError = instrprof_error::success;
+ return E;
+ }
};
namespace object {
@@ -250,27 +411,41 @@ public:
private:
StringRef Data;
uint64_t Address;
- // A map from MD5 hash keys to function name strings.
- std::vector<std::pair<uint64_t, std::string>> HashNameMap;
+ // Unique name strings.
+ StringSet<> NameTab;
+ // A map from MD5 keys to function name strings.
+ std::vector<std::pair<uint64_t, StringRef>> MD5NameMap;
+ // A map from MD5 keys to function define. We only populate this map
+ // when build the Symtab from a Module.
+ std::vector<std::pair<uint64_t, Function *>> MD5FuncMap;
// A map from function runtime address to function name MD5 hash.
// This map is only populated and used by raw instr profile reader.
AddrHashMap AddrToMD5Map;
public:
- InstrProfSymtab() : Data(), Address(0), HashNameMap(), AddrToMD5Map() {}
+ InstrProfSymtab()
+ : Data(), Address(0), NameTab(), MD5NameMap(), MD5FuncMap(),
+ AddrToMD5Map() {}
/// Create InstrProfSymtab from an object file section which
- /// contains function PGO names that are uncompressed.
- /// This interface is used by CoverageMappingReader.
- std::error_code create(object::SectionRef &Section);
+ /// contains function PGO names. When section may contain raw
+ /// string data or string data in compressed form. This method
+ /// only initialize the symtab with reference to the data and
+ /// the section base address. The decompression will be delayed
+ /// until before it is used. See also \c create(StringRef) method.
+ Error create(object::SectionRef &Section);
/// This interface is used by reader of CoverageMapping test
/// format.
- inline std::error_code create(StringRef D, uint64_t BaseAddr);
+ inline Error create(StringRef D, uint64_t BaseAddr);
/// \c NameStrings is a string composed of one of more sub-strings
- /// encoded in the format described above. The substrings are
- /// seperated by 0 or more zero bytes. This method decodes the
- /// string and populates the \c Symtab.
- inline std::error_code create(StringRef NameStrings);
+ /// encoded in the format described in \c collectPGOFuncNameStrings.
+ /// This method is a wrapper to \c readPGOFuncNameStrings method.
+ inline Error create(StringRef NameStrings);
+ /// A wrapper interface to populate the PGO symtab with functions
+ /// decls from module \c M. This interface is used by transformation
+ /// passes such as indirect function call promotion. Variable \c InLTO
+ /// indicates if this is called from LTO optimization passes.
+ void create(Module &M, bool InLTO = false);
/// Create InstrProfSymtab from a set of names iteratable from
/// \p IterRange. This interface is used by IndexedProfReader.
template <typename NameIterRange> void create(const NameIterRange &IterRange);
@@ -282,8 +457,10 @@ public:
/// Update the symtab by adding \p FuncName to the table. This interface
/// is used by the raw and text profile readers.
void addFuncName(StringRef FuncName) {
- HashNameMap.push_back(std::make_pair(
- IndexedInstrProf::ComputeHash(FuncName), FuncName.str()));
+ auto Ins = NameTab.insert(FuncName);
+ if (Ins.second)
+ MD5NameMap.push_back(std::make_pair(
+ IndexedInstrProf::ComputeHash(FuncName), Ins.first->getKey()));
}
/// Map a function address to its name's MD5 hash. This interface
/// is only used by the raw profiler reader.
@@ -298,32 +475,37 @@ public:
/// Return function's PGO name from the name's md5 hash value.
/// If not found, return an empty string.
inline StringRef getFuncName(uint64_t FuncMD5Hash);
+ /// Return function from the name's md5 hash. Return nullptr if not found.
+ inline Function *getFunction(uint64_t FuncMD5Hash);
+ /// Return the function's original assembly name by stripping off
+ /// the prefix attached (to symbols with priviate linkage). For
+ /// global functions, it returns the same string as getFuncName.
+ inline StringRef getOrigFuncName(uint64_t FuncMD5Hash);
+ /// Return the name section data.
+ inline StringRef getNameData() const { return Data; }
};
-std::error_code InstrProfSymtab::create(StringRef D, uint64_t BaseAddr) {
+Error InstrProfSymtab::create(StringRef D, uint64_t BaseAddr) {
Data = D;
Address = BaseAddr;
- return std::error_code();
+ return Error::success();
}
-std::error_code InstrProfSymtab::create(StringRef NameStrings) {
- if (readPGOFuncNameStrings(NameStrings, *this))
- return make_error_code(instrprof_error::malformed);
- return std::error_code();
+Error InstrProfSymtab::create(StringRef NameStrings) {
+ return readPGOFuncNameStrings(NameStrings, *this);
}
template <typename NameIterRange>
void InstrProfSymtab::create(const NameIterRange &IterRange) {
for (auto Name : IterRange)
- HashNameMap.push_back(
- std::make_pair(IndexedInstrProf::ComputeHash(Name), Name.str()));
+ addFuncName(Name);
+
finalizeSymtab();
}
void InstrProfSymtab::finalizeSymtab() {
- std::sort(HashNameMap.begin(), HashNameMap.end(), less_first());
- HashNameMap.erase(std::unique(HashNameMap.begin(), HashNameMap.end()),
- HashNameMap.end());
+ std::sort(MD5NameMap.begin(), MD5NameMap.end(), less_first());
+ std::sort(MD5FuncMap.begin(), MD5FuncMap.end(), less_first());
std::sort(AddrToMD5Map.begin(), AddrToMD5Map.end(), less_first());
AddrToMD5Map.erase(std::unique(AddrToMD5Map.begin(), AddrToMD5Map.end()),
AddrToMD5Map.end());
@@ -331,14 +513,34 @@ void InstrProfSymtab::finalizeSymtab() {
StringRef InstrProfSymtab::getFuncName(uint64_t FuncMD5Hash) {
auto Result =
- std::lower_bound(HashNameMap.begin(), HashNameMap.end(), FuncMD5Hash,
+ std::lower_bound(MD5NameMap.begin(), MD5NameMap.end(), FuncMD5Hash,
[](const std::pair<uint64_t, std::string> &LHS,
uint64_t RHS) { return LHS.first < RHS; });
- if (Result != HashNameMap.end())
+ if (Result != MD5NameMap.end() && Result->first == FuncMD5Hash)
return Result->second;
return StringRef();
}
+Function* InstrProfSymtab::getFunction(uint64_t FuncMD5Hash) {
+ auto Result =
+ std::lower_bound(MD5FuncMap.begin(), MD5FuncMap.end(), FuncMD5Hash,
+ [](const std::pair<uint64_t, Function*> &LHS,
+ uint64_t RHS) { return LHS.first < RHS; });
+ if (Result != MD5FuncMap.end() && Result->first == FuncMD5Hash)
+ return Result->second;
+ return nullptr;
+}
+
+// See also getPGOFuncName implementation. These two need to be
+// matched.
+StringRef InstrProfSymtab::getOrigFuncName(uint64_t FuncMD5Hash) {
+ StringRef PGOName = getFuncName(FuncMD5Hash);
+ size_t S = PGOName.find_first_of(':');
+ if (S == StringRef::npos)
+ return PGOName;
+ return PGOName.drop_front(S + 1);
+}
+
struct InstrProfValueSiteRecord {
/// Value profiling data pairs at a given value site.
std::list<InstrProfValueData> ValueData;
@@ -360,19 +562,21 @@ struct InstrProfValueSiteRecord {
/// Merge data from another InstrProfValueSiteRecord
/// Optionally scale merged counts by \p Weight.
- instrprof_error merge(InstrProfValueSiteRecord &Input, uint64_t Weight = 1);
+ void merge(SoftInstrProfErrors &SIPE, InstrProfValueSiteRecord &Input,
+ uint64_t Weight = 1);
/// Scale up value profile data counts.
- instrprof_error scale(uint64_t Weight);
+ void scale(SoftInstrProfErrors &SIPE, uint64_t Weight);
};
/// Profiling information for a single function.
struct InstrProfRecord {
- InstrProfRecord() {}
+ InstrProfRecord() : SIPE() {}
InstrProfRecord(StringRef Name, uint64_t Hash, std::vector<uint64_t> Counts)
- : Name(Name), Hash(Hash), Counts(std::move(Counts)) {}
+ : Name(Name), Hash(Hash), Counts(std::move(Counts)), SIPE() {}
StringRef Name;
uint64_t Hash;
std::vector<uint64_t> Counts;
+ SoftInstrProfErrors SIPE;
typedef std::vector<std::pair<uint64_t, uint64_t>> ValueMapType;
@@ -387,13 +591,17 @@ struct InstrProfRecord {
/// site: Site.
inline uint32_t getNumValueDataForSite(uint32_t ValueKind,
uint32_t Site) const;
- /// Return the array of profiled values at \p Site.
+ /// Return the array of profiled values at \p Site. If \p TotalC
+ /// is not null, the total count of all target values at this site
+ /// will be stored in \c *TotalC.
inline std::unique_ptr<InstrProfValueData[]>
getValueForSite(uint32_t ValueKind, uint32_t Site,
- uint64_t (*ValueMapper)(uint32_t, uint64_t) = 0) const;
- inline void
- getValueForSite(InstrProfValueData Dest[], uint32_t ValueKind, uint32_t Site,
- uint64_t (*ValueMapper)(uint32_t, uint64_t) = 0) const;
+ uint64_t *TotalC = 0) const;
+ /// Get the target value/counts of kind \p ValueKind collected at site
+ /// \p Site and store the result in array \p Dest. Return the total
+ /// counts of all target values at this site.
+ inline uint64_t getValueForSite(InstrProfValueData Dest[], uint32_t ValueKind,
+ uint32_t Site) const;
/// Reserve space for NumValueSites sites.
inline void reserveSites(uint32_t ValueKind, uint32_t NumValueSites);
/// Add ValueData for ValueKind at value Site.
@@ -403,11 +611,11 @@ struct InstrProfRecord {
/// Merge the counts in \p Other into this one.
/// Optionally scale merged counts by \p Weight.
- instrprof_error merge(InstrProfRecord &Other, uint64_t Weight = 1);
+ void merge(InstrProfRecord &Other, uint64_t Weight = 1);
/// Scale up profile counts (including value profile data) by
/// \p Weight.
- instrprof_error scale(uint64_t Weight);
+ void scale(uint64_t Weight);
/// Sort value profile data (per site) by count.
void sortValueData() {
@@ -424,6 +632,9 @@ struct InstrProfRecord {
getValueSitesForKind(Kind).clear();
}
+ /// Get the error contained within the record's soft error counter.
+ Error takeError() { return SIPE.takeError(); }
+
private:
std::vector<InstrProfValueSiteRecord> IndirectCallSites;
const std::vector<InstrProfValueSiteRecord> &
@@ -450,10 +661,10 @@ private:
// Merge Value Profile data from Src record to this record for ValueKind.
// Scale merged value counts by \p Weight.
- instrprof_error mergeValueProfData(uint32_t ValueKind, InstrProfRecord &Src,
- uint64_t Weight);
+ void mergeValueProfData(uint32_t ValueKind, InstrProfRecord &Src,
+ uint64_t Weight);
// Scale up value profile data count.
- instrprof_error scaleValueProfData(uint32_t ValueKind, uint64_t Weight);
+ void scaleValueProfData(uint32_t ValueKind, uint64_t Weight);
};
uint32_t InstrProfRecord::getNumValueKinds() const {
@@ -482,29 +693,35 @@ uint32_t InstrProfRecord::getNumValueDataForSite(uint32_t ValueKind,
return getValueSitesForKind(ValueKind)[Site].ValueData.size();
}
-std::unique_ptr<InstrProfValueData[]> InstrProfRecord::getValueForSite(
- uint32_t ValueKind, uint32_t Site,
- uint64_t (*ValueMapper)(uint32_t, uint64_t)) const {
+std::unique_ptr<InstrProfValueData[]>
+InstrProfRecord::getValueForSite(uint32_t ValueKind, uint32_t Site,
+ uint64_t *TotalC) const {
+ uint64_t Dummy;
+ uint64_t &TotalCount = (TotalC == 0 ? Dummy : *TotalC);
uint32_t N = getNumValueDataForSite(ValueKind, Site);
- if (N == 0)
+ if (N == 0) {
+ TotalCount = 0;
return std::unique_ptr<InstrProfValueData[]>(nullptr);
+ }
auto VD = llvm::make_unique<InstrProfValueData[]>(N);
- getValueForSite(VD.get(), ValueKind, Site, ValueMapper);
+ TotalCount = getValueForSite(VD.get(), ValueKind, Site);
return VD;
}
-void InstrProfRecord::getValueForSite(InstrProfValueData Dest[],
- uint32_t ValueKind, uint32_t Site,
- uint64_t (*ValueMapper)(uint32_t,
- uint64_t)) const {
+uint64_t InstrProfRecord::getValueForSite(InstrProfValueData Dest[],
+ uint32_t ValueKind,
+ uint32_t Site) const {
uint32_t I = 0;
+ uint64_t TotalCount = 0;
for (auto V : getValueSitesForKind(ValueKind)[Site].ValueData) {
- Dest[I].Value = ValueMapper ? ValueMapper(ValueKind, V.Value) : V.Value;
+ Dest[I].Value = V.Value;
Dest[I].Count = V.Count;
+ TotalCount = SaturatingAdd(TotalCount, V.Count);
I++;
}
+ return TotalCount;
}
void InstrProfRecord::reserveSites(uint32_t ValueKind, uint32_t NumValueSites) {
@@ -532,27 +749,6 @@ void InstrProfValueSiteRecord::sortByCount() {
ValueData.resize(max_s);
}
-/*
-* Initialize the record for runtime value profile data.
-* Return 0 if the initialization is successful, otherwise
-* return 1.
-*/
-int initializeValueProfRuntimeRecord(ValueProfRuntimeRecord *RuntimeRecord,
- const uint16_t *NumValueSites,
- ValueProfNode **Nodes);
-
-/* Release memory allocated for the runtime record. */
-void finalizeValueProfRuntimeRecord(ValueProfRuntimeRecord *RuntimeRecord);
-
-/* Return the size of ValueProfData structure that can be used to store
- the value profile data collected at runtime. */
-uint32_t getValueProfDataSizeRT(const ValueProfRuntimeRecord *Record);
-
-/* Return a ValueProfData instance that stores the data collected at runtime. */
-ValueProfData *
-serializeValueProfDataFromRT(const ValueProfRuntimeRecord *Record,
- ValueProfData *Dst);
-
namespace IndexedInstrProf {
enum class HashT : uint32_t {
@@ -561,27 +757,38 @@ enum class HashT : uint32_t {
Last = MD5
};
-static inline uint64_t MD5Hash(StringRef Str) {
- MD5 Hash;
- Hash.update(Str);
- llvm::MD5::MD5Result Result;
- Hash.final(Result);
- // Return the least significant 8 bytes. Our MD5 implementation returns the
- // result in little endian, so we may need to swap bytes.
- using namespace llvm::support;
- return endian::read<uint64_t, little, unaligned>(Result);
-}
-
inline uint64_t ComputeHash(HashT Type, StringRef K) {
switch (Type) {
case HashT::MD5:
- return IndexedInstrProf::MD5Hash(K);
+ return MD5Hash(K);
}
llvm_unreachable("Unhandled hash type");
}
const uint64_t Magic = 0x8169666f72706cff; // "\xfflprofi\x81"
-const uint64_t Version = INSTR_PROF_INDEX_VERSION;
+
+enum ProfVersion {
+ // Version 1 is the first version. In this version, the value of
+ // a key/value pair can only include profile data of a single function.
+ // Due to this restriction, the number of block counters for a given
+ // function is not recorded but derived from the length of the value.
+ Version1 = 1,
+ // The version 2 format supports recording profile data of multiple
+ // functions which share the same key in one value field. To support this,
+ // the number block counters is recorded as an uint64_t field right after the
+ // function structural hash.
+ Version2 = 2,
+ // Version 3 supports value profile data. The value profile data is expected
+ // to follow the block counter profile data.
+ Version3 = 3,
+ // In this version, profile summary data \c IndexedInstrProf::Summary is
+ // stored after the profile header.
+ Version4 = 4,
+ // The current version is 4.
+ CurrentVersion = INSTR_PROF_INDEX_VERSION
+};
+const uint64_t Version = ProfVersion::CurrentVersion;
+
const HashT HashType = HashT::MD5;
inline uint64_t ComputeHash(StringRef K) { return ComputeHash(HashType, K); }
@@ -591,15 +798,104 @@ inline uint64_t ComputeHash(StringRef K) { return ComputeHash(HashType, K); }
struct Header {
uint64_t Magic;
uint64_t Version;
- uint64_t MaxFunctionCount;
+ uint64_t Unused; // Becomes unused since version 4
uint64_t HashType;
uint64_t HashOffset;
};
+// Profile summary data recorded in the profile data file in indexed
+// format. It is introduced in version 4. The summary data follows
+// right after the profile file header.
+struct Summary {
+
+ struct Entry {
+ uint64_t Cutoff; ///< The required percentile of total execution count.
+ uint64_t
+ MinBlockCount; ///< The minimum execution count for this percentile.
+ uint64_t NumBlocks; ///< Number of blocks >= the minumum execution count.
+ };
+ // The field kind enumerator to assigned value mapping should remain
+ // unchanged when a new kind is added or an old kind gets deleted in
+ // the future.
+ enum SummaryFieldKind {
+ /// The total number of functions instrumented.
+ TotalNumFunctions = 0,
+ /// Total number of instrumented blocks/edges.
+ TotalNumBlocks = 1,
+ /// The maximal execution count among all functions.
+ /// This field does not exist for profile data from IR based
+ /// instrumentation.
+ MaxFunctionCount = 2,
+ /// Max block count of the program.
+ MaxBlockCount = 3,
+ /// Max internal block count of the program (excluding entry blocks).
+ MaxInternalBlockCount = 4,
+ /// The sum of all instrumented block counts.
+ TotalBlockCount = 5,
+ NumKinds = TotalBlockCount + 1
+ };
+
+ // The number of summmary fields following the summary header.
+ uint64_t NumSummaryFields;
+ // The number of Cutoff Entries (Summary::Entry) following summary fields.
+ uint64_t NumCutoffEntries;
+
+ static uint32_t getSize(uint32_t NumSumFields, uint32_t NumCutoffEntries) {
+ return sizeof(Summary) + NumCutoffEntries * sizeof(Entry) +
+ NumSumFields * sizeof(uint64_t);
+ }
+
+ const uint64_t *getSummaryDataBase() const {
+ return reinterpret_cast<const uint64_t *>(this + 1);
+ }
+ uint64_t *getSummaryDataBase() {
+ return reinterpret_cast<uint64_t *>(this + 1);
+ }
+ const Entry *getCutoffEntryBase() const {
+ return reinterpret_cast<const Entry *>(
+ &getSummaryDataBase()[NumSummaryFields]);
+ }
+ Entry *getCutoffEntryBase() {
+ return reinterpret_cast<Entry *>(&getSummaryDataBase()[NumSummaryFields]);
+ }
+
+ uint64_t get(SummaryFieldKind K) const {
+ return getSummaryDataBase()[K];
+ }
+
+ void set(SummaryFieldKind K, uint64_t V) {
+ getSummaryDataBase()[K] = V;
+ }
+
+ const Entry &getEntry(uint32_t I) const { return getCutoffEntryBase()[I]; }
+ void setEntry(uint32_t I, const ProfileSummaryEntry &E) {
+ Entry &ER = getCutoffEntryBase()[I];
+ ER.Cutoff = E.Cutoff;
+ ER.MinBlockCount = E.MinCount;
+ ER.NumBlocks = E.NumCounts;
+ }
+
+ Summary(uint32_t Size) { memset(this, 0, Size); }
+ void operator delete(void *ptr) { ::operator delete(ptr); }
+
+ Summary() = delete;
+};
+
+inline std::unique_ptr<Summary> allocSummary(uint32_t TotalSize) {
+ return std::unique_ptr<Summary>(new (::operator new(TotalSize))
+ Summary(TotalSize));
+}
} // end namespace IndexedInstrProf
namespace RawInstrProf {
+// Version 1: First version
+// Version 2: Added value profile data section. Per-function control data
+// struct has more fields to describe value profile information.
+// Version 3: Compressed name section support. Function PGO name reference
+// from control data struct is changed from raw pointer to Name's MD5 value.
+// Version 4: ValueDataBegin and ValueDataSizes fields are removed from the
+// raw header.
const uint64_t Version = INSTR_PROF_RAW_VERSION;
template <class IntPtrT> inline uint64_t getMagic();
@@ -630,13 +926,8 @@ struct Header {
#include "llvm/ProfileData/InstrProfData.inc"
};
-} // end namespace RawInstrProf
+} // end namespace RawInstrProf
} // end namespace llvm
-namespace std {
-template <>
-struct is_error_code_enum<llvm::instrprof_error> : std::true_type {};
-}
-
-#endif // LLVM_PROFILEDATA_INSTRPROF_H_
+#endif // LLVM_PROFILEDATA_INSTRPROF_H
diff --git a/include/llvm/ProfileData/InstrProfData.inc b/include/llvm/ProfileData/InstrProfData.inc
index 33c7d94aea2a..4138e18fa22f 100644
--- a/include/llvm/ProfileData/InstrProfData.inc
+++ b/include/llvm/ProfileData/InstrProfData.inc
@@ -57,6 +57,12 @@
*
\*===----------------------------------------------------------------------===*/
+/* Functions marked with INSTR_PROF_VISIBILITY must have hidden visibility in
+ * the compiler runtime. */
+#ifndef INSTR_PROF_VISIBILITY
+#define INSTR_PROF_VISIBILITY
+#endif
+
/* INSTR_PROF_DATA start. */
/* Definition of member fields of the per-function control structure. */
#ifndef INSTR_PROF_DATA
@@ -64,29 +70,57 @@
#else
#define INSTR_PROF_DATA_DEFINED
#endif
-
-INSTR_PROF_DATA(const uint32_t, llvm::Type::getInt32Ty(Ctx), NameSize, \
- ConstantInt::get(llvm::Type::getInt32Ty(Ctx), \
- NamePtr->getType()->getPointerElementType()->getArrayNumElements()))
-INSTR_PROF_DATA(const uint32_t, llvm::Type::getInt32Ty(Ctx), NumCounters, \
- ConstantInt::get(llvm::Type::getInt32Ty(Ctx), NumCounters))
+INSTR_PROF_DATA(const uint64_t, llvm::Type::getInt64Ty(Ctx), NameRef, \
+ ConstantInt::get(llvm::Type::getInt64Ty(Ctx), \
+ IndexedInstrProf::ComputeHash(getPGOFuncNameVarInitializer(Inc->getName()))))
INSTR_PROF_DATA(const uint64_t, llvm::Type::getInt64Ty(Ctx), FuncHash, \
ConstantInt::get(llvm::Type::getInt64Ty(Ctx), \
Inc->getHash()->getZExtValue()))
-INSTR_PROF_DATA(const IntPtrT, llvm::Type::getInt8PtrTy(Ctx), NamePtr, \
- ConstantExpr::getBitCast(NamePtr, llvm::Type::getInt8PtrTy(Ctx)))
INSTR_PROF_DATA(const IntPtrT, llvm::Type::getInt64PtrTy(Ctx), CounterPtr, \
ConstantExpr::getBitCast(CounterPtr, \
llvm::Type::getInt64PtrTy(Ctx)))
+/* This is used to map function pointers for the indirect call targets to
+ * function name hashes during the conversion from raw to merged profile
+ * data.
+ */
INSTR_PROF_DATA(const IntPtrT, llvm::Type::getInt8PtrTy(Ctx), FunctionPointer, \
FunctionAddr)
INSTR_PROF_DATA(IntPtrT, llvm::Type::getInt8PtrTy(Ctx), Values, \
- ConstantPointerNull::get(Int8PtrTy))
+ ValuesPtrExpr)
+INSTR_PROF_DATA(const uint32_t, llvm::Type::getInt32Ty(Ctx), NumCounters, \
+ ConstantInt::get(llvm::Type::getInt32Ty(Ctx), NumCounters))
INSTR_PROF_DATA(const uint16_t, Int16ArrayTy, NumValueSites[IPVK_Last+1], \
ConstantArray::get(Int16ArrayTy, Int16ArrayVals))
#undef INSTR_PROF_DATA
/* INSTR_PROF_DATA end. */
+
+/* This is an internal data structure used by value profiler. It
+ * is defined here to allow serialization code sharing by LLVM
+ * to be used in unit test.
+ *
+ * typedef struct ValueProfNode {
+ * // InstrProfValueData VData;
+ * uint64_t Value;
+ * uint64_t Count;
+ * struct ValueProfNode *Next;
+ * } ValueProfNode;
+ */
+/* INSTR_PROF_VALUE_NODE start. */
+#ifndef INSTR_PROF_VALUE_NODE
+#define INSTR_PROF_VALUE_NODE(Type, LLVMType, Name, Initializer)
+#else
+#define INSTR_PROF_DATA_DEFINED
+#endif
+INSTR_PROF_VALUE_NODE(uint64_t, llvm::Type::getInt64Ty(Ctx), Value, \
+ ConstantInt::get(llvm::Type::GetInt64Ty(Ctx), 0))
+INSTR_PROF_VALUE_NODE(uint64_t, llvm::Type::getInt64Ty(Ctx), Count, \
+ ConstantInt::get(llvm::Type::GetInt64Ty(Ctx), 0))
+INSTR_PROF_VALUE_NODE(PtrToNodeT, llvm::Type::getInt8PtrTy(Ctx), Next, \
+ ConstantInt::get(llvm::Type::GetInt8PtrTy(Ctx), 0))
+#undef INSTR_PROF_VALUE_NODE
+/* INSTR_PROF_VALUE_NODE end. */
+
/* INSTR_PROF_RAW_HEADER start */
/* Definition of member fields of the raw profile header data structure. */
#ifndef INSTR_PROF_RAW_HEADER
@@ -102,8 +136,6 @@ INSTR_PROF_RAW_HEADER(uint64_t, NamesSize, NamesSize)
INSTR_PROF_RAW_HEADER(uint64_t, CountersDelta, (uintptr_t)CountersBegin)
INSTR_PROF_RAW_HEADER(uint64_t, NamesDelta, (uintptr_t)NamesBegin)
INSTR_PROF_RAW_HEADER(uint64_t, ValueKindLast, IPVK_Last)
-INSTR_PROF_RAW_HEADER(uint64_t, ValueDataSize, ValueDataSize)
-INSTR_PROF_RAW_HEADER(uint64_t, ValueDataDelta, (uintptr_t)ValueDataBegin)
#undef INSTR_PROF_RAW_HEADER
/* INSTR_PROF_RAW_HEADER end */
@@ -132,6 +164,15 @@ VALUE_PROF_FUNC_PARAM(uint32_t, CounterIndex, Type::getInt32Ty(Ctx))
#else
#define INSTR_PROF_DATA_DEFINED
#endif
+/* For indirect function call value profiling, the addresses of the target
+ * functions are profiled by the instrumented code. The target addresses are
+ * written in the raw profile data and converted to target function name's MD5
+ * hash by the profile reader during deserialization. Typically, this happens
+ * when the the raw profile data is read during profile merging.
+ *
+ * For this remapping the ProfData is used. ProfData contains both the function
+ * name hash and the function address.
+ */
VALUE_PROF_KIND(IPVK_IndirectCallTarget, 0)
/* These two kinds must be the last to be
* declared. This is to make sure the string
@@ -153,12 +194,18 @@ VALUE_PROF_KIND(IPVK_Last, IPVK_IndirectCallTarget)
#else
#define INSTR_PROF_DATA_DEFINED
#endif
+#ifdef COVMAP_V1
COVMAP_FUNC_RECORD(const IntPtrT, llvm::Type::getInt8PtrTy(Ctx), \
NamePtr, llvm::ConstantExpr::getBitCast(NamePtr, \
llvm::Type::getInt8PtrTy(Ctx)))
COVMAP_FUNC_RECORD(const uint32_t, llvm::Type::getInt32Ty(Ctx), NameSize, \
- llvm::ConstantInt::get(llvm::Type::getInt32Ty(Ctx),\
+ llvm::ConstantInt::get(llvm::Type::getInt32Ty(Ctx), \
NameValue.size()))
+#else
+COVMAP_FUNC_RECORD(const int64_t, llvm::Type::getInt64Ty(Ctx), NameRef, \
+ llvm::ConstantInt::get(llvm::Type::getInt64Ty(Ctx), \
+ llvm::IndexedInstrProf::ComputeHash(NameValue)))
+#endif
COVMAP_FUNC_RECORD(const uint32_t, llvm::Type::getInt32Ty(Ctx), DataSize, \
llvm::ConstantInt::get(llvm::Type::getInt32Ty(Ctx),\
CoverageMapping.size()))
@@ -182,7 +229,7 @@ COVMAP_HEADER(uint32_t, Int32Ty, FilenamesSize, \
COVMAP_HEADER(uint32_t, Int32Ty, CoverageSize, \
llvm::ConstantInt::get(Int32Ty, CoverageMappingSize))
COVMAP_HEADER(uint32_t, Int32Ty, Version, \
- llvm::ConstantInt::get(Int32Ty, CoverageMappingCurrentVersion))
+ llvm::ConstantInt::get(Int32Ty, CovMapVersion::CurrentVersion))
#undef COVMAP_HEADER
/* COVMAP_HEADER end. */
@@ -281,16 +328,15 @@ typedef struct ValueProfData {
static std::unique_ptr<ValueProfData>
serializeFrom(const InstrProfRecord &Record);
/*!
- * Check the integrity of the record. Return the error code when
- * an error is detected, otherwise return instrprof_error::success.
+ * Check the integrity of the record.
*/
- instrprof_error checkIntegrity();
+ Error checkIntegrity();
/*!
* Return a pointer to \c ValueProfileData instance ready to be read.
* All data in the instance are properly byte swapped. The input
* data is assumed to be in little endian order.
*/
- static ErrorOr<std::unique_ptr<ValueProfData>>
+ static Expected<std::unique_ptr<ValueProfData>>
getValueProfData(const unsigned char *SrcBuffer,
const unsigned char *const SrcBufferEnd,
support::endianness SrcDataEndianness);
@@ -343,46 +389,18 @@ typedef struct ValueProfRecordClosure {
*/
uint64_t (*RemapValueData)(uint32_t, uint64_t Value);
void (*GetValueForSite)(const void *R, InstrProfValueData *Dst, uint32_t K,
- uint32_t S, uint64_t (*Mapper)(uint32_t, uint64_t));
+ uint32_t S);
ValueProfData *(*AllocValueProfData)(size_t TotalSizeInBytes);
} ValueProfRecordClosure;
-/*
- * A wrapper struct that represents value profile runtime data.
- * Like InstrProfRecord class which is used by profiling host tools,
- * ValueProfRuntimeRecord also implements the abstract intefaces defined in
- * ValueProfRecordClosure so that the runtime data can be serialized using
- * shared C implementation. In this structure, NumValueSites and Nodes
- * members are the primary fields while other fields hold the derived
- * information for fast implementation of closure interfaces.
- */
-typedef struct ValueProfRuntimeRecord {
- /* Number of sites for each value profile kind. */
- const uint16_t *NumValueSites;
- /* An array of linked-list headers. The size of of the array is the
- * total number of value profile sites : sum(NumValueSites[*])). Each
- * linked-list stores the values profiled for a value profile site. */
- ValueProfNode **Nodes;
-
- /* Total number of value profile kinds which have at least one
- * value profile sites. */
- uint32_t NumValueKinds;
- /* An array recording the number of values tracked at each site.
- * The size of the array is TotalNumValueSites. */
- uint8_t *SiteCountArray[IPVK_Last + 1];
- ValueProfNode **NodesKind[IPVK_Last + 1];
-} ValueProfRuntimeRecord;
-
-/* Forward declarations of C interfaces. */
-int initializeValueProfRuntimeRecord(ValueProfRuntimeRecord *RuntimeRecord,
- const uint16_t *NumValueSites,
- ValueProfNode **Nodes);
-void finalizeValueProfRuntimeRecord(ValueProfRuntimeRecord *RuntimeRecord);
-uint32_t getValueProfDataSizeRT(const ValueProfRuntimeRecord *Record);
-ValueProfData *
-serializeValueProfDataFromRT(const ValueProfRuntimeRecord *Record,
- ValueProfData *Dst);
-uint32_t getNumValueKindsRT(const void *R);
+INSTR_PROF_VISIBILITY ValueProfRecord *
+getFirstValueProfRecord(ValueProfData *VPD);
+INSTR_PROF_VISIBILITY ValueProfRecord *
+getValueProfRecordNext(ValueProfRecord *VPR);
+INSTR_PROF_VISIBILITY InstrProfValueData *
+getValueProfRecordValueData(ValueProfRecord *VPR);
+INSTR_PROF_VISIBILITY uint32_t
+getValueProfRecordHeaderSize(uint32_t NumValueSites);
#undef INSTR_PROF_VALUE_PROF_DATA
#endif /* INSTR_PROF_VALUE_PROF_DATA */
@@ -392,8 +410,10 @@ uint32_t getNumValueKindsRT(const void *R);
#define INSTR_PROF_DATA_DEFINED
#ifdef __cplusplus
#define INSTR_PROF_INLINE inline
+#define INSTR_PROF_NULLPTR nullptr
#else
#define INSTR_PROF_INLINE
+#define INSTR_PROF_NULLPTR NULL
#endif
#ifndef offsetof
@@ -404,7 +424,7 @@ uint32_t getNumValueKindsRT(const void *R);
* \brief Return the \c ValueProfRecord header size including the
* padding bytes.
*/
-INSTR_PROF_INLINE
+INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
uint32_t getValueProfRecordHeaderSize(uint32_t NumValueSites) {
uint32_t Size = offsetof(ValueProfRecord, SiteCountArray) +
sizeof(uint8_t) * NumValueSites;
@@ -417,7 +437,7 @@ uint32_t getValueProfRecordHeaderSize(uint32_t NumValueSites) {
* \brief Return the total size of the value profile record including the
* header and the value data.
*/
-INSTR_PROF_INLINE
+INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
uint32_t getValueProfRecordSize(uint32_t NumValueSites,
uint32_t NumValueData) {
return getValueProfRecordHeaderSize(NumValueSites) +
@@ -427,7 +447,7 @@ uint32_t getValueProfRecordSize(uint32_t NumValueSites,
/*!
* \brief Return the pointer to the start of value data array.
*/
-INSTR_PROF_INLINE
+INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
InstrProfValueData *getValueProfRecordValueData(ValueProfRecord *This) {
return (InstrProfValueData *)((char *)This + getValueProfRecordHeaderSize(
This->NumValueSites));
@@ -436,7 +456,7 @@ InstrProfValueData *getValueProfRecordValueData(ValueProfRecord *This) {
/*!
* \brief Return the total number of value data for \c This record.
*/
-INSTR_PROF_INLINE
+INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
uint32_t getValueProfRecordNumValueData(ValueProfRecord *This) {
uint32_t NumValueData = 0;
uint32_t I;
@@ -448,7 +468,7 @@ uint32_t getValueProfRecordNumValueData(ValueProfRecord *This) {
/*!
* \brief Use this method to advance to the next \c This \c ValueProfRecord.
*/
-INSTR_PROF_INLINE
+INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
ValueProfRecord *getValueProfRecordNext(ValueProfRecord *This) {
uint32_t NumValueData = getValueProfRecordNumValueData(This);
return (ValueProfRecord *)((char *)This +
@@ -459,7 +479,7 @@ ValueProfRecord *getValueProfRecordNext(ValueProfRecord *This) {
/*!
* \brief Return the first \c ValueProfRecord instance.
*/
-INSTR_PROF_INLINE
+INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
ValueProfRecord *getFirstValueProfRecord(ValueProfData *This) {
return (ValueProfRecord *)((char *)This + sizeof(ValueProfData));
}
@@ -470,13 +490,11 @@ ValueProfRecord *getFirstValueProfRecord(ValueProfData *This) {
* Return the total size in bytes of the on-disk value profile data
* given the data stored in Record.
*/
-uint32_t getValueProfDataSize(ValueProfRecordClosure *Closure) {
+INSTR_PROF_VISIBILITY uint32_t
+getValueProfDataSize(ValueProfRecordClosure *Closure) {
uint32_t Kind;
uint32_t TotalSize = sizeof(ValueProfData);
const void *Record = Closure->Record;
- uint32_t NumValueKinds = Closure->GetNumValueKinds(Record);
- if (NumValueKinds == 0)
- return TotalSize;
for (Kind = IPVK_First; Kind <= IPVK_Last; Kind++) {
uint32_t NumValueSites = Closure->GetNumValueSites(Record, Kind);
@@ -492,9 +510,10 @@ uint32_t getValueProfDataSize(ValueProfRecordClosure *Closure) {
* Extract value profile data of a function for the profile kind \c ValueKind
* from the \c Closure and serialize the data into \c This record instance.
*/
-void serializeValueProfRecordFrom(ValueProfRecord *This,
- ValueProfRecordClosure *Closure,
- uint32_t ValueKind, uint32_t NumValueSites) {
+INSTR_PROF_VISIBILITY void
+serializeValueProfRecordFrom(ValueProfRecord *This,
+ ValueProfRecordClosure *Closure,
+ uint32_t ValueKind, uint32_t NumValueSites) {
uint32_t S;
const void *Record = Closure->Record;
This->Kind = ValueKind;
@@ -504,8 +523,7 @@ void serializeValueProfRecordFrom(ValueProfRecord *This,
for (S = 0; S < NumValueSites; S++) {
uint32_t ND = Closure->GetNumValueDataForSite(Record, ValueKind, S);
This->SiteCountArray[S] = ND;
- Closure->GetValueForSite(Record, DstVD, ValueKind, S,
- Closure->RemapValueData);
+ Closure->GetValueForSite(Record, DstVD, ValueKind, S);
DstVD += ND;
}
}
@@ -513,12 +531,16 @@ void serializeValueProfRecordFrom(ValueProfRecord *This,
/*!
* Extract value profile data of a function from the \c Closure
* and serialize the data into \c DstData if it is not NULL or heap
- * memory allocated by the \c Closure's allocator method.
+ * memory allocated by the \c Closure's allocator method. If \c
+ * DstData is not null, the caller is expected to set the TotalSize
+ * in DstData.
*/
-ValueProfData *serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
- ValueProfData *DstData) {
+INSTR_PROF_VISIBILITY ValueProfData *
+serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
+ ValueProfData *DstData) {
uint32_t Kind;
- uint32_t TotalSize = getValueProfDataSize(Closure);
+ uint32_t TotalSize =
+ DstData ? DstData->TotalSize : getValueProfDataSize(Closure);
ValueProfData *VPD =
DstData ? DstData : Closure->AllocValueProfData(TotalSize);
@@ -536,144 +558,15 @@ ValueProfData *serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
return VPD;
}
-/*
- * The value profiler runtime library stores the value profile data
- * for a given function in \c NumValueSites and \c Nodes structures.
- * \c ValueProfRuntimeRecord class is used to encapsulate the runtime
- * profile data and provides fast interfaces to retrieve the profile
- * information. This interface is used to initialize the runtime record
- * and pre-compute the information needed for efficient implementation
- * of callbacks required by ValueProfRecordClosure class.
- */
-int initializeValueProfRuntimeRecord(ValueProfRuntimeRecord *RuntimeRecord,
- const uint16_t *NumValueSites,
- ValueProfNode **Nodes) {
- unsigned I, J, S = 0, NumValueKinds = 0;
- RuntimeRecord->NumValueSites = NumValueSites;
- RuntimeRecord->Nodes = Nodes;
- for (I = 0; I <= IPVK_Last; I++) {
- uint16_t N = NumValueSites[I];
- if (!N) {
- RuntimeRecord->SiteCountArray[I] = 0;
- continue;
- }
- NumValueKinds++;
- RuntimeRecord->SiteCountArray[I] = (uint8_t *)calloc(N, 1);
- if (!RuntimeRecord->SiteCountArray[I])
- return 1;
- RuntimeRecord->NodesKind[I] = Nodes ? &Nodes[S] : NULL;
- for (J = 0; J < N; J++) {
- /* Compute value count for each site. */
- uint32_t C = 0;
- ValueProfNode *Site = Nodes ? RuntimeRecord->NodesKind[I][J] : NULL;
- while (Site) {
- C++;
- Site = Site->Next;
- }
- if (C > UCHAR_MAX)
- C = UCHAR_MAX;
- RuntimeRecord->SiteCountArray[I][J] = C;
- }
- S += N;
- }
- RuntimeRecord->NumValueKinds = NumValueKinds;
- return 0;
-}
-
-void finalizeValueProfRuntimeRecord(ValueProfRuntimeRecord *RuntimeRecord) {
- unsigned I;
- for (I = 0; I <= IPVK_Last; I++) {
- if (RuntimeRecord->SiteCountArray[I])
- free(RuntimeRecord->SiteCountArray[I]);
- }
-}
-
-/* ValueProfRecordClosure Interface implementation for
- * ValueProfDataRuntimeRecord. */
-uint32_t getNumValueKindsRT(const void *R) {
- return ((const ValueProfRuntimeRecord *)R)->NumValueKinds;
-}
-
-uint32_t getNumValueSitesRT(const void *R, uint32_t VK) {
- return ((const ValueProfRuntimeRecord *)R)->NumValueSites[VK];
-}
-
-uint32_t getNumValueDataForSiteRT(const void *R, uint32_t VK, uint32_t S) {
- const ValueProfRuntimeRecord *Record = (const ValueProfRuntimeRecord *)R;
- return Record->SiteCountArray[VK][S];
-}
-
-uint32_t getNumValueDataRT(const void *R, uint32_t VK) {
- unsigned I, S = 0;
- const ValueProfRuntimeRecord *Record = (const ValueProfRuntimeRecord *)R;
- if (Record->SiteCountArray[VK] == 0)
- return 0;
- for (I = 0; I < Record->NumValueSites[VK]; I++)
- S += Record->SiteCountArray[VK][I];
- return S;
-}
-
-void getValueForSiteRT(const void *R, InstrProfValueData *Dst, uint32_t VK,
- uint32_t S, uint64_t (*Mapper)(uint32_t, uint64_t)) {
- unsigned I, N = 0;
- const ValueProfRuntimeRecord *Record = (const ValueProfRuntimeRecord *)R;
- N = getNumValueDataForSiteRT(R, VK, S);
- if (N == 0)
- return;
- ValueProfNode *VNode = Record->NodesKind[VK][S];
- for (I = 0; I < N; I++) {
- Dst[I] = VNode->VData;
- VNode = VNode->Next;
- }
-}
-
-ValueProfData *allocValueProfDataRT(size_t TotalSizeInBytes) {
- return (ValueProfData *)calloc(TotalSizeInBytes, 1);
-}
-
-static ValueProfRecordClosure RTRecordClosure = {0,
- getNumValueKindsRT,
- getNumValueSitesRT,
- getNumValueDataRT,
- getNumValueDataForSiteRT,
- 0,
- getValueForSiteRT,
- allocValueProfDataRT};
-
-/*
- * Return the size of ValueProfData structure to store data
- * recorded in the runtime record.
- */
-uint32_t getValueProfDataSizeRT(const ValueProfRuntimeRecord *Record) {
- RTRecordClosure.Record = Record;
- return getValueProfDataSize(&RTRecordClosure);
-}
-
-/*
- * Return a ValueProfData instance that stores the data collected
- * from runtime. If \c DstData is provided by the caller, the value
- * profile data will be store in *DstData and DstData is returned,
- * otherwise the method will allocate space for the value data and
- * return pointer to the newly allocated space.
- */
-ValueProfData *
-serializeValueProfDataFromRT(const ValueProfRuntimeRecord *Record,
- ValueProfData *DstData) {
- RTRecordClosure.Record = Record;
- return serializeValueProfDataFrom(&RTRecordClosure, DstData);
-}
-
-
#undef INSTR_PROF_COMMON_API_IMPL
#endif /* INSTR_PROF_COMMON_API_IMPL */
/*============================================================================*/
-
#ifndef INSTR_PROF_DATA_DEFINED
-#ifndef INSTR_PROF_DATA_INC_
-#define INSTR_PROF_DATA_INC_
+#ifndef INSTR_PROF_DATA_INC
+#define INSTR_PROF_DATA_INC
/* Helper macros. */
#define INSTR_PROF_SIMPLE_QUOTE(x) #x
@@ -695,23 +588,33 @@ serializeValueProfDataFromRT(const ValueProfRuntimeRecord *Record,
(uint64_t)'p' << 40 | (uint64_t)'r' << 32 | (uint64_t)'o' << 24 | \
(uint64_t)'f' << 16 | (uint64_t)'R' << 8 | (uint64_t)129
-/* Raw profile format version. */
-#define INSTR_PROF_RAW_VERSION 2
-#define INSTR_PROF_INDEX_VERSION 3
-#define INSTR_PROF_COVMAP_VERSION 0
+/* Raw profile format version (start from 1). */
+#define INSTR_PROF_RAW_VERSION 4
+/* Indexed profile format version (start from 1). */
+#define INSTR_PROF_INDEX_VERSION 4
+/* Coverage mapping format vresion (start from 0). */
+#define INSTR_PROF_COVMAP_VERSION 1
-/* Profile version is always of type uint_64_t. Reserve the upper 8 bits in the
+/* Profile version is always of type uint64_t. Reserve the upper 8 bits in the
* version for other variants of profile. We set the lowest bit of the upper 8
* bits (i.e. bit 56) to 1 to indicate if this is an IR-level instrumentaiton
* generated profile, and 0 if this is a Clang FE generated profile.
-*/
+ */
#define VARIANT_MASKS_ALL 0xff00000000000000ULL
#define GET_VERSION(V) ((V) & ~VARIANT_MASKS_ALL)
+#define VARIANT_MASK_IR_PROF (0x1ULL << 56)
+#define IR_LEVEL_PROF_VERSION_VAR __llvm_profile_raw_version
/* Runtime section names and name strings. */
#define INSTR_PROF_DATA_SECT_NAME __llvm_prf_data
#define INSTR_PROF_NAME_SECT_NAME __llvm_prf_names
#define INSTR_PROF_CNTS_SECT_NAME __llvm_prf_cnts
+/* Array of pointers. Each pointer points to a list
+ * of value nodes associated with one value site.
+ */
+#define INSTR_PROF_VALS_SECT_NAME __llvm_prf_vals
+/* Value profile nodes section. */
+#define INSTR_PROF_VNODES_SECT_NAME __llvm_prf_vnds
#define INSTR_PROF_COVMAP_SECT_NAME __llvm_covmap
#define INSTR_PROF_DATA_SECT_NAME_STR \
@@ -722,6 +625,10 @@ serializeValueProfDataFromRT(const ValueProfRuntimeRecord *Record,
INSTR_PROF_QUOTE(INSTR_PROF_CNTS_SECT_NAME)
#define INSTR_PROF_COVMAP_SECT_NAME_STR \
INSTR_PROF_QUOTE(INSTR_PROF_COVMAP_SECT_NAME)
+#define INSTR_PROF_VALS_SECT_NAME_STR \
+ INSTR_PROF_QUOTE(INSTR_PROF_VALS_SECT_NAME)
+#define INSTR_PROF_VNODES_SECT_NAME_STR \
+ INSTR_PROF_QUOTE(INSTR_PROF_VNODES_SECT_NAME)
/* Macros to define start/stop section symbol for a given
* section on Linux. For instance
@@ -751,16 +658,7 @@ typedef struct InstrProfValueData {
uint64_t Count;
} InstrProfValueData;
-/* This is an internal data structure used by value profiler. It
- * is defined here to allow serialization code sharing by LLVM
- * to be used in unit test.
- */
-typedef struct ValueProfNode {
- InstrProfValueData VData;
- struct ValueProfNode *Next;
-} ValueProfNode;
-
-#endif /* INSTR_PROF_DATA_INC_ */
+#endif /* INSTR_PROF_DATA_INC */
#else
#undef INSTR_PROF_DATA_DEFINED
diff --git a/include/llvm/ProfileData/InstrProfReader.h b/include/llvm/ProfileData/InstrProfReader.h
index fed3e693e7a0..65b11f61d10b 100644
--- a/include/llvm/ProfileData/InstrProfReader.h
+++ b/include/llvm/ProfileData/InstrProfReader.h
@@ -19,7 +19,6 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/EndianStream.h"
-#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/OnDiskHashTable.h"
@@ -51,19 +50,20 @@ public:
/// Base class and interface for reading profiling data of any known instrprof
/// format. Provides an iterator over InstrProfRecords.
class InstrProfReader {
- std::error_code LastError;
+ instrprof_error LastError;
public:
InstrProfReader() : LastError(instrprof_error::success), Symtab() {}
virtual ~InstrProfReader() {}
/// Read the header. Required before reading first record.
- virtual std::error_code readHeader() = 0;
+ virtual Error readHeader() = 0;
/// Read a single record.
- virtual std::error_code readNextRecord(InstrProfRecord &Record) = 0;
+ virtual Error readNextRecord(InstrProfRecord &Record) = 0;
/// Iterator over profile data.
InstrProfIterator begin() { return InstrProfIterator(this); }
InstrProfIterator end() { return InstrProfIterator(); }
+ virtual bool isIRLevelProfile() const = 0;
/// Return the PGO symtab. There are three different readers:
/// Raw, Text, and Indexed profile readers. The first two types
@@ -79,28 +79,35 @@ public:
protected:
std::unique_ptr<InstrProfSymtab> Symtab;
- /// Set the current std::error_code and return same.
- std::error_code error(std::error_code EC) {
- LastError = EC;
- return EC;
+ /// Set the current error and return same.
+ Error error(instrprof_error Err) {
+ LastError = Err;
+ if (Err == instrprof_error::success)
+ return Error::success();
+ return make_error<InstrProfError>(Err);
}
+ Error error(Error E) { return error(InstrProfError::take(std::move(E))); }
- /// Clear the current error code and return a successful one.
- std::error_code success() { return error(instrprof_error::success); }
+ /// Clear the current error and return a successful one.
+ Error success() { return error(instrprof_error::success); }
public:
/// Return true if the reader has finished reading the profile data.
bool isEOF() { return LastError == instrprof_error::eof; }
/// Return true if the reader encountered an error reading profiling data.
- bool hasError() { return LastError && !isEOF(); }
- /// Get the current error code.
- std::error_code getError() { return LastError; }
+ bool hasError() { return LastError != instrprof_error::success && !isEOF(); }
+ /// Get the current error.
+ Error getError() {
+ if (hasError())
+ return make_error<InstrProfError>(LastError);
+ return Error::success();
+ }
/// Factory method to create an appropriately typed reader for the given
/// instrprof file.
- static ErrorOr<std::unique_ptr<InstrProfReader>> create(std::string Path);
+ static Expected<std::unique_ptr<InstrProfReader>> create(const Twine &Path);
- static ErrorOr<std::unique_ptr<InstrProfReader>>
+ static Expected<std::unique_ptr<InstrProfReader>>
create(std::unique_ptr<MemoryBuffer> Buffer);
};
@@ -118,22 +125,26 @@ private:
std::unique_ptr<MemoryBuffer> DataBuffer;
/// Iterator over the profile data.
line_iterator Line;
+ bool IsIRLevelProfile;
TextInstrProfReader(const TextInstrProfReader &) = delete;
TextInstrProfReader &operator=(const TextInstrProfReader &) = delete;
- std::error_code readValueProfileData(InstrProfRecord &Record);
+ Error readValueProfileData(InstrProfRecord &Record);
public:
TextInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer_)
- : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#') {}
+ : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#'),
+ IsIRLevelProfile(false) {}
/// Return true if the given buffer is in text instrprof format.
static bool hasFormat(const MemoryBuffer &Buffer);
+ bool isIRLevelProfile() const override { return IsIRLevelProfile; }
+
/// Read the header.
- std::error_code readHeader() override;
+ Error readHeader() override;
/// Read a single record.
- std::error_code readNextRecord(InstrProfRecord &Record) override;
+ Error readNextRecord(InstrProfRecord &Record) override;
InstrProfSymtab &getSymtab() override {
assert(Symtab.get());
@@ -154,14 +165,20 @@ private:
/// The profile data file contents.
std::unique_ptr<MemoryBuffer> DataBuffer;
bool ShouldSwapBytes;
+ // The value of the version field of the raw profile data header. The lower 56
+ // bits specifies the format version and the most significant 8 bits specify
+ // the variant types of the profile.
+ uint64_t Version;
uint64_t CountersDelta;
uint64_t NamesDelta;
const RawInstrProf::ProfileData<IntPtrT> *Data;
const RawInstrProf::ProfileData<IntPtrT> *DataEnd;
const uint64_t *CountersStart;
const char *NamesStart;
+ uint64_t NamesSize;
+ // After value profile is all read, this pointer points to
+ // the header of next profile data (if exists)
const uint8_t *ValueDataStart;
- const char *ProfileEnd;
uint32_t ValueKindLast;
uint32_t CurValueDataSize;
@@ -174,8 +191,11 @@ public:
: DataBuffer(std::move(DataBuffer)) { }
static bool hasFormat(const MemoryBuffer &DataBuffer);
- std::error_code readHeader() override;
- std::error_code readNextRecord(InstrProfRecord &Record) override;
+ Error readHeader() override;
+ Error readNextRecord(InstrProfRecord &Record) override;
+ bool isIRLevelProfile() const override {
+ return (Version & VARIANT_MASK_IR_PROF) != 0;
+ }
InstrProfSymtab &getSymtab() override {
assert(Symtab.get());
@@ -183,9 +203,9 @@ public:
}
private:
- void createSymtab(InstrProfSymtab &Symtab);
- std::error_code readNextHeader(const char *CurrentPos);
- std::error_code readHeader(const RawInstrProf::Header &Header);
+ Error createSymtab(InstrProfSymtab &Symtab);
+ Error readNextHeader(const char *CurrentPos);
+ Error readHeader(const RawInstrProf::Header &Header);
template <class IntT> IntT swap(IntT Int) const {
return ShouldSwapBytes ? sys::getSwappedBytes(Int) : Int;
}
@@ -202,23 +222,26 @@ private:
inline uint8_t getNumPaddingBytes(uint64_t SizeInBytes) {
return 7 & (sizeof(uint64_t) - SizeInBytes % sizeof(uint64_t));
}
- std::error_code readName(InstrProfRecord &Record);
- std::error_code readFuncHash(InstrProfRecord &Record);
- std::error_code readRawCounts(InstrProfRecord &Record);
- std::error_code readValueProfilingData(InstrProfRecord &Record);
+ Error readName(InstrProfRecord &Record);
+ Error readFuncHash(InstrProfRecord &Record);
+ Error readRawCounts(InstrProfRecord &Record);
+ Error readValueProfilingData(InstrProfRecord &Record);
bool atEnd() const { return Data == DataEnd; }
void advanceData() {
Data++;
ValueDataStart += CurValueDataSize;
}
+ const char *getNextHeaderPos() const {
+ assert(atEnd());
+ return (const char *)ValueDataStart;
+ }
const uint64_t *getCounter(IntPtrT CounterPtr) const {
ptrdiff_t Offset = (swap(CounterPtr) - CountersDelta) / sizeof(uint64_t);
return CountersStart + Offset;
}
- const char *getName(IntPtrT NamePtr) const {
- ptrdiff_t Offset = (swap(NamePtr) - NamesDelta) / sizeof(char);
- return NamesStart + Offset;
+ StringRef getName(uint64_t NameRef) const {
+ return Symtab->getFuncName(swap(NameRef));
}
};
@@ -283,15 +306,16 @@ public:
struct InstrProfReaderIndexBase {
// Read all the profile records with the same key pointed to the current
// iterator.
- virtual std::error_code getRecords(ArrayRef<InstrProfRecord> &Data) = 0;
+ virtual Error getRecords(ArrayRef<InstrProfRecord> &Data) = 0;
// Read all the profile records with the key equal to FuncName
- virtual std::error_code getRecords(StringRef FuncName,
+ virtual Error getRecords(StringRef FuncName,
ArrayRef<InstrProfRecord> &Data) = 0;
virtual void advanceToNextKey() = 0;
virtual bool atEnd() const = 0;
virtual void setValueProfDataEndianness(support::endianness Endianness) = 0;
virtual ~InstrProfReaderIndexBase() {}
virtual uint64_t getVersion() const = 0;
+ virtual bool isIRLevelProfile() const = 0;
virtual void populateSymtab(InstrProfSymtab &) = 0;
};
@@ -312,9 +336,9 @@ public:
const unsigned char *const Base,
IndexedInstrProf::HashT HashType, uint64_t Version);
- std::error_code getRecords(ArrayRef<InstrProfRecord> &Data) override;
- std::error_code getRecords(StringRef FuncName,
- ArrayRef<InstrProfRecord> &Data) override;
+ Error getRecords(ArrayRef<InstrProfRecord> &Data) override;
+ Error getRecords(StringRef FuncName,
+ ArrayRef<InstrProfRecord> &Data) override;
void advanceToNextKey() override { RecordIterator++; }
bool atEnd() const override {
return RecordIterator == HashTable->data_end();
@@ -323,7 +347,10 @@ public:
HashTable->getInfoObj().setValueProfDataEndianness(Endianness);
}
~InstrProfReaderIndex() override {}
- uint64_t getVersion() const override { return FormatVersion; }
+ uint64_t getVersion() const override { return GET_VERSION(FormatVersion); }
+ bool isIRLevelProfile() const override {
+ return (FormatVersion & VARIANT_MASK_IR_PROF) != 0;
+ }
void populateSymtab(InstrProfSymtab &Symtab) override {
Symtab.create(HashTable->keys());
}
@@ -336,14 +363,21 @@ private:
std::unique_ptr<MemoryBuffer> DataBuffer;
/// The index into the profile data.
std::unique_ptr<InstrProfReaderIndexBase> Index;
- /// The maximal execution count among all functions.
- uint64_t MaxFunctionCount;
+ /// Profile summary data.
+ std::unique_ptr<ProfileSummary> Summary;
IndexedInstrProfReader(const IndexedInstrProfReader &) = delete;
IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) = delete;
+ // Read the profile summary. Return a pointer pointing to one byte past the
+ // end of the summary data if it exists or the input \c Cur.
+ const unsigned char *readSummary(IndexedInstrProf::ProfVersion Version,
+ const unsigned char *Cur);
+
public:
+ /// Return the profile version.
uint64_t getVersion() const { return Index->getVersion(); }
+ bool isIRLevelProfile() const override { return Index->isIRLevelProfile(); }
IndexedInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)
: DataBuffer(std::move(DataBuffer)), Index(nullptr) {}
@@ -351,27 +385,27 @@ public:
static bool hasFormat(const MemoryBuffer &DataBuffer);
/// Read the file header.
- std::error_code readHeader() override;
+ Error readHeader() override;
/// Read a single record.
- std::error_code readNextRecord(InstrProfRecord &Record) override;
+ Error readNextRecord(InstrProfRecord &Record) override;
/// Return the pointer to InstrProfRecord associated with FuncName
/// and FuncHash
- ErrorOr<InstrProfRecord> getInstrProfRecord(StringRef FuncName,
- uint64_t FuncHash);
+ Expected<InstrProfRecord> getInstrProfRecord(StringRef FuncName,
+ uint64_t FuncHash);
/// Fill Counts with the profile data for the given function name.
- std::error_code getFunctionCounts(StringRef FuncName, uint64_t FuncHash,
- std::vector<uint64_t> &Counts);
+ Error getFunctionCounts(StringRef FuncName, uint64_t FuncHash,
+ std::vector<uint64_t> &Counts);
/// Return the maximum of all known function counts.
- uint64_t getMaximumFunctionCount() { return MaxFunctionCount; }
+ uint64_t getMaximumFunctionCount() { return Summary->getMaxFunctionCount(); }
/// Factory method to create an indexed reader.
- static ErrorOr<std::unique_ptr<IndexedInstrProfReader>>
- create(std::string Path);
+ static Expected<std::unique_ptr<IndexedInstrProfReader>>
+ create(const Twine &Path);
- static ErrorOr<std::unique_ptr<IndexedInstrProfReader>>
+ static Expected<std::unique_ptr<IndexedInstrProfReader>>
create(std::unique_ptr<MemoryBuffer> Buffer);
// Used for testing purpose only.
@@ -383,6 +417,7 @@ public:
// to be used by llvm-profdata (for dumping). Avoid using this when
// the client is the compiler.
InstrProfSymtab &getSymtab() override;
+ ProfileSummary &getSummary() { return *(Summary.get()); }
};
} // end namespace llvm
diff --git a/include/llvm/ProfileData/InstrProfWriter.h b/include/llvm/ProfileData/InstrProfWriter.h
index e7f53de051c3..7d292731cccb 100644
--- a/include/llvm/ProfileData/InstrProfWriter.h
+++ b/include/llvm/ProfileData/InstrProfWriter.h
@@ -24,21 +24,29 @@
namespace llvm {
/// Writer for instrumentation based profile data.
+class ProfOStream;
+class InstrProfRecordWriterTrait;
+
class InstrProfWriter {
public:
typedef SmallDenseMap<uint64_t, InstrProfRecord, 1> ProfilingData;
+ enum ProfKind { PF_Unknown = 0, PF_FE, PF_IRLevel };
private:
+ bool Sparse;
StringMap<ProfilingData> FunctionData;
- uint64_t MaxFunctionCount;
+ ProfKind ProfileKind;
+ // Use raw pointer here for the incomplete type object.
+ InstrProfRecordWriterTrait *InfoObj;
public:
- InstrProfWriter() : MaxFunctionCount(0) {}
+ InstrProfWriter(bool Sparse = false);
+ ~InstrProfWriter();
/// Add function counts for the given function. If there are already counts
/// for this function and the hash and number of counts match, each counter is
/// summed. Optionally scale counts by \p Weight.
- std::error_code addRecord(InstrProfRecord &&I, uint64_t Weight = 1);
+ Error addRecord(InstrProfRecord &&I, uint64_t Weight = 1);
/// Write the profile to \c OS
void write(raw_fd_ostream &OS);
/// Write the profile in text format to \c OS
@@ -49,11 +57,25 @@ public:
/// Write the profile, returning the raw data. For testing.
std::unique_ptr<MemoryBuffer> writeBuffer();
+ /// Set the ProfileKind. Report error if mixing FE and IR level profiles.
+ Error setIsIRLevelProfile(bool IsIRLevel) {
+ if (ProfileKind == PF_Unknown) {
+ ProfileKind = IsIRLevel ? PF_IRLevel: PF_FE;
+ return Error::success();
+ }
+ return (IsIRLevel == (ProfileKind == PF_IRLevel))
+ ? Error::success()
+ : make_error<InstrProfError>(
+ instrprof_error::unsupported_version);
+ }
+
// Internal interface for testing purpose only.
void setValueProfDataEndianness(support::endianness Endianness);
+ void setOutputSparse(bool Sparse);
private:
- std::pair<uint64_t, uint64_t> writeImpl(raw_ostream &OS);
+ bool shouldEncodeData(const ProfilingData &PD);
+ void writeImpl(ProfOStream &OS);
};
} // end namespace llvm
diff --git a/include/llvm/ProfileData/ProfileCommon.h b/include/llvm/ProfileData/ProfileCommon.h
new file mode 100644
index 000000000000..ecb228ca59c4
--- /dev/null
+++ b/include/llvm/ProfileData/ProfileCommon.h
@@ -0,0 +1,102 @@
+//===-- ProfileCommon.h - Common profiling APIs. ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains data structures and functions common to both instrumented
+// and sample profiling.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_PROFILEDATA_PROFILE_COMMON_H
+#define LLVM_PROFILEDATA_PROFILE_COMMON_H
+
+#include <cstdint>
+#include <functional>
+#include <map>
+#include <utility>
+#include <vector>
+
+#include "llvm/IR/ProfileSummary.h"
+#include "llvm/Support/Error.h"
+#include "llvm/ADT/ArrayRef.h"
+
+namespace llvm {
+class Function;
+namespace IndexedInstrProf {
+struct Summary;
+}
+namespace sampleprof {
+class FunctionSamples;
+}
+struct InstrProfRecord;
+class LLVMContext;
+class Metadata;
+class MDTuple;
+class MDNode;
+
+inline const char *getHotSectionPrefix() { return ".hot"; }
+inline const char *getUnlikelySectionPrefix() { return ".unlikely"; }
+
+class ProfileSummaryBuilder {
+
+private:
+ // We keep track of the number of times a count (block count or samples)
+ // appears in the profile. The map is kept sorted in the descending order of
+ // counts.
+ std::map<uint64_t, uint32_t, std::greater<uint64_t>> CountFrequencies;
+ std::vector<uint32_t> DetailedSummaryCutoffs;
+
+protected:
+ SummaryEntryVector DetailedSummary;
+ ProfileSummaryBuilder(std::vector<uint32_t> Cutoffs)
+ : DetailedSummaryCutoffs(std::move(Cutoffs)), TotalCount(0), MaxCount(0),
+ MaxFunctionCount(0), NumCounts(0), NumFunctions(0) {}
+ inline void addCount(uint64_t Count);
+ ~ProfileSummaryBuilder() = default;
+ void computeDetailedSummary();
+ uint64_t TotalCount, MaxCount, MaxFunctionCount;
+ uint32_t NumCounts, NumFunctions;
+
+public:
+ /// \brief A vector of useful cutoff values for detailed summary.
+ static const ArrayRef<uint32_t> DefaultCutoffs;
+};
+
+class InstrProfSummaryBuilder final : public ProfileSummaryBuilder {
+ uint64_t MaxInternalBlockCount;
+ inline void addEntryCount(uint64_t Count);
+ inline void addInternalCount(uint64_t Count);
+
+public:
+ InstrProfSummaryBuilder(std::vector<uint32_t> Cutoffs)
+ : ProfileSummaryBuilder(std::move(Cutoffs)), MaxInternalBlockCount(0) {}
+ void addRecord(const InstrProfRecord &);
+ std::unique_ptr<ProfileSummary> getSummary();
+};
+
+class SampleProfileSummaryBuilder final : public ProfileSummaryBuilder {
+
+public:
+ void addRecord(const sampleprof::FunctionSamples &FS);
+ SampleProfileSummaryBuilder(std::vector<uint32_t> Cutoffs)
+ : ProfileSummaryBuilder(std::move(Cutoffs)) {}
+ std::unique_ptr<ProfileSummary> getSummary();
+};
+
+// This is called when a count is seen in the profile.
+void ProfileSummaryBuilder::addCount(uint64_t Count) {
+ TotalCount += Count;
+ if (Count > MaxCount)
+ MaxCount = Count;
+ NumCounts++;
+ CountFrequencies[Count]++;
+}
+
+
+} // end namespace llvm
+#endif
diff --git a/include/llvm/ProfileData/SampleProf.h b/include/llvm/ProfileData/SampleProf.h
index 6c39cf9458dc..9fefefa627b1 100644
--- a/include/llvm/ProfileData/SampleProf.h
+++ b/include/llvm/ProfileData/SampleProf.h
@@ -74,7 +74,7 @@ static inline uint64_t SPMagic() {
uint64_t('2') << (64 - 56) | uint64_t(0xff);
}
-static inline uint64_t SPVersion() { return 102; }
+static inline uint64_t SPVersion() { return 103; }
/// Represents the relative location of an instruction.
///
@@ -100,23 +100,6 @@ struct LineLocation {
raw_ostream &operator<<(raw_ostream &OS, const LineLocation &Loc);
-/// Represents the relative location of a callsite.
-///
-/// Callsite locations are specified by the line offset from the
-/// beginning of the function (marked by the line where the function
-/// head is), the discriminator value within that line, and the callee
-/// function name.
-struct CallsiteLocation : public LineLocation {
- CallsiteLocation(uint32_t L, uint32_t D, StringRef N)
- : LineLocation(L, D), CalleeName(N) {}
- void print(raw_ostream &OS) const;
- void dump() const;
-
- StringRef CalleeName;
-};
-
-raw_ostream &operator<<(raw_ostream &OS, const CallsiteLocation &Loc);
-
/// Representation of a single sample record.
///
/// A sample record is represented by a positive integer value, which
@@ -188,7 +171,7 @@ raw_ostream &operator<<(raw_ostream &OS, const SampleRecord &Sample);
typedef std::map<LineLocation, SampleRecord> BodySampleMap;
class FunctionSamples;
-typedef std::map<CallsiteLocation, FunctionSamples> CallsiteSampleMap;
+typedef std::map<LineLocation, FunctionSamples> CallsiteSampleMap;
/// Representation of the samples collected for a function.
///
@@ -197,7 +180,7 @@ typedef std::map<CallsiteLocation, FunctionSamples> CallsiteSampleMap;
/// within the body of the function.
class FunctionSamples {
public:
- FunctionSamples() : TotalSamples(0), TotalHeadSamples(0) {}
+ FunctionSamples() : Name(), TotalSamples(0), TotalHeadSamples(0) {}
void print(raw_ostream &OS = dbgs(), unsigned Indent = 0) const;
void dump() const;
sampleprof_error addTotalSamples(uint64_t Num, uint64_t Weight = 1) {
@@ -221,8 +204,8 @@ public:
}
sampleprof_error addCalledTargetSamples(uint32_t LineOffset,
uint32_t Discriminator,
- std::string FName, uint64_t Num,
- uint64_t Weight = 1) {
+ const std::string &FName,
+ uint64_t Num, uint64_t Weight = 1) {
return BodySamples[LineLocation(LineOffset, Discriminator)].addCalledTarget(
FName, Num, Weight);
}
@@ -240,13 +223,12 @@ public:
}
/// Return the function samples at the given callsite location.
- FunctionSamples &functionSamplesAt(const CallsiteLocation &Loc) {
+ FunctionSamples &functionSamplesAt(const LineLocation &Loc) {
return CallsiteSamples[Loc];
}
/// Return a pointer to function samples at the given callsite location.
- const FunctionSamples *
- findFunctionSamplesAt(const CallsiteLocation &Loc) const {
+ const FunctionSamples *findFunctionSamplesAt(const LineLocation &Loc) const {
auto iter = CallsiteSamples.find(Loc);
if (iter == CallsiteSamples.end()) {
return nullptr;
@@ -276,6 +258,7 @@ public:
/// Optionally scale samples by \p Weight.
sampleprof_error merge(const FunctionSamples &Other, uint64_t Weight = 1) {
sampleprof_error Result = sampleprof_error::success;
+ Name = Other.getName();
MergeResult(Result, addTotalSamples(Other.getTotalSamples(), Weight));
MergeResult(Result, addHeadSamples(Other.getHeadSamples(), Weight));
for (const auto &I : Other.getBodySamples()) {
@@ -284,14 +267,23 @@ public:
MergeResult(Result, BodySamples[Loc].merge(Rec, Weight));
}
for (const auto &I : Other.getCallsiteSamples()) {
- const CallsiteLocation &Loc = I.first;
+ const LineLocation &Loc = I.first;
const FunctionSamples &Rec = I.second;
MergeResult(Result, functionSamplesAt(Loc).merge(Rec, Weight));
}
return Result;
}
+ /// Set the name of the function.
+ void setName(StringRef FunctionName) { Name = FunctionName; }
+
+ /// Return the function name.
+ const StringRef &getName() const { return Name; }
+
private:
+ /// Mangled name of the function.
+ StringRef Name;
+
/// Total number of samples collected inside this function.
///
/// Samples are cumulative, they include all the samples collected
diff --git a/include/llvm/ProfileData/SampleProfReader.h b/include/llvm/ProfileData/SampleProfReader.h
index 6db0fbb0e7ab..bf86721709c7 100644
--- a/include/llvm/ProfileData/SampleProfReader.h
+++ b/include/llvm/ProfileData/SampleProfReader.h
@@ -129,6 +129,30 @@
// VERSION (uint32_t)
// File format version number computed by SPVersion()
//
+// SUMMARY
+// TOTAL_COUNT (uint64_t)
+// Total number of samples in the profile.
+// MAX_COUNT (uint64_t)
+// Maximum value of samples on a line.
+// MAX_FUNCTION_COUNT (uint64_t)
+// Maximum number of samples at function entry (head samples).
+// NUM_COUNTS (uint64_t)
+// Number of lines with samples.
+// NUM_FUNCTIONS (uint64_t)
+// Number of functions with samples.
+// NUM_DETAILED_SUMMARY_ENTRIES (size_t)
+// Number of entries in detailed summary
+// DETAILED_SUMMARY
+// A list of detailed summary entry. Each entry consists of
+// CUTOFF (uint32_t)
+// Required percentile of total sample count expressed as a fraction
+// multiplied by 1000000.
+// MIN_COUNT (uint64_t)
+// The minimum number of samples required to reach the target
+// CUTOFF.
+// NUM_COUNTS (uint64_t)
+// Number of samples to get to the desrired percentile.
+//
// NAME TABLE
// SIZE (uint32_t)
// Number of entries in the name table.
@@ -190,6 +214,7 @@
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/LLVMContext.h"
+#include "llvm/ProfileData/ProfileCommon.h"
#include "llvm/ProfileData/SampleProf.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
@@ -264,12 +289,15 @@ public:
/// \brief Create a sample profile reader appropriate to the file format.
static ErrorOr<std::unique_ptr<SampleProfileReader>>
- create(StringRef Filename, LLVMContext &C);
+ create(const Twine &Filename, LLVMContext &C);
/// \brief Create a sample profile reader from the supplied memory buffer.
static ErrorOr<std::unique_ptr<SampleProfileReader>>
create(std::unique_ptr<MemoryBuffer> &B, LLVMContext &C);
+ /// \brief Return the profile summary.
+ ProfileSummary &getSummary() { return *(Summary.get()); }
+
protected:
/// \brief Map every function to its associated profile.
///
@@ -283,6 +311,12 @@ protected:
/// \brief Memory buffer holding the profile file.
std::unique_ptr<MemoryBuffer> Buffer;
+
+ /// \brief Profile summary information.
+ std::unique_ptr<ProfileSummary> Summary;
+
+ /// \brief Compute summary for this profile.
+ void computeSummary();
};
class SampleProfileReaderText : public SampleProfileReader {
@@ -348,6 +382,12 @@ protected:
/// Function name table.
std::vector<StringRef> NameTable;
+
+private:
+ std::error_code readSummaryEntry(std::vector<ProfileSummaryEntry> &Entries);
+
+ /// \brief Read profile summary.
+ std::error_code readSummary();
};
typedef SmallVector<FunctionSamples *, 10> InlineCallStack;
diff --git a/include/llvm/ProfileData/SampleProfWriter.h b/include/llvm/ProfileData/SampleProfWriter.h
index 029dd2ebacb0..f6f2e2702e31 100644
--- a/include/llvm/ProfileData/SampleProfWriter.h
+++ b/include/llvm/ProfileData/SampleProfWriter.h
@@ -15,6 +15,7 @@
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ProfileData/ProfileCommon.h"
#include "llvm/ProfileData/SampleProf.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
@@ -31,10 +32,10 @@ class SampleProfileWriter {
public:
virtual ~SampleProfileWriter() {}
- /// Write sample profiles in \p S for function \p FName.
+ /// Write sample profiles in \p S.
///
/// \returns status code of the file update operation.
- virtual std::error_code write(StringRef FName, const FunctionSamples &S) = 0;
+ virtual std::error_code write(const FunctionSamples &S) = 0;
/// Write all the sample profiles in the given map of samples.
///
@@ -42,11 +43,9 @@ public:
std::error_code write(const StringMap<FunctionSamples> &ProfileMap) {
if (std::error_code EC = writeHeader(ProfileMap))
return EC;
-
for (const auto &I : ProfileMap) {
- StringRef FName = I.first();
const FunctionSamples &Profile = I.second;
- if (std::error_code EC = write(FName, Profile))
+ if (std::error_code EC = write(Profile))
return EC;
}
return sampleprof_error::success;
@@ -75,12 +74,18 @@ protected:
/// \brief Output stream where to emit the profile to.
std::unique_ptr<raw_ostream> OutputStream;
+
+ /// \brief Profile summary.
+ std::unique_ptr<ProfileSummary> Summary;
+
+ /// \brief Compute summary for this profile.
+ void computeSummary(const StringMap<FunctionSamples> &ProfileMap);
};
/// \brief Sample-based profile writer (text format).
class SampleProfileWriterText : public SampleProfileWriter {
public:
- std::error_code write(StringRef FName, const FunctionSamples &S) override;
+ std::error_code write(const FunctionSamples &S) override;
protected:
SampleProfileWriterText(std::unique_ptr<raw_ostream> &OS)
@@ -105,7 +110,7 @@ private:
/// \brief Sample-based profile writer (binary format).
class SampleProfileWriterBinary : public SampleProfileWriter {
public:
- std::error_code write(StringRef F, const FunctionSamples &S) override;
+ std::error_code write(const FunctionSamples &S) override;
protected:
SampleProfileWriterBinary(std::unique_ptr<raw_ostream> &OS)
@@ -113,8 +118,9 @@ protected:
std::error_code
writeHeader(const StringMap<FunctionSamples> &ProfileMap) override;
+ std::error_code writeSummary();
std::error_code writeNameIdx(StringRef FName);
- std::error_code writeBody(StringRef FName, const FunctionSamples &S);
+ std::error_code writeBody(const FunctionSamples &S);
private:
void addName(StringRef FName);
diff --git a/include/llvm/Support/AArch64TargetParser.def b/include/llvm/Support/AArch64TargetParser.def
new file mode 100644
index 000000000000..67f981b8f2fa
--- /dev/null
+++ b/include/llvm/Support/AArch64TargetParser.def
@@ -0,0 +1,72 @@
+//===- AARCH64TargetParser.def - AARCH64 target parsing defines ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides defines to build up the AARCH64 target parser's logic.
+//
+//===----------------------------------------------------------------------===//
+
+// NOTE: NO INCLUDE GUARD DESIRED!
+
+#ifndef AARCH64_ARCH
+#define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT)
+#endif
+AARCH64_ARCH("armv8-a", AK_ARMV8A, "8-A", "v8", ARMBuildAttrs::CPUArch::v8_A,
+ FK_CRYPTO_NEON_FP_ARMV8,
+ (AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |
+ AArch64::AEK_SIMD | AArch64::AEK_FP16 | AArch64::AEK_PROFILE))
+AARCH64_ARCH("armv8.1-a", AK_ARMV8_1A, "8.1-A", "v8.1a",
+ ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8,
+ (AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |
+ AArch64::AEK_SIMD | AArch64::AEK_FP16 | AArch64::AEK_PROFILE))
+AARCH64_ARCH("armv8.2-a", AK_ARMV8_2A, "8.2-A", "v8.2a",
+ ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8,
+ (AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |
+ AArch64::AEK_SIMD | AArch64::AEK_FP16 | AArch64::AEK_PROFILE |
+ AArch64::AEK_RAS))
+#undef AARCH64_ARCH
+
+#ifndef AARCH64_ARCH_EXT_NAME
+#define AARCH64_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE)
+#endif
+// FIXME: This would be nicer were it tablegen
+AARCH64_ARCH_EXT_NAME("invalid", AArch64::AEK_INVALID, nullptr, nullptr)
+AARCH64_ARCH_EXT_NAME("none", AArch64::AEK_NONE, nullptr, nullptr)
+AARCH64_ARCH_EXT_NAME("crc", AArch64::AEK_CRC, "+crc", "-crc")
+AARCH64_ARCH_EXT_NAME("crypto", AArch64::AEK_CRYPTO, "+crypto","-crypto")
+AARCH64_ARCH_EXT_NAME("fp", AArch64::AEK_FP, "+fp-armv8", "-fp-armv8")
+AARCH64_ARCH_EXT_NAME("simd", AArch64::AEK_SIMD, "+neon", "-neon")
+AARCH64_ARCH_EXT_NAME("fp16", AArch64::AEK_FP16, "+fullfp16", "-fullfp16")
+AARCH64_ARCH_EXT_NAME("profile", AArch64::AEK_PROFILE, "+spe", "-spe")
+AARCH64_ARCH_EXT_NAME("ras", AArch64::AEK_RAS, "+ras", "-ras")
+#undef AARCH64_ARCH_EXT_NAME
+
+#ifndef AARCH64_CPU_NAME
+#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT)
+#endif
+AARCH64_CPU_NAME("cortex-a35", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO))
+AARCH64_CPU_NAME("cortex-a53", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, true,
+ ( AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO))
+AARCH64_CPU_NAME("cortex-a57", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO))
+AARCH64_CPU_NAME("cortex-a72", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO))
+AARCH64_CPU_NAME("cortex-a73", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO))
+AARCH64_CPU_NAME("cyclone", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_SIMD | AArch64::AEK_CRYPTO))
+AARCH64_CPU_NAME("exynos-m1", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO))
+AARCH64_CPU_NAME("kryo", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO))
+AARCH64_CPU_NAME("vulcan", AK_ARMV8_1A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO))
+// Invalid CPU
+AARCH64_CPU_NAME("invalid", AK_INVALID, FK_INVALID, true, AArch64::AEK_INVALID)
+#undef AARCH64_CPU_NAME
diff --git a/include/llvm/Support/AIXDataTypesFix.h b/include/llvm/Support/AIXDataTypesFix.h
deleted file mode 100644
index a9a9147de294..000000000000
--- a/include/llvm/Support/AIXDataTypesFix.h
+++ /dev/null
@@ -1,25 +0,0 @@
-//===-- llvm/Support/AIXDataTypesFix.h - Fix datatype defs ------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file overrides default system-defined types and limits which cannot be
-// done in DataTypes.h.in because it is processed by autoheader first, which
-// comments out any #undef statement
-//
-//===----------------------------------------------------------------------===//
-
-// No include guards desired!
-
-#ifndef SUPPORT_DATATYPES_H
-#error "AIXDataTypesFix.h must only be included via DataTypes.h!"
-#endif
-
-// GCC is strict about defining large constants: they must have LL modifier.
-// These will be defined properly at the end of DataTypes.h
-#undef INT64_MAX
-#undef INT64_MIN
diff --git a/include/llvm/Support/ARMBuildAttributes.h b/include/llvm/Support/ARMBuildAttributes.h
index fc14cb2d0b0c..f447cd072b5f 100644
--- a/include/llvm/Support/ARMBuildAttributes.h
+++ b/include/llvm/Support/ARMBuildAttributes.h
@@ -67,6 +67,7 @@ enum AttrType {
ABI_FP_16bit_format = 38,
MPextension_use = 42, // recoded from 70 (ABI r2.08)
DIV_use = 44,
+ DSP_extension = 46,
also_compatible_with = 65,
conformance = 67,
Virtualization_use = 68,
@@ -106,7 +107,9 @@ enum CPUArch {
v6_M = 11, // e.g. Cortex M1
v6S_M = 12, // v6_M with the System extensions
v7E_M = 13, // v7_M with DSP extensions
- v8 = 14, // v8,v8.1a AArch32
+ v8_A = 14, // v8_A AArch32
+ v8_M_Base= 16, // v8_M_Base AArch32
+ v8_M_Main= 17, // v8_M_Main AArch32
};
enum CPUArchProfile { // (=7), uleb128
@@ -126,6 +129,7 @@ enum {
// Tag_THUMB_ISA_use, (=9), uleb128
AllowThumb32 = 2, // 32-bit Thumb (implies 16-bit instructions)
+ AllowThumbDerived = 3, // Thumb allowed, derived from arch/profile
// Tag_FP_arch (=10), uleb128 (formerly Tag_VFP_arch = 10)
AllowFPv2 = 2, // v2 FP ISA permitted (implies use of the v1 FP ISA)
diff --git a/include/llvm/Support/ARMTargetParser.def b/include/llvm/Support/ARMTargetParser.def
index d94a51b8bcf9..195f7112d6a0 100644
--- a/include/llvm/Support/ARMTargetParser.def
+++ b/include/llvm/Support/ARMTargetParser.def
@@ -45,180 +45,198 @@ ARM_FPU("softvfp", FK_SOFTVFP, FV_NONE, NS_None, FR_None)
#define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT)
#endif
ARM_ARCH("invalid", AK_INVALID, nullptr, nullptr,
- ARMBuildAttrs::CPUArch::Pre_v4, FK_NONE, AEK_NONE)
+ ARMBuildAttrs::CPUArch::Pre_v4, FK_NONE, ARM::AEK_NONE)
ARM_ARCH("armv2", AK_ARMV2, "2", "v2", ARMBuildAttrs::CPUArch::Pre_v4,
- FK_NONE, AEK_NONE)
+ FK_NONE, ARM::AEK_NONE)
ARM_ARCH("armv2a", AK_ARMV2A, "2A", "v2a", ARMBuildAttrs::CPUArch::Pre_v4,
- FK_NONE, AEK_NONE)
+ FK_NONE, ARM::AEK_NONE)
ARM_ARCH("armv3", AK_ARMV3, "3", "v3", ARMBuildAttrs::CPUArch::Pre_v4,
- FK_NONE, AEK_NONE)
+ FK_NONE, ARM::AEK_NONE)
ARM_ARCH("armv3m", AK_ARMV3M, "3M", "v3m", ARMBuildAttrs::CPUArch::Pre_v4,
- FK_NONE, AEK_NONE)
+ FK_NONE, ARM::AEK_NONE)
ARM_ARCH("armv4", AK_ARMV4, "4", "v4", ARMBuildAttrs::CPUArch::v4,
- FK_NONE, AEK_NONE)
+ FK_NONE, ARM::AEK_NONE)
ARM_ARCH("armv4t", AK_ARMV4T, "4T", "v4t", ARMBuildAttrs::CPUArch::v4T,
- FK_NONE, AEK_NONE)
+ FK_NONE, ARM::AEK_NONE)
ARM_ARCH("armv5t", AK_ARMV5T, "5T", "v5", ARMBuildAttrs::CPUArch::v5T,
- FK_NONE, AEK_NONE)
+ FK_NONE, ARM::AEK_NONE)
ARM_ARCH("armv5te", AK_ARMV5TE, "5TE", "v5e", ARMBuildAttrs::CPUArch::v5TE,
- FK_NONE, AEK_DSP)
+ FK_NONE, ARM::AEK_DSP)
ARM_ARCH("armv5tej", AK_ARMV5TEJ, "5TEJ", "v5e", ARMBuildAttrs::CPUArch::v5TEJ,
- FK_NONE, AEK_DSP)
+ FK_NONE, ARM::AEK_DSP)
ARM_ARCH("armv6", AK_ARMV6, "6", "v6", ARMBuildAttrs::CPUArch::v6,
- FK_VFPV2, AEK_DSP)
+ FK_VFPV2, ARM::AEK_DSP)
ARM_ARCH("armv6k", AK_ARMV6K, "6K", "v6k", ARMBuildAttrs::CPUArch::v6K,
- FK_VFPV2, AEK_DSP)
+ FK_VFPV2, ARM::AEK_DSP)
ARM_ARCH("armv6t2", AK_ARMV6T2, "6T2", "v6t2", ARMBuildAttrs::CPUArch::v6T2,
- FK_NONE, AEK_DSP)
+ FK_NONE, ARM::AEK_DSP)
ARM_ARCH("armv6kz", AK_ARMV6KZ, "6KZ", "v6kz", ARMBuildAttrs::CPUArch::v6KZ,
- FK_VFPV2, (AEK_SEC | AEK_DSP))
+ FK_VFPV2, (ARM::AEK_SEC | ARM::AEK_DSP))
ARM_ARCH("armv6-m", AK_ARMV6M, "6-M", "v6m", ARMBuildAttrs::CPUArch::v6_M,
- FK_NONE, AEK_NONE)
+ FK_NONE, ARM::AEK_NONE)
ARM_ARCH("armv7-a", AK_ARMV7A, "7-A", "v7", ARMBuildAttrs::CPUArch::v7,
- FK_NEON, AEK_DSP)
+ FK_NEON, ARM::AEK_DSP)
ARM_ARCH("armv7-r", AK_ARMV7R, "7-R", "v7r", ARMBuildAttrs::CPUArch::v7,
- FK_NONE, (AEK_HWDIV | AEK_DSP))
+ FK_NONE, (ARM::AEK_HWDIV | ARM::AEK_DSP))
ARM_ARCH("armv7-m", AK_ARMV7M, "7-M", "v7m", ARMBuildAttrs::CPUArch::v7,
- FK_NONE, AEK_HWDIV)
+ FK_NONE, ARM::AEK_HWDIV)
ARM_ARCH("armv7e-m", AK_ARMV7EM, "7E-M", "v7em", ARMBuildAttrs::CPUArch::v7E_M,
- FK_NONE, (AEK_HWDIV | AEK_DSP))
-ARM_ARCH("armv8-a", AK_ARMV8A, "8-A", "v8", ARMBuildAttrs::CPUArch::v8,
- FK_CRYPTO_NEON_FP_ARMV8, (AEK_SEC | AEK_MP | AEK_VIRT | AEK_HWDIVARM |
- AEK_HWDIV | AEK_DSP | AEK_CRC))
-ARM_ARCH("armv8.1-a", AK_ARMV8_1A, "8.1-A", "v8.1a", ARMBuildAttrs::CPUArch::v8,
- FK_CRYPTO_NEON_FP_ARMV8, (AEK_SEC | AEK_MP | AEK_VIRT | AEK_HWDIVARM |
- AEK_HWDIV | AEK_DSP | AEK_CRC))
-ARM_ARCH("armv8.2-a", AK_ARMV8_2A, "8.2-A", "v8.2a", ARMBuildAttrs::CPUArch::v8,
- FK_CRYPTO_NEON_FP_ARMV8, (AEK_SEC | AEK_MP | AEK_VIRT | AEK_HWDIVARM |
- AEK_HWDIV | AEK_DSP | AEK_CRC))
+ FK_NONE, (ARM::AEK_HWDIV | ARM::AEK_DSP))
+ARM_ARCH("armv8-a", AK_ARMV8A, "8-A", "v8", ARMBuildAttrs::CPUArch::v8_A,
+ FK_CRYPTO_NEON_FP_ARMV8,
+ (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
+ ARM::AEK_HWDIV | ARM::AEK_DSP | ARM::AEK_CRC))
+ARM_ARCH("armv8.1-a", AK_ARMV8_1A, "8.1-A", "v8.1a",
+ ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8,
+ (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
+ ARM::AEK_HWDIV | ARM::AEK_DSP | ARM::AEK_CRC | ARM::AEK_RAS))
+ARM_ARCH("armv8.2-a", AK_ARMV8_2A, "8.2-A", "v8.2a",
+ ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8,
+ (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
+ ARM::AEK_HWDIV | ARM::AEK_DSP | ARM::AEK_CRC))
+ARM_ARCH("armv8-m.base", AK_ARMV8MBaseline, "8-M.Baseline", "v8m.base",
+ ARMBuildAttrs::CPUArch::v8_M_Base, FK_NONE, ARM::AEK_HWDIV)
+ARM_ARCH("armv8-m.main", AK_ARMV8MMainline, "8-M.Mainline", "v8m.main",
+ ARMBuildAttrs::CPUArch::v8_M_Main, FK_FPV5_D16, ARM::AEK_HWDIV)
// Non-standard Arch names.
ARM_ARCH("iwmmxt", AK_IWMMXT, "iwmmxt", "", ARMBuildAttrs::CPUArch::v5TE,
- FK_NONE, AEK_NONE)
+ FK_NONE, ARM::AEK_NONE)
ARM_ARCH("iwmmxt2", AK_IWMMXT2, "iwmmxt2", "", ARMBuildAttrs::CPUArch::v5TE,
- FK_NONE, AEK_NONE)
+ FK_NONE, ARM::AEK_NONE)
ARM_ARCH("xscale", AK_XSCALE, "xscale", "v5e", ARMBuildAttrs::CPUArch::v5TE,
- FK_NONE, AEK_NONE)
+ FK_NONE, ARM::AEK_NONE)
ARM_ARCH("armv7s", AK_ARMV7S, "7-S", "v7s", ARMBuildAttrs::CPUArch::v7,
- FK_NEON_VFPV4, AEK_DSP)
+ FK_NEON_VFPV4, ARM::AEK_DSP)
ARM_ARCH("armv7k", AK_ARMV7K, "7-K", "v7k", ARMBuildAttrs::CPUArch::v7,
- FK_NONE, AEK_DSP)
+ FK_NONE, ARM::AEK_DSP)
#undef ARM_ARCH
#ifndef ARM_ARCH_EXT_NAME
#define ARM_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE)
#endif
// FIXME: This would be nicer were it tablegen
-ARM_ARCH_EXT_NAME("invalid", AEK_INVALID, nullptr, nullptr)
-ARM_ARCH_EXT_NAME("none", AEK_NONE, nullptr, nullptr)
-ARM_ARCH_EXT_NAME("crc", AEK_CRC, "+crc", "-crc")
-ARM_ARCH_EXT_NAME("crypto", AEK_CRYPTO, "+crypto","-crypto")
-ARM_ARCH_EXT_NAME("fp", AEK_FP, nullptr, nullptr)
-ARM_ARCH_EXT_NAME("idiv", (AEK_HWDIVARM | AEK_HWDIV), nullptr, nullptr)
-ARM_ARCH_EXT_NAME("mp", AEK_MP, nullptr, nullptr)
-ARM_ARCH_EXT_NAME("simd", AEK_SIMD, nullptr, nullptr)
-ARM_ARCH_EXT_NAME("sec", AEK_SEC, nullptr, nullptr)
-ARM_ARCH_EXT_NAME("virt", AEK_VIRT, nullptr, nullptr)
-ARM_ARCH_EXT_NAME("fp16", AEK_FP16, "+fullfp16", "-fullfp16")
-ARM_ARCH_EXT_NAME("os", AEK_OS, nullptr, nullptr)
-ARM_ARCH_EXT_NAME("iwmmxt", AEK_IWMMXT, nullptr, nullptr)
-ARM_ARCH_EXT_NAME("iwmmxt2", AEK_IWMMXT2, nullptr, nullptr)
-ARM_ARCH_EXT_NAME("maverick", AEK_MAVERICK, nullptr, nullptr)
-ARM_ARCH_EXT_NAME("xscale", AEK_XSCALE, nullptr, nullptr)
+ARM_ARCH_EXT_NAME("invalid", ARM::AEK_INVALID, nullptr, nullptr)
+ARM_ARCH_EXT_NAME("none", ARM::AEK_NONE, nullptr, nullptr)
+ARM_ARCH_EXT_NAME("crc", ARM::AEK_CRC, "+crc", "-crc")
+ARM_ARCH_EXT_NAME("crypto", ARM::AEK_CRYPTO, "+crypto","-crypto")
+ARM_ARCH_EXT_NAME("dsp", ARM::AEK_DSP, "+dsp", "-dsp")
+ARM_ARCH_EXT_NAME("fp", ARM::AEK_FP, nullptr, nullptr)
+ARM_ARCH_EXT_NAME("idiv", (ARM::AEK_HWDIVARM | ARM::AEK_HWDIV), nullptr, nullptr)
+ARM_ARCH_EXT_NAME("mp", ARM::AEK_MP, nullptr, nullptr)
+ARM_ARCH_EXT_NAME("simd", ARM::AEK_SIMD, nullptr, nullptr)
+ARM_ARCH_EXT_NAME("sec", ARM::AEK_SEC, nullptr, nullptr)
+ARM_ARCH_EXT_NAME("virt", ARM::AEK_VIRT, nullptr, nullptr)
+ARM_ARCH_EXT_NAME("fp16", ARM::AEK_FP16, "+fullfp16", "-fullfp16")
+ARM_ARCH_EXT_NAME("ras", ARM::AEK_RAS, "+ras", "-ras")
+ARM_ARCH_EXT_NAME("os", ARM::AEK_OS, nullptr, nullptr)
+ARM_ARCH_EXT_NAME("iwmmxt", ARM::AEK_IWMMXT, nullptr, nullptr)
+ARM_ARCH_EXT_NAME("iwmmxt2", ARM::AEK_IWMMXT2, nullptr, nullptr)
+ARM_ARCH_EXT_NAME("maverick", ARM::AEK_MAVERICK, nullptr, nullptr)
+ARM_ARCH_EXT_NAME("xscale", ARM::AEK_XSCALE, nullptr, nullptr)
#undef ARM_ARCH_EXT_NAME
#ifndef ARM_HW_DIV_NAME
#define ARM_HW_DIV_NAME(NAME, ID)
#endif
-ARM_HW_DIV_NAME("invalid", AEK_INVALID)
-ARM_HW_DIV_NAME("none", AEK_NONE)
-ARM_HW_DIV_NAME("thumb", AEK_HWDIV)
-ARM_HW_DIV_NAME("arm", AEK_HWDIVARM)
-ARM_HW_DIV_NAME("arm,thumb", (AEK_HWDIVARM | AEK_HWDIV))
+ARM_HW_DIV_NAME("invalid", ARM::AEK_INVALID)
+ARM_HW_DIV_NAME("none", ARM::AEK_NONE)
+ARM_HW_DIV_NAME("thumb", ARM::AEK_HWDIV)
+ARM_HW_DIV_NAME("arm", ARM::AEK_HWDIVARM)
+ARM_HW_DIV_NAME("arm,thumb", (ARM::AEK_HWDIVARM | ARM::AEK_HWDIV))
#undef ARM_HW_DIV_NAME
#ifndef ARM_CPU_NAME
#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT)
#endif
-ARM_CPU_NAME("arm2", AK_ARMV2, FK_NONE, true, AEK_NONE)
-ARM_CPU_NAME("arm3", AK_ARMV2A, FK_NONE, true, AEK_NONE)
-ARM_CPU_NAME("arm6", AK_ARMV3, FK_NONE, true, AEK_NONE)
-ARM_CPU_NAME("arm7m", AK_ARMV3M, FK_NONE, true, AEK_NONE)
-ARM_CPU_NAME("arm8", AK_ARMV4, FK_NONE, false, AEK_NONE)
-ARM_CPU_NAME("arm810", AK_ARMV4, FK_NONE, false, AEK_NONE)
-ARM_CPU_NAME("strongarm", AK_ARMV4, FK_NONE, true, AEK_NONE)
-ARM_CPU_NAME("strongarm110", AK_ARMV4, FK_NONE, false, AEK_NONE)
-ARM_CPU_NAME("strongarm1100", AK_ARMV4, FK_NONE, false, AEK_NONE)
-ARM_CPU_NAME("strongarm1110", AK_ARMV4, FK_NONE, false, AEK_NONE)
-ARM_CPU_NAME("arm7tdmi", AK_ARMV4T, FK_NONE, true, AEK_NONE)
-ARM_CPU_NAME("arm7tdmi-s", AK_ARMV4T, FK_NONE, false, AEK_NONE)
-ARM_CPU_NAME("arm710t", AK_ARMV4T, FK_NONE, false, AEK_NONE)
-ARM_CPU_NAME("arm720t", AK_ARMV4T, FK_NONE, false, AEK_NONE)
-ARM_CPU_NAME("arm9", AK_ARMV4T, FK_NONE, false, AEK_NONE)
-ARM_CPU_NAME("arm9tdmi", AK_ARMV4T, FK_NONE, false, AEK_NONE)
-ARM_CPU_NAME("arm920", AK_ARMV4T, FK_NONE, false, AEK_NONE)
-ARM_CPU_NAME("arm920t", AK_ARMV4T, FK_NONE, false, AEK_NONE)
-ARM_CPU_NAME("arm922t", AK_ARMV4T, FK_NONE, false, AEK_NONE)
-ARM_CPU_NAME("arm9312", AK_ARMV4T, FK_NONE, false, AEK_NONE)
-ARM_CPU_NAME("arm940t", AK_ARMV4T, FK_NONE, false, AEK_NONE)
-ARM_CPU_NAME("ep9312", AK_ARMV4T, FK_NONE, false, AEK_NONE)
-ARM_CPU_NAME("arm10tdmi", AK_ARMV5T, FK_NONE, true, AEK_NONE)
-ARM_CPU_NAME("arm1020t", AK_ARMV5T, FK_NONE, false, AEK_NONE)
-ARM_CPU_NAME("arm9e", AK_ARMV5TE, FK_NONE, false, AEK_NONE)
-ARM_CPU_NAME("arm946e-s", AK_ARMV5TE, FK_NONE, false, AEK_NONE)
-ARM_CPU_NAME("arm966e-s", AK_ARMV5TE, FK_NONE, false, AEK_NONE)
-ARM_CPU_NAME("arm968e-s", AK_ARMV5TE, FK_NONE, false, AEK_NONE)
-ARM_CPU_NAME("arm10e", AK_ARMV5TE, FK_NONE, false, AEK_NONE)
-ARM_CPU_NAME("arm1020e", AK_ARMV5TE, FK_NONE, false, AEK_NONE)
-ARM_CPU_NAME("arm1022e", AK_ARMV5TE, FK_NONE, true, AEK_NONE)
-ARM_CPU_NAME("arm926ej-s", AK_ARMV5TEJ, FK_NONE, true, AEK_NONE)
-ARM_CPU_NAME("arm1136j-s", AK_ARMV6, FK_NONE, false, AEK_NONE)
-ARM_CPU_NAME("arm1136jf-s", AK_ARMV6, FK_VFPV2, true, AEK_NONE)
-ARM_CPU_NAME("arm1136jz-s", AK_ARMV6, FK_NONE, false, AEK_NONE)
-ARM_CPU_NAME("arm1176j-s", AK_ARMV6K, FK_NONE, true, AEK_NONE)
-ARM_CPU_NAME("arm1176jz-s", AK_ARMV6KZ, FK_NONE, false, AEK_NONE)
-ARM_CPU_NAME("mpcore", AK_ARMV6K, FK_VFPV2, false, AEK_NONE)
-ARM_CPU_NAME("mpcorenovfp", AK_ARMV6K, FK_NONE, false, AEK_NONE)
-ARM_CPU_NAME("arm1176jzf-s", AK_ARMV6KZ, FK_VFPV2, true, AEK_NONE)
-ARM_CPU_NAME("arm1156t2-s", AK_ARMV6T2, FK_NONE, true, AEK_NONE)
-ARM_CPU_NAME("arm1156t2f-s", AK_ARMV6T2, FK_VFPV2, false, AEK_NONE)
-ARM_CPU_NAME("cortex-m0", AK_ARMV6M, FK_NONE, true, AEK_NONE)
-ARM_CPU_NAME("cortex-m0plus", AK_ARMV6M, FK_NONE, false, AEK_NONE)
-ARM_CPU_NAME("cortex-m1", AK_ARMV6M, FK_NONE, false, AEK_NONE)
-ARM_CPU_NAME("sc000", AK_ARMV6M, FK_NONE, false, AEK_NONE)
-ARM_CPU_NAME("cortex-a5", AK_ARMV7A, FK_NEON_VFPV4, false, (AEK_SEC | AEK_MP))
+ARM_CPU_NAME("arm2", AK_ARMV2, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm3", AK_ARMV2A, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm6", AK_ARMV3, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm7m", AK_ARMV3M, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm8", AK_ARMV4, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm810", AK_ARMV4, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("strongarm", AK_ARMV4, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("strongarm110", AK_ARMV4, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("strongarm1100", AK_ARMV4, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("strongarm1110", AK_ARMV4, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm7tdmi", AK_ARMV4T, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm7tdmi-s", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm710t", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm720t", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm9", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm9tdmi", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm920", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm920t", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm922t", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm9312", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm940t", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("ep9312", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm10tdmi", AK_ARMV5T, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm1020t", AK_ARMV5T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm9e", AK_ARMV5TE, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm946e-s", AK_ARMV5TE, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm966e-s", AK_ARMV5TE, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm968e-s", AK_ARMV5TE, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm10e", AK_ARMV5TE, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm1020e", AK_ARMV5TE, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm1022e", AK_ARMV5TE, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm926ej-s", AK_ARMV5TEJ, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm1136j-s", AK_ARMV6, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm1136jf-s", AK_ARMV6, FK_VFPV2, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm1136jz-s", AK_ARMV6, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm1176j-s", AK_ARMV6K, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm1176jz-s", AK_ARMV6KZ, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("mpcore", AK_ARMV6K, FK_VFPV2, false, ARM::AEK_NONE)
+ARM_CPU_NAME("mpcorenovfp", AK_ARMV6K, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm1176jzf-s", AK_ARMV6KZ, FK_VFPV2, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm1156t2-s", AK_ARMV6T2, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm1156t2f-s", AK_ARMV6T2, FK_VFPV2, false, ARM::AEK_NONE)
+ARM_CPU_NAME("cortex-m0", AK_ARMV6M, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("cortex-m0plus", AK_ARMV6M, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("cortex-m1", AK_ARMV6M, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("sc000", AK_ARMV6M, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("cortex-a5", AK_ARMV7A, FK_NEON_VFPV4, false,
+ (ARM::AEK_SEC | ARM::AEK_MP))
ARM_CPU_NAME("cortex-a7", AK_ARMV7A, FK_NEON_VFPV4, false,
- (AEK_SEC | AEK_MP | AEK_VIRT | AEK_HWDIVARM | AEK_HWDIV))
-ARM_CPU_NAME("cortex-a8", AK_ARMV7A, FK_NEON, true, AEK_SEC)
-ARM_CPU_NAME("cortex-a9", AK_ARMV7A, FK_NEON_FP16, false, (AEK_SEC | AEK_MP))
+ (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
+ ARM::AEK_HWDIV))
+ARM_CPU_NAME("cortex-a8", AK_ARMV7A, FK_NEON, true, ARM::AEK_SEC)
+ARM_CPU_NAME("cortex-a9", AK_ARMV7A, FK_NEON_FP16, false, (ARM::AEK_SEC | ARM::AEK_MP))
ARM_CPU_NAME("cortex-a12", AK_ARMV7A, FK_NEON_VFPV4, false,
- (AEK_SEC | AEK_MP | AEK_VIRT | AEK_HWDIVARM | AEK_HWDIV))
+ (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
+ ARM::AEK_HWDIV))
ARM_CPU_NAME("cortex-a15", AK_ARMV7A, FK_NEON_VFPV4, false,
- (AEK_SEC | AEK_MP | AEK_VIRT | AEK_HWDIVARM | AEK_HWDIV))
+ (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
+ ARM::AEK_HWDIV))
ARM_CPU_NAME("cortex-a17", AK_ARMV7A, FK_NEON_VFPV4, false,
- (AEK_SEC | AEK_MP | AEK_VIRT | AEK_HWDIVARM | AEK_HWDIV))
+ (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
+ ARM::AEK_HWDIV))
ARM_CPU_NAME("krait", AK_ARMV7A, FK_NEON_VFPV4, false,
- (AEK_HWDIVARM | AEK_HWDIV))
-ARM_CPU_NAME("cortex-r4", AK_ARMV7R, FK_NONE, true, AEK_NONE)
-ARM_CPU_NAME("cortex-r4f", AK_ARMV7R, FK_VFPV3_D16, false, AEK_NONE)
+ (ARM::AEK_HWDIVARM | ARM::AEK_HWDIV))
+ARM_CPU_NAME("cortex-r4", AK_ARMV7R, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("cortex-r4f", AK_ARMV7R, FK_VFPV3_D16, false, ARM::AEK_NONE)
ARM_CPU_NAME("cortex-r5", AK_ARMV7R, FK_VFPV3_D16, false,
- (AEK_MP | AEK_HWDIVARM))
+ (ARM::AEK_MP | ARM::AEK_HWDIVARM))
ARM_CPU_NAME("cortex-r7", AK_ARMV7R, FK_VFPV3_D16_FP16, false,
- (AEK_MP | AEK_HWDIVARM))
-ARM_CPU_NAME("sc300", AK_ARMV7M, FK_NONE, false, AEK_NONE)
-ARM_CPU_NAME("cortex-m3", AK_ARMV7M, FK_NONE, true, AEK_NONE)
-ARM_CPU_NAME("cortex-m4", AK_ARMV7EM, FK_FPV4_SP_D16, true, AEK_NONE)
-ARM_CPU_NAME("cortex-m7", AK_ARMV7EM, FK_FPV5_D16, false, AEK_NONE)
-ARM_CPU_NAME("cortex-a35", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, AEK_CRC)
-ARM_CPU_NAME("cortex-a53", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, true, AEK_CRC)
-ARM_CPU_NAME("cortex-a57", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, AEK_CRC)
-ARM_CPU_NAME("cortex-a72", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, AEK_CRC)
-ARM_CPU_NAME("cyclone", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, AEK_CRC)
-ARM_CPU_NAME("exynos-m1", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, AEK_CRC)
+ (ARM::AEK_MP | ARM::AEK_HWDIVARM))
+ARM_CPU_NAME("cortex-r8", AK_ARMV7R, FK_VFPV3_D16_FP16, false,
+ (ARM::AEK_MP | ARM::AEK_HWDIVARM))
+ARM_CPU_NAME("sc300", AK_ARMV7M, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("cortex-m3", AK_ARMV7M, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("cortex-m4", AK_ARMV7EM, FK_FPV4_SP_D16, true, ARM::AEK_NONE)
+ARM_CPU_NAME("cortex-m7", AK_ARMV7EM, FK_FPV5_D16, false, ARM::AEK_NONE)
+ARM_CPU_NAME("cortex-a32", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
+ARM_CPU_NAME("cortex-a35", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
+ARM_CPU_NAME("cortex-a53", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, true, ARM::AEK_CRC)
+ARM_CPU_NAME("cortex-a57", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
+ARM_CPU_NAME("cortex-a72", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
+ARM_CPU_NAME("cortex-a73", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
+ARM_CPU_NAME("cyclone", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
+ARM_CPU_NAME("exynos-m1", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
// Non-standard Arch names.
-ARM_CPU_NAME("iwmmxt", AK_IWMMXT, FK_NONE, true, AEK_NONE)
-ARM_CPU_NAME("xscale", AK_XSCALE, FK_NONE, true, AEK_NONE)
+ARM_CPU_NAME("iwmmxt", AK_IWMMXT, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("xscale", AK_XSCALE, FK_NONE, true, ARM::AEK_NONE)
ARM_CPU_NAME("swift", AK_ARMV7S, FK_NEON_VFPV4, true,
- (AEK_HWDIVARM | AEK_HWDIV))
+ (ARM::AEK_HWDIVARM | ARM::AEK_HWDIV))
// Invalid CPU
-ARM_CPU_NAME("invalid", AK_INVALID, FK_INVALID, true, AEK_INVALID)
+ARM_CPU_NAME("invalid", AK_INVALID, FK_INVALID, true, ARM::AEK_INVALID)
#undef ARM_CPU_NAME
diff --git a/include/llvm/Support/AlignOf.h b/include/llvm/Support/AlignOf.h
index 5268c8d16986..af7f20028b6d 100644
--- a/include/llvm/Support/AlignOf.h
+++ b/include/llvm/Support/AlignOf.h
@@ -38,7 +38,7 @@ struct AlignmentCalcImpl {
#endif
T t;
private:
- AlignmentCalcImpl() {} // Never instantiate.
+ AlignmentCalcImpl() = delete;
};
// Abstract base class helper, this will have the minimal alignment and size
@@ -55,7 +55,7 @@ struct AlignmentCalcImplBase {
// of type T.
template <typename T>
struct AlignmentCalcImpl<T, true> : AlignmentCalcImplBase, T {
- virtual ~AlignmentCalcImpl() = 0;
+ ~AlignmentCalcImpl() override = 0;
};
} // End detail namespace.
@@ -79,8 +79,8 @@ struct AlignOf {
sizeof(detail::AlignmentCalcImpl<T>) - sizeof(T));
#else
enum {
- Alignment = static_cast<unsigned int>(sizeof(detail::AlignmentCalcImpl<T>) -
- sizeof(T))
+ Alignment = static_cast<unsigned int>(
+ sizeof(::llvm::detail::AlignmentCalcImpl<T>) - sizeof(T))
};
#endif
enum { Alignment_GreaterEqual_2Bytes = Alignment >= 2 ? 1 : 0 };
@@ -223,7 +223,7 @@ template <typename T1,
class AlignerImpl {
T1 t1; T2 t2; T3 t3; T4 t4; T5 t5; T6 t6; T7 t7; T8 t8; T9 t9; T10 t10;
- AlignerImpl(); // Never defined or instantiated.
+ AlignerImpl() = delete;
};
template <typename T1,
@@ -249,10 +249,11 @@ template <typename T1,
typename T5 = char, typename T6 = char, typename T7 = char,
typename T8 = char, typename T9 = char, typename T10 = char>
struct AlignedCharArrayUnion : llvm::AlignedCharArray<
- AlignOf<detail::AlignerImpl<T1, T2, T3, T4, T5,
- T6, T7, T8, T9, T10> >::Alignment,
- sizeof(detail::SizerImpl<T1, T2, T3, T4, T5,
- T6, T7, T8, T9, T10>)> {
+ AlignOf<llvm::detail::AlignerImpl<T1, T2, T3, T4, T5,
+ T6, T7, T8, T9, T10> >::Alignment,
+ sizeof(::llvm::detail::SizerImpl<T1, T2, T3, T4, T5,
+ T6, T7, T8, T9, T10>)> {
};
} // end namespace llvm
-#endif
+
+#endif // LLVM_SUPPORT_ALIGNOF_H
diff --git a/include/llvm/Support/Allocator.h b/include/llvm/Support/Allocator.h
index 043d82314609..1c9508661d6f 100644
--- a/include/llvm/Support/Allocator.h
+++ b/include/llvm/Support/Allocator.h
@@ -278,6 +278,8 @@ public:
return TotalMemory;
}
+ size_t getBytesAllocated() const { return BytesAllocated; }
+
void PrintStats() const {
detail::printBumpPtrAllocatorStats(Slabs.size(), BytesAllocated,
getTotalMemory());
diff --git a/include/llvm/Support/Atomic.h b/include/llvm/Support/Atomic.h
index 9ec23e827023..d03714b009c5 100644
--- a/include/llvm/Support/Atomic.h
+++ b/include/llvm/Support/Atomic.h
@@ -9,6 +9,10 @@
//
// This file declares the llvm::sys atomic operations.
//
+// DO NOT USE IN NEW CODE!
+//
+// New code should always rely on the std::atomic facilities in C++11.
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_SUPPORT_ATOMIC_H
@@ -28,11 +32,6 @@ namespace llvm {
cas_flag CompareAndSwap(volatile cas_flag* ptr,
cas_flag new_value,
cas_flag old_value);
- cas_flag AtomicIncrement(volatile cas_flag* ptr);
- cas_flag AtomicDecrement(volatile cas_flag* ptr);
- cas_flag AtomicAdd(volatile cas_flag* ptr, cas_flag val);
- cas_flag AtomicMul(volatile cas_flag* ptr, cas_flag val);
- cas_flag AtomicDiv(volatile cas_flag* ptr, cas_flag val);
}
}
diff --git a/include/llvm/Support/AtomicOrdering.h b/include/llvm/Support/AtomicOrdering.h
new file mode 100644
index 000000000000..8837fab19575
--- /dev/null
+++ b/include/llvm/Support/AtomicOrdering.h
@@ -0,0 +1,153 @@
+//===-- llvm/Support/AtomicOrdering.h ---Atomic Ordering---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Atomic ordering constants.
+///
+/// These values are used by LLVM to represent atomic ordering for C++11's
+/// memory model and more, as detailed in docs/Atomics.rst.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_ATOMICORDERING_H
+#define LLVM_SUPPORT_ATOMICORDERING_H
+
+#include <cstddef>
+
+namespace llvm {
+
+/// Atomic ordering for C11 / C++11's memody models.
+///
+/// These values cannot change because they are shared with standard library
+/// implementations as well as with other compilers.
+enum class AtomicOrderingCABI {
+ relaxed = 0,
+ consume = 1,
+ acquire = 2,
+ release = 3,
+ acq_rel = 4,
+ seq_cst = 5,
+};
+
+bool operator<(AtomicOrderingCABI, AtomicOrderingCABI) = delete;
+bool operator>(AtomicOrderingCABI, AtomicOrderingCABI) = delete;
+bool operator<=(AtomicOrderingCABI, AtomicOrderingCABI) = delete;
+bool operator>=(AtomicOrderingCABI, AtomicOrderingCABI) = delete;
+
+// Validate an integral value which isn't known to fit within the enum's range
+// is a valid AtomicOrderingCABI.
+template <typename Int> static inline bool isValidAtomicOrderingCABI(Int I) {
+ return (Int)AtomicOrderingCABI::relaxed <= I &&
+ I <= (Int)AtomicOrderingCABI::seq_cst;
+}
+
+/// Atomic ordering for LLVM's memory model.
+///
+/// C++ defines ordering as a lattice. LLVM supplements this with NotAtomic and
+/// Unordered, which are both below the C++ orders.
+///
+/// not_atomic-->unordered-->relaxed-->release--------------->acq_rel-->seq_cst
+/// \-->consume-->acquire--/
+enum class AtomicOrdering {
+ NotAtomic = 0,
+ Unordered = 1,
+ Monotonic = 2, // Equivalent to C++'s relaxed.
+ // Consume = 3, // Not specified yet.
+ Acquire = 4,
+ Release = 5,
+ AcquireRelease = 6,
+ SequentiallyConsistent = 7
+};
+
+bool operator<(AtomicOrdering, AtomicOrdering) = delete;
+bool operator>(AtomicOrdering, AtomicOrdering) = delete;
+bool operator<=(AtomicOrdering, AtomicOrdering) = delete;
+bool operator>=(AtomicOrdering, AtomicOrdering) = delete;
+
+// Validate an integral value which isn't known to fit within the enum's range
+// is a valid AtomicOrdering.
+template <typename Int> static inline bool isValidAtomicOrdering(Int I) {
+ return (Int)AtomicOrdering::NotAtomic <= I &&
+ I <= (Int)AtomicOrdering::SequentiallyConsistent;
+}
+
+/// String used by LLVM IR to represent atomic ordering.
+static inline const char *toIRString(AtomicOrdering ao) {
+ static const char *names[8] = {"not_atomic", "unordered", "monotonic",
+ "consume", "acquire", "release",
+ "acq_rel", "seq_cst"};
+ return names[(size_t)ao];
+}
+
+/// Returns true if ao is stronger than other as defined by the AtomicOrdering
+/// lattice, which is based on C++'s definition.
+static inline bool isStrongerThan(AtomicOrdering ao, AtomicOrdering other) {
+ static const bool lookup[8][8] = {
+ // NA UN RX CO AC RE AR SC
+ /* NotAtomic */ {0, 0, 0, 0, 0, 0, 0, 0},
+ /* Unordered */ {1, 0, 0, 0, 0, 0, 0, 0},
+ /* relaxed */ {1, 1, 0, 0, 0, 0, 0, 0},
+ /* consume */ {1, 1, 1, 0, 0, 0, 0, 0},
+ /* acquire */ {1, 1, 1, 1, 0, 0, 0, 0},
+ /* release */ {1, 1, 1, 0, 0, 0, 0, 0},
+ /* acq_rel */ {1, 1, 1, 1, 1, 1, 0, 0},
+ /* seq_cst */ {1, 1, 1, 1, 1, 1, 1, 0},
+ };
+ return lookup[(size_t)ao][(size_t)other];
+}
+
+static inline bool isAtLeastOrStrongerThan(AtomicOrdering ao,
+ AtomicOrdering other) {
+ static const bool lookup[8][8] = {
+ // NA UN RX CO AC RE AR SC
+ /* NotAtomic */ {1, 0, 0, 0, 0, 0, 0, 0},
+ /* Unordered */ {1, 1, 0, 0, 0, 0, 0, 0},
+ /* relaxed */ {1, 1, 1, 0, 0, 0, 0, 0},
+ /* consume */ {1, 1, 1, 1, 0, 0, 0, 0},
+ /* acquire */ {1, 1, 1, 1, 1, 0, 0, 0},
+ /* release */ {1, 1, 1, 0, 0, 1, 0, 0},
+ /* acq_rel */ {1, 1, 1, 1, 1, 1, 1, 0},
+ /* seq_cst */ {1, 1, 1, 1, 1, 1, 1, 1},
+ };
+ return lookup[(size_t)ao][(size_t)other];
+}
+
+static inline bool isStrongerThanUnordered(AtomicOrdering ao) {
+ return isStrongerThan(ao, AtomicOrdering::Unordered);
+}
+
+static inline bool isStrongerThanMonotonic(AtomicOrdering ao) {
+ return isStrongerThan(ao, AtomicOrdering::Monotonic);
+}
+
+static inline bool isAcquireOrStronger(AtomicOrdering ao) {
+ return isAtLeastOrStrongerThan(ao, AtomicOrdering::Acquire);
+}
+
+static inline bool isReleaseOrStronger(AtomicOrdering ao) {
+ return isAtLeastOrStrongerThan(ao, AtomicOrdering::Release);
+}
+
+static inline AtomicOrderingCABI toCABI(AtomicOrdering ao) {
+ static const AtomicOrderingCABI lookup[8] = {
+ /* NotAtomic */ AtomicOrderingCABI::relaxed,
+ /* Unordered */ AtomicOrderingCABI::relaxed,
+ /* relaxed */ AtomicOrderingCABI::relaxed,
+ /* consume */ AtomicOrderingCABI::consume,
+ /* acquire */ AtomicOrderingCABI::acquire,
+ /* release */ AtomicOrderingCABI::release,
+ /* acq_rel */ AtomicOrderingCABI::acq_rel,
+ /* seq_cst */ AtomicOrderingCABI::seq_cst,
+ };
+ return lookup[(size_t)ao];
+}
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_ATOMICORDERING_H
diff --git a/include/llvm/Support/BranchProbability.h b/include/llvm/Support/BranchProbability.h
index 26bc888d1cab..e8eb50d53eb6 100644
--- a/include/llvm/Support/BranchProbability.h
+++ b/include/llvm/Support/BranchProbability.h
@@ -203,7 +203,7 @@ void BranchProbability::normalizeProbabilities(ProbabilityIter Begin,
if (Sum <= BranchProbability::getDenominator())
return;
}
-
+
if (Sum == 0) {
BranchProbability BP(1, std::distance(Begin, End));
std::fill(Begin, End, BP);
diff --git a/include/llvm/Support/COFF.h b/include/llvm/Support/COFF.h
index 0245632c96a0..7dad3e82bda6 100644
--- a/include/llvm/Support/COFF.h
+++ b/include/llvm/Support/COFF.h
@@ -377,7 +377,6 @@ namespace COFF {
uint8_t unused[10];
};
- /// These are not documented in the spec, but are located in WinNT.h.
enum WeakExternalCharacteristics {
IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY = 1,
IMAGE_WEAK_EXTERN_SEARCH_LIBRARY = 2,
@@ -530,7 +529,7 @@ namespace COFF {
EXCEPTION_TABLE,
CERTIFICATE_TABLE,
BASE_RELOCATION_TABLE,
- DEBUG,
+ DEBUG_DIRECTORY,
ARCHITECTURE,
GLOBAL_PTR,
TLS_TABLE,
@@ -599,7 +598,13 @@ namespace COFF {
IMAGE_DEBUG_TYPE_OMAP_TO_SRC = 7,
IMAGE_DEBUG_TYPE_OMAP_FROM_SRC = 8,
IMAGE_DEBUG_TYPE_BORLAND = 9,
- IMAGE_DEBUG_TYPE_CLSID = 11
+ IMAGE_DEBUG_TYPE_RESERVED10 = 10,
+ IMAGE_DEBUG_TYPE_CLSID = 11,
+ IMAGE_DEBUG_TYPE_VC_FEATURE = 12,
+ IMAGE_DEBUG_TYPE_POGO = 13,
+ IMAGE_DEBUG_TYPE_ILTCG = 14,
+ IMAGE_DEBUG_TYPE_MPX = 15,
+ IMAGE_DEBUG_TYPE_REPRO = 16,
};
enum BaseRelocationType {
@@ -656,26 +661,8 @@ namespace COFF {
}
};
- enum CodeViewLine : unsigned {
- CVL_LineNumberStartBits = 24,
- CVL_LineNumberEndDeltaBits = 7,
- CVL_LineNumberEndDeltaMask = (1U << CVL_LineNumberEndDeltaBits) - 1,
- CVL_MaxLineNumber = (1U << CVL_LineNumberStartBits) - 1,
- CVL_IsStatement = 1U << 31,
- CVL_MaxColumnNumber = UINT16_MAX,
- };
-
enum CodeViewIdentifiers {
- DEBUG_LINE_TABLES_HAVE_COLUMN_RECORDS = 0x1,
DEBUG_SECTION_MAGIC = 0x4,
- DEBUG_SYMBOL_SUBSECTION = 0xF1,
- DEBUG_LINE_TABLE_SUBSECTION = 0xF2,
- DEBUG_STRING_TABLE_SUBSECTION = 0xF3,
- DEBUG_INDEX_SUBSECTION = 0xF4,
-
- // Symbol subsections are split into records of different types.
- DEBUG_SYMBOL_TYPE_PROC_START = 0x1147,
- DEBUG_SYMBOL_TYPE_PROC_END = 0x114F
};
inline bool isReservedSectionNumber(int32_t SectionNumber) {
diff --git a/include/llvm/Support/CachePruning.h b/include/llvm/Support/CachePruning.h
new file mode 100644
index 000000000000..383414119139
--- /dev/null
+++ b/include/llvm/Support/CachePruning.h
@@ -0,0 +1,69 @@
+//=- CachePruning.h - Helper to manage the pruning of a cache dir -*- C++ -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements pruning of a directory intended for cache storage, using
+// various policies.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_CACHE_PRUNING_H
+#define LLVM_SUPPORT_CACHE_PRUNING_H
+
+#include "llvm/ADT/StringRef.h"
+
+namespace llvm {
+
+/// Handle pruning a directory provided a path and some options to control what
+/// to prune.
+class CachePruning {
+public:
+ /// Prepare to prune \p Path.
+ CachePruning(StringRef Path) : Path(Path) {}
+
+ /// Define the pruning interval. This is intended to be used to avoid scanning
+ /// the directory too often. It does not impact the decision of which file to
+ /// prune. A value of 0 forces the scan to occurs.
+ CachePruning &setPruningInterval(int PruningInterval) {
+ Interval = PruningInterval;
+ return *this;
+ }
+
+ /// Define the expiration for a file. When a file hasn't been accessed for
+ /// \p ExpireAfter seconds, it is removed from the cache. A value of 0 disable
+ /// the expiration-based pruning.
+ CachePruning &setEntryExpiration(unsigned ExpireAfter) {
+ Expiration = ExpireAfter;
+ return *this;
+ }
+
+ /// Define the maximum size for the cache directory, in terms of percentage of
+ /// the available space on the the disk. Set to 100 to indicate no limit, 50
+ /// to indicate that the cache size will not be left over half the
+ /// available disk space. A value over 100 will be reduced to 100. A value of
+ /// 0 disable the size-based pruning.
+ CachePruning &setMaxSize(unsigned Percentage) {
+ PercentageOfAvailableSpace = std::min(100u, Percentage);
+ return *this;
+ }
+
+ /// Peform pruning using the supplied options, returns true if pruning
+ /// occured, i.e. if PruningInterval was expired.
+ bool prune();
+
+private:
+ // Options that matches the setters above.
+ std::string Path;
+ unsigned Expiration = 0;
+ unsigned Interval = 0;
+ unsigned PercentageOfAvailableSpace = 0;
+};
+
+} // namespace llvm
+
+#endif \ No newline at end of file
diff --git a/include/llvm/Support/CodeGen.h b/include/llvm/Support/CodeGen.h
index 243f2dd7498c..e19abf8271eb 100644
--- a/include/llvm/Support/CodeGen.h
+++ b/include/llvm/Support/CodeGen.h
@@ -15,22 +15,25 @@
#ifndef LLVM_SUPPORT_CODEGEN_H
#define LLVM_SUPPORT_CODEGEN_H
-#include "llvm-c/TargetMachine.h"
-#include "llvm/Support/ErrorHandling.h"
-
namespace llvm {
// Relocation model types.
namespace Reloc {
- enum Model { Default, Static, PIC_, DynamicNoPIC };
+ enum Model { Static, PIC_, DynamicNoPIC };
}
// Code model types.
namespace CodeModel {
+ // Sync changes with CodeGenCWrappers.h.
enum Model { Default, JITDefault, Small, Kernel, Medium, Large };
}
namespace PICLevel {
+ // This is used to map -fpic/-fPIC.
+ enum Level { NotPIC=0, SmallPIC=1, BigPIC=2 };
+ }
+
+ namespace PIELevel {
enum Level { Default=0, Small=1, Large=2 };
}
@@ -54,42 +57,6 @@ namespace llvm {
};
}
- // Create wrappers for C Binding types (see CBindingWrapping.h).
- inline CodeModel::Model unwrap(LLVMCodeModel Model) {
- switch (Model) {
- case LLVMCodeModelDefault:
- return CodeModel::Default;
- case LLVMCodeModelJITDefault:
- return CodeModel::JITDefault;
- case LLVMCodeModelSmall:
- return CodeModel::Small;
- case LLVMCodeModelKernel:
- return CodeModel::Kernel;
- case LLVMCodeModelMedium:
- return CodeModel::Medium;
- case LLVMCodeModelLarge:
- return CodeModel::Large;
- }
- return CodeModel::Default;
- }
-
- inline LLVMCodeModel wrap(CodeModel::Model Model) {
- switch (Model) {
- case CodeModel::Default:
- return LLVMCodeModelDefault;
- case CodeModel::JITDefault:
- return LLVMCodeModelJITDefault;
- case CodeModel::Small:
- return LLVMCodeModelSmall;
- case CodeModel::Kernel:
- return LLVMCodeModelKernel;
- case CodeModel::Medium:
- return LLVMCodeModelMedium;
- case CodeModel::Large:
- return LLVMCodeModelLarge;
- }
- llvm_unreachable("Bad CodeModel!");
- }
} // end llvm namespace
#endif
diff --git a/include/llvm/Support/CodeGenCWrappers.h b/include/llvm/Support/CodeGenCWrappers.h
new file mode 100644
index 000000000000..6db4433a4350
--- /dev/null
+++ b/include/llvm/Support/CodeGenCWrappers.h
@@ -0,0 +1,64 @@
+//===- llvm/Support/CodeGenCWrappers.h - CodeGen C Wrappers -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines C bindings wrappers for enums in llvm/Support/CodeGen.h
+// that need them. The wrappers are separated to avoid adding an indirect
+// dependency on llvm/Config/Targets.def to CodeGen.h.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_CODEGENCWRAPPERS_H
+#define LLVM_SUPPORT_CODEGENCWRAPPERS_H
+
+#include "llvm-c/TargetMachine.h"
+#include "llvm/Support/CodeGen.h"
+#include "llvm/Support/ErrorHandling.h"
+
+namespace llvm {
+
+inline CodeModel::Model unwrap(LLVMCodeModel Model) {
+ switch (Model) {
+ case LLVMCodeModelDefault:
+ return CodeModel::Default;
+ case LLVMCodeModelJITDefault:
+ return CodeModel::JITDefault;
+ case LLVMCodeModelSmall:
+ return CodeModel::Small;
+ case LLVMCodeModelKernel:
+ return CodeModel::Kernel;
+ case LLVMCodeModelMedium:
+ return CodeModel::Medium;
+ case LLVMCodeModelLarge:
+ return CodeModel::Large;
+ }
+ return CodeModel::Default;
+}
+
+inline LLVMCodeModel wrap(CodeModel::Model Model) {
+ switch (Model) {
+ case CodeModel::Default:
+ return LLVMCodeModelDefault;
+ case CodeModel::JITDefault:
+ return LLVMCodeModelJITDefault;
+ case CodeModel::Small:
+ return LLVMCodeModelSmall;
+ case CodeModel::Kernel:
+ return LLVMCodeModelKernel;
+ case CodeModel::Medium:
+ return LLVMCodeModelMedium;
+ case CodeModel::Large:
+ return LLVMCodeModelLarge;
+ }
+ llvm_unreachable("Bad CodeModel!");
+}
+
+} // end llvm namespace
+
+#endif
+
diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h
index 943d2df37708..70465a0e3fd3 100644
--- a/include/llvm/Support/CommandLine.h
+++ b/include/llvm/Support/CommandLine.h
@@ -21,10 +21,12 @@
#define LLVM_SUPPORT_COMMANDLINE_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ManagedStatic.h"
#include <cassert>
#include <climits>
#include <cstdarg>
@@ -43,8 +45,9 @@ namespace cl {
//===----------------------------------------------------------------------===//
// ParseCommandLineOptions - Command line option processing entry point.
//
-void ParseCommandLineOptions(int argc, const char *const *argv,
- const char *Overview = nullptr);
+bool ParseCommandLineOptions(int argc, const char *const *argv,
+ const char *Overview = nullptr,
+ bool IgnoreErrors = false);
//===----------------------------------------------------------------------===//
// ParseEnvironmentOptions - Environment variable option processing alternate
@@ -171,6 +174,45 @@ public:
extern OptionCategory GeneralCategory;
//===----------------------------------------------------------------------===//
+// SubCommand class
+//
+class SubCommand {
+private:
+ const char *const Name = nullptr;
+ const char *const Description = nullptr;
+
+protected:
+ void registerSubCommand();
+ void unregisterSubCommand();
+
+public:
+ SubCommand(const char *const Name, const char *const Description = nullptr)
+ : Name(Name), Description(Description) {
+ registerSubCommand();
+ }
+ SubCommand() {}
+
+ void reset();
+
+ operator bool() const;
+
+ const char *getName() const { return Name; }
+ const char *getDescription() const { return Description; }
+
+ SmallVector<Option *, 4> PositionalOpts;
+ SmallVector<Option *, 4> SinkOpts;
+ StringMap<Option *> OptionsMap;
+
+ Option *ConsumeAfterOpt = nullptr; // The ConsumeAfter option if it exists.
+};
+
+// A special subcommand representing no subcommand
+extern ManagedStatic<SubCommand> TopLevelSubCommand;
+
+// A special subcommand that can be used to put an option into all subcommands.
+extern ManagedStatic<SubCommand> AllSubCommands;
+
+//===----------------------------------------------------------------------===//
// Option Base class
//
class alias;
@@ -209,6 +251,7 @@ public:
StringRef HelpStr; // The descriptive text message for -help
StringRef ValueStr; // String describing what the value of this option is
OptionCategory *Category; // The Category this option belongs to
+ SmallPtrSet<SubCommand *, 4> Subs; // The subcommands this option belongs to.
bool FullyInitialized; // Has addArguemnt been called?
inline enum NumOccurrencesFlag getNumOccurrencesFlag() const {
@@ -229,6 +272,16 @@ public:
// hasArgStr - Return true if the argstr != ""
bool hasArgStr() const { return !ArgStr.empty(); }
+ bool isPositional() const { return getFormattingFlag() == cl::Positional; }
+ bool isSink() const { return getMiscFlags() & cl::Sink; }
+ bool isConsumeAfter() const {
+ return getNumOccurrencesFlag() == cl::ConsumeAfter;
+ }
+ bool isInAllSubCommands() const {
+ return std::any_of(Subs.begin(), Subs.end(), [](const SubCommand *SC) {
+ return SC == &*AllSubCommands;
+ });
+ }
//-------------------------------------------------------------------------===
// Accessor functions set by OptionModifiers
@@ -243,6 +296,7 @@ public:
void setMiscFlag(enum MiscFlags M) { Misc |= M; }
void setPosition(unsigned pos) { Position = pos; }
void setCategory(OptionCategory &C) { Category = &C; }
+ void addSubCommand(SubCommand &S) { Subs.insert(&S); }
protected:
explicit Option(enum NumOccurrencesFlag OccurrencesFlag,
@@ -287,6 +341,7 @@ public:
public:
inline int getNumOccurrences() const { return NumOccurrences; }
+ inline void reset() { NumOccurrences = 0; }
virtual ~Option() {}
};
@@ -349,6 +404,14 @@ struct cat {
template <class Opt> void apply(Opt &O) const { O.setCategory(Category); }
};
+// sub - Specify the subcommand that this option belongs to.
+struct sub {
+ SubCommand &Sub;
+ sub(SubCommand &S) : Sub(S) {}
+
+ template <class Opt> void apply(Opt &O) const { O.addSubCommand(Sub); }
+};
+
//===----------------------------------------------------------------------===//
// OptionValue class
@@ -946,7 +1009,7 @@ public:
// getValueName - Overload in subclass to provide a better default value.
const char *getValueName() const override { return "string"; }
- void printOptionDiff(const Option &O, StringRef V, OptVal Default,
+ void printOptionDiff(const Option &O, StringRef V, const OptVal &Default,
size_t GlobalWidth) const;
// An out-of-line virtual method to provide a 'home' for this class.
@@ -1589,6 +1652,7 @@ class alias : public Option {
error("cl::alias must have argument name specified!");
if (!AliasFor)
error("cl::alias must have an cl::aliasopt(option) specified!");
+ Subs = AliasFor->Subs;
addArgument();
}
@@ -1669,7 +1733,7 @@ void PrintHelpMessage(bool Hidden = false, bool Categorized = false);
/// Hopefully this API can be depricated soon. Any situation where options need
/// to be modified by tools or libraries should be handled by sane APIs rather
/// than just handing around a global list.
-StringMap<Option *> &getRegisteredOptions();
+StringMap<Option *> &getRegisteredOptions(SubCommand &Sub = *TopLevelSubCommand);
//===----------------------------------------------------------------------===//
// Standalone command line processing utilities.
@@ -1737,7 +1801,8 @@ bool ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
/// Some tools (like clang-format) like to be able to hide all options that are
/// not specific to the tool. This function allows a tool to specify a single
/// option category to display in the -help output.
-void HideUnrelatedOptions(cl::OptionCategory &Category);
+void HideUnrelatedOptions(cl::OptionCategory &Category,
+ SubCommand &Sub = *TopLevelSubCommand);
/// \brief Mark all options not part of the categories as cl::ReallyHidden.
///
@@ -1746,7 +1811,19 @@ void HideUnrelatedOptions(cl::OptionCategory &Category);
/// Some tools (like clang-format) like to be able to hide all options that are
/// not specific to the tool. This function allows a tool to specify a single
/// option category to display in the -help output.
-void HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories);
+void HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories,
+ SubCommand &Sub = *TopLevelSubCommand);
+
+/// \brief Reset all command line options to a state that looks as if they have
+/// never appeared on the command line. This is useful for being able to parse
+/// a command line multiple times (especially useful for writing tests).
+void ResetAllOptionOccurrences();
+
+/// \brief Reset the command line parser back to its initial state. This
+/// removes
+/// all options, categories, and subcommands and returns the parser to a state
+/// where no options are supported.
+void ResetCommandLineParser();
} // End namespace cl
diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h
index b3416bbfffb6..fae0d8f4419e 100644
--- a/include/llvm/Support/Compiler.h
+++ b/include/llvm/Support/Compiler.h
@@ -17,6 +17,10 @@
#include "llvm/Config/llvm-config.h"
+#if defined(_MSC_VER)
+#include <sal.h>
+#endif
+
#ifndef __has_feature
# define __has_feature(x) 0
#endif
@@ -92,7 +96,7 @@
#define LLVM_LVALUE_FUNCTION
#endif
-#if __has_feature(cxx_constexpr) || defined(__GXX_EXPERIMENTAL_CXX0X__)
+#if __has_feature(cxx_constexpr) || defined(__GXX_EXPERIMENTAL_CXX0X__) || LLVM_MSC_PREREQ(1900)
# define LLVM_CONSTEXPR constexpr
#else
# define LLVM_CONSTEXPR
@@ -124,6 +128,8 @@
#if __has_attribute(warn_unused_result) || LLVM_GNUC_PREREQ(3, 4, 0)
#define LLVM_ATTRIBUTE_UNUSED_RESULT __attribute__((__warn_unused_result__))
+#elif defined(_MSC_VER)
+#define LLVM_ATTRIBUTE_UNUSED_RESULT _Check_return_
#else
#define LLVM_ATTRIBUTE_UNUSED_RESULT
#endif
@@ -206,6 +212,8 @@
#if __has_attribute(returns_nonnull) || LLVM_GNUC_PREREQ(4, 9, 0)
#define LLVM_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull))
+#elif defined(_MSC_VER)
+#define LLVM_ATTRIBUTE_RETURNS_NONNULL _Ret_notnull_
#else
#define LLVM_ATTRIBUTE_RETURNS_NONNULL
#endif
@@ -266,6 +274,23 @@
# define LLVM_BUILTIN_TRAP *(volatile int*)0x11 = 0
#endif
+/// LLVM_BUILTIN_DEBUGTRAP - On compilers which support it, expands to
+/// an expression which causes the program to break while running
+/// under a debugger.
+#if __has_builtin(__builtin_debugtrap)
+# define LLVM_BUILTIN_DEBUGTRAP __builtin_debugtrap()
+#elif defined(_MSC_VER)
+// The __debugbreak intrinsic is supported by MSVC and breaks while
+// running under the debugger, and also supports invoking a debugger
+// when the OS is configured appropriately.
+# define LLVM_BUILTIN_DEBUGTRAP __debugbreak()
+#else
+// Just continue execution when built with compilers that have no
+// support. This is a debugging aid and not intended to force the
+// program to abort if encountered.
+# define LLVM_BUILTIN_DEBUGTRAP
+#endif
+
/// \macro LLVM_ASSUME_ALIGNED
/// \brief Returns a pointer with an assumed alignment.
#if __has_builtin(__builtin_assume_aligned) || LLVM_GNUC_PREREQ(4, 7, 0)
@@ -407,6 +432,14 @@ void AnnotateIgnoreWritesEnd(const char *file, int line);
# define TsanIgnoreWritesEnd()
#endif
+/// \macro LLVM_NO_SANITIZE
+/// \brief Disable a particular sanitizer for a function.
+#if __has_attribute(no_sanitize)
+#define LLVM_NO_SANITIZE(KIND) __attribute__((no_sanitize(KIND)))
+#else
+#define LLVM_NO_SANITIZE(KIND)
+#endif
+
/// \brief Mark debug helper function definitions like dump() that should not be
/// stripped from debug builds.
// FIXME: Move this to a private config.h as it's not usable in public headers.
diff --git a/include/llvm/Support/ConvertUTF.h b/include/llvm/Support/ConvertUTF.h
index 38952ec99e61..5de5774f9db5 100644
--- a/include/llvm/Support/ConvertUTF.h
+++ b/include/llvm/Support/ConvertUTF.h
@@ -180,10 +180,13 @@ unsigned getNumBytesForUTF8(UTF8 firstByte);
/*************************************************************************/
/* Below are LLVM-specific wrappers of the functions above. */
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringRef.h"
+#include <string>
+#include <cstddef>
namespace llvm {
+template <typename T> class ArrayRef;
+template <typename T> class SmallVectorImpl;
+class StringRef;
/**
* Convert an UTF8 StringRef to UTF8, UTF16, or UTF32 depending on
@@ -198,6 +201,25 @@ bool ConvertUTF8toWide(unsigned WideCharWidth, llvm::StringRef Source,
char *&ResultPtr, const UTF8 *&ErrorPtr);
/**
+* Converts a UTF-8 StringRef to a std::wstring.
+* \return true on success.
+*/
+bool ConvertUTF8toWide(llvm::StringRef Source, std::wstring &Result);
+
+/**
+* Converts a UTF-8 C-string to a std::wstring.
+* \return true on success.
+*/
+bool ConvertUTF8toWide(const char *Source, std::wstring &Result);
+
+/**
+* Converts a std::wstring to a UTF-8 encoded std::string.
+* \return true on success.
+*/
+bool convertWideToUTF8(const std::wstring &Source, std::string &Result);
+
+
+/**
* Convert an Unicode code point to UTF8 sequence.
*
* \param Source a Unicode code point.
@@ -252,6 +274,15 @@ bool hasUTF16ByteOrderMark(ArrayRef<char> SrcBytes);
bool convertUTF16ToUTF8String(ArrayRef<char> SrcBytes, std::string &Out);
/**
+* Converts a UTF16 string into a UTF8 std::string.
+*
+* \param [in] Src A buffer of UTF-16 encoded text.
+* \param [out] Out Converted UTF-8 is stored here on success.
+* \returns true on success
+*/
+bool convertUTF16ToUTF8String(ArrayRef<UTF16> Src, std::string &Out);
+
+/**
* Converts a UTF-8 string into a UTF-16 string with native endianness.
*
* \returns true on success
diff --git a/include/llvm/Support/CrashRecoveryContext.h b/include/llvm/Support/CrashRecoveryContext.h
index 1a1c74368761..6cbc331d2731 100644
--- a/include/llvm/Support/CrashRecoveryContext.h
+++ b/include/llvm/Support/CrashRecoveryContext.h
@@ -11,7 +11,6 @@
#define LLVM_SUPPORT_CRASHRECOVERYCONTEXT_H
#include "llvm/ADT/STLExtras.h"
-#include <string>
namespace llvm {
class CrashRecoveryContextCleanup;
@@ -70,8 +69,7 @@ public:
/// \return True if the function completed successfully, and false if the
/// function crashed (or HandleCrash was called explicitly). Clients should
/// make as little assumptions as possible about the program state when
- /// RunSafely has returned false. Clients can use getBacktrace() to retrieve
- /// the backtrace of the crash on failures.
+ /// RunSafely has returned false.
bool RunSafely(function_ref<void()> Fn);
bool RunSafely(void (*Fn)(void*), void *UserData) {
return RunSafely([&]() { Fn(UserData); });
@@ -94,13 +92,6 @@ public:
/// \brief Explicitly trigger a crash recovery in the current process, and
/// return failure from RunSafely(). This function does not return.
void HandleCrash();
-
- /// \brief Return a string containing the backtrace where the crash was
- /// detected; or empty if the backtrace wasn't recovered.
- ///
- /// This function is only valid when a crash has been detected (i.e.,
- /// RunSafely() has returned false.
- const std::string &getBacktrace() const;
};
class CrashRecoveryContextCleanup {
diff --git a/include/llvm/Support/DataTypes.h.cmake b/include/llvm/Support/DataTypes.h.cmake
index c90bf51afaee..541dbc3d635d 100644
--- a/include/llvm/Support/DataTypes.h.cmake
+++ b/include/llvm/Support/DataTypes.h.cmake
@@ -21,8 +21,6 @@
/* Please leave this file C-compatible. */
-/* Please keep this file in sync with DataTypes.h.in */
-
#ifndef SUPPORT_DATATYPES_H
#define SUPPORT_DATATYPES_H
@@ -37,36 +35,43 @@
#include <math.h>
#endif
+#ifdef __cplusplus
+#include <cinttypes>
+#else
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
+#endif
+#ifdef __cplusplus
+#include <cstdint>
+#else
#ifdef HAVE_STDINT_H
#include <stdint.h>
#else
#error "Compiler must provide an implementation of stdint.h"
#endif
+#endif
#ifndef _MSC_VER
-/* Note that this header's correct operation depends on __STDC_LIMIT_MACROS
- being defined. We would define it here, but in order to prevent Bad Things
- happening when system headers or C++ STL headers include stdint.h before we
- define it here, we define it on the g++ command line (in Makefile.rules). */
-#if !defined(__STDC_LIMIT_MACROS)
-# error "Must #define __STDC_LIMIT_MACROS before #including Support/DataTypes.h"
+#if !defined(UINT32_MAX)
+# error "The standard header <cstdint> is not C++11 compliant. Must #define "\
+ "__STDC_LIMIT_MACROS before #including Support/DataTypes.h"
#endif
-#if !defined(__STDC_CONSTANT_MACROS)
-# error "Must #define __STDC_CONSTANT_MACROS before " \
- "#including Support/DataTypes.h"
+#if !defined(UINT32_C)
+# error "The standard header <cstdint> is not C++11 compliant. Must #define "\
+ "__STDC_CONSTANT_MACROS before #including Support/DataTypes.h"
#endif
/* Note that <inttypes.h> includes <stdint.h>, if this is a C99 system. */
#include <sys/types.h>
#ifdef _AIX
-#include "llvm/Support/AIXDataTypesFix.h"
+// GCC is strict about defining large constants: they must have LL modifier.
+#undef INT64_MAX
+#undef INT64_MIN
#endif
/* Handle incorrect definition of uint64_t as u_int64_t */
@@ -79,14 +84,14 @@ typedef u_int64_t uint64_t;
#endif
#else /* _MSC_VER */
-#include <stdlib.h>
-#include <stddef.h>
-#include <sys/types.h>
#ifdef __cplusplus
-#include <cmath>
+#include <cstdlib>
+#include <cstddef>
#else
-#include <math.h>
+#include <stdlib.h>
+#include <stddef.h>
#endif
+#include <sys/types.h>
#if defined(_WIN64)
typedef signed __int64 ssize_t;
@@ -127,4 +132,4 @@ typedef signed int ssize_t;
#define HUGE_VALF (float)HUGE_VAL
#endif
-#endif /* SUPPORT_DATATYPES_H */
+#endif /* SUPPORT_DATATYPES_H */
diff --git a/include/llvm/Support/DataTypes.h.in b/include/llvm/Support/DataTypes.h.in
deleted file mode 100644
index b8b2ba56ff30..000000000000
--- a/include/llvm/Support/DataTypes.h.in
+++ /dev/null
@@ -1,123 +0,0 @@
-/*===-- include/Support/DataTypes.h - Define fixed size types -----*- C -*-===*\
-|* *|
-|* The LLVM Compiler Infrastructure *|
-|* *|
-|* This file is distributed under the University of Illinois Open Source *|
-|* License. See LICENSE.TXT for details. *|
-|* *|
-|*===----------------------------------------------------------------------===*|
-|* *|
-|* This file contains definitions to figure out the size of _HOST_ data types.*|
-|* This file is important because different host OS's define different macros,*|
-|* which makes portability tough. This file exports the following *|
-|* definitions: *|
-|* *|
-|* [u]int(32|64)_t : typedefs for signed and unsigned 32/64 bit system types*|
-|* [U]INT(8|16|32|64)_(MIN|MAX) : Constants for the min and max values. *|
-|* *|
-|* No library is required when using these functions. *|
-|* *|
-|*===----------------------------------------------------------------------===*/
-
-/* Please leave this file C-compatible. */
-
-/* Please keep this file in sync with DataTypes.h.cmake */
-
-#ifndef SUPPORT_DATATYPES_H
-#define SUPPORT_DATATYPES_H
-
-#undef HAVE_INTTYPES_H
-#undef HAVE_STDINT_H
-#undef HAVE_UINT64_T
-#undef HAVE_U_INT64_T
-
-#ifdef __cplusplus
-#include <cmath>
-#else
-#include <math.h>
-#endif
-
-#ifdef HAVE_INTTYPES_H
-#include <inttypes.h>
-#endif
-
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#else
-#error "Compiler must provide an implementation of stdint.h"
-#endif
-
-#ifndef _MSC_VER
-
-/* Note that this header's correct operation depends on __STDC_LIMIT_MACROS
- being defined. We would define it here, but in order to prevent Bad Things
- happening when system headers or C++ STL headers include stdint.h before we
- define it here, we define it on the g++ command line (in Makefile.rules). */
-#if !defined(__STDC_LIMIT_MACROS)
-# error "Must #define __STDC_LIMIT_MACROS before #including Support/DataTypes.h"
-#endif
-
-#if !defined(__STDC_CONSTANT_MACROS)
-# error "Must #define __STDC_CONSTANT_MACROS before " \
- "#including Support/DataTypes.h"
-#endif
-
-/* Note that <inttypes.h> includes <stdint.h>, if this is a C99 system. */
-#include <sys/types.h>
-
-#ifdef _AIX
-#include "llvm/Support/AIXDataTypesFix.h"
-#endif
-
-/* Handle incorrect definition of uint64_t as u_int64_t */
-#ifndef HAVE_UINT64_T
-#ifdef HAVE_U_INT64_T
-typedef u_int64_t uint64_t;
-#else
-# error "Don't have a definition for uint64_t on this platform"
-#endif
-#endif
-
-#else /* _MSC_VER */
-#include <stdlib.h>
-#include <stddef.h>
-#include <sys/types.h>
-#ifdef __cplusplus
-#include <cmath>
-#else
-#include <math.h>
-#endif
-
-#if defined(_WIN64)
-typedef signed __int64 ssize_t;
-#else
-typedef signed int ssize_t;
-#endif /* _WIN64 */
-
-#ifndef HAVE_INTTYPES_H
-#define PRId64 "I64d"
-#define PRIi64 "I64i"
-#define PRIo64 "I64o"
-#define PRIu64 "I64u"
-#define PRIx64 "I64x"
-#define PRIX64 "I64X"
-#endif /* HAVE_INTTYPES_H */
-
-#endif /* _MSC_VER */
-
-/* Set defaults for constants which we cannot find. */
-#if !defined(INT64_MAX)
-# define INT64_MAX 9223372036854775807LL
-#endif
-#if !defined(INT64_MIN)
-# define INT64_MIN ((-INT64_MAX)-1)
-#endif
-#if !defined(UINT64_MAX)
-# define UINT64_MAX 0xffffffffffffffffULL
-#endif
-
-#ifndef HUGE_VALF
-#define HUGE_VALF (float)HUGE_VAL
-#endif
-
-#endif /* SUPPORT_DATATYPES_H */
diff --git a/include/llvm/Support/Dwarf.def b/include/llvm/Support/Dwarf.def
index b15070b3e9b0..b73f2aed5311 100644
--- a/include/llvm/Support/Dwarf.def
+++ b/include/llvm/Support/Dwarf.def
@@ -14,7 +14,7 @@
// TODO: Add other DW-based macros.
#if !(defined HANDLE_DW_TAG || defined HANDLE_DW_OP || \
defined HANDLE_DW_LANG || defined HANDLE_DW_ATE || \
- defined HANDLE_DW_VIRTUALITY)
+ defined HANDLE_DW_VIRTUALITY || defined HANDLE_DW_CC)
#error "Missing macro definition of HANDLE_DW*"
#endif
@@ -38,6 +38,11 @@
#define HANDLE_DW_VIRTUALITY(ID, NAME)
#endif
+#ifndef HANDLE_DW_CC
+#define HANDLE_DW_CC(ID, NAME)
+#endif
+
+
HANDLE_DW_TAG(0x0001, array_type)
HANDLE_DW_TAG(0x0002, class_type)
HANDLE_DW_TAG(0x0003, entry_point)
@@ -320,6 +325,7 @@ HANDLE_DW_LANG(0x0021, C_plus_plus_14)
HANDLE_DW_LANG(0x0022, Fortran03)
HANDLE_DW_LANG(0x0023, Fortran08)
HANDLE_DW_LANG(0x8001, Mips_Assembler)
+HANDLE_DW_LANG(0x8e57, GOOGLE_RenderScript)
HANDLE_DW_LANG(0xb000, BORLAND_Delphi)
// DWARF attribute type encodings.
@@ -345,8 +351,23 @@ HANDLE_DW_VIRTUALITY(0x00, none)
HANDLE_DW_VIRTUALITY(0x01, virtual)
HANDLE_DW_VIRTUALITY(0x02, pure_virtual)
+// DWARF calling convention codes.
+HANDLE_DW_CC(0x01, normal)
+HANDLE_DW_CC(0x02, program)
+HANDLE_DW_CC(0x03, nocall)
+HANDLE_DW_CC(0x41, GNU_borland_fastcall_i386)
+HANDLE_DW_CC(0xb0, BORLAND_safecall)
+HANDLE_DW_CC(0xb1, BORLAND_stdcall)
+HANDLE_DW_CC(0xb2, BORLAND_pascal)
+HANDLE_DW_CC(0xb3, BORLAND_msfastcall)
+HANDLE_DW_CC(0xb4, BORLAND_msreturn)
+HANDLE_DW_CC(0xb5, BORLAND_thiscall)
+HANDLE_DW_CC(0xb6, BORLAND_fastcall)
+HANDLE_DW_CC(0xc0, LLVM_vectorcall)
+
#undef HANDLE_DW_TAG
#undef HANDLE_DW_OP
#undef HANDLE_DW_LANG
#undef HANDLE_DW_ATE
#undef HANDLE_DW_VIRTUALITY
+#undef HANDLE_DW_CC
diff --git a/include/llvm/Support/Dwarf.h b/include/llvm/Support/Dwarf.h
index cea61bd75833..86b19676c345 100644
--- a/include/llvm/Support/Dwarf.h
+++ b/include/llvm/Support/Dwarf.h
@@ -20,11 +20,11 @@
#ifndef LLVM_SUPPORT_DWARF_H
#define LLVM_SUPPORT_DWARF_H
-#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
+class StringRef;
namespace dwarf {
@@ -389,18 +389,9 @@ enum CaseSensitivity {
enum CallingConvention {
// Calling convention codes
- DW_CC_normal = 0x01,
- DW_CC_program = 0x02,
- DW_CC_nocall = 0x03,
+#define HANDLE_DW_CC(ID, NAME) DW_CC_##NAME = ID,
+#include "llvm/Support/Dwarf.def"
DW_CC_lo_user = 0x40,
- DW_CC_GNU_borland_fastcall_i386 = 0x41,
- DW_CC_BORLAND_safecall = 0xb0,
- DW_CC_BORLAND_stdcall = 0xb1,
- DW_CC_BORLAND_pascal = 0xb2,
- DW_CC_BORLAND_msfastcall = 0xb3,
- DW_CC_BORLAND_msreturn = 0xb4,
- DW_CC_BORLAND_thiscall = 0xb5,
- DW_CC_BORLAND_fastcall = 0xb6,
DW_CC_hi_user = 0xff
};
@@ -547,7 +538,7 @@ enum LocationListEntry : unsigned char {
DW_LLE_offset_pair_entry
};
-/// Contstants for the DW_APPLE_PROPERTY_attributes attribute.
+/// Constants for the DW_APPLE_PROPERTY_attributes attribute.
/// Keep this list in sync with clang's DeclSpec.h ObjCPropertyAttributeKind.
enum ApplePropertyAttributes {
// Apple Objective-C Property Attributes
@@ -562,7 +553,10 @@ enum ApplePropertyAttributes {
DW_APPLE_PROPERTY_atomic = 0x100,
DW_APPLE_PROPERTY_weak = 0x200,
DW_APPLE_PROPERTY_strong = 0x400,
- DW_APPLE_PROPERTY_unsafe_unretained = 0x800
+ DW_APPLE_PROPERTY_unsafe_unretained = 0x800,
+ DW_APPLE_PROPERTY_nullability = 0x1000,
+ DW_APPLE_PROPERTY_null_resettable = 0x2000,
+ DW_APPLE_PROPERTY_class = 0x4000
};
// Constants for the DWARF5 Accelerator Table Proposal
@@ -652,6 +646,7 @@ unsigned getTag(StringRef TagString);
unsigned getOperationEncoding(StringRef OperationEncodingString);
unsigned getVirtuality(StringRef VirtualityString);
unsigned getLanguage(StringRef LanguageString);
+unsigned getCallingConvention(StringRef LanguageString);
unsigned getAttributeEncoding(StringRef EncodingString);
unsigned getMacinfo(StringRef MacinfoString);
/// @}
diff --git a/include/llvm/Support/ELF.h b/include/llvm/Support/ELF.h
index e24420fc1fe4..70b9daab8360 100644
--- a/include/llvm/Support/ELF.h
+++ b/include/llvm/Support/ELF.h
@@ -310,6 +310,8 @@ enum {
EM_NORC = 218, // Nanoradio Optimized RISC
EM_CSR_KALIMBA = 219, // CSR Kalimba architecture family
EM_AMDGPU = 224, // AMD GPU architecture
+ EM_LANAI = 244, // Lanai 32-bit processor
+ EM_BPF = 247, // Linux kernel bpf virtual machine
// A request has been made to the maintainer of the official registry for
// such numbers for an official value for WebAssembly. As soon as one is
@@ -481,6 +483,7 @@ enum : unsigned {
EF_MIPS_ABI = 0x0000f000, // Mask for selecting EF_MIPS_ABI_ variant.
// MIPS machine variant
+ EF_MIPS_MACH_NONE = 0x00000000, // A standard MIPS implementation.
EF_MIPS_MACH_3900 = 0x00810000, // Toshiba R3900
EF_MIPS_MACH_4010 = 0x00820000, // LSI R4010
EF_MIPS_MACH_4100 = 0x00830000, // NEC VR4100
@@ -589,6 +592,11 @@ enum {
#include "ELFRelocs/Hexagon.def"
};
+// ELF Relocation type for Lanai.
+enum {
+#include "ELFRelocs/Lanai.def"
+};
+
// ELF Relocation types for S390/zSeries
enum {
#include "ELFRelocs/SystemZ.def"
@@ -604,6 +612,16 @@ enum {
#include "ELFRelocs/WebAssembly.def"
};
+// ELF Relocation types for AMDGPU
+enum {
+#include "ELFRelocs/AMDGPU.def"
+};
+
+// ELF Relocation types for BPF
+enum {
+#include "ELFRelocs/BPF.def"
+};
+
#undef ELF_RELOC
// Section header.
@@ -730,6 +748,9 @@ enum : unsigned {
// This section holds Thread-Local Storage.
SHF_TLS = 0x400U,
+ // Identifies a section containing compressed data.
+ SHF_COMPRESSED = 0x800U,
+
// This section is excluded from the final executable or shared library.
SHF_EXCLUDE = 0x80000000U,
@@ -1116,6 +1137,8 @@ enum {
DT_HIPROC = 0x7FFFFFFF, // End of processor specific tags.
DT_GNU_HASH = 0x6FFFFEF5, // Reference to the GNU hash table.
+ DT_TLSDESC_PLT = 0x6FFFFEF6, // Location of PLT entry for TLS descriptor resolver calls.
+ DT_TLSDESC_GOT = 0x6FFFFEF7, // Location of GOT entry used by TLS descriptor resolver PLT entry.
DT_RELACOUNT = 0x6FFFFFF9, // ELF32_Rela count.
DT_RELCOUNT = 0x6FFFFFFA, // ELF32_Rel count.
@@ -1199,8 +1222,12 @@ enum {
DT_MIPS_PLTGOT = 0x70000032, // Address of the base of the PLTGOT.
DT_MIPS_RWPLT = 0x70000034, // Points to the base
// of a writable PLT.
- DT_MIPS_RLD_MAP_REL = 0x70000035 // Relative offset of run time loader
+ DT_MIPS_RLD_MAP_REL = 0x70000035, // Relative offset of run time loader
// map, used for debugging.
+
+ // Sun machine-independent extensions.
+ DT_AUXILIARY = 0x7FFFFFFD, // Shared object to load before self
+ DT_FILTER = 0x7FFFFFFF // Shared object to get values from
};
// DT_FLAGS values.
@@ -1294,6 +1321,35 @@ enum {
VER_NEED_CURRENT = 1
};
+// SHT_NOTE section types
+enum {
+ NT_GNU_BUILD_ID = 3
+};
+
+// Compressed section header for ELF32.
+struct Elf32_Chdr {
+ Elf32_Word ch_type;
+ Elf32_Word ch_size;
+ Elf32_Word ch_addralign;
+};
+
+// Compressed section header for ELF64.
+struct Elf64_Chdr {
+ Elf64_Word ch_type;
+ Elf64_Word ch_reserved;
+ Elf64_Xword ch_size;
+ Elf64_Xword ch_addralign;
+};
+
+// Legal values for ch_type field of compressed section header.
+enum {
+ ELFCOMPRESS_ZLIB = 1, // ZLIB/DEFLATE algorithm.
+ ELFCOMPRESS_LOOS = 0x60000000, // Start of OS-specific.
+ ELFCOMPRESS_HIOS = 0x6fffffff, // End of OS-specific.
+ ELFCOMPRESS_LOPROC = 0x70000000, // Start of processor-specific.
+ ELFCOMPRESS_HIPROC = 0x7fffffff // End of processor-specific.
+};
+
} // end namespace ELF
} // end namespace llvm
diff --git a/include/llvm/Support/ELFRelocs/AMDGPU.def b/include/llvm/Support/ELFRelocs/AMDGPU.def
new file mode 100644
index 000000000000..c1e6797fdb0d
--- /dev/null
+++ b/include/llvm/Support/ELFRelocs/AMDGPU.def
@@ -0,0 +1,12 @@
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+ELF_RELOC(R_AMDGPU_NONE, 0)
+ELF_RELOC(R_AMDGPU_ABS32_LO, 1)
+ELF_RELOC(R_AMDGPU_ABS32_HI, 2)
+ELF_RELOC(R_AMDGPU_ABS64, 3)
+ELF_RELOC(R_AMDGPU_REL32, 4)
+ELF_RELOC(R_AMDGPU_REL64, 5)
+ELF_RELOC(R_AMDGPU_ABS32, 6)
+ELF_RELOC(R_AMDGPU_GOTPCREL, 7)
diff --git a/include/llvm/Support/ELFRelocs/BPF.def b/include/llvm/Support/ELFRelocs/BPF.def
new file mode 100644
index 000000000000..868974d683c7
--- /dev/null
+++ b/include/llvm/Support/ELFRelocs/BPF.def
@@ -0,0 +1,9 @@
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+// No relocation
+ELF_RELOC(R_BPF_NONE, 0)
+// Map index in "maps" section to file descriptor
+// within ld_64 instruction.
+ELF_RELOC(R_BPF_MAP_FD, 1)
diff --git a/include/llvm/Support/ELFRelocs/Hexagon.def b/include/llvm/Support/ELFRelocs/Hexagon.def
index a698ecb89e16..74e1d405cebd 100644
--- a/include/llvm/Support/ELFRelocs/Hexagon.def
+++ b/include/llvm/Support/ELFRelocs/Hexagon.def
@@ -98,3 +98,4 @@ ELF_RELOC(R_HEX_LD_GOT_16, 90)
ELF_RELOC(R_HEX_LD_GOT_32_6_X, 91)
ELF_RELOC(R_HEX_LD_GOT_16_X, 92)
ELF_RELOC(R_HEX_LD_GOT_11_X, 93)
+ELF_RELOC(R_HEX_23_REG, 94)
diff --git a/include/llvm/Support/ELFRelocs/Lanai.def b/include/llvm/Support/ELFRelocs/Lanai.def
new file mode 100644
index 000000000000..77ecb048403d
--- /dev/null
+++ b/include/llvm/Support/ELFRelocs/Lanai.def
@@ -0,0 +1,19 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+// No relocation
+ELF_RELOC(R_LANAI_NONE, 0)
+// 21-bit symbol relocation
+ELF_RELOC(R_LANAI_21, 1)
+// 21-bit symbol relocation with last two bits masked to 0
+ELF_RELOC(R_LANAI_21_F, 2)
+// 25-bit branch targets
+ELF_RELOC(R_LANAI_25, 3)
+// General 32-bit relocation
+ELF_RELOC(R_LANAI_32, 4)
+// Upper 16-bits of a symbolic relocation
+ELF_RELOC(R_LANAI_HI16, 5)
+// Lower 16-bits of a symbolic relocation
+ELF_RELOC(R_LANAI_LO16, 6)
diff --git a/include/llvm/Support/ELFRelocs/Mips.def b/include/llvm/Support/ELFRelocs/Mips.def
index 77e7f8e8712b..bc0088dff3f4 100644
--- a/include/llvm/Support/ELFRelocs/Mips.def
+++ b/include/llvm/Support/ELFRelocs/Mips.def
@@ -108,8 +108,8 @@ ELF_RELOC(R_MICROMIPS_TLS_TPREL_HI16, 169)
ELF_RELOC(R_MICROMIPS_TLS_TPREL_LO16, 170)
ELF_RELOC(R_MICROMIPS_GPREL7_S2, 172)
ELF_RELOC(R_MICROMIPS_PC23_S2, 173)
-ELF_RELOC(R_MICROMIPS_PC21_S2, 174)
-ELF_RELOC(R_MICROMIPS_PC26_S2, 175)
+ELF_RELOC(R_MICROMIPS_PC21_S1, 174)
+ELF_RELOC(R_MICROMIPS_PC26_S1, 175)
ELF_RELOC(R_MICROMIPS_PC18_S3, 176)
ELF_RELOC(R_MICROMIPS_PC19_S2, 177)
ELF_RELOC(R_MIPS_NUM, 218)
diff --git a/include/llvm/Support/ELFRelocs/i386.def b/include/llvm/Support/ELFRelocs/i386.def
index 45eae7fe426b..1d28cf595cd5 100644
--- a/include/llvm/Support/ELFRelocs/i386.def
+++ b/include/llvm/Support/ELFRelocs/i386.def
@@ -44,4 +44,4 @@ ELF_RELOC(R_386_TLS_GOTDESC, 39)
ELF_RELOC(R_386_TLS_DESC_CALL, 40)
ELF_RELOC(R_386_TLS_DESC, 41)
ELF_RELOC(R_386_IRELATIVE, 42)
-ELF_RELOC(R_386_NUM, 43)
+ELF_RELOC(R_386_GOT32X, 43)
diff --git a/include/llvm/Support/ELFRelocs/x86_64.def b/include/llvm/Support/ELFRelocs/x86_64.def
index 36ad0618eb2d..18fdcf9472dc 100644
--- a/include/llvm/Support/ELFRelocs/x86_64.def
+++ b/include/llvm/Support/ELFRelocs/x86_64.def
@@ -41,4 +41,5 @@ ELF_RELOC(R_X86_64_GOTPC32_TLSDESC, 34)
ELF_RELOC(R_X86_64_TLSDESC_CALL, 35)
ELF_RELOC(R_X86_64_TLSDESC, 36)
ELF_RELOC(R_X86_64_IRELATIVE, 37)
-
+ELF_RELOC(R_X86_64_GOTPCRELX, 41)
+ELF_RELOC(R_X86_64_REX_GOTPCRELX, 42)
diff --git a/include/llvm/Support/Endian.h b/include/llvm/Support/Endian.h
index bc93c9a66eef..cb5cd8e511b1 100644
--- a/include/llvm/Support/Endian.h
+++ b/include/llvm/Support/Endian.h
@@ -173,6 +173,10 @@ template<typename value_type,
endianness endian,
std::size_t alignment>
struct packed_endian_specific_integral {
+ packed_endian_specific_integral() = default;
+
+ explicit packed_endian_specific_integral(value_type val) { *this = val; }
+
operator value_type() const {
return endian::read<value_type, endian, alignment>(
(const void*)Value.buffer);
diff --git a/include/llvm/Support/EndianStream.h b/include/llvm/Support/EndianStream.h
index d44a9b3b7ce8..43ecd4a5c97e 100644
--- a/include/llvm/Support/EndianStream.h
+++ b/include/llvm/Support/EndianStream.h
@@ -15,6 +15,7 @@
#ifndef LLVM_SUPPORT_ENDIANSTREAM_H
#define LLVM_SUPPORT_ENDIANSTREAM_H
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/raw_ostream.h"
@@ -26,6 +27,10 @@ namespace endian {
template <endianness endian> struct Writer {
raw_ostream &OS;
Writer(raw_ostream &OS) : OS(OS) {}
+ template <typename value_type> void write(ArrayRef<value_type> Vals) {
+ for (value_type V : Vals)
+ write(V);
+ }
template <typename value_type> void write(value_type Val) {
Val = byte_swap<value_type, endian>(Val);
OS.write((const char *)&Val, sizeof(value_type));
diff --git a/include/llvm/Support/Error.h b/include/llvm/Support/Error.h
new file mode 100644
index 000000000000..5f515a88a021
--- /dev/null
+++ b/include/llvm/Support/Error.h
@@ -0,0 +1,950 @@
+//===----- llvm/Support/Error.h - Recoverable error handling ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines an API used to report recoverable errors.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_ERROR_H
+#define LLVM_SUPPORT_ERROR_H
+
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/raw_ostream.h"
+#include <vector>
+
+namespace llvm {
+
+class Error;
+class ErrorList;
+
+/// Base class for error info classes. Do not extend this directly: Extend
+/// the ErrorInfo template subclass instead.
+class ErrorInfoBase {
+public:
+ virtual ~ErrorInfoBase() {}
+
+ /// Print an error message to an output stream.
+ virtual void log(raw_ostream &OS) const = 0;
+
+ /// Return the error message as a string.
+ virtual std::string message() const {
+ std::string Msg;
+ raw_string_ostream OS(Msg);
+ log(OS);
+ return OS.str();
+ }
+
+ /// Convert this error to a std::error_code.
+ ///
+ /// This is a temporary crutch to enable interaction with code still
+ /// using std::error_code. It will be removed in the future.
+ virtual std::error_code convertToErrorCode() const = 0;
+
+ // Check whether this instance is a subclass of the class identified by
+ // ClassID.
+ virtual bool isA(const void *const ClassID) const {
+ return ClassID == classID();
+ }
+
+ // Check whether this instance is a subclass of ErrorInfoT.
+ template <typename ErrorInfoT> bool isA() const {
+ return isA(ErrorInfoT::classID());
+ }
+
+ // Returns the class ID for this type.
+ static const void *classID() { return &ID; }
+
+private:
+ virtual void anchor();
+ static char ID;
+};
+
+/// Lightweight error class with error context and mandatory checking.
+///
+/// Instances of this class wrap a ErrorInfoBase pointer. Failure states
+/// are represented by setting the pointer to a ErrorInfoBase subclass
+/// instance containing information describing the failure. Success is
+/// represented by a null pointer value.
+///
+/// Instances of Error also contains a 'Checked' flag, which must be set
+/// before the destructor is called, otherwise the destructor will trigger a
+/// runtime error. This enforces at runtime the requirement that all Error
+/// instances be checked or returned to the caller.
+///
+/// There are two ways to set the checked flag, depending on what state the
+/// Error instance is in. For Error instances indicating success, it
+/// is sufficient to invoke the boolean conversion operator. E.g.:
+///
+/// Error foo(<...>);
+///
+/// if (auto E = foo(<...>))
+/// return E; // <- Return E if it is in the error state.
+/// // We have verified that E was in the success state. It can now be safely
+/// // destroyed.
+///
+/// A success value *can not* be dropped. For example, just calling 'foo(<...>)'
+/// without testing the return value will raise a runtime error, even if foo
+/// returns success.
+///
+/// For Error instances representing failure, you must use either the
+/// handleErrors or handleAllErrors function with a typed handler. E.g.:
+///
+/// class MyErrorInfo : public ErrorInfo<MyErrorInfo> {
+/// // Custom error info.
+/// };
+///
+/// Error foo(<...>) { return make_error<MyErrorInfo>(...); }
+///
+/// auto E = foo(<...>); // <- foo returns failure with MyErrorInfo.
+/// auto NewE =
+/// handleErrors(E,
+/// [](const MyErrorInfo &M) {
+/// // Deal with the error.
+/// },
+/// [](std::unique_ptr<OtherError> M) -> Error {
+/// if (canHandle(*M)) {
+/// // handle error.
+/// return Error::success();
+/// }
+/// // Couldn't handle this error instance. Pass it up the stack.
+/// return Error(std::move(M));
+/// );
+/// // Note - we must check or return NewE in case any of the handlers
+/// // returned a new error.
+///
+/// The handleAllErrors function is identical to handleErrors, except
+/// that it has a void return type, and requires all errors to be handled and
+/// no new errors be returned. It prevents errors (assuming they can all be
+/// handled) from having to be bubbled all the way to the top-level.
+///
+/// *All* Error instances must be checked before destruction, even if
+/// they're moved-assigned or constructed from Success values that have already
+/// been checked. This enforces checking through all levels of the call stack.
+class Error {
+
+ // ErrorList needs to be able to yank ErrorInfoBase pointers out of this
+ // class to add to the error list.
+ friend class ErrorList;
+
+ // handleErrors needs to be able to set the Checked flag.
+ template <typename... HandlerTs>
+ friend Error handleErrors(Error E, HandlerTs &&... Handlers);
+
+ // Expected<T> needs to be able to steal the payload when constructed from an
+ // error.
+ template <typename T> class Expected;
+
+public:
+ /// Create a success value. Prefer using 'Error::success()' for readability
+ /// where possible.
+ Error() {
+ setPtr(nullptr);
+ setChecked(false);
+ }
+
+ /// Create a success value. This is equivalent to calling the default
+ /// constructor, but should be preferred for readability where possible.
+ static Error success() { return Error(); }
+
+ // Errors are not copy-constructable.
+ Error(const Error &Other) = delete;
+
+ /// Move-construct an error value. The newly constructed error is considered
+ /// unchecked, even if the source error had been checked. The original error
+ /// becomes a checked Success value, regardless of its original state.
+ Error(Error &&Other) {
+ setChecked(true);
+ *this = std::move(Other);
+ }
+
+ /// Create an error value. Prefer using the 'make_error' function, but
+ /// this constructor can be useful when "re-throwing" errors from handlers.
+ Error(std::unique_ptr<ErrorInfoBase> Payload) {
+ setPtr(Payload.release());
+ setChecked(false);
+ }
+
+ // Errors are not copy-assignable.
+ Error &operator=(const Error &Other) = delete;
+
+ /// Move-assign an error value. The current error must represent success, you
+ /// you cannot overwrite an unhandled error. The current error is then
+ /// considered unchecked. The source error becomes a checked success value,
+ /// regardless of its original state.
+ Error &operator=(Error &&Other) {
+ // Don't allow overwriting of unchecked values.
+ assertIsChecked();
+ setPtr(Other.getPtr());
+
+ // This Error is unchecked, even if the source error was checked.
+ setChecked(false);
+
+ // Null out Other's payload and set its checked bit.
+ Other.setPtr(nullptr);
+ Other.setChecked(true);
+
+ return *this;
+ }
+
+ /// Destroy a Error. Fails with a call to abort() if the error is
+ /// unchecked.
+ ~Error() {
+ assertIsChecked();
+ delete getPtr();
+ }
+
+ /// Bool conversion. Returns true if this Error is in a failure state,
+ /// and false if it is in an accept state. If the error is in a Success state
+ /// it will be considered checked.
+ explicit operator bool() {
+ setChecked(getPtr() == nullptr);
+ return getPtr() != nullptr;
+ }
+
+ /// Check whether one error is a subclass of another.
+ template <typename ErrT> bool isA() const {
+ return getPtr() && getPtr()->isA(ErrT::classID());
+ }
+
+private:
+ void assertIsChecked() {
+#ifndef NDEBUG
+ if (!getChecked() || getPtr()) {
+ dbgs() << "Program aborted due to an unhandled Error:\n";
+ if (getPtr())
+ getPtr()->log(dbgs());
+ else
+ dbgs()
+ << "Error value was Success. (Note: Success values must still be "
+ "checked prior to being destroyed).\n";
+ abort();
+ }
+#endif
+ }
+
+ ErrorInfoBase *getPtr() const {
+#ifndef NDEBUG
+ return PayloadAndCheckedBit.getPointer();
+#else
+ return Payload;
+#endif
+ }
+
+ void setPtr(ErrorInfoBase *EI) {
+#ifndef NDEBUG
+ PayloadAndCheckedBit.setPointer(EI);
+#else
+ Payload = EI;
+#endif
+ }
+
+ bool getChecked() const {
+#ifndef NDEBUG
+ return PayloadAndCheckedBit.getInt();
+#else
+ return true;
+#endif
+ }
+
+ void setChecked(bool V) {
+#ifndef NDEBUG
+ PayloadAndCheckedBit.setInt(V);
+#endif
+ }
+
+ std::unique_ptr<ErrorInfoBase> takePayload() {
+ std::unique_ptr<ErrorInfoBase> Tmp(getPtr());
+ setPtr(nullptr);
+ setChecked(true);
+ return Tmp;
+ }
+
+#ifndef NDEBUG
+ PointerIntPair<ErrorInfoBase *, 1> PayloadAndCheckedBit;
+#else
+ ErrorInfoBase *Payload;
+#endif
+};
+
+/// Make a Error instance representing failure using the given error info
+/// type.
+template <typename ErrT, typename... ArgTs> Error make_error(ArgTs &&... Args) {
+ return Error(llvm::make_unique<ErrT>(std::forward<ArgTs>(Args)...));
+}
+
+/// Base class for user error types. Users should declare their error types
+/// like:
+///
+/// class MyError : public ErrorInfo<MyError> {
+/// ....
+/// };
+///
+/// This class provides an implementation of the ErrorInfoBase::kind
+/// method, which is used by the Error RTTI system.
+template <typename ThisErrT, typename ParentErrT = ErrorInfoBase>
+class ErrorInfo : public ParentErrT {
+public:
+ bool isA(const void *const ClassID) const override {
+ return ClassID == classID() || ParentErrT::isA(ClassID);
+ }
+
+ static const void *classID() { return &ThisErrT::ID; }
+};
+
+/// Special ErrorInfo subclass representing a list of ErrorInfos.
+/// Instances of this class are constructed by joinError.
+class ErrorList final : public ErrorInfo<ErrorList> {
+
+ // handleErrors needs to be able to iterate the payload list of an
+ // ErrorList.
+ template <typename... HandlerTs>
+ friend Error handleErrors(Error E, HandlerTs &&... Handlers);
+
+ // joinErrors is implemented in terms of join.
+ friend Error joinErrors(Error, Error);
+
+public:
+ void log(raw_ostream &OS) const override {
+ OS << "Multiple errors:\n";
+ for (auto &ErrPayload : Payloads) {
+ ErrPayload->log(OS);
+ OS << "\n";
+ }
+ }
+
+ std::error_code convertToErrorCode() const override;
+
+ // Used by ErrorInfo::classID.
+ static char ID;
+
+private:
+ ErrorList(std::unique_ptr<ErrorInfoBase> Payload1,
+ std::unique_ptr<ErrorInfoBase> Payload2) {
+ assert(!Payload1->isA<ErrorList>() && !Payload2->isA<ErrorList>() &&
+ "ErrorList constructor payloads should be singleton errors");
+ Payloads.push_back(std::move(Payload1));
+ Payloads.push_back(std::move(Payload2));
+ }
+
+ static Error join(Error E1, Error E2) {
+ if (!E1)
+ return E2;
+ if (!E2)
+ return E1;
+ if (E1.isA<ErrorList>()) {
+ auto &E1List = static_cast<ErrorList &>(*E1.getPtr());
+ if (E2.isA<ErrorList>()) {
+ auto E2Payload = E2.takePayload();
+ auto &E2List = static_cast<ErrorList &>(*E2Payload);
+ for (auto &Payload : E2List.Payloads)
+ E1List.Payloads.push_back(std::move(Payload));
+ } else
+ E1List.Payloads.push_back(E2.takePayload());
+
+ return E1;
+ }
+ if (E2.isA<ErrorList>()) {
+ auto &E2List = static_cast<ErrorList &>(*E2.getPtr());
+ E2List.Payloads.insert(E2List.Payloads.begin(), E1.takePayload());
+ return E2;
+ }
+ return Error(std::unique_ptr<ErrorList>(
+ new ErrorList(E1.takePayload(), E2.takePayload())));
+ }
+
+ std::vector<std::unique_ptr<ErrorInfoBase>> Payloads;
+};
+
+/// Concatenate errors. The resulting Error is unchecked, and contains the
+/// ErrorInfo(s), if any, contained in E1, followed by the
+/// ErrorInfo(s), if any, contained in E2.
+inline Error joinErrors(Error E1, Error E2) {
+ return ErrorList::join(std::move(E1), std::move(E2));
+}
+
+/// Helper for testing applicability of, and applying, handlers for
+/// ErrorInfo types.
+template <typename HandlerT>
+class ErrorHandlerTraits
+ : public ErrorHandlerTraits<decltype(
+ &std::remove_reference<HandlerT>::type::operator())> {};
+
+// Specialization functions of the form 'Error (const ErrT&)'.
+template <typename ErrT> class ErrorHandlerTraits<Error (&)(ErrT &)> {
+public:
+ static bool appliesTo(const ErrorInfoBase &E) {
+ return E.template isA<ErrT>();
+ }
+
+ template <typename HandlerT>
+ static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) {
+ assert(appliesTo(*E) && "Applying incorrect handler");
+ return H(static_cast<ErrT &>(*E));
+ }
+};
+
+// Specialization functions of the form 'void (const ErrT&)'.
+template <typename ErrT> class ErrorHandlerTraits<void (&)(ErrT &)> {
+public:
+ static bool appliesTo(const ErrorInfoBase &E) {
+ return E.template isA<ErrT>();
+ }
+
+ template <typename HandlerT>
+ static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) {
+ assert(appliesTo(*E) && "Applying incorrect handler");
+ H(static_cast<ErrT &>(*E));
+ return Error::success();
+ }
+};
+
+/// Specialization for functions of the form 'Error (std::unique_ptr<ErrT>)'.
+template <typename ErrT>
+class ErrorHandlerTraits<Error (&)(std::unique_ptr<ErrT>)> {
+public:
+ static bool appliesTo(const ErrorInfoBase &E) {
+ return E.template isA<ErrT>();
+ }
+
+ template <typename HandlerT>
+ static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) {
+ assert(appliesTo(*E) && "Applying incorrect handler");
+ std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release()));
+ return H(std::move(SubE));
+ }
+};
+
+/// Specialization for functions of the form 'Error (std::unique_ptr<ErrT>)'.
+template <typename ErrT>
+class ErrorHandlerTraits<void (&)(std::unique_ptr<ErrT>)> {
+public:
+ static bool appliesTo(const ErrorInfoBase &E) {
+ return E.template isA<ErrT>();
+ }
+
+ template <typename HandlerT>
+ static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) {
+ assert(appliesTo(*E) && "Applying incorrect handler");
+ std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release()));
+ H(std::move(SubE));
+ return Error::success();
+ }
+};
+
+// Specialization for member functions of the form 'RetT (const ErrT&)'.
+template <typename C, typename RetT, typename ErrT>
+class ErrorHandlerTraits<RetT (C::*)(ErrT &)>
+ : public ErrorHandlerTraits<RetT (&)(ErrT &)> {};
+
+// Specialization for member functions of the form 'RetT (const ErrT&) const'.
+template <typename C, typename RetT, typename ErrT>
+class ErrorHandlerTraits<RetT (C::*)(ErrT &) const>
+ : public ErrorHandlerTraits<RetT (&)(ErrT &)> {};
+
+// Specialization for member functions of the form 'RetT (const ErrT&)'.
+template <typename C, typename RetT, typename ErrT>
+class ErrorHandlerTraits<RetT (C::*)(const ErrT &)>
+ : public ErrorHandlerTraits<RetT (&)(ErrT &)> {};
+
+// Specialization for member functions of the form 'RetT (const ErrT&) const'.
+template <typename C, typename RetT, typename ErrT>
+class ErrorHandlerTraits<RetT (C::*)(const ErrT &) const>
+ : public ErrorHandlerTraits<RetT (&)(ErrT &)> {};
+
+/// Specialization for member functions of the form
+/// 'RetT (std::unique_ptr<ErrT>) const'.
+template <typename C, typename RetT, typename ErrT>
+class ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>)>
+ : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {};
+
+/// Specialization for member functions of the form
+/// 'RetT (std::unique_ptr<ErrT>) const'.
+template <typename C, typename RetT, typename ErrT>
+class ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>) const>
+ : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {};
+
+inline Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload) {
+ return Error(std::move(Payload));
+}
+
+template <typename HandlerT, typename... HandlerTs>
+Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload,
+ HandlerT &&Handler, HandlerTs &&... Handlers) {
+ if (ErrorHandlerTraits<HandlerT>::appliesTo(*Payload))
+ return ErrorHandlerTraits<HandlerT>::apply(std::forward<HandlerT>(Handler),
+ std::move(Payload));
+ return handleErrorImpl(std::move(Payload),
+ std::forward<HandlerTs>(Handlers)...);
+}
+
+/// Pass the ErrorInfo(s) contained in E to their respective handlers. Any
+/// unhandled errors (or Errors returned by handlers) are re-concatenated and
+/// returned.
+/// Because this function returns an error, its result must also be checked
+/// or returned. If you intend to handle all errors use handleAllErrors
+/// (which returns void, and will abort() on unhandled errors) instead.
+template <typename... HandlerTs>
+Error handleErrors(Error E, HandlerTs &&... Hs) {
+ if (!E)
+ return Error::success();
+
+ std::unique_ptr<ErrorInfoBase> Payload = E.takePayload();
+
+ if (Payload->isA<ErrorList>()) {
+ ErrorList &List = static_cast<ErrorList &>(*Payload);
+ Error R;
+ for (auto &P : List.Payloads)
+ R = ErrorList::join(
+ std::move(R),
+ handleErrorImpl(std::move(P), std::forward<HandlerTs>(Hs)...));
+ return R;
+ }
+
+ return handleErrorImpl(std::move(Payload), std::forward<HandlerTs>(Hs)...);
+}
+
+/// Behaves the same as handleErrors, except that it requires that all
+/// errors be handled by the given handlers. If any unhandled error remains
+/// after the handlers have run, abort() will be called.
+template <typename... HandlerTs>
+void handleAllErrors(Error E, HandlerTs &&... Handlers) {
+ auto F = handleErrors(std::move(E), std::forward<HandlerTs>(Handlers)...);
+ // Cast 'F' to bool to set the 'Checked' flag if it's a success value:
+ (void)!F;
+}
+
+/// Check that E is a non-error, then drop it.
+inline void handleAllErrors(Error E) {
+ // Cast 'E' to a bool to set the 'Checked' flag if it's a success value:
+ (void)!E;
+}
+
+/// Log all errors (if any) in E to OS. If there are any errors, ErrorBanner
+/// will be printed before the first one is logged. A newline will be printed
+/// after each error.
+///
+/// This is useful in the base level of your program to allow clean termination
+/// (allowing clean deallocation of resources, etc.), while reporting error
+/// information to the user.
+void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner);
+
+/// Write all error messages (if any) in E to a string. The newline character
+/// is used to separate error messages.
+inline std::string toString(Error E) {
+ SmallVector<std::string, 2> Errors;
+ handleAllErrors(std::move(E), [&Errors](const ErrorInfoBase &EI) {
+ Errors.push_back(EI.message());
+ });
+ return join(Errors.begin(), Errors.end(), "\n");
+}
+
+/// Consume a Error without doing anything. This method should be used
+/// only where an error can be considered a reasonable and expected return
+/// value.
+///
+/// Uses of this method are potentially indicative of design problems: If it's
+/// legitimate to do nothing while processing an "error", the error-producer
+/// might be more clearly refactored to return an Optional<T>.
+inline void consumeError(Error Err) {
+ handleAllErrors(std::move(Err), [](const ErrorInfoBase &) {});
+}
+
+/// Helper for Errors used as out-parameters.
+///
+/// This helper is for use with the Error-as-out-parameter idiom, where an error
+/// is passed to a function or method by reference, rather than being returned.
+/// In such cases it is helpful to set the checked bit on entry to the function
+/// so that the error can be written to (unchecked Errors abort on assignment)
+/// and clear the checked bit on exit so that clients cannot accidentally forget
+/// to check the result. This helper performs these actions automatically using
+/// RAII:
+///
+/// Result foo(Error &Err) {
+/// ErrorAsOutParameter ErrAsOutParam(Err); // 'Checked' flag set
+/// // <body of foo>
+/// // <- 'Checked' flag auto-cleared when ErrAsOutParam is destructed.
+/// }
+class ErrorAsOutParameter {
+public:
+ ErrorAsOutParameter(Error &Err) : Err(Err) {
+ // Raise the checked bit if Err is success.
+ (void)!!Err;
+ }
+ ~ErrorAsOutParameter() {
+ // Clear the checked bit.
+ if (!Err)
+ Err = Error::success();
+ }
+
+private:
+ Error &Err;
+};
+
+/// Tagged union holding either a T or a Error.
+///
+/// This class parallels ErrorOr, but replaces error_code with Error. Since
+/// Error cannot be copied, this class replaces getError() with
+/// takeError(). It also adds an bool errorIsA<ErrT>() method for testing the
+/// error class type.
+template <class T> class Expected {
+ template <class OtherT> friend class Expected;
+ static const bool isRef = std::is_reference<T>::value;
+ typedef ReferenceStorage<typename std::remove_reference<T>::type> wrap;
+
+ typedef std::unique_ptr<ErrorInfoBase> error_type;
+
+public:
+ typedef typename std::conditional<isRef, wrap, T>::type storage_type;
+ typedef T value_type;
+
+private:
+ typedef typename std::remove_reference<T>::type &reference;
+ typedef const typename std::remove_reference<T>::type &const_reference;
+ typedef typename std::remove_reference<T>::type *pointer;
+ typedef const typename std::remove_reference<T>::type *const_pointer;
+
+public:
+ /// Create an Expected<T> error value from the given Error.
+ Expected(Error Err)
+ : HasError(true)
+#ifndef NDEBUG
+ ,
+ Checked(false)
+#endif
+ {
+ assert(Err && "Cannot create Expected<T> from Error success value.");
+ new (getErrorStorage()) Error(std::move(Err));
+ }
+
+ /// Create an Expected<T> success value from the given OtherT value, which
+ /// must be convertible to T.
+ template <typename OtherT>
+ Expected(OtherT &&Val,
+ typename std::enable_if<std::is_convertible<OtherT, T>::value>::type
+ * = nullptr)
+ : HasError(false)
+#ifndef NDEBUG
+ ,
+ Checked(false)
+#endif
+ {
+ new (getStorage()) storage_type(std::forward<OtherT>(Val));
+ }
+
+ /// Move construct an Expected<T> value.
+ Expected(Expected &&Other) { moveConstruct(std::move(Other)); }
+
+ /// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT
+ /// must be convertible to T.
+ template <class OtherT>
+ Expected(Expected<OtherT> &&Other,
+ typename std::enable_if<std::is_convertible<OtherT, T>::value>::type
+ * = nullptr) {
+ moveConstruct(std::move(Other));
+ }
+
+ /// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT
+ /// isn't convertible to T.
+ template <class OtherT>
+ explicit Expected(
+ Expected<OtherT> &&Other,
+ typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * =
+ nullptr) {
+ moveConstruct(std::move(Other));
+ }
+
+ /// Move-assign from another Expected<T>.
+ Expected &operator=(Expected &&Other) {
+ moveAssign(std::move(Other));
+ return *this;
+ }
+
+ /// Destroy an Expected<T>.
+ ~Expected() {
+ assertIsChecked();
+ if (!HasError)
+ getStorage()->~storage_type();
+ else
+ getErrorStorage()->~error_type();
+ }
+
+ /// \brief Return false if there is an error.
+ explicit operator bool() {
+#ifndef NDEBUG
+ Checked = !HasError;
+#endif
+ return !HasError;
+ }
+
+ /// \brief Returns a reference to the stored T value.
+ reference get() {
+ assertIsChecked();
+ return *getStorage();
+ }
+
+ /// \brief Returns a const reference to the stored T value.
+ const_reference get() const {
+ assertIsChecked();
+ return const_cast<Expected<T> *>(this)->get();
+ }
+
+ /// \brief Check that this Expected<T> is an error of type ErrT.
+ template <typename ErrT> bool errorIsA() const {
+ return HasError && getErrorStorage()->template isA<ErrT>();
+ }
+
+ /// \brief Take ownership of the stored error.
+ /// After calling this the Expected<T> is in an indeterminate state that can
+ /// only be safely destructed. No further calls (beside the destructor) should
+ /// be made on the Expected<T> vaule.
+ Error takeError() {
+#ifndef NDEBUG
+ Checked = true;
+#endif
+ return HasError ? Error(std::move(*getErrorStorage())) : Error::success();
+ }
+
+ /// \brief Returns a pointer to the stored T value.
+ pointer operator->() {
+ assertIsChecked();
+ return toPointer(getStorage());
+ }
+
+ /// \brief Returns a const pointer to the stored T value.
+ const_pointer operator->() const {
+ assertIsChecked();
+ return toPointer(getStorage());
+ }
+
+ /// \brief Returns a reference to the stored T value.
+ reference operator*() {
+ assertIsChecked();
+ return *getStorage();
+ }
+
+ /// \brief Returns a const reference to the stored T value.
+ const_reference operator*() const {
+ assertIsChecked();
+ return *getStorage();
+ }
+
+private:
+ template <class T1>
+ static bool compareThisIfSameType(const T1 &a, const T1 &b) {
+ return &a == &b;
+ }
+
+ template <class T1, class T2>
+ static bool compareThisIfSameType(const T1 &a, const T2 &b) {
+ return false;
+ }
+
+ template <class OtherT> void moveConstruct(Expected<OtherT> &&Other) {
+ HasError = Other.HasError;
+
+#ifndef NDEBUG
+ Checked = false;
+ Other.Checked = true;
+#endif
+
+ if (!HasError)
+ new (getStorage()) storage_type(std::move(*Other.getStorage()));
+ else
+ new (getErrorStorage()) error_type(std::move(*Other.getErrorStorage()));
+ }
+
+ template <class OtherT> void moveAssign(Expected<OtherT> &&Other) {
+ assertIsChecked();
+
+ if (compareThisIfSameType(*this, Other))
+ return;
+
+ this->~Expected();
+ new (this) Expected(std::move(Other));
+ }
+
+ pointer toPointer(pointer Val) { return Val; }
+
+ const_pointer toPointer(const_pointer Val) const { return Val; }
+
+ pointer toPointer(wrap *Val) { return &Val->get(); }
+
+ const_pointer toPointer(const wrap *Val) const { return &Val->get(); }
+
+ storage_type *getStorage() {
+ assert(!HasError && "Cannot get value when an error exists!");
+ return reinterpret_cast<storage_type *>(TStorage.buffer);
+ }
+
+ const storage_type *getStorage() const {
+ assert(!HasError && "Cannot get value when an error exists!");
+ return reinterpret_cast<const storage_type *>(TStorage.buffer);
+ }
+
+ error_type *getErrorStorage() {
+ assert(HasError && "Cannot get error when a value exists!");
+ return reinterpret_cast<error_type *>(ErrorStorage.buffer);
+ }
+
+ void assertIsChecked() {
+#ifndef NDEBUG
+ if (!Checked) {
+ dbgs() << "Expected<T> must be checked before access or destruction.\n";
+ if (HasError) {
+ dbgs() << "Unchecked Expected<T> contained error:\n";
+ (*getErrorStorage())->log(dbgs());
+ } else
+ dbgs() << "Expected<T> value was in success state. (Note: Expected<T> "
+ "values in success mode must still be checked prior to being "
+ "destroyed).\n";
+ abort();
+ }
+#endif
+ }
+
+ union {
+ AlignedCharArrayUnion<storage_type> TStorage;
+ AlignedCharArrayUnion<error_type> ErrorStorage;
+ };
+ bool HasError : 1;
+#ifndef NDEBUG
+ bool Checked : 1;
+#endif
+};
+
+/// This class wraps a std::error_code in a Error.
+///
+/// This is useful if you're writing an interface that returns a Error
+/// (or Expected) and you want to call code that still returns
+/// std::error_codes.
+class ECError : public ErrorInfo<ECError> {
+ friend Error errorCodeToError(std::error_code);
+public:
+ void setErrorCode(std::error_code EC) { this->EC = EC; }
+ std::error_code convertToErrorCode() const override { return EC; }
+ void log(raw_ostream &OS) const override { OS << EC.message(); }
+
+ // Used by ErrorInfo::classID.
+ static char ID;
+
+protected:
+ ECError() = default;
+ ECError(std::error_code EC) : EC(EC) {}
+ std::error_code EC;
+};
+
+/// The value returned by this function can be returned from convertToErrorCode
+/// for Error values where no sensible translation to std::error_code exists.
+/// It should only be used in this situation, and should never be used where a
+/// sensible conversion to std::error_code is available, as attempts to convert
+/// to/from this error will result in a fatal error. (i.e. it is a programmatic
+///error to try to convert such a value).
+std::error_code inconvertibleErrorCode();
+
+/// Helper for converting an std::error_code to a Error.
+Error errorCodeToError(std::error_code EC);
+
+/// Helper for converting an ECError to a std::error_code.
+///
+/// This method requires that Err be Error() or an ECError, otherwise it
+/// will trigger a call to abort().
+std::error_code errorToErrorCode(Error Err);
+
+/// Convert an ErrorOr<T> to an Expected<T>.
+template <typename T> Expected<T> errorOrToExpected(ErrorOr<T> &&EO) {
+ if (auto EC = EO.getError())
+ return errorCodeToError(EC);
+ return std::move(*EO);
+}
+
+/// Convert an Expected<T> to an ErrorOr<T>.
+template <typename T> ErrorOr<T> expectedToErrorOr(Expected<T> &&E) {
+ if (auto Err = E.takeError())
+ return errorToErrorCode(std::move(Err));
+ return std::move(*E);
+}
+
+/// This class wraps a string in an Error.
+///
+/// StringError is useful in cases where the client is not expected to be able
+/// to consume the specific error message programmatically (for example, if the
+/// error message is to be presented to the user).
+class StringError : public ErrorInfo<StringError> {
+public:
+ static char ID;
+ StringError(const Twine &S, std::error_code EC);
+ void log(raw_ostream &OS) const override;
+ std::error_code convertToErrorCode() const override;
+private:
+ std::string Msg;
+ std::error_code EC;
+};
+
+/// Helper for check-and-exit error handling.
+///
+/// For tool use only. NOT FOR USE IN LIBRARY CODE.
+///
+class ExitOnError {
+public:
+ /// Create an error on exit helper.
+ ExitOnError(std::string Banner = "", int DefaultErrorExitCode = 1)
+ : Banner(std::move(Banner)),
+ GetExitCode([=](const Error &) { return DefaultErrorExitCode; }) {}
+
+ /// Set the banner string for any errors caught by operator().
+ void setBanner(std::string Banner) { this->Banner = std::move(Banner); }
+
+ /// Set the exit-code mapper function.
+ void setExitCodeMapper(std::function<int(const Error &)> GetExitCode) {
+ this->GetExitCode = std::move(GetExitCode);
+ }
+
+ /// Check Err. If it's in a failure state log the error(s) and exit.
+ void operator()(Error Err) const { checkError(std::move(Err)); }
+
+ /// Check E. If it's in a success state then return the contained value. If
+ /// it's in a failure state log the error(s) and exit.
+ template <typename T> T operator()(Expected<T> &&E) const {
+ checkError(E.takeError());
+ return std::move(*E);
+ }
+
+ /// Check E. If it's in a success state then return the contained reference. If
+ /// it's in a failure state log the error(s) and exit.
+ template <typename T> T& operator()(Expected<T&> &&E) const {
+ checkError(E.takeError());
+ return *E;
+ }
+
+private:
+ void checkError(Error Err) const {
+ if (Err) {
+ int ExitCode = GetExitCode(Err);
+ logAllUnhandledErrors(std::move(Err), errs(), Banner);
+ exit(ExitCode);
+ }
+ }
+
+ std::string Banner;
+ std::function<int(const Error &)> GetExitCode;
+};
+
+/// Report a serious error, calling any installed error handler. See
+/// ErrorHandling.h.
+LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err,
+ bool gen_crash_diag = true);
+
+} // namespace llvm
+
+#endif // LLVM_SUPPORT_ERROR_H
diff --git a/include/llvm/Support/ErrorHandling.h b/include/llvm/Support/ErrorHandling.h
index 32f05e0e9610..7c1edd801571 100644
--- a/include/llvm/Support/ErrorHandling.h
+++ b/include/llvm/Support/ErrorHandling.h
@@ -15,11 +15,11 @@
#ifndef LLVM_SUPPORT_ERRORHANDLING_H
#define LLVM_SUPPORT_ERRORHANDLING_H
-#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Compiler.h"
#include <string>
namespace llvm {
+class StringRef;
class Twine;
/// An error handler callback.
diff --git a/include/llvm/Support/ErrorOr.h b/include/llvm/Support/ErrorOr.h
index ca6ede73e8df..877f4063cd23 100644
--- a/include/llvm/Support/ErrorOr.h
+++ b/include/llvm/Support/ErrorOr.h
@@ -23,20 +23,6 @@
#include <type_traits>
namespace llvm {
-template<class T, class V>
-typename std::enable_if< std::is_constructible<T, V>::value
- , typename std::remove_reference<V>::type>::type &&
- moveIfMoveConstructible(V &Val) {
- return std::move(Val);
-}
-
-template<class T, class V>
-typename std::enable_if< !std::is_constructible<T, V>::value
- , typename std::remove_reference<V>::type>::type &
-moveIfMoveConstructible(V &Val) {
- return Val;
-}
-
/// \brief Stores a reference that can be changed.
template <typename T>
class ReferenceStorage {
@@ -72,7 +58,7 @@ public:
/// unary * and -> operators provide pointer like access to the value. Accessing
/// the value when there is an error has undefined behavior.
///
-/// When T is a reference type the behaivor is slightly different. The reference
+/// When T is a reference type the behavior is slightly different. The reference
/// is held in a std::reference_wrapper<std::remove_reference<T>::type>, and
/// there is special handling to make operator -> work as if T was not a
/// reference.
@@ -98,7 +84,7 @@ public:
ErrorOr(E ErrorCode,
typename std::enable_if<std::is_error_code_enum<E>::value ||
std::is_error_condition_enum<E>::value,
- void *>::type = 0)
+ void *>::type = nullptr)
: HasError(true) {
new (getErrorStorage()) std::error_code(make_error_code(ErrorCode));
}
@@ -107,8 +93,12 @@ public:
new (getErrorStorage()) std::error_code(EC);
}
- ErrorOr(T Val) : HasError(false) {
- new (getStorage()) storage_type(moveIfMoveConstructible<storage_type>(Val));
+ template <class OtherT>
+ ErrorOr(OtherT &&Val,
+ typename std::enable_if<std::is_convertible<OtherT, T>::value>::type
+ * = nullptr)
+ : HasError(false) {
+ new (getStorage()) storage_type(std::forward<OtherT>(Val));
}
ErrorOr(const ErrorOr &Other) {
@@ -278,7 +268,6 @@ private:
return const_cast<ErrorOr<T> *>(this)->getErrorStorage();
}
-
union {
AlignedCharArrayUnion<storage_type> TStorage;
AlignedCharArrayUnion<std::error_code> ErrorStorage;
@@ -295,4 +284,4 @@ operator==(const ErrorOr<T> &Err, E Code) {
}
} // end namespace llvm
-#endif
+#endif // LLVM_SUPPORT_ERROROR_H
diff --git a/include/llvm/Support/FileSystem.h b/include/llvm/Support/FileSystem.h
index 4733ddb77575..42a6180e0eb3 100644
--- a/include/llvm/Support/FileSystem.h
+++ b/include/llvm/Support/FileSystem.h
@@ -29,12 +29,15 @@
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/TimeValue.h"
+#include <cassert>
+#include <cstdint>
#include <ctime>
-#include <iterator>
#include <stack>
#include <string>
#include <system_error>
@@ -140,11 +143,14 @@ class file_status
#if defined(LLVM_ON_UNIX)
dev_t fs_st_dev;
ino_t fs_st_ino;
+ time_t fs_st_atime;
time_t fs_st_mtime;
uid_t fs_st_uid;
gid_t fs_st_gid;
off_t fs_st_size;
#elif defined (LLVM_ON_WIN32)
+ uint32_t LastAccessedTimeHigh;
+ uint32_t LastAccessedTimeLow;
uint32_t LastWriteTimeHigh;
uint32_t LastWriteTimeLow;
uint32_t VolumeSerialNumber;
@@ -159,43 +165,51 @@ class file_status
public:
#if defined(LLVM_ON_UNIX)
- file_status() : fs_st_dev(0), fs_st_ino(0), fs_st_mtime(0),
+ file_status()
+ : fs_st_dev(0), fs_st_ino(0), fs_st_atime(0), fs_st_mtime(0),
fs_st_uid(0), fs_st_gid(0), fs_st_size(0),
Type(file_type::status_error), Perms(perms_not_known) {}
- file_status(file_type Type) : fs_st_dev(0), fs_st_ino(0), fs_st_mtime(0),
+ file_status(file_type Type)
+ : fs_st_dev(0), fs_st_ino(0), fs_st_atime(0), fs_st_mtime(0),
fs_st_uid(0), fs_st_gid(0), fs_st_size(0), Type(Type),
Perms(perms_not_known) {}
- file_status(file_type Type, perms Perms, dev_t Dev, ino_t Ino, time_t MTime,
- uid_t UID, gid_t GID, off_t Size)
- : fs_st_dev(Dev), fs_st_ino(Ino), fs_st_mtime(MTime), fs_st_uid(UID),
- fs_st_gid(GID), fs_st_size(Size), Type(Type), Perms(Perms) {}
+ file_status(file_type Type, perms Perms, dev_t Dev, ino_t Ino, time_t ATime,
+ time_t MTime, uid_t UID, gid_t GID, off_t Size)
+ : fs_st_dev(Dev), fs_st_ino(Ino), fs_st_atime(ATime), fs_st_mtime(MTime),
+ fs_st_uid(UID), fs_st_gid(GID), fs_st_size(Size), Type(Type),
+ Perms(Perms) {}
#elif defined(LLVM_ON_WIN32)
- file_status() : LastWriteTimeHigh(0), LastWriteTimeLow(0),
- VolumeSerialNumber(0), FileSizeHigh(0), FileSizeLow(0),
- FileIndexHigh(0), FileIndexLow(0), Type(file_type::status_error),
- Perms(perms_not_known) {}
+ file_status()
+ : LastAccessedTimeHigh(0), LastAccessedTimeLow(0), LastWriteTimeHigh(0),
+ LastWriteTimeLow(0), VolumeSerialNumber(0), FileSizeHigh(0),
+ FileSizeLow(0), FileIndexHigh(0), FileIndexLow(0),
+ Type(file_type::status_error), Perms(perms_not_known) {}
- file_status(file_type Type) : LastWriteTimeHigh(0), LastWriteTimeLow(0),
- VolumeSerialNumber(0), FileSizeHigh(0), FileSizeLow(0),
- FileIndexHigh(0), FileIndexLow(0), Type(Type),
+ file_status(file_type Type)
+ : LastAccessedTimeHigh(0), LastAccessedTimeLow(0), LastWriteTimeHigh(0),
+ LastWriteTimeLow(0), VolumeSerialNumber(0), FileSizeHigh(0),
+ FileSizeLow(0), FileIndexHigh(0), FileIndexLow(0), Type(Type),
Perms(perms_not_known) {}
- file_status(file_type Type, uint32_t LastWriteTimeHigh,
- uint32_t LastWriteTimeLow, uint32_t VolumeSerialNumber,
- uint32_t FileSizeHigh, uint32_t FileSizeLow,
- uint32_t FileIndexHigh, uint32_t FileIndexLow)
- : LastWriteTimeHigh(LastWriteTimeHigh),
- LastWriteTimeLow(LastWriteTimeLow),
- VolumeSerialNumber(VolumeSerialNumber), FileSizeHigh(FileSizeHigh),
- FileSizeLow(FileSizeLow), FileIndexHigh(FileIndexHigh),
- FileIndexLow(FileIndexLow), Type(Type), Perms(perms_not_known) {}
+ file_status(file_type Type, uint32_t LastAccessTimeHigh,
+ uint32_t LastAccessTimeLow, uint32_t LastWriteTimeHigh,
+ uint32_t LastWriteTimeLow, uint32_t VolumeSerialNumber,
+ uint32_t FileSizeHigh, uint32_t FileSizeLow,
+ uint32_t FileIndexHigh, uint32_t FileIndexLow)
+ : LastAccessedTimeHigh(LastAccessTimeHigh), LastAccessedTimeLow(LastAccessTimeLow),
+ LastWriteTimeHigh(LastWriteTimeHigh),
+ LastWriteTimeLow(LastWriteTimeLow),
+ VolumeSerialNumber(VolumeSerialNumber), FileSizeHigh(FileSizeHigh),
+ FileSizeLow(FileSizeLow), FileIndexHigh(FileIndexHigh),
+ FileIndexLow(FileIndexLow), Type(Type), Perms(perms_not_known) {}
#endif
// getters
file_type type() const { return Type; }
perms permissions() const { return Perms; }
+ TimeValue getLastAccessedTime() const;
TimeValue getLastModificationTime() const;
UniqueID getUniqueID() const;
@@ -251,7 +265,7 @@ struct file_magic {
};
bool is_object() const {
- return V == unknown ? false : true;
+ return V != unknown;
}
file_magic() : V(unknown) {}
@@ -590,6 +604,12 @@ std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
std::error_code createUniqueDirectory(const Twine &Prefix,
SmallVectorImpl<char> &ResultPath);
+/// @brief Fetch a path to an open file, as specified by a file descriptor
+///
+/// @param FD File descriptor to a currently open file
+/// @param ResultPath The buffer into which to write the path
+std::error_code getPathFromOpenFD(int FD, SmallVectorImpl<char> &ResultPath);
+
enum OpenFlags : unsigned {
F_None = 0,
@@ -622,7 +642,8 @@ inline OpenFlags &operator|=(OpenFlags &A, OpenFlags B) {
std::error_code openFileForWrite(const Twine &Name, int &ResultFD,
OpenFlags Flags, unsigned Mode = 0666);
-std::error_code openFileForRead(const Twine &Name, int &ResultFD);
+std::error_code openFileForRead(const Twine &Name, int &ResultFD,
+ SmallVectorImpl<char> *RealPath = nullptr);
/// @brief Identify the type of a binary file based on how magical it is.
file_magic identify_magic(StringRef magic);
@@ -637,6 +658,17 @@ std::error_code identify_magic(const Twine &path, file_magic &result);
std::error_code getUniqueID(const Twine Path, UniqueID &Result);
+/// @brief Get disk space usage information.
+///
+/// Note: Users must be careful about "Time Of Check, Time Of Use" kind of bug.
+/// Note: Windows reports results according to the quota allocated to the user.
+///
+/// @param Path Input path.
+/// @returns a space_info structure filled with the capacity, free, and
+/// available space on the device \a Path is on. A platform specific error_code
+/// is returned on error.
+ErrorOr<space_info> disk_space(const Twine &Path);
+
/// This class represents a memory mapped file. It is based on
/// boost::iostreams::mapped_file.
class mapped_file_region {
@@ -739,7 +771,7 @@ namespace detail {
intptr_t IterationHandle;
directory_entry CurrentEntry;
};
-}
+} // end namespace detail
/// directory_iterator - Iterates through the entries in path. There is no
/// operator++ because we need an error_code. If it's really needed we can make
@@ -801,7 +833,7 @@ namespace detail {
uint16_t Level;
bool HasNoPushRequest;
};
-}
+} // end namespace detail
/// recursive_directory_iterator - Same as directory_iterator except for it
/// recurses down into child directories.
@@ -900,4 +932,4 @@ public:
} // end namespace sys
} // end namespace llvm
-#endif
+#endif // LLVM_SUPPORT_FILESYSTEM_H
diff --git a/include/llvm/Support/Format.h b/include/llvm/Support/Format.h
index f0b437a0cbed..d5c301cd7e2b 100644
--- a/include/llvm/Support/Format.h
+++ b/include/llvm/Support/Format.h
@@ -170,13 +170,13 @@ inline FormattedNumber format_hex(uint64_t N, unsigned Width,
/// format_hex_no_prefix - Output \p N as a fixed width hexadecimal. Does not
/// prepend '0x' to the outputted string. If number will not fit in width,
/// full number is still printed. Examples:
-/// OS << format_hex_no_prefix(255, 4) => ff
-/// OS << format_hex_no_prefix(255, 4, true) => FF
-/// OS << format_hex_no_prefix(255, 6) => 00ff
/// OS << format_hex_no_prefix(255, 2) => ff
+/// OS << format_hex_no_prefix(255, 2, true) => FF
+/// OS << format_hex_no_prefix(255, 4) => 00ff
+/// OS << format_hex_no_prefix(255, 1) => ff
inline FormattedNumber format_hex_no_prefix(uint64_t N, unsigned Width,
bool Upper = false) {
- assert(Width <= 18 && "hex width must be <= 18");
+ assert(Width <= 16 && "hex width must be <= 16");
return FormattedNumber(N, 0, Width, true, Upper, false);
}
diff --git a/include/llvm/Support/GenericDomTree.h b/include/llvm/Support/GenericDomTree.h
index 8bae582d18c7..77b5ba7e3e97 100644
--- a/include/llvm/Support/GenericDomTree.h
+++ b/include/llvm/Support/GenericDomTree.h
@@ -109,13 +109,13 @@ public:
return true;
SmallPtrSet<const NodeT *, 4> OtherChildren;
- for (const_iterator I = Other->begin(), E = Other->end(); I != E; ++I) {
- const NodeT *Nd = (*I)->getBlock();
+ for (const DomTreeNodeBase *I : *Other) {
+ const NodeT *Nd = I->getBlock();
OtherChildren.insert(Nd);
}
- for (const_iterator I = begin(), E = end(); I != E; ++I) {
- const NodeT *N = (*I)->getBlock();
+ for (const DomTreeNodeBase *I : *this) {
+ const NodeT *N = I->getBlock();
if (OtherChildren.count(N) == 0)
return true;
}
@@ -138,8 +138,9 @@ public:
}
}
- /// getDFSNumIn/getDFSNumOut - These are an internal implementation detail, do
- /// not call them.
+ /// getDFSNumIn/getDFSNumOut - These return the DFS visitation order for nodes
+ /// in the dominator tree. They are only guaranteed valid if
+ /// updateDFSNumbers() has been called.
unsigned getDFSNumIn() const { return DFSNumIn; }
unsigned getDFSNumOut() const { return DFSNumOut; }
@@ -348,17 +349,14 @@ public:
if (DomTreeNodes.size() != OtherDomTreeNodes.size())
return true;
- for (typename DomTreeNodeMapType::const_iterator
- I = this->DomTreeNodes.begin(),
- E = this->DomTreeNodes.end();
- I != E; ++I) {
- NodeT *BB = I->first;
+ for (const auto &DomTreeNode : this->DomTreeNodes) {
+ NodeT *BB = DomTreeNode.first;
typename DomTreeNodeMapType::const_iterator OI =
OtherDomTreeNodes.find(BB);
if (OI == OtherDomTreeNodes.end())
return true;
- DomTreeNodeBase<NodeT> &MyNd = *I->second;
+ DomTreeNodeBase<NodeT> &MyNd = *DomTreeNode.second;
DomTreeNodeBase<NodeT> &OtherNd = *OI->second;
if (MyNd.compare(&OtherNd))
@@ -453,7 +451,7 @@ public:
// Compare the result of the tree walk and the dfs numbers, if expensive
// checks are enabled.
-#ifdef XDEBUG
+#ifdef EXPENSIVE_CHECKS
assert((!DFSInfoValid ||
(dominatedBySlowTreeWalk(A, B) == B->DominatedBy(A))) &&
"Tree walk disagrees with dfs numbers!");
diff --git a/include/llvm/Support/Host.h b/include/llvm/Support/Host.h
index 8f4bf3c1ba56..8114f9bf846b 100644
--- a/include/llvm/Support/Host.h
+++ b/include/llvm/Support/Host.h
@@ -16,7 +16,7 @@
#include "llvm/ADT/StringMap.h"
-#if defined(__linux__) || defined(__GNU__)
+#if defined(__linux__) || defined(__GNU__) || defined(__HAIKU__)
#include <endian.h>
#else
#if !defined(BYTE_ORDER) && !defined(LLVM_ON_WIN32)
diff --git a/include/llvm/Support/JamCRC.h b/include/llvm/Support/JamCRC.h
index 20c28a5f8e45..5268bbd9ba1e 100644
--- a/include/llvm/Support/JamCRC.h
+++ b/include/llvm/Support/JamCRC.h
@@ -27,10 +27,11 @@
#ifndef LLVM_SUPPORT_JAMCRC_H
#define LLVM_SUPPORT_JAMCRC_H
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
+template <typename T> class ArrayRef;
+
class JamCRC {
public:
JamCRC(uint32_t Init = 0xFFFFFFFFU) : CRC(Init) {}
diff --git a/include/llvm/Support/Locale.h b/include/llvm/Support/Locale.h
index b384d58baea7..f7a2c036ed5e 100644
--- a/include/llvm/Support/Locale.h
+++ b/include/llvm/Support/Locale.h
@@ -1,9 +1,9 @@
#ifndef LLVM_SUPPORT_LOCALE_H
#define LLVM_SUPPORT_LOCALE_H
-#include "llvm/ADT/StringRef.h"
-
namespace llvm {
+class StringRef;
+
namespace sys {
namespace locale {
diff --git a/include/llvm/Support/LockFileManager.h b/include/llvm/Support/LockFileManager.h
index 8e88d4279bd8..13d252425b93 100644
--- a/include/llvm/Support/LockFileManager.h
+++ b/include/llvm/Support/LockFileManager.h
@@ -11,11 +11,12 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringRef.h"
#include <system_error>
#include <utility> // for std::pair
namespace llvm {
+class StringRef;
+
/// \brief Class that manages the creation of a lock file to aid
/// implicit coordination between different processes.
///
@@ -56,6 +57,7 @@ private:
Optional<std::pair<std::string, int> > Owner;
Optional<std::error_code> Error;
+ std::string ErrorDiagMsg;
LockFileManager(const LockFileManager &) = delete;
LockFileManager &operator=(const LockFileManager &) = delete;
@@ -81,6 +83,15 @@ public:
/// \brief Remove the lock file. This may delete a different lock file than
/// the one previously read if there is a race.
std::error_code unsafeRemoveLockFile();
+
+ /// \brief Get error message, or "" if there is no error.
+ std::string getErrorMessage() const;
+
+ /// \brief Set error and error message
+ void setError(std::error_code &EC, StringRef ErrorMsg = "") {
+ Error = EC;
+ ErrorDiagMsg = ErrorMsg.str();
+ }
};
} // end namespace llvm
diff --git a/include/llvm/Support/MD5.h b/include/llvm/Support/MD5.h
index f6e1e92c9fa8..42d8ca8a1ebb 100644
--- a/include/llvm/Support/MD5.h
+++ b/include/llvm/Support/MD5.h
@@ -28,11 +28,12 @@
#ifndef LLVM_SUPPORT_MD5_H
#define LLVM_SUPPORT_MD5_H
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Endian.h"
namespace llvm {
+template <typename T> class ArrayRef;
class MD5 {
// Any 32-bit or wider unsigned integer data type will do.
@@ -65,6 +66,18 @@ private:
const uint8_t *body(ArrayRef<uint8_t> Data);
};
+/// Helper to compute and return lower 64 bits of the given string's MD5 hash.
+inline uint64_t MD5Hash(StringRef Str) {
+ MD5 Hash;
+ Hash.update(Str);
+ llvm::MD5::MD5Result Result;
+ Hash.final(Result);
+ // Return the least significant 8 bytes. Our MD5 implementation returns the
+ // result in little endian, so we may need to swap bytes.
+ using namespace llvm::support;
+ return endian::read<uint64_t, little, unaligned>(Result);
+}
+
}
#endif
diff --git a/include/llvm/Support/MachO.def b/include/llvm/Support/MachO.def
new file mode 100644
index 000000000000..9ca6440dd82b
--- /dev/null
+++ b/include/llvm/Support/MachO.def
@@ -0,0 +1,106 @@
+//,,,-- llvm/Support/MachO.def - The MachO file definitions -----*- C++ -*-,,,//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//,,,----------------------------------------------------------------------,,,//
+//
+// Definitions for MachO files
+//
+//,,,----------------------------------------------------------------------,,,//
+
+#ifdef HANDLE_LOAD_COMMAND
+
+HANDLE_LOAD_COMMAND(LC_SEGMENT, 0x00000001u, segment_command)
+HANDLE_LOAD_COMMAND(LC_SYMTAB, 0x00000002u, symtab_command)
+HANDLE_LOAD_COMMAND(LC_SYMSEG, 0x00000003u, symseg_command)
+HANDLE_LOAD_COMMAND(LC_THREAD, 0x00000004u, thread_command)
+HANDLE_LOAD_COMMAND(LC_UNIXTHREAD, 0x00000005u, thread_command)
+HANDLE_LOAD_COMMAND(LC_LOADFVMLIB, 0x00000006u, fvmlib_command)
+HANDLE_LOAD_COMMAND(LC_IDFVMLIB, 0x00000007u, fvmlib_command)
+HANDLE_LOAD_COMMAND(LC_IDENT, 0x00000008u, ident_command)
+HANDLE_LOAD_COMMAND(LC_FVMFILE, 0x00000009u, fvmfile_command)
+HANDLE_LOAD_COMMAND(LC_PREPAGE, 0x0000000Au, load_command)
+HANDLE_LOAD_COMMAND(LC_DYSYMTAB, 0x0000000Bu, dysymtab_command)
+HANDLE_LOAD_COMMAND(LC_LOAD_DYLIB, 0x0000000Cu, dylib_command)
+HANDLE_LOAD_COMMAND(LC_ID_DYLIB, 0x0000000Du, dylib_command)
+HANDLE_LOAD_COMMAND(LC_LOAD_DYLINKER, 0x0000000Eu, dylinker_command)
+HANDLE_LOAD_COMMAND(LC_ID_DYLINKER, 0x0000000Fu, dylinker_command)
+HANDLE_LOAD_COMMAND(LC_PREBOUND_DYLIB, 0x00000010u, prebound_dylib_command)
+HANDLE_LOAD_COMMAND(LC_ROUTINES, 0x00000011u, routines_command)
+HANDLE_LOAD_COMMAND(LC_SUB_FRAMEWORK, 0x00000012u, sub_framework_command)
+HANDLE_LOAD_COMMAND(LC_SUB_UMBRELLA, 0x00000013u, sub_umbrella_command)
+HANDLE_LOAD_COMMAND(LC_SUB_CLIENT, 0x00000014u, sub_client_command)
+HANDLE_LOAD_COMMAND(LC_SUB_LIBRARY, 0x00000015u, sub_library_command)
+HANDLE_LOAD_COMMAND(LC_TWOLEVEL_HINTS, 0x00000016u, twolevel_hints_command)
+HANDLE_LOAD_COMMAND(LC_PREBIND_CKSUM, 0x00000017u, prebind_cksum_command)
+HANDLE_LOAD_COMMAND(LC_LOAD_WEAK_DYLIB, 0x80000018u, dylib_command)
+HANDLE_LOAD_COMMAND(LC_SEGMENT_64, 0x00000019u, segment_command_64)
+HANDLE_LOAD_COMMAND(LC_ROUTINES_64, 0x0000001Au, routines_command_64)
+HANDLE_LOAD_COMMAND(LC_UUID, 0x0000001Bu, uuid_command)
+HANDLE_LOAD_COMMAND(LC_RPATH, 0x8000001Cu, rpath_command)
+HANDLE_LOAD_COMMAND(LC_CODE_SIGNATURE, 0x0000001Du, linkedit_data_command)
+HANDLE_LOAD_COMMAND(LC_SEGMENT_SPLIT_INFO, 0x0000001Eu, linkedit_data_command)
+HANDLE_LOAD_COMMAND(LC_REEXPORT_DYLIB, 0x8000001Fu, dylib_command)
+HANDLE_LOAD_COMMAND(LC_LAZY_LOAD_DYLIB, 0x00000020u, dylib_command)
+HANDLE_LOAD_COMMAND(LC_ENCRYPTION_INFO, 0x00000021u, encryption_info_command)
+HANDLE_LOAD_COMMAND(LC_DYLD_INFO, 0x00000022u, dyld_info_command)
+HANDLE_LOAD_COMMAND(LC_DYLD_INFO_ONLY, 0x80000022u, dyld_info_command)
+HANDLE_LOAD_COMMAND(LC_LOAD_UPWARD_DYLIB, 0x80000023u, dylib_command)
+HANDLE_LOAD_COMMAND(LC_VERSION_MIN_MACOSX, 0x00000024u, version_min_command)
+HANDLE_LOAD_COMMAND(LC_VERSION_MIN_IPHONEOS, 0x00000025u, version_min_command)
+HANDLE_LOAD_COMMAND(LC_FUNCTION_STARTS, 0x00000026u, linkedit_data_command)
+HANDLE_LOAD_COMMAND(LC_DYLD_ENVIRONMENT, 0x00000027u, dylinker_command)
+HANDLE_LOAD_COMMAND(LC_MAIN, 0x80000028u, entry_point_command)
+HANDLE_LOAD_COMMAND(LC_DATA_IN_CODE, 0x00000029u, linkedit_data_command)
+HANDLE_LOAD_COMMAND(LC_SOURCE_VERSION, 0x0000002Au, source_version_command)
+HANDLE_LOAD_COMMAND(LC_DYLIB_CODE_SIGN_DRS, 0x0000002Bu, linkedit_data_command)
+HANDLE_LOAD_COMMAND(LC_ENCRYPTION_INFO_64, 0x0000002Cu,
+ encryption_info_command_64)
+HANDLE_LOAD_COMMAND(LC_LINKER_OPTION, 0x0000002Du, linker_option_command)
+HANDLE_LOAD_COMMAND(LC_LINKER_OPTIMIZATION_HINT, 0x0000002Eu, linkedit_data_command)
+HANDLE_LOAD_COMMAND(LC_VERSION_MIN_TVOS, 0x0000002Fu, version_min_command)
+HANDLE_LOAD_COMMAND(LC_VERSION_MIN_WATCHOS, 0x00000030u, version_min_command)
+
+#endif
+
+#ifdef LOAD_COMMAND_STRUCT
+
+LOAD_COMMAND_STRUCT(dyld_info_command)
+LOAD_COMMAND_STRUCT(dylib_command)
+LOAD_COMMAND_STRUCT(dylinker_command)
+LOAD_COMMAND_STRUCT(dysymtab_command)
+LOAD_COMMAND_STRUCT(encryption_info_command)
+LOAD_COMMAND_STRUCT(encryption_info_command_64)
+LOAD_COMMAND_STRUCT(entry_point_command)
+LOAD_COMMAND_STRUCT(fvmfile_command)
+LOAD_COMMAND_STRUCT(fvmlib_command)
+LOAD_COMMAND_STRUCT(ident_command)
+LOAD_COMMAND_STRUCT(linkedit_data_command)
+LOAD_COMMAND_STRUCT(linker_option_command)
+LOAD_COMMAND_STRUCT(load_command)
+LOAD_COMMAND_STRUCT(prebind_cksum_command)
+LOAD_COMMAND_STRUCT(prebound_dylib_command)
+LOAD_COMMAND_STRUCT(routines_command)
+LOAD_COMMAND_STRUCT(routines_command_64)
+LOAD_COMMAND_STRUCT(rpath_command)
+LOAD_COMMAND_STRUCT(segment_command)
+LOAD_COMMAND_STRUCT(segment_command_64)
+LOAD_COMMAND_STRUCT(source_version_command)
+LOAD_COMMAND_STRUCT(sub_client_command)
+LOAD_COMMAND_STRUCT(sub_framework_command)
+LOAD_COMMAND_STRUCT(sub_library_command)
+LOAD_COMMAND_STRUCT(sub_umbrella_command)
+LOAD_COMMAND_STRUCT(symseg_command)
+LOAD_COMMAND_STRUCT(symtab_command)
+LOAD_COMMAND_STRUCT(thread_command)
+LOAD_COMMAND_STRUCT(twolevel_hints_command)
+LOAD_COMMAND_STRUCT(uuid_command)
+LOAD_COMMAND_STRUCT(version_min_command)
+
+#endif
+
+#undef HANDLE_LOAD_COMMAND
+#undef LOAD_COMMAND_STRUCT
diff --git a/include/llvm/Support/MachO.h b/include/llvm/Support/MachO.h
index 54b8745de1c1..9a03722d250f 100644
--- a/include/llvm/Support/MachO.h
+++ b/include/llvm/Support/MachO.h
@@ -29,7 +29,9 @@ namespace llvm {
MH_MAGIC_64 = 0xFEEDFACFu,
MH_CIGAM_64 = 0xCFFAEDFEu,
FAT_MAGIC = 0xCAFEBABEu,
- FAT_CIGAM = 0xBEBAFECAu
+ FAT_CIGAM = 0xBEBAFECAu,
+ FAT_MAGIC_64 = 0xCAFEBABFu,
+ FAT_CIGAM_64 = 0xBFBAFECAu
};
enum HeaderFileType {
@@ -84,59 +86,15 @@ namespace llvm {
LC_REQ_DYLD = 0x80000000u
};
+#define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \
+ LCName = LCValue,
+
enum LoadCommandType : uint32_t {
- // Constants for the "cmd" field in llvm::MachO::load_command
- LC_SEGMENT = 0x00000001u,
- LC_SYMTAB = 0x00000002u,
- LC_SYMSEG = 0x00000003u,
- LC_THREAD = 0x00000004u,
- LC_UNIXTHREAD = 0x00000005u,
- LC_LOADFVMLIB = 0x00000006u,
- LC_IDFVMLIB = 0x00000007u,
- LC_IDENT = 0x00000008u,
- LC_FVMFILE = 0x00000009u,
- LC_PREPAGE = 0x0000000Au,
- LC_DYSYMTAB = 0x0000000Bu,
- LC_LOAD_DYLIB = 0x0000000Cu,
- LC_ID_DYLIB = 0x0000000Du,
- LC_LOAD_DYLINKER = 0x0000000Eu,
- LC_ID_DYLINKER = 0x0000000Fu,
- LC_PREBOUND_DYLIB = 0x00000010u,
- LC_ROUTINES = 0x00000011u,
- LC_SUB_FRAMEWORK = 0x00000012u,
- LC_SUB_UMBRELLA = 0x00000013u,
- LC_SUB_CLIENT = 0x00000014u,
- LC_SUB_LIBRARY = 0x00000015u,
- LC_TWOLEVEL_HINTS = 0x00000016u,
- LC_PREBIND_CKSUM = 0x00000017u,
- LC_LOAD_WEAK_DYLIB = 0x80000018u,
- LC_SEGMENT_64 = 0x00000019u,
- LC_ROUTINES_64 = 0x0000001Au,
- LC_UUID = 0x0000001Bu,
- LC_RPATH = 0x8000001Cu,
- LC_CODE_SIGNATURE = 0x0000001Du,
- LC_SEGMENT_SPLIT_INFO = 0x0000001Eu,
- LC_REEXPORT_DYLIB = 0x8000001Fu,
- LC_LAZY_LOAD_DYLIB = 0x00000020u,
- LC_ENCRYPTION_INFO = 0x00000021u,
- LC_DYLD_INFO = 0x00000022u,
- LC_DYLD_INFO_ONLY = 0x80000022u,
- LC_LOAD_UPWARD_DYLIB = 0x80000023u,
- LC_VERSION_MIN_MACOSX = 0x00000024u,
- LC_VERSION_MIN_IPHONEOS = 0x00000025u,
- LC_FUNCTION_STARTS = 0x00000026u,
- LC_DYLD_ENVIRONMENT = 0x00000027u,
- LC_MAIN = 0x80000028u,
- LC_DATA_IN_CODE = 0x00000029u,
- LC_SOURCE_VERSION = 0x0000002Au,
- LC_DYLIB_CODE_SIGN_DRS = 0x0000002Bu,
- LC_ENCRYPTION_INFO_64 = 0x0000002Cu,
- LC_LINKER_OPTION = 0x0000002Du,
- LC_LINKER_OPTIMIZATION_HINT = 0x0000002Eu,
- LC_VERSION_MIN_TVOS = 0x0000002Fu,
- LC_VERSION_MIN_WATCHOS = 0x00000030u,
+ #include "llvm/Support/MachO.def"
};
+#undef HANDLE_LOAD_COMMAND
+
enum : uint32_t {
// Constant bits for the "flags" field in llvm::MachO::segment_command
SG_HIGHVM = 0x1u,
@@ -935,6 +893,15 @@ namespace llvm {
uint32_t align;
};
+ struct fat_arch_64 {
+ uint32_t cputype;
+ uint32_t cpusubtype;
+ uint64_t offset;
+ uint64_t size;
+ uint32_t align;
+ uint32_t reserved;
+ };
+
// Structs from <mach-o/reloc.h>
struct relocation_info {
int32_t r_address;
@@ -993,6 +960,28 @@ namespace llvm {
// Byte order swapping functions for MachO structs
+ inline void swapStruct(fat_header &mh) {
+ sys::swapByteOrder(mh.magic);
+ sys::swapByteOrder(mh.nfat_arch);
+ }
+
+ inline void swapStruct(fat_arch &mh) {
+ sys::swapByteOrder(mh.cputype);
+ sys::swapByteOrder(mh.cpusubtype);
+ sys::swapByteOrder(mh.offset);
+ sys::swapByteOrder(mh.size);
+ sys::swapByteOrder(mh.align);
+ }
+
+ inline void swapStruct(fat_arch_64 &mh) {
+ sys::swapByteOrder(mh.cputype);
+ sys::swapByteOrder(mh.cpusubtype);
+ sys::swapByteOrder(mh.offset);
+ sys::swapByteOrder(mh.size);
+ sys::swapByteOrder(mh.align);
+ sys::swapByteOrder(mh.reserved);
+ }
+
inline void swapStruct(mach_header &mh) {
sys::swapByteOrder(mh.magic);
sys::swapByteOrder(mh.cputype);
@@ -1279,6 +1268,58 @@ namespace llvm {
sys::swapByteOrder(C);
}
+ inline void swapStruct(prebind_cksum_command &C) {
+ sys::swapByteOrder(C.cmd);
+ sys::swapByteOrder(C.cmdsize);
+ sys::swapByteOrder(C.cksum);
+ }
+
+ inline void swapStruct(twolevel_hints_command &C) {
+ sys::swapByteOrder(C.cmd);
+ sys::swapByteOrder(C.cmdsize);
+ sys::swapByteOrder(C.offset);
+ sys::swapByteOrder(C.nhints);
+ }
+
+ inline void swapStruct(prebound_dylib_command &C) {
+ sys::swapByteOrder(C.cmd);
+ sys::swapByteOrder(C.cmdsize);
+ sys::swapByteOrder(C.name);
+ sys::swapByteOrder(C.nmodules);
+ sys::swapByteOrder(C.linked_modules);
+ }
+
+ inline void swapStruct(fvmfile_command &C) {
+ sys::swapByteOrder(C.cmd);
+ sys::swapByteOrder(C.cmdsize);
+ sys::swapByteOrder(C.name);
+ sys::swapByteOrder(C.header_addr);
+ }
+
+ inline void swapStruct(symseg_command &C) {
+ sys::swapByteOrder(C.cmd);
+ sys::swapByteOrder(C.cmdsize);
+ sys::swapByteOrder(C.offset);
+ sys::swapByteOrder(C.size);
+ }
+
+ inline void swapStruct(ident_command &C) {
+ sys::swapByteOrder(C.cmd);
+ sys::swapByteOrder(C.cmdsize);
+ }
+
+ inline void swapStruct(fvmlib &C) {
+ sys::swapByteOrder(C.name);
+ sys::swapByteOrder(C.minor_version);
+ sys::swapByteOrder(C.header_addr);
+ }
+
+ inline void swapStruct(fvmlib_command &C) {
+ sys::swapByteOrder(C.cmd);
+ sys::swapByteOrder(C.cmdsize);
+ swapStruct(C.fvmlib);
+ }
+
// Get/Set functions from <mach-o/nlist.h>
static inline uint16_t GET_LIBRARY_ORDINAL(uint16_t n_desc) {
@@ -1669,6 +1710,13 @@ namespace llvm {
const uint32_t x86_EXCEPTION_STATE_COUNT =
sizeof(x86_exception_state_t) / sizeof(uint32_t);
+ // Define a union of all load command structs
+ #define LOAD_COMMAND_STRUCT(LCStruct) LCStruct LCStruct##_data;
+
+ union macho_load_command {
+ #include "llvm/Support/MachO.def"
+ };
+
} // end namespace MachO
} // end namespace llvm
diff --git a/include/llvm/Support/ManagedStatic.h b/include/llvm/Support/ManagedStatic.h
index 2e131e47177d..ec8154b828e5 100644
--- a/include/llvm/Support/ManagedStatic.h
+++ b/include/llvm/Support/ManagedStatic.h
@@ -14,25 +14,26 @@
#ifndef LLVM_SUPPORT_MANAGEDSTATIC_H
#define LLVM_SUPPORT_MANAGEDSTATIC_H
-#include "llvm/Support/Atomic.h"
#include "llvm/Support/Compiler.h"
-#include "llvm/Support/Threading.h"
+#include <atomic>
+#include <cstddef>
namespace llvm {
/// object_creator - Helper method for ManagedStatic.
template<class C>
-void* object_creator() {
+LLVM_LIBRARY_VISIBILITY void* object_creator() {
return new C();
}
/// object_deleter - Helper method for ManagedStatic.
///
-template<typename T> struct object_deleter {
- static void call(void * Ptr) { delete (T*)Ptr; }
+template <typename T> struct LLVM_LIBRARY_VISIBILITY object_deleter {
+ static void call(void *Ptr) { delete (T *)Ptr; }
};
-template<typename T, size_t N> struct object_deleter<T[N]> {
- static void call(void * Ptr) { delete[] (T*)Ptr; }
+template <typename T, size_t N>
+struct LLVM_LIBRARY_VISIBILITY object_deleter<T[N]> {
+ static void call(void *Ptr) { delete[](T *)Ptr; }
};
/// ManagedStaticBase - Common base class for ManagedStatic instances.
@@ -40,7 +41,7 @@ class ManagedStaticBase {
protected:
// This should only be used as a static variable, which guarantees that this
// will be zero initialized.
- mutable void *Ptr;
+ mutable std::atomic<void *> Ptr;
mutable void (*DeleterFn)(void*);
mutable const ManagedStaticBase *Next;
@@ -60,40 +61,26 @@ public:
template<class C>
class ManagedStatic : public ManagedStaticBase {
public:
-
// Accessors.
C &operator*() {
- void* tmp = Ptr;
- if (llvm_is_multithreaded()) sys::MemoryFence();
- if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
- TsanHappensAfter(this);
+ void *Tmp = Ptr.load(std::memory_order_acquire);
+ if (!Tmp)
+ RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
- return *static_cast<C*>(Ptr);
+ return *static_cast<C *>(Ptr.load(std::memory_order_relaxed));
}
- C *operator->() {
- void* tmp = Ptr;
- if (llvm_is_multithreaded()) sys::MemoryFence();
- if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
- TsanHappensAfter(this);
- return static_cast<C*>(Ptr);
- }
+ C *operator->() { return &**this; }
+
const C &operator*() const {
- void* tmp = Ptr;
- if (llvm_is_multithreaded()) sys::MemoryFence();
- if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
- TsanHappensAfter(this);
+ void *Tmp = Ptr.load(std::memory_order_acquire);
+ if (!Tmp)
+ RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
- return *static_cast<C*>(Ptr);
+ return *static_cast<C *>(Ptr.load(std::memory_order_relaxed));
}
- const C *operator->() const {
- void* tmp = Ptr;
- if (llvm_is_multithreaded()) sys::MemoryFence();
- if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
- TsanHappensAfter(this);
- return static_cast<C*>(Ptr);
- }
+ const C *operator->() const { return &**this; }
};
/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h
index 408ae3c339a2..5c816ac9df92 100644
--- a/include/llvm/Support/MathExtras.h
+++ b/include/llvm/Support/MathExtras.h
@@ -16,9 +16,11 @@
#include "llvm/Support/Compiler.h"
#include "llvm/Support/SwapByteOrder.h"
+#include <algorithm>
#include <cassert>
#include <cstring>
#include <type_traits>
+#include <limits>
#ifdef _MSC_VER
#include <intrin.h>
@@ -281,14 +283,19 @@ inline bool isInt<32>(int64_t x) {
/// left by S.
template<unsigned N, unsigned S>
inline bool isShiftedInt(int64_t x) {
- return isInt<N+S>(x) && (x % (1<<S) == 0);
+ static_assert(
+ N > 0, "isShiftedInt<0> doesn't make sense (refers to a 0-bit number.");
+ static_assert(N + S <= 64, "isShiftedInt<N, S> with N + S > 64 is too wide.");
+ return isInt<N + S>(x) && (x % (UINT64_C(1) << S) == 0);
}
/// isUInt - Checks if an unsigned integer fits into the given bit width.
template<unsigned N>
inline bool isUInt(uint64_t x) {
+ static_assert(N > 0, "isUInt<0> doesn't make sense.");
return N >= 64 || x < (UINT64_C(1)<<(N));
}
+
// Template specializations to get better code for common cases.
template<>
inline bool isUInt<8>(uint64_t x) {
@@ -303,23 +310,55 @@ inline bool isUInt<32>(uint64_t x) {
return static_cast<uint32_t>(x) == x;
}
-/// isShiftedUInt<N,S> - Checks if a unsigned integer is an N bit number shifted
-/// left by S.
+/// Checks if a unsigned integer is an N bit number shifted left by S.
template<unsigned N, unsigned S>
inline bool isShiftedUInt(uint64_t x) {
- return isUInt<N+S>(x) && (x % (1<<S) == 0);
+ static_assert(
+ N > 0, "isShiftedUInt<0> doesn't make sense (refers to a 0-bit number)");
+ static_assert(N + S <= 64,
+ "isShiftedUInt<N, S> with N + S > 64 is too wide.");
+ // Per the two static_asserts above, S must be strictly less than 64. So
+ // 1 << S is not undefined behavior.
+ return isUInt<N + S>(x) && (x % (UINT64_C(1) << S) == 0);
+}
+
+/// Gets the maximum value for a N-bit unsigned integer.
+inline uint64_t maxUIntN(uint64_t N) {
+ assert(N > 0 && N <= 64 && "integer width out of range");
+
+ // uint64_t(1) << 64 is undefined behavior, so we can't do
+ // (uint64_t(1) << N) - 1
+ // without checking first that N != 64. But this works and doesn't have a
+ // branch.
+ return UINT64_MAX >> (64 - N);
+}
+
+/// Gets the minimum value for a N-bit signed integer.
+inline int64_t minIntN(int64_t N) {
+ assert(N > 0 && N <= 64 && "integer width out of range");
+
+ return -(UINT64_C(1)<<(N-1));
+}
+
+/// Gets the maximum value for a N-bit signed integer.
+inline int64_t maxIntN(int64_t N) {
+ assert(N > 0 && N <= 64 && "integer width out of range");
+
+ // This relies on two's complement wraparound when N == 64, so we convert to
+ // int64_t only at the very end to avoid UB.
+ return (UINT64_C(1) << (N - 1)) - 1;
}
/// isUIntN - Checks if an unsigned integer fits into the given (dynamic)
/// bit width.
inline bool isUIntN(unsigned N, uint64_t x) {
- return N >= 64 || x < (UINT64_C(1)<<(N));
+ return N >= 64 || x <= maxUIntN(N);
}
/// isIntN - Checks if an signed integer fits into the given (dynamic)
/// bit width.
inline bool isIntN(unsigned N, int64_t x) {
- return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1)));
+ return N >= 64 || (minIntN(N) <= x && x <= maxIntN(N));
}
/// isMask_32 - This function returns true if the argument is a non-empty
@@ -606,57 +645,78 @@ inline uint64_t PowerOf2Floor(uint64_t A) {
///
/// Examples:
/// \code
-/// RoundUpToAlignment(5, 8) = 8
-/// RoundUpToAlignment(17, 8) = 24
-/// RoundUpToAlignment(~0LL, 8) = 0
-/// RoundUpToAlignment(321, 255) = 510
+/// alignTo(5, 8) = 8
+/// alignTo(17, 8) = 24
+/// alignTo(~0LL, 8) = 0
+/// alignTo(321, 255) = 510
///
-/// RoundUpToAlignment(5, 8, 7) = 7
-/// RoundUpToAlignment(17, 8, 1) = 17
-/// RoundUpToAlignment(~0LL, 8, 3) = 3
-/// RoundUpToAlignment(321, 255, 42) = 552
+/// alignTo(5, 8, 7) = 7
+/// alignTo(17, 8, 1) = 17
+/// alignTo(~0LL, 8, 3) = 3
+/// alignTo(321, 255, 42) = 552
/// \endcode
-inline uint64_t RoundUpToAlignment(uint64_t Value, uint64_t Align,
- uint64_t Skew = 0) {
+inline uint64_t alignTo(uint64_t Value, uint64_t Align, uint64_t Skew = 0) {
Skew %= Align;
return (Value + Align - 1 - Skew) / Align * Align + Skew;
}
+/// Returns the largest uint64_t less than or equal to \p Value and is
+/// \p Skew mod \p Align. \p Align must be non-zero
+inline uint64_t alignDown(uint64_t Value, uint64_t Align, uint64_t Skew = 0) {
+ Skew %= Align;
+ return (Value - Skew) / Align * Align + Skew;
+}
+
/// Returns the offset to the next integer (mod 2**64) that is greater than
/// or equal to \p Value and is a multiple of \p Align. \p Align must be
/// non-zero.
inline uint64_t OffsetToAlignment(uint64_t Value, uint64_t Align) {
- return RoundUpToAlignment(Value, Align) - Value;
+ return alignTo(Value, Align) - Value;
}
-/// SignExtend32 - Sign extend B-bit number x to 32-bit int.
-/// Usage int32_t r = SignExtend32<5>(x);
-template <unsigned B> inline int32_t SignExtend32(uint32_t x) {
- return int32_t(x << (32 - B)) >> (32 - B);
+/// Sign-extend the number in the bottom B bits of X to a 32-bit integer.
+/// Requires 0 < B <= 32.
+template <unsigned B> inline int32_t SignExtend32(uint32_t X) {
+ static_assert(B > 0, "Bit width can't be 0.");
+ static_assert(B <= 32, "Bit width out of range.");
+ return int32_t(X << (32 - B)) >> (32 - B);
}
-/// \brief Sign extend number in the bottom B bits of X to a 32-bit int.
-/// Requires 0 < B <= 32.
+/// Sign-extend the number in the bottom B bits of X to a 32-bit integer.
+/// Requires 0 < B < 32.
inline int32_t SignExtend32(uint32_t X, unsigned B) {
+ assert(B > 0 && "Bit width can't be 0.");
+ assert(B <= 32 && "Bit width out of range.");
return int32_t(X << (32 - B)) >> (32 - B);
}
-/// SignExtend64 - Sign extend B-bit number x to 64-bit int.
-/// Usage int64_t r = SignExtend64<5>(x);
+/// Sign-extend the number in the bottom B bits of X to a 64-bit integer.
+/// Requires 0 < B < 64.
template <unsigned B> inline int64_t SignExtend64(uint64_t x) {
+ static_assert(B > 0, "Bit width can't be 0.");
+ static_assert(B <= 64, "Bit width out of range.");
return int64_t(x << (64 - B)) >> (64 - B);
}
-/// \brief Sign extend number in the bottom B bits of X to a 64-bit int.
-/// Requires 0 < B <= 64.
+/// Sign-extend the number in the bottom B bits of X to a 64-bit integer.
+/// Requires 0 < B < 64.
inline int64_t SignExtend64(uint64_t X, unsigned B) {
+ assert(B > 0 && "Bit width can't be 0.");
+ assert(B <= 64 && "Bit width out of range.");
return int64_t(X << (64 - B)) >> (64 - B);
}
-/// \brief Add two unsigned integers, X and Y, of type T.
-/// Clamp the result to the maximum representable value of T on overflow.
-/// ResultOverflowed indicates if the result is larger than the maximum
-/// representable value of type T.
+/// Subtract two unsigned integers, X and Y, of type T and return the absolute
+/// value of the result.
+template <typename T>
+typename std::enable_if<std::is_unsigned<T>::value, T>::type
+AbsoluteDifference(T X, T Y) {
+ return std::max(X, Y) - std::min(X, Y);
+}
+
+/// Add two unsigned integers, X and Y, of type T. Clamp the result to the
+/// maximum representable value of T on overflow. ResultOverflowed indicates if
+/// the result is larger than the maximum representable value of type T.
template <typename T>
typename std::enable_if<std::is_unsigned<T>::value, T>::type
SaturatingAdd(T X, T Y, bool *ResultOverflowed = nullptr) {
@@ -671,10 +731,9 @@ SaturatingAdd(T X, T Y, bool *ResultOverflowed = nullptr) {
return Z;
}
-/// \brief Multiply two unsigned integers, X and Y, of type T.
-/// Clamp the result to the maximum representable value of T on overflow.
-/// ResultOverflowed indicates if the result is larger than the maximum
-/// representable value of type T.
+/// Multiply two unsigned integers, X and Y, of type T. Clamp the result to the
+/// maximum representable value of T on overflow. ResultOverflowed indicates if
+/// the result is larger than the maximum representable value of type T.
template <typename T>
typename std::enable_if<std::is_unsigned<T>::value, T>::type
SaturatingMultiply(T X, T Y, bool *ResultOverflowed = nullptr) {
@@ -717,12 +776,10 @@ SaturatingMultiply(T X, T Y, bool *ResultOverflowed = nullptr) {
return Z;
}
-/// \brief Multiply two unsigned integers, X and Y, and add the unsigned
-/// integer, A to the product. Clamp the result to the maximum representable
-/// value of T on overflow. ResultOverflowed indicates if the result is larger
-/// than the maximum representable value of type T.
-/// Note that this is purely a convenience function as there is no distinction
-/// where overflow occurred in a 'fused' multiply-add for unsigned numbers.
+/// Multiply two unsigned integers, X and Y, and add the unsigned integer, A to
+/// the product. Clamp the result to the maximum representable value of T on
+/// overflow. ResultOverflowed indicates if the result is larger than the
+/// maximum representable value of type T.
template <typename T>
typename std::enable_if<std::is_unsigned<T>::value, T>::type
SaturatingMultiplyAdd(T X, T Y, T A, bool *ResultOverflowed = nullptr) {
@@ -736,6 +793,7 @@ SaturatingMultiplyAdd(T X, T Y, T A, bool *ResultOverflowed = nullptr) {
return SaturatingAdd(A, Product, &Overflowed);
}
+/// Use this rather than HUGE_VALF; the latter causes warnings on MSVC.
extern const float huge_valf;
} // End llvm namespace
diff --git a/include/llvm/Support/OnDiskHashTable.h b/include/llvm/Support/OnDiskHashTable.h
index ac978d4c242c..c28fcabe78fc 100644
--- a/include/llvm/Support/OnDiskHashTable.h
+++ b/include/llvm/Support/OnDiskHashTable.h
@@ -152,6 +152,22 @@ public:
using namespace llvm::support;
endian::Writer<little> LE(Out);
+ // Now we're done adding entries, resize the bucket list if it's
+ // significantly too large. (This only happens if the number of
+ // entries is small and we're within our initial allocation of
+ // 64 buckets.) We aim for an occupancy ratio in [3/8, 3/4).
+ //
+ // As a special case, if there are two or fewer entries, just
+ // form a single bucket. A linear scan is fine in that case, and
+ // this is very common in C++ class lookup tables. This also
+ // guarantees we produce at least one bucket for an empty table.
+ //
+ // FIXME: Try computing a perfect hash function at this point.
+ unsigned TargetNumBuckets =
+ NumEntries <= 2 ? 1 : NextPowerOf2(NumEntries * 4 / 3);
+ if (TargetNumBuckets != NumBuckets)
+ resize(TargetNumBuckets);
+
// Emit the payload of the table.
for (offset_type I = 0; I < NumBuckets; ++I) {
Bucket &B = Buckets[I];
@@ -309,7 +325,7 @@ public:
Info *InfoObj;
public:
- iterator() : Data(nullptr), Len(0) {}
+ iterator() : Key(), Data(nullptr), Len(0), InfoObj(nullptr) {}
iterator(const internal_key_type K, const unsigned char *D, offset_type L,
Info *InfoObj)
: Key(K), Data(D), Len(L), InfoObj(InfoObj) {}
diff --git a/include/llvm/Support/Path.h b/include/llvm/Support/Path.h
index 955cc991d9b7..853f0997571c 100644
--- a/include/llvm/Support/Path.h
+++ b/include/llvm/Support/Path.h
@@ -16,7 +16,6 @@
#ifndef LLVM_SUPPORT_PATH_H
#define LLVM_SUPPORT_PATH_H
-#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/DataTypes.h"
#include <iterator>
@@ -88,6 +87,9 @@ public:
reverse_iterator &operator++(); // preincrement
bool operator==(const reverse_iterator &RHS) const;
bool operator!=(const reverse_iterator &RHS) const { return !(*this == RHS); }
+
+ /// @brief Difference in bytes between this and RHS.
+ ptrdiff_t operator-(const reverse_iterator &RHS) const;
};
/// @brief Get begin iterator over \a path.
@@ -140,6 +142,23 @@ void remove_filename(SmallVectorImpl<char> &path);
/// prepended.
void replace_extension(SmallVectorImpl<char> &path, const Twine &extension);
+/// @brief Replace matching path prefix with another path.
+///
+/// @code
+/// /foo, /old, /new => /foo
+/// /old/foo, /old, /new => /new/foo
+/// /foo, <empty>, /new => /new/foo
+/// /old/foo, /old, <empty> => /foo
+/// @endcode
+///
+/// @param Path If \a Path starts with \a OldPrefix modify to instead
+/// start with \a NewPrefix.
+/// @param OldPrefix The path prefix to strip from \a Path.
+/// @param NewPrefix The path prefix to replace \a NewPrefix with.
+void replace_path_prefix(SmallVectorImpl<char> &Path,
+ const StringRef &OldPrefix,
+ const StringRef &NewPrefix);
+
/// @brief Append to path.
///
/// @code
diff --git a/include/llvm/Support/PointerLikeTypeTraits.h b/include/llvm/Support/PointerLikeTypeTraits.h
index c12d237b2796..96cdaed142c2 100644
--- a/include/llvm/Support/PointerLikeTypeTraits.h
+++ b/include/llvm/Support/PointerLikeTypeTraits.h
@@ -37,7 +37,8 @@ template <> struct ConstantLog2<1> : std::integral_constant<size_t, 0> {};
}
// Provide PointerLikeTypeTraits for non-cvr pointers.
-template <typename T> struct PointerLikeTypeTraits<T *> {
+template <typename T> class PointerLikeTypeTraits<T *> {
+public:
static inline void *getAsVoidPointer(T *P) { return P; }
static inline T *getFromVoidPointer(void *P) { return static_cast<T *>(P); }
@@ -46,7 +47,8 @@ template <typename T> struct PointerLikeTypeTraits<T *> {
};
};
-template <> struct PointerLikeTypeTraits<void *> {
+template <> class PointerLikeTypeTraits<void *> {
+public:
static inline void *getAsVoidPointer(void *P) { return P; }
static inline void *getFromVoidPointer(void *P) { return P; }
diff --git a/include/llvm/Support/PrettyStackTrace.h b/include/llvm/Support/PrettyStackTrace.h
index 027f9433969d..62e3bbc0ddbc 100644
--- a/include/llvm/Support/PrettyStackTrace.h
+++ b/include/llvm/Support/PrettyStackTrace.h
@@ -29,9 +29,11 @@ namespace llvm {
/// constructed and destructed, they will add their symbolic frames to a
/// virtual stack trace. This gets dumped out if the program crashes.
class PrettyStackTraceEntry {
- const PrettyStackTraceEntry *NextEntry;
+ friend PrettyStackTraceEntry *ReverseStackTrace(PrettyStackTraceEntry *);
+
+ PrettyStackTraceEntry *NextEntry;
PrettyStackTraceEntry(const PrettyStackTraceEntry &) = delete;
- void operator=(const PrettyStackTraceEntry&) = delete;
+ void operator=(const PrettyStackTraceEntry &) = delete;
public:
PrettyStackTraceEntry();
virtual ~PrettyStackTraceEntry();
@@ -67,7 +69,7 @@ namespace llvm {
};
/// Returns the topmost element of the "pretty" stack state.
- const void* SavePrettyStackState();
+ const void *SavePrettyStackState();
/// Restores the topmost element of the "pretty" stack state to State, which
/// should come from a previous call to SavePrettyStackState(). This is
@@ -76,7 +78,7 @@ namespace llvm {
/// happens after a crash that's been recovered by CrashRecoveryContext
/// doesn't have frames on it that were added in code unwound by the
/// CrashRecoveryContext.
- void RestorePrettyStackState(const void* State);
+ void RestorePrettyStackState(const void *State);
} // end namespace llvm
diff --git a/include/llvm/Support/Printable.h b/include/llvm/Support/Printable.h
index 5c1b8d5070d4..83b8f0998ae6 100644
--- a/include/llvm/Support/Printable.h
+++ b/include/llvm/Support/Printable.h
@@ -38,8 +38,8 @@ class raw_ostream;
class Printable {
public:
std::function<void(raw_ostream &OS)> Print;
- Printable(const std::function<void(raw_ostream &OS)> Print)
- : Print(Print) {}
+ Printable(std::function<void(raw_ostream &OS)> Print)
+ : Print(std::move(Print)) {}
};
static inline raw_ostream &operator<<(raw_ostream &OS, const Printable &P) {
diff --git a/include/llvm/Support/Process.h b/include/llvm/Support/Process.h
index cfdd06c62f33..06fd0af10aa4 100644
--- a/include/llvm/Support/Process.h
+++ b/include/llvm/Support/Process.h
@@ -25,7 +25,6 @@
#ifndef LLVM_SUPPORT_PROCESS_H
#define LLVM_SUPPORT_PROCESS_H
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Support/Allocator.h"
@@ -34,6 +33,7 @@
#include <system_error>
namespace llvm {
+template <typename T> class ArrayRef;
class StringRef;
namespace sys {
@@ -69,6 +69,9 @@ public:
/// @brief Prevent core file generation.
static void PreventCoreFiles();
+ /// \brief true if PreventCoreFiles has been called, false otherwise.
+ static bool AreCoreFilesPrevented();
+
// This function returns the environment variable \arg name's value as a UTF-8
// string. \arg Name is assumed to be in UTF-8 encoding too.
static Optional<std::string> GetEnv(StringRef name);
diff --git a/include/llvm/Support/Program.h b/include/llvm/Support/Program.h
index 727864df2721..055f016d8243 100644
--- a/include/llvm/Support/Program.h
+++ b/include/llvm/Support/Program.h
@@ -44,6 +44,8 @@ struct ProcessInfo {
#error "ProcessInfo is not defined for this platform!"
#endif
+ enum : ProcessId { InvalidPid = 0 };
+
/// The process identifier.
ProcessId Pid;
@@ -88,7 +90,7 @@ struct ProcessInfo {
/// -2 indicates a crash during execution or timeout
int ExecuteAndWait(
StringRef Program, ///< Path of the program to be executed. It is
- /// presumed this is the result of the findProgramByName method.
+ ///< presumed this is the result of the findProgramByName method.
const char **args, ///< A vector of strings that are passed to the
///< program. The first element should be the name of the program.
///< The list *must* be terminated by a null char* entry.
diff --git a/include/llvm/Support/RandomNumberGenerator.h b/include/llvm/Support/RandomNumberGenerator.h
index 7446558f0c88..f146e350fe62 100644
--- a/include/llvm/Support/RandomNumberGenerator.h
+++ b/include/llvm/Support/RandomNumberGenerator.h
@@ -16,12 +16,12 @@
#ifndef LLVM_SUPPORT_RANDOMNUMBERGENERATOR_H_
#define LLVM_SUPPORT_RANDOMNUMBERGENERATOR_H_
-#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/DataTypes.h" // Needed for uint64_t on Windows.
#include <random>
namespace llvm {
+class StringRef;
/// A random number generator.
///
diff --git a/include/llvm/Support/Registry.h b/include/llvm/Support/Registry.h
index bbea97b289a6..27f025fcd080 100644
--- a/include/llvm/Support/Registry.h
+++ b/include/llvm/Support/Registry.h
@@ -14,9 +14,10 @@
#ifndef LLVM_SUPPORT_REGISTRY_H
#define LLVM_SUPPORT_REGISTRY_H
-#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/DynamicLibrary.h"
#include <memory>
namespace llvm {
@@ -37,69 +38,45 @@ namespace llvm {
std::unique_ptr<T> instantiate() const { return Ctor(); }
};
- /// Traits for registry entries. If using other than SimpleRegistryEntry, it
- /// is necessary to define an alternate traits class.
- template <typename T>
- class RegistryTraits {
- RegistryTraits() = delete;
-
- public:
- typedef SimpleRegistryEntry<T> entry;
-
- /// nameof/descof - Accessors for name and description of entries. These are
- // used to generate help for command-line options.
- static const char *nameof(const entry &Entry) { return Entry.getName(); }
- static const char *descof(const entry &Entry) { return Entry.getDesc(); }
- };
-
/// A global registry used in conjunction with static constructors to make
/// pluggable components (like targets or garbage collectors) "just work" when
/// linked with an executable.
- template <typename T, typename U = RegistryTraits<T> >
+ template <typename T>
class Registry {
public:
- typedef U traits;
- typedef typename U::entry entry;
+ typedef SimpleRegistryEntry<T> entry;
class node;
- class listener;
class iterator;
private:
Registry() = delete;
- static void Announce(const entry &E) {
- for (listener *Cur = ListenerHead; Cur; Cur = Cur->Next)
- Cur->registered(E);
- }
-
friend class node;
static node *Head, *Tail;
- friend class listener;
- static listener *ListenerHead, *ListenerTail;
-
public:
/// Node in linked list of entries.
///
class node {
friend class iterator;
+ friend Registry<T>;
node *Next;
const entry& Val;
public:
- node(const entry& V) : Next(nullptr), Val(V) {
- if (Tail)
- Tail->Next = this;
- else
- Head = this;
- Tail = this;
-
- Announce(V);
- }
+ node(const entry &V) : Next(nullptr), Val(V) {}
};
+ static void add_node(node *N) {
+ if (Tail)
+ Tail->Next = N;
+ else
+ Head = N;
+ Tail = N;
+ }
+
/// Iterators for registry entries.
///
class iterator {
@@ -122,60 +99,6 @@ namespace llvm {
return make_range(begin(), end());
}
- /// Abstract base class for registry listeners, which are informed when new
- /// entries are added to the registry. Simply subclass and instantiate:
- ///
- /// \code
- /// class CollectorPrinter : public Registry<Collector>::listener {
- /// protected:
- /// void registered(const Registry<Collector>::entry &e) {
- /// cerr << "collector now available: " << e->getName() << "\n";
- /// }
- ///
- /// public:
- /// CollectorPrinter() { init(); } // Print those already registered.
- /// };
- ///
- /// CollectorPrinter Printer;
- /// \endcode
- class listener {
- listener *Prev, *Next;
-
- friend void Registry::Announce(const entry &E);
-
- protected:
- /// Called when an entry is added to the registry.
- ///
- virtual void registered(const entry &) = 0;
-
- /// Calls 'registered' for each pre-existing entry.
- ///
- void init() {
- for (iterator I = begin(), E = end(); I != E; ++I)
- registered(*I);
- }
-
- public:
- listener() : Prev(ListenerTail), Next(nullptr) {
- if (Prev)
- Prev->Next = this;
- else
- ListenerHead = this;
- ListenerTail = this;
- }
-
- virtual ~listener() {
- if (Next)
- Next->Prev = Prev;
- else
- ListenerTail = Prev;
- if (Prev)
- Prev->Next = Next;
- else
- ListenerHead = Next;
- }
- };
-
/// A static registration template. Use like such:
///
/// Registry<Collector>::Add<FancyGC>
@@ -184,14 +107,6 @@ namespace llvm {
/// Use of this template requires that:
///
/// 1. The registered subclass has a default constructor.
- //
- /// 2. The registry entry type has a constructor compatible with this
- /// signature:
- ///
- /// entry(const char *Name, const char *ShortDesc, T *(*Ctor)());
- ///
- /// If you have more elaborate requirements, then copy and modify.
- ///
template <typename V>
class Add {
entry Entry;
@@ -201,27 +116,65 @@ namespace llvm {
public:
Add(const char *Name, const char *Desc)
- : Entry(Name, Desc, CtorFn), Node(Entry) {}
+ : Entry(Name, Desc, CtorFn), Node(Entry) {
+ add_node(&Node);
+ }
};
- /// Registry::Parser now lives in llvm/Support/RegistryParser.h.
+ /// A dynamic import facility. This is used on Windows to
+ /// import the entries added in the plugin.
+ static void import(sys::DynamicLibrary &DL, const char *RegistryName) {
+ typedef void *(*GetRegistry)();
+ std::string Name("LLVMGetRegistry_");
+ Name.append(RegistryName);
+ GetRegistry Getter =
+ (GetRegistry)(intptr_t)DL.getAddressOfSymbol(Name.c_str());
+ if (Getter) {
+ // Call the getter function in order to get the full copy of the
+ // registry defined in the plugin DLL, and copy them over to the
+ // current Registry.
+ typedef std::pair<const node *, const node *> Info;
+ Info *I = static_cast<Info *>(Getter());
+ iterator begin(I->first);
+ iterator end(I->second);
+ for (++end; begin != end; ++begin) {
+ // This Node object needs to remain alive for the
+ // duration of the program.
+ add_node(new node(*begin));
+ }
+ }
+ }
+
+ /// Retrieve the data to be passed across DLL boundaries when
+ /// importing registries from another DLL on Windows.
+ static void *exportRegistry() {
+ static std::pair<const node *, const node *> Info(Head, Tail);
+ return &Info;
+ }
};
+
// Since these are defined in a header file, plugins must be sure to export
// these symbols.
+ template <typename T>
+ typename Registry<T>::node *Registry<T>::Head;
- template <typename T, typename U>
- typename Registry<T,U>::node *Registry<T,U>::Head;
-
- template <typename T, typename U>
- typename Registry<T,U>::node *Registry<T,U>::Tail;
-
- template <typename T, typename U>
- typename Registry<T,U>::listener *Registry<T,U>::ListenerHead;
-
- template <typename T, typename U>
- typename Registry<T,U>::listener *Registry<T,U>::ListenerTail;
-
+ template <typename T>
+ typename Registry<T>::node *Registry<T>::Tail;
} // end namespace llvm
+#ifdef LLVM_ON_WIN32
+#define LLVM_EXPORT_REGISTRY(REGISTRY_CLASS) \
+ extern "C" { \
+ __declspec(dllexport) void *__cdecl LLVMGetRegistry_##REGISTRY_CLASS() { \
+ return REGISTRY_CLASS::exportRegistry(); \
+ } \
+ }
+#define LLVM_IMPORT_REGISTRY(REGISTRY_CLASS, DL) \
+ REGISTRY_CLASS::import(DL, #REGISTRY_CLASS)
+#else
+#define LLVM_EXPORT_REGISTRY(REGISTRY_CLASS)
+#define LLVM_IMPORT_REGISTRY(REGISTRY_CLASS, DL)
+#endif
+
#endif // LLVM_SUPPORT_REGISTRY_H
diff --git a/include/llvm/Support/RegistryParser.h b/include/llvm/Support/RegistryParser.h
deleted file mode 100644
index a6997b6fe774..000000000000
--- a/include/llvm/Support/RegistryParser.h
+++ /dev/null
@@ -1,55 +0,0 @@
-//=== RegistryParser.h - Linker-supported plugin registries -----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Defines a command-line parser for a registry.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_SUPPORT_REGISTRYPARSER_H
-#define LLVM_SUPPORT_REGISTRYPARSER_H
-
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Registry.h"
-
-namespace llvm {
-
- /// A command-line parser for a registry. Use like such:
- ///
- /// static cl::opt<Registry<Collector>::entry, false,
- /// RegistryParser<Collector> >
- /// GCOpt("gc", cl::desc("Garbage collector to use."),
- /// cl::value_desc());
- ///
- /// To make use of the value:
- ///
- /// Collector *TheCollector = GCOpt->instantiate();
- ///
- template <typename T, typename U = RegistryTraits<T> >
- class RegistryParser :
- public cl::parser<const typename U::entry*>,
- public Registry<T, U>::listener {
- typedef U traits;
- typedef typename U::entry entry;
- typedef typename Registry<T, U>::listener listener;
-
- protected:
- void registered(const entry &E) {
- addLiteralOption(traits::nameof(E), &E, traits::descof(E));
- }
-
- public:
- void initialize(cl::Option &O) {
- listener::init();
- cl::parser<const typename U::entry*>::initialize(O);
- }
- };
-
-}
-
-#endif // LLVM_SUPPORT_REGISTRYPARSER_H
diff --git a/include/llvm/Support/SHA1.h b/include/llvm/Support/SHA1.h
new file mode 100644
index 000000000000..8347a713f272
--- /dev/null
+++ b/include/llvm/Support/SHA1.h
@@ -0,0 +1,82 @@
+//==- SHA1.h - SHA1 implementation for LLVM --*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// This code is taken from public domain
+// (http://oauth.googlecode.com/svn/code/c/liboauth/src/sha1.c)
+// and modified by wrapping it in a C++ interface for LLVM,
+// and removing unnecessary code.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_SHA1_H
+#define LLVM_SUPPORT_SHA1_H
+
+#include "llvm/ADT/ArrayRef.h"
+
+#include <cstdint>
+
+namespace llvm {
+template <typename T> class ArrayRef;
+class StringRef;
+
+/// A class that wrap the SHA1 algorithm.
+class SHA1 {
+public:
+ SHA1() { init(); }
+
+ /// Reinitialize the internal state
+ void init();
+
+ /// Digest more data.
+ void update(ArrayRef<uint8_t> Data);
+
+ /// Digest more data.
+ void update(StringRef Str) {
+ update(ArrayRef<uint8_t>((uint8_t *)const_cast<char *>(Str.data()),
+ Str.size()));
+ }
+
+ /// Return a reference to the current raw 160-bits SHA1 for the digested data
+ /// since the last call to init(). This call will add data to the internal
+ /// state and as such is not suited for getting an intermediate result
+ /// (see result()).
+ StringRef final();
+
+ /// Return a reference to the current raw 160-bits SHA1 for the digested data
+ /// since the last call to init(). This is suitable for getting the SHA1 at
+ /// any time without invalidating the internal state so that more calls can be
+ /// made into update.
+ StringRef result();
+
+private:
+ /// Define some constants.
+ /// "static constexpr" would be cleaner but MSVC does not support it yet.
+ enum { BLOCK_LENGTH = 64 };
+ enum { HASH_LENGTH = 20 };
+
+ // Internal State
+ struct {
+ uint32_t Buffer[BLOCK_LENGTH / 4];
+ uint32_t State[HASH_LENGTH / 4];
+ uint32_t ByteCount;
+ uint8_t BufferOffset;
+ } InternalState;
+
+ // Internal copy of the hash, populated and accessed on calls to result()
+ uint32_t HashResult[HASH_LENGTH / 4];
+
+ // Helper
+ void writebyte(uint8_t data);
+ void hashBlock();
+ void addUncounted(uint8_t data);
+ void pad();
+};
+
+} // end llvm namespace
+
+#endif
diff --git a/include/llvm/Support/ScaledNumber.h b/include/llvm/Support/ScaledNumber.h
index c6421efc8b49..910174732994 100644
--- a/include/llvm/Support/ScaledNumber.h
+++ b/include/llvm/Support/ScaledNumber.h
@@ -859,7 +859,6 @@ template <class DigitsT> void ScaledNumber<DigitsT>::shiftLeft(int32_t Shift) {
}
Digits <<= Shift;
- return;
}
template <class DigitsT> void ScaledNumber<DigitsT>::shiftRight(int32_t Shift) {
@@ -886,7 +885,6 @@ template <class DigitsT> void ScaledNumber<DigitsT>::shiftRight(int32_t Shift) {
}
Digits >>= Shift;
- return;
}
template <typename T> struct isPodLike;
@@ -896,4 +894,4 @@ template <typename T> struct isPodLike<ScaledNumber<T>> {
} // end namespace llvm
-#endif
+#endif // LLVM_SUPPORT_SCALEDNUMBER_H
diff --git a/include/llvm/Support/ScopedPrinter.h b/include/llvm/Support/ScopedPrinter.h
new file mode 100644
index 000000000000..a2f2e0985431
--- /dev/null
+++ b/include/llvm/Support/ScopedPrinter.h
@@ -0,0 +1,378 @@
+//===-- ScopedPrinter.h ---------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_SCOPEDPRINTER_H
+#define LLVM_SUPPORT_SCOPEDPRINTER_H
+
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+
+namespace llvm {
+
+template <typename T> struct EnumEntry {
+ StringRef Name;
+ // While Name suffices in most of the cases, in certain cases
+ // GNU style and LLVM style of ELFDumper do not
+ // display same string for same enum. The AltName if initialized appropriately
+ // will hold the string that GNU style emits.
+ // Example:
+ // "EM_X86_64" string on LLVM style for Elf_Ehdr->e_machine corresponds to
+ // "Advanced Micro Devices X86-64" on GNU style
+ StringRef AltName;
+ T Value;
+ EnumEntry(StringRef N, StringRef A, T V) : Name(N), AltName(A), Value(V) {}
+ EnumEntry(StringRef N, T V) : Name(N), AltName(N), Value(V) {}
+};
+
+struct HexNumber {
+ // To avoid sign-extension we have to explicitly cast to the appropriate
+ // unsigned type. The overloads are here so that every type that is implicitly
+ // convertible to an integer (including enums and endian helpers) can be used
+ // without requiring type traits or call-site changes.
+ HexNumber(char Value) : Value(static_cast<unsigned char>(Value)) {}
+ HexNumber(signed char Value) : Value(static_cast<unsigned char>(Value)) {}
+ HexNumber(signed short Value) : Value(static_cast<unsigned short>(Value)) {}
+ HexNumber(signed int Value) : Value(static_cast<unsigned int>(Value)) {}
+ HexNumber(signed long Value) : Value(static_cast<unsigned long>(Value)) {}
+ HexNumber(signed long long Value)
+ : Value(static_cast<unsigned long long>(Value)) {}
+ HexNumber(unsigned char Value) : Value(Value) {}
+ HexNumber(unsigned short Value) : Value(Value) {}
+ HexNumber(unsigned int Value) : Value(Value) {}
+ HexNumber(unsigned long Value) : Value(Value) {}
+ HexNumber(unsigned long long Value) : Value(Value) {}
+ uint64_t Value;
+};
+
+raw_ostream &operator<<(raw_ostream &OS, const HexNumber &Value);
+const std::string to_hexString(uint64_t Value, bool UpperCase = true);
+
+template <class T> const std::string to_string(const T &Value) {
+ std::string number;
+ llvm::raw_string_ostream stream(number);
+ stream << Value;
+ return stream.str();
+}
+
+class ScopedPrinter {
+public:
+ ScopedPrinter(raw_ostream &OS) : OS(OS), IndentLevel(0) {}
+
+ void flush() { OS.flush(); }
+
+ void indent(int Levels = 1) { IndentLevel += Levels; }
+
+ void unindent(int Levels = 1) {
+ IndentLevel = std::max(0, IndentLevel - Levels);
+ }
+
+ void resetIndent() { IndentLevel = 0; }
+
+ void setPrefix(StringRef P) { Prefix = P; }
+
+ void printIndent() {
+ OS << Prefix;
+ for (int i = 0; i < IndentLevel; ++i)
+ OS << " ";
+ }
+
+ template <typename T> HexNumber hex(T Value) { return HexNumber(Value); }
+
+ template <typename T, typename TEnum>
+ void printEnum(StringRef Label, T Value,
+ ArrayRef<EnumEntry<TEnum>> EnumValues) {
+ StringRef Name;
+ bool Found = false;
+ for (const auto &EnumItem : EnumValues) {
+ if (EnumItem.Value == Value) {
+ Name = EnumItem.Name;
+ Found = true;
+ break;
+ }
+ }
+
+ if (Found) {
+ startLine() << Label << ": " << Name << " (" << hex(Value) << ")\n";
+ } else {
+ startLine() << Label << ": " << hex(Value) << "\n";
+ }
+ }
+
+ template <typename T, typename TFlag>
+ void printFlags(StringRef Label, T Value, ArrayRef<EnumEntry<TFlag>> Flags,
+ TFlag EnumMask1 = {}, TFlag EnumMask2 = {},
+ TFlag EnumMask3 = {}) {
+ typedef EnumEntry<TFlag> FlagEntry;
+ typedef SmallVector<FlagEntry, 10> FlagVector;
+ FlagVector SetFlags;
+
+ for (const auto &Flag : Flags) {
+ if (Flag.Value == 0)
+ continue;
+
+ TFlag EnumMask{};
+ if (Flag.Value & EnumMask1)
+ EnumMask = EnumMask1;
+ else if (Flag.Value & EnumMask2)
+ EnumMask = EnumMask2;
+ else if (Flag.Value & EnumMask3)
+ EnumMask = EnumMask3;
+ bool IsEnum = (Flag.Value & EnumMask) != 0;
+ if ((!IsEnum && (Value & Flag.Value) == Flag.Value) ||
+ (IsEnum && (Value & EnumMask) == Flag.Value)) {
+ SetFlags.push_back(Flag);
+ }
+ }
+
+ std::sort(SetFlags.begin(), SetFlags.end(), &flagName<TFlag>);
+
+ startLine() << Label << " [ (" << hex(Value) << ")\n";
+ for (const auto &Flag : SetFlags) {
+ startLine() << " " << Flag.Name << " (" << hex(Flag.Value) << ")\n";
+ }
+ startLine() << "]\n";
+ }
+
+ template <typename T> void printFlags(StringRef Label, T Value) {
+ startLine() << Label << " [ (" << hex(Value) << ")\n";
+ uint64_t Flag = 1;
+ uint64_t Curr = Value;
+ while (Curr > 0) {
+ if (Curr & 1)
+ startLine() << " " << hex(Flag) << "\n";
+ Curr >>= 1;
+ Flag <<= 1;
+ }
+ startLine() << "]\n";
+ }
+
+ void printNumber(StringRef Label, uint64_t Value) {
+ startLine() << Label << ": " << Value << "\n";
+ }
+
+ void printNumber(StringRef Label, uint32_t Value) {
+ startLine() << Label << ": " << Value << "\n";
+ }
+
+ void printNumber(StringRef Label, uint16_t Value) {
+ startLine() << Label << ": " << Value << "\n";
+ }
+
+ void printNumber(StringRef Label, uint8_t Value) {
+ startLine() << Label << ": " << unsigned(Value) << "\n";
+ }
+
+ void printNumber(StringRef Label, int64_t Value) {
+ startLine() << Label << ": " << Value << "\n";
+ }
+
+ void printNumber(StringRef Label, int32_t Value) {
+ startLine() << Label << ": " << Value << "\n";
+ }
+
+ void printNumber(StringRef Label, int16_t Value) {
+ startLine() << Label << ": " << Value << "\n";
+ }
+
+ void printNumber(StringRef Label, int8_t Value) {
+ startLine() << Label << ": " << int(Value) << "\n";
+ }
+
+ void printNumber(StringRef Label, const APSInt &Value) {
+ startLine() << Label << ": " << Value << "\n";
+ }
+
+ void printBoolean(StringRef Label, bool Value) {
+ startLine() << Label << ": " << (Value ? "Yes" : "No") << '\n';
+ }
+
+ template <typename... T> void printVersion(StringRef Label, T... Version) {
+ startLine() << Label << ": ";
+ printVersionInternal(Version...);
+ getOStream() << "\n";
+ }
+
+ template <typename T> void printList(StringRef Label, const T &List) {
+ startLine() << Label << ": [";
+ bool Comma = false;
+ for (const auto &Item : List) {
+ if (Comma)
+ OS << ", ";
+ OS << Item;
+ Comma = true;
+ }
+ OS << "]\n";
+ }
+
+ template <typename T, typename U>
+ void printList(StringRef Label, const T &List, const U &Printer) {
+ startLine() << Label << ": [";
+ bool Comma = false;
+ for (const auto &Item : List) {
+ if (Comma)
+ OS << ", ";
+ Printer(OS, Item);
+ Comma = true;
+ }
+ OS << "]\n";
+ }
+
+ template <typename T> void printHexList(StringRef Label, const T &List) {
+ startLine() << Label << ": [";
+ bool Comma = false;
+ for (const auto &Item : List) {
+ if (Comma)
+ OS << ", ";
+ OS << hex(Item);
+ Comma = true;
+ }
+ OS << "]\n";
+ }
+
+ template <typename T> void printHex(StringRef Label, T Value) {
+ startLine() << Label << ": " << hex(Value) << "\n";
+ }
+
+ template <typename T> void printHex(StringRef Label, StringRef Str, T Value) {
+ startLine() << Label << ": " << Str << " (" << hex(Value) << ")\n";
+ }
+
+ template <typename T>
+ void printSymbolOffset(StringRef Label, StringRef Symbol, T Value) {
+ startLine() << Label << ": " << Symbol << '+' << hex(Value) << '\n';
+ }
+
+ void printString(StringRef Value) { startLine() << Value << "\n"; }
+
+ void printString(StringRef Label, StringRef Value) {
+ startLine() << Label << ": " << Value << "\n";
+ }
+
+ void printString(StringRef Label, const std::string &Value) {
+ startLine() << Label << ": " << Value << "\n";
+ }
+
+ template <typename T>
+ void printNumber(StringRef Label, StringRef Str, T Value) {
+ startLine() << Label << ": " << Str << " (" << Value << ")\n";
+ }
+
+ void printBinary(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value) {
+ printBinaryImpl(Label, Str, Value, false);
+ }
+
+ void printBinary(StringRef Label, StringRef Str, ArrayRef<char> Value) {
+ auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
+ Value.size());
+ printBinaryImpl(Label, Str, V, false);
+ }
+
+ void printBinary(StringRef Label, ArrayRef<uint8_t> Value) {
+ printBinaryImpl(Label, StringRef(), Value, false);
+ }
+
+ void printBinary(StringRef Label, ArrayRef<char> Value) {
+ auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
+ Value.size());
+ printBinaryImpl(Label, StringRef(), V, false);
+ }
+
+ void printBinary(StringRef Label, StringRef Value) {
+ auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
+ Value.size());
+ printBinaryImpl(Label, StringRef(), V, false);
+ }
+
+ void printBinaryBlock(StringRef Label, ArrayRef<uint8_t> Value) {
+ printBinaryImpl(Label, StringRef(), Value, true);
+ }
+
+ void printBinaryBlock(StringRef Label, StringRef Value) {
+ auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
+ Value.size());
+ printBinaryImpl(Label, StringRef(), V, true);
+ }
+
+ template <typename T> void printObject(StringRef Label, const T &Value) {
+ startLine() << Label << ": " << Value << "\n";
+ }
+
+ raw_ostream &startLine() {
+ printIndent();
+ return OS;
+ }
+
+ raw_ostream &getOStream() { return OS; }
+
+private:
+ template <typename T> void printVersionInternal(T Value) {
+ getOStream() << Value;
+ }
+
+ template <typename S, typename T, typename... TArgs>
+ void printVersionInternal(S Value, T Value2, TArgs... Args) {
+ getOStream() << Value << ".";
+ printVersionInternal(Value2, Args...);
+ }
+
+ template <typename T>
+ static bool flagName(const EnumEntry<T> &lhs, const EnumEntry<T> &rhs) {
+ return lhs.Name < rhs.Name;
+ }
+
+ void printBinaryImpl(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value,
+ bool Block);
+
+ raw_ostream &OS;
+ int IndentLevel;
+ StringRef Prefix;
+};
+
+template <>
+inline void
+ScopedPrinter::printHex<support::ulittle16_t>(StringRef Label,
+ support::ulittle16_t Value) {
+ startLine() << Label << ": " << hex(Value) << "\n";
+}
+
+template<char Open, char Close>
+struct DelimitedScope {
+ explicit DelimitedScope(ScopedPrinter &W) : W(W) {
+ W.startLine() << Open << '\n';
+ W.indent();
+ }
+
+ DelimitedScope(ScopedPrinter &W, StringRef N) : W(W) {
+ W.startLine() << N;
+ if (!N.empty())
+ W.getOStream() << ' ';
+ W.getOStream() << Open << '\n';
+ W.indent();
+ }
+
+ ~DelimitedScope() {
+ W.unindent();
+ W.startLine() << Close << '\n';
+ }
+
+ ScopedPrinter &W;
+};
+
+using DictScope = DelimitedScope<'{', '}'>;
+using ListScope = DelimitedScope<'[', ']'>;
+
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/Support/Signals.h b/include/llvm/Support/Signals.h
index 2a4d84bd891a..cbd6f686a778 100644
--- a/include/llvm/Support/Signals.h
+++ b/include/llvm/Support/Signals.h
@@ -38,8 +38,14 @@ namespace sys {
/// When an error signal (such as SIBABRT or SIGSEGV) is delivered to the
/// process, print a stack trace and then exit.
- /// @brief Print a stack trace if a fatal signal occurs.
- void PrintStackTraceOnErrorSignal(bool DisableCrashReporting = false);
+ /// \brief Print a stack trace if a fatal signal occurs.
+ /// \param Argv0 the current binary name, used to find the symbolizer
+ /// relative to the current binary before searching $PATH; can be
+ /// StringRef(), in which case we will only search $PATH.
+ /// \param DisableCrashReporting if \c true, disable the normal crash
+ /// reporting mechanisms on the underlying operating system.
+ void PrintStackTraceOnErrorSignal(StringRef Argv0,
+ bool DisableCrashReporting = false);
/// Disable all system dialog boxes that appear when the process crashes.
void DisableSystemDialogsOnCrash();
diff --git a/include/llvm/Support/StreamingMemoryObject.h b/include/llvm/Support/StreamingMemoryObject.h
index a5980c235946..1ab85372cd20 100644
--- a/include/llvm/Support/StreamingMemoryObject.h
+++ b/include/llvm/Support/StreamingMemoryObject.h
@@ -28,15 +28,7 @@ public:
uint64_t getExtent() const override;
uint64_t readBytes(uint8_t *Buf, uint64_t Size,
uint64_t Address) const override;
- const uint8_t *getPointer(uint64_t address, uint64_t size) const override {
- // FIXME: This could be fixed by ensuring the bytes are fetched and
- // making a copy, requiring that the bitcode size be known, or
- // otherwise ensuring that the memory doesn't go away/get reallocated,
- // but it's not currently necessary. Users that need the pointer (any
- // that need Blobs) don't stream.
- report_fatal_error("getPointer in streaming memory objects not allowed");
- return nullptr;
- }
+ const uint8_t *getPointer(uint64_t Address, uint64_t Size) const override;
bool isValidAddress(uint64_t address) const override;
/// Drop s bytes from the front of the stream, pushing the positions of the
diff --git a/include/llvm/Support/SwapByteOrder.h b/include/llvm/Support/SwapByteOrder.h
index 7761fa1d7e01..91693aceb27d 100644
--- a/include/llvm/Support/SwapByteOrder.h
+++ b/include/llvm/Support/SwapByteOrder.h
@@ -18,7 +18,6 @@
#include "llvm/Support/Compiler.h"
#include "llvm/Support/DataTypes.h"
#include <cstddef>
-#include <limits>
namespace llvm {
namespace sys {
diff --git a/include/llvm/Support/TargetParser.h b/include/llvm/Support/TargetParser.h
index c21019d0c5b8..0e2141f6d46f 100644
--- a/include/llvm/Support/TargetParser.h
+++ b/include/llvm/Support/TargetParser.h
@@ -83,6 +83,7 @@ enum ArchExtKind : unsigned {
AEK_VIRT = 0x200,
AEK_DSP = 0x400,
AEK_FP16 = 0x800,
+ AEK_RAS = 0x1000,
// Unsupported extensions.
AEK_OS = 0x8000000,
AEK_IWMMXT = 0x10000000,
@@ -140,6 +141,61 @@ unsigned parseArchProfile(StringRef Arch);
unsigned parseArchVersion(StringRef Arch);
} // namespace ARM
+
+// FIXME:This should be made into class design,to avoid dupplication.
+namespace AArch64 {
+
+// Arch extension modifiers for CPUs.
+enum ArchExtKind : unsigned {
+ AEK_INVALID = 0x0,
+ AEK_NONE = 0x1,
+ AEK_CRC = 0x2,
+ AEK_CRYPTO = 0x4,
+ AEK_FP = 0x8,
+ AEK_SIMD = 0x10,
+ AEK_FP16 = 0x20,
+ AEK_PROFILE = 0x40,
+ AEK_RAS = 0x80
+};
+
+StringRef getCanonicalArchName(StringRef Arch);
+
+// Information by ID
+StringRef getFPUName(unsigned FPUKind);
+unsigned getFPUVersion(unsigned FPUKind);
+unsigned getFPUNeonSupportLevel(unsigned FPUKind);
+unsigned getFPURestriction(unsigned FPUKind);
+
+// FIXME: These should be moved to TargetTuple once it exists
+bool getFPUFeatures(unsigned FPUKind, std::vector<const char *> &Features);
+bool getExtensionFeatures(unsigned Extensions,
+ std::vector<const char*> &Features);
+bool getArchFeatures(unsigned ArchKind, std::vector<const char *> &Features);
+
+StringRef getArchName(unsigned ArchKind);
+unsigned getArchAttr(unsigned ArchKind);
+StringRef getCPUAttr(unsigned ArchKind);
+StringRef getSubArch(unsigned ArchKind);
+StringRef getArchExtName(unsigned ArchExtKind);
+const char *getArchExtFeature(StringRef ArchExt);
+unsigned checkArchVersion(StringRef Arch);
+
+// Information by Name
+unsigned getDefaultFPU(StringRef CPU, unsigned ArchKind);
+unsigned getDefaultExtensions(StringRef CPU, unsigned ArchKind);
+StringRef getDefaultCPU(StringRef Arch);
+
+// Parser
+unsigned parseFPU(StringRef FPU);
+unsigned parseArch(StringRef Arch);
+unsigned parseArchExt(StringRef ArchExt);
+unsigned parseCPUArch(StringRef CPU);
+unsigned parseArchISA(StringRef Arch);
+unsigned parseArchEndian(StringRef Arch);
+unsigned parseArchProfile(StringRef Arch);
+unsigned parseArchVersion(StringRef Arch);
+
+} // namespace AArch64
} // namespace llvm
#endif
diff --git a/include/llvm/Support/TargetRegistry.h b/include/llvm/Support/TargetRegistry.h
index aec181b1d266..076558e4df77 100644
--- a/include/llvm/Support/TargetRegistry.h
+++ b/include/llvm/Support/TargetRegistry.h
@@ -20,6 +20,7 @@
#define LLVM_SUPPORT_TARGETREGISTRY_H
#include "llvm-c/Disassembler.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/FormattedStream.h"
@@ -33,7 +34,6 @@ class MCAsmBackend;
class MCAsmInfo;
class MCAsmParser;
class MCCodeEmitter;
-class MCCodeGenInfo;
class MCContext;
class MCDisassembler;
class MCInstrAnalysis;
@@ -92,10 +92,9 @@ public:
typedef MCAsmInfo *(*MCAsmInfoCtorFnTy)(const MCRegisterInfo &MRI,
const Triple &TT);
- typedef MCCodeGenInfo *(*MCCodeGenInfoCtorFnTy)(const Triple &TT,
- Reloc::Model RM,
- CodeModel::Model CM,
- CodeGenOpt::Level OL);
+ typedef void (*MCAdjustCodeGenOptsFnTy)(const Triple &TT, Reloc::Model RM,
+ CodeModel::Model &CM);
+
typedef MCInstrInfo *(*MCInstrInfoCtorFnTy)(void);
typedef MCInstrAnalysis *(*MCInstrAnalysisCtorFnTy)(const MCInstrInfo *Info);
typedef MCRegisterInfo *(*MCRegInfoCtorFnTy)(const Triple &TT);
@@ -104,8 +103,8 @@ public:
StringRef Features);
typedef TargetMachine *(*TargetMachineCtorTy)(
const Target &T, const Triple &TT, StringRef CPU, StringRef Features,
- const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM,
- CodeGenOpt::Level OL);
+ const TargetOptions &Options, Optional<Reloc::Model> RM,
+ CodeModel::Model CM, CodeGenOpt::Level OL);
// If it weren't for layering issues (this header is in llvm/Support, but
// depends on MC?) this should take the Streamer by value rather than rvalue
// reference.
@@ -177,9 +176,7 @@ private:
/// registered.
MCAsmInfoCtorFnTy MCAsmInfoCtorFn;
- /// MCCodeGenInfoCtorFn - Constructor function for this target's
- /// MCCodeGenInfo, if registered.
- MCCodeGenInfoCtorFnTy MCCodeGenInfoCtorFn;
+ MCAdjustCodeGenOptsFnTy MCAdjustCodeGenOptsFn;
/// MCInstrInfoCtorFn - Constructor function for this target's MCInstrInfo,
/// if registered.
@@ -300,14 +297,10 @@ public:
return MCAsmInfoCtorFn(MRI, Triple(TheTriple));
}
- /// createMCCodeGenInfo - Create a MCCodeGenInfo implementation.
- ///
- MCCodeGenInfo *createMCCodeGenInfo(StringRef TT, Reloc::Model RM,
- CodeModel::Model CM,
- CodeGenOpt::Level OL) const {
- if (!MCCodeGenInfoCtorFn)
- return nullptr;
- return MCCodeGenInfoCtorFn(Triple(TT), RM, CM, OL);
+ void adjustCodeGenOpts(const Triple &TT, Reloc::Model RM,
+ CodeModel::Model &CM) const {
+ if (MCAdjustCodeGenOptsFn)
+ MCAdjustCodeGenOptsFn(TT, RM, CM);
}
/// createMCInstrInfo - Create a MCInstrInfo implementation.
@@ -359,8 +352,7 @@ public:
/// host if that does not exist.
TargetMachine *
createTargetMachine(StringRef TT, StringRef CPU, StringRef Features,
- const TargetOptions &Options,
- Reloc::Model RM = Reloc::Default,
+ const TargetOptions &Options, Optional<Reloc::Model> RM,
CodeModel::Model CM = CodeModel::Default,
CodeGenOpt::Level OL = CodeGenOpt::Default) const {
if (!TargetMachineCtorFn)
@@ -646,18 +638,9 @@ struct TargetRegistry {
T.MCAsmInfoCtorFn = Fn;
}
- /// RegisterMCCodeGenInfo - Register a MCCodeGenInfo implementation for the
- /// given target.
- ///
- /// Clients are responsible for ensuring that registration doesn't occur
- /// while another thread is attempting to access the registry. Typically
- /// this is done by initializing all targets at program startup.
- ///
- /// @param T - The target being registered.
- /// @param Fn - A function to construct a MCCodeGenInfo for the target.
- static void RegisterMCCodeGenInfo(Target &T,
- Target::MCCodeGenInfoCtorFnTy Fn) {
- T.MCCodeGenInfoCtorFn = Fn;
+ static void registerMCAdjustCodeGenOpts(Target &T,
+ Target::MCAdjustCodeGenOptsFnTy Fn) {
+ T.MCAdjustCodeGenOptsFn = Fn;
}
/// RegisterMCInstrInfo - Register a MCInstrInfo implementation for the
@@ -914,39 +897,9 @@ struct RegisterMCAsmInfoFn {
}
};
-/// RegisterMCCodeGenInfo - Helper template for registering a target codegen
-/// info
-/// implementation. This invokes the static "Create" method on the class
-/// to actually do the construction. Usage:
-///
-/// extern "C" void LLVMInitializeFooTarget() {
-/// extern Target TheFooTarget;
-/// RegisterMCCodeGenInfo<FooMCCodeGenInfo> X(TheFooTarget);
-/// }
-template <class MCCodeGenInfoImpl> struct RegisterMCCodeGenInfo {
- RegisterMCCodeGenInfo(Target &T) {
- TargetRegistry::RegisterMCCodeGenInfo(T, &Allocator);
- }
-
-private:
- static MCCodeGenInfo *Allocator(const Triple & /*TT*/, Reloc::Model /*RM*/,
- CodeModel::Model /*CM*/,
- CodeGenOpt::Level /*OL*/) {
- return new MCCodeGenInfoImpl();
- }
-};
-
-/// RegisterMCCodeGenInfoFn - Helper template for registering a target codegen
-/// info implementation. This invokes the specified function to do the
-/// construction. Usage:
-///
-/// extern "C" void LLVMInitializeFooTarget() {
-/// extern Target TheFooTarget;
-/// RegisterMCCodeGenInfoFn X(TheFooTarget, TheFunction);
-/// }
-struct RegisterMCCodeGenInfoFn {
- RegisterMCCodeGenInfoFn(Target &T, Target::MCCodeGenInfoCtorFnTy Fn) {
- TargetRegistry::RegisterMCCodeGenInfo(T, Fn);
+struct RegisterMCAdjustCodeGenOptsFn {
+ RegisterMCAdjustCodeGenOptsFn(Target &T, Target::MCAdjustCodeGenOptsFnTy Fn) {
+ TargetRegistry::registerMCAdjustCodeGenOpts(T, Fn);
}
};
@@ -1097,7 +1050,8 @@ template <class TargetMachineImpl> struct RegisterTargetMachine {
private:
static TargetMachine *Allocator(const Target &T, const Triple &TT,
StringRef CPU, StringRef FS,
- const TargetOptions &Options, Reloc::Model RM,
+ const TargetOptions &Options,
+ Optional<Reloc::Model> RM,
CodeModel::Model CM, CodeGenOpt::Level OL) {
return new TargetMachineImpl(T, TT, CPU, FS, Options, RM, CM, OL);
}
diff --git a/include/llvm/Support/ThreadPool.h b/include/llvm/Support/ThreadPool.h
index 745334db4450..665cec2465bf 100644
--- a/include/llvm/Support/ThreadPool.h
+++ b/include/llvm/Support/ThreadPool.h
@@ -33,6 +33,7 @@
#pragma warning(pop)
#endif
+#include <atomic>
#include <condition_variable>
#include <functional>
#include <memory>
diff --git a/include/llvm/Support/Threading.h b/include/llvm/Support/Threading.h
index 9007c132a99a..09b96dfb4c1c 100644
--- a/include/llvm/Support/Threading.h
+++ b/include/llvm/Support/Threading.h
@@ -15,6 +15,27 @@
#ifndef LLVM_SUPPORT_THREADING_H
#define LLVM_SUPPORT_THREADING_H
+#include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX
+#include "llvm/Support/Compiler.h"
+#include <ciso646> // So we can check the C++ standard lib macros.
+#include <functional>
+
+// We use std::call_once on all Unix platforms except for NetBSD with
+// libstdc++. That platform has a bug they are working to fix, and they'll
+// remove the NetBSD checks once fixed.
+#if defined(LLVM_ON_UNIX) && \
+ !(defined(__NetBSD__) && !defined(_LIBCPP_VERSION)) && !defined(__ppc__)
+#define LLVM_THREADING_USE_STD_CALL_ONCE 1
+#else
+#define LLVM_THREADING_USE_STD_CALL_ONCE 0
+#endif
+
+#if LLVM_THREADING_USE_STD_CALL_ONCE
+#include <mutex>
+#else
+#include "llvm/Support/Atomic.h"
+#endif
+
namespace llvm {
/// Returns true if LLVM is compiled with support for multi-threading, and
/// false otherwise.
@@ -34,6 +55,66 @@ namespace llvm {
/// the thread stack.
void llvm_execute_on_thread(void (*UserFn)(void*), void *UserData,
unsigned RequestedStackSize = 0);
+
+#if LLVM_THREADING_USE_STD_CALL_ONCE
+
+ typedef std::once_flag once_flag;
+
+ /// This macro is the only way you should define your once flag for LLVM's
+ /// call_once.
+#define LLVM_DEFINE_ONCE_FLAG(flag) static once_flag flag
+
+#else
+
+ enum InitStatus { Uninitialized = 0, Wait = 1, Done = 2 };
+ typedef volatile sys::cas_flag once_flag;
+
+ /// This macro is the only way you should define your once flag for LLVM's
+ /// call_once.
+#define LLVM_DEFINE_ONCE_FLAG(flag) static once_flag flag = Uninitialized
+
+#endif
+
+ /// \brief Execute the function specified as a parameter once.
+ ///
+ /// Typical usage:
+ /// \code
+ /// void foo() {...};
+ /// ...
+ /// LLVM_DEFINE_ONCE_FLAG(flag);
+ /// call_once(flag, foo);
+ /// \endcode
+ ///
+ /// \param flag Flag used for tracking whether or not this has run.
+ /// \param F Function to call once.
+ template <typename Function, typename... Args>
+ void call_once(once_flag &flag, Function &&F, Args &&... ArgList) {
+#if LLVM_THREADING_USE_STD_CALL_ONCE
+ std::call_once(flag, std::forward<Function>(F),
+ std::forward<Args>(ArgList)...);
+#else
+ // For other platforms we use a generic (if brittle) version based on our
+ // atomics.
+ sys::cas_flag old_val = sys::CompareAndSwap(&flag, Wait, Uninitialized);
+ if (old_val == Uninitialized) {
+ std::forward<Function>(F)(std::forward<Args>(ArgList)...);
+ sys::MemoryFence();
+ TsanIgnoreWritesBegin();
+ TsanHappensBefore(&flag);
+ flag = Done;
+ TsanIgnoreWritesEnd();
+ } else {
+ // Wait until any thread doing the call has finished.
+ sys::cas_flag tmp = flag;
+ sys::MemoryFence();
+ while (tmp != Done) {
+ tmp = flag;
+ sys::MemoryFence();
+ }
+ }
+ TsanHappensAfter(&flag);
+#endif
+ }
}
#endif
diff --git a/include/llvm/Support/Timer.h b/include/llvm/Support/Timer.h
index 499fe7b7e70c..f0cb07599b86 100644
--- a/include/llvm/Support/Timer.h
+++ b/include/llvm/Support/Timer.h
@@ -104,6 +104,9 @@ public:
const std::string &getName() const { return Name; }
bool isInitialized() const { return TG != nullptr; }
+ /// Check if the timer is currently running.
+ bool isRunning() const { return Running; }
+
/// Check if startTimer() has ever been called on this timer.
bool hasTriggered() const { return Triggered; }
diff --git a/include/llvm/Support/TrailingObjects.h b/include/llvm/Support/TrailingObjects.h
index 8529746eeccc..5a21cddf9731 100644
--- a/include/llvm/Support/TrailingObjects.h
+++ b/include/llvm/Support/TrailingObjects.h
@@ -197,7 +197,7 @@ struct TrailingObjectsImpl<Align, BaseTy, TopTrailingObj, PrevTy, NextTy,
typename ExtractSecondType<MoreTys, size_t>::type... MoreCounts) {
return additionalSizeToAllocImpl(
(requiresRealignment()
- ? llvm::RoundUpToAlignment(SizeSoFar, llvm::alignOf<NextTy>())
+ ? llvm::alignTo(SizeSoFar, llvm::alignOf<NextTy>())
: SizeSoFar) +
sizeof(NextTy) * Count1,
MoreCounts...);
@@ -290,7 +290,7 @@ class TrailingObjects : private trailing_objects_internal::TrailingObjectsImpl<
}
public:
- // make this (privately inherited) class public.
+ // Make this (privately inherited) member public.
using ParentType::OverloadToken;
/// Returns a pointer to the trailing object array of the given type
@@ -342,6 +342,51 @@ public:
TrailingTys, size_t>::type... Counts) {
return sizeof(BaseTy) + ParentType::additionalSizeToAllocImpl(0, Counts...);
}
+
+ /// A type where its ::with_counts template member has a ::type member
+ /// suitable for use as uninitialized storage for an object with the given
+ /// trailing object counts. The template arguments are similar to those
+ /// of additionalSizeToAlloc.
+ ///
+ /// Use with FixedSizeStorageOwner, e.g.:
+ ///
+ /// \code{.cpp}
+ ///
+ /// MyObj::FixedSizeStorage<void *>::with_counts<1u>::type myStackObjStorage;
+ /// MyObj::FixedSizeStorageOwner
+ /// myStackObjOwner(new ((void *)&myStackObjStorage) MyObj);
+ /// MyObj *const myStackObjPtr = myStackObjOwner.get();
+ ///
+ /// \endcode
+ template <typename... Tys> struct FixedSizeStorage {
+ template <size_t... Counts> struct with_counts {
+ enum { Size = totalSizeToAlloc<Tys...>(Counts...) };
+ typedef llvm::AlignedCharArray<
+ llvm::AlignOf<BaseTy>::Alignment, Size
+ > type;
+ };
+ };
+
+ /// A type that acts as the owner for an object placed into fixed storage.
+ class FixedSizeStorageOwner {
+ public:
+ FixedSizeStorageOwner(BaseTy *p) : p(p) {}
+ ~FixedSizeStorageOwner() {
+ assert(p && "FixedSizeStorageOwner owns null?");
+ p->~BaseTy();
+ }
+
+ BaseTy *get() { return p; }
+ const BaseTy *get() const { return p; }
+
+ private:
+ FixedSizeStorageOwner(const FixedSizeStorageOwner &) = delete;
+ FixedSizeStorageOwner(FixedSizeStorageOwner &&) = delete;
+ FixedSizeStorageOwner &operator=(const FixedSizeStorageOwner &) = delete;
+ FixedSizeStorageOwner &operator=(FixedSizeStorageOwner &&) = delete;
+
+ BaseTy *const p;
+ };
};
} // end namespace llvm
diff --git a/include/llvm/Support/TypeName.h b/include/llvm/Support/TypeName.h
new file mode 100644
index 000000000000..0eb7ead98b21
--- /dev/null
+++ b/include/llvm/Support/TypeName.h
@@ -0,0 +1,65 @@
+//===- TypeName.h -----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_TYPENAME_H
+#define LLVM_SUPPORT_TYPENAME_H
+
+#include "llvm/ADT/StringRef.h"
+
+namespace llvm {
+
+/// We provide a function which tries to compute the (demangled) name of a type
+/// statically.
+///
+/// This routine may fail on some platforms or for particularly unusual types.
+/// Do not use it for anything other than logging and debugging aids. It isn't
+/// portable or dependendable in any real sense.
+///
+/// The returned StringRef will point into a static storage duration string.
+/// However, it may not be null terminated and may be some strangely aligned
+/// inner substring of a larger string.
+template <typename DesiredTypeName>
+inline StringRef getTypeName() {
+#if defined(__clang__) || defined(__GNUC__)
+ StringRef Name = __PRETTY_FUNCTION__;
+
+ StringRef Key = "DesiredTypeName = ";
+ Name = Name.substr(Name.find(Key));
+ assert(!Name.empty() && "Unable to find the template parameter!");
+ Name = Name.drop_front(Key.size());
+
+ assert(Name.endswith("]") && "Name doesn't end in the substitution key!");
+ return Name.drop_back(1);
+#elif defined(_MSC_VER)
+ StringRef Name = __FUNCSIG__;
+
+ StringRef Key = "getTypeName<";
+ Name = Name.substr(Name.find(Key));
+ assert(!Name.empty() && "Unable to find the function name!");
+ Name = Name.drop_front(Key.size());
+
+ for (StringRef Prefix : {"class ", "struct ", "union ", "enum "})
+ if (Name.startswith(Prefix)) {
+ Name = Name.drop_front(Prefix.size());
+ break;
+ }
+
+ auto AnglePos = Name.rfind('>');
+ assert(AnglePos != StringRef::npos && "Unable to find the closing '>'!");
+ return Name.substr(0, AnglePos);
+#else
+ // No known technique for statically extracting a type name on this compiler.
+ // We return a string that is unlikely to look like any type in LLVM.
+ return "UNKNOWN_TYPE";
+#endif
+}
+
+}
+
+#endif
diff --git a/include/llvm/Support/Unicode.h b/include/llvm/Support/Unicode.h
index f668a5bc88df..adedb1ed83a6 100644
--- a/include/llvm/Support/Unicode.h
+++ b/include/llvm/Support/Unicode.h
@@ -15,9 +15,9 @@
#ifndef LLVM_SUPPORT_UNICODE_H
#define LLVM_SUPPORT_UNICODE_H
-#include "llvm/ADT/StringRef.h"
-
namespace llvm {
+class StringRef;
+
namespace sys {
namespace unicode {
diff --git a/include/llvm/Support/Valgrind.h b/include/llvm/Support/Valgrind.h
index 12b0dc961daa..084b901b326c 100644
--- a/include/llvm/Support/Valgrind.h
+++ b/include/llvm/Support/Valgrind.h
@@ -1,4 +1,4 @@
-//===- llvm/Support/Valgrind.h - Communication with Valgrind -----*- C++ -*-===//
+//===- llvm/Support/Valgrind.h - Communication with Valgrind ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,9 +16,7 @@
#ifndef LLVM_SUPPORT_VALGRIND_H
#define LLVM_SUPPORT_VALGRIND_H
-#include "llvm/Config/llvm-config.h"
-#include "llvm/Support/Compiler.h"
-#include <stddef.h>
+#include <cstddef>
namespace llvm {
namespace sys {
@@ -28,7 +26,7 @@ namespace sys {
// Discard valgrind's translation of code in the range [Addr .. Addr + Len).
// Otherwise valgrind may continue to execute the old version of the code.
void ValgrindDiscardTranslations(const void *Addr, size_t Len);
-}
-}
+} // namespace sys
+} // end namespace llvm
-#endif
+#endif // LLVM_SUPPORT_VALGRIND_H
diff --git a/include/llvm/Support/YAMLParser.h b/include/llvm/Support/YAMLParser.h
index a5addfa3c7ae..23014fc10a3f 100644
--- a/include/llvm/Support/YAMLParser.h
+++ b/include/llvm/Support/YAMLParser.h
@@ -41,7 +41,6 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/SMLoc.h"
-#include <limits>
#include <map>
#include <utility>
diff --git a/include/llvm/Support/YAMLTraits.h b/include/llvm/Support/YAMLTraits.h
index fb2badfd93ba..bc3fa8ad11da 100644
--- a/include/llvm/Support/YAMLTraits.h
+++ b/include/llvm/Support/YAMLTraits.h
@@ -10,8 +10,6 @@
#ifndef LLVM_SUPPORT_YAMLTRAITS_H
#define LLVM_SUPPORT_YAMLTRAITS_H
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
@@ -19,6 +17,7 @@
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Endian.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/YAMLParser.h"
@@ -512,11 +511,11 @@ public:
template <typename FBT, typename T>
void enumFallback(T &Val) {
- if ( matchEnumFallback() ) {
+ if (matchEnumFallback()) {
// FIXME: Force integral conversion to allow strong typedefs to convert.
- FBT Res = (uint64_t)Val;
+ FBT Res = static_cast<typename FBT::BaseType>(Val);
yamlize(*this, Res, true);
- Val = (uint64_t)Res;
+ Val = static_cast<T>(static_cast<typename FBT::BaseType>(Res));
}
}
@@ -858,6 +857,32 @@ struct ScalarTraits<double> {
static bool mustQuote(StringRef) { return false; }
};
+// For endian types, we just use the existing ScalarTraits for the underlying
+// type. This way endian aware types are supported whenever a ScalarTraits
+// is defined for the underlying type.
+template <typename value_type, support::endianness endian, size_t alignment>
+struct ScalarTraits<support::detail::packed_endian_specific_integral<
+ value_type, endian, alignment>> {
+ typedef support::detail::packed_endian_specific_integral<value_type, endian,
+ alignment>
+ endian_type;
+
+ static void output(const endian_type &E, void *Ctx,
+ llvm::raw_ostream &Stream) {
+ ScalarTraits<value_type>::output(static_cast<value_type>(E), Ctx, Stream);
+ }
+ static StringRef input(StringRef Str, void *Ctx, endian_type &E) {
+ value_type V;
+ auto R = ScalarTraits<value_type>::input(Str, Ctx, V);
+ E = static_cast<endian_type>(V);
+ return R;
+ }
+
+ static bool mustQuote(StringRef Str) {
+ return ScalarTraits<value_type>::mustQuote(Str);
+ }
+};
+
// Utility for use within MappingTraits<>::mapping() method
// to [de]normalize an object for use with YAML conversion.
template <typename TNorm, typename TFinal>
@@ -894,12 +919,16 @@ private:
// to [de]normalize an object for use with YAML conversion.
template <typename TNorm, typename TFinal>
struct MappingNormalizationHeap {
- MappingNormalizationHeap(IO &i_o, TFinal &Obj)
+ MappingNormalizationHeap(IO &i_o, TFinal &Obj,
+ llvm::BumpPtrAllocator *allocator)
: io(i_o), BufPtr(nullptr), Result(Obj) {
if ( io.outputting() ) {
BufPtr = new (&Buffer) TNorm(io, Obj);
}
- else {
+ else if (allocator) {
+ BufPtr = allocator->Allocate<TNorm>();
+ new (BufPtr) TNorm(io);
+ } else {
BufPtr = new TNorm(io);
}
}
@@ -1166,6 +1195,7 @@ private:
bool operator==(const _base &rhs) const { return value == rhs; } \
bool operator<(const _type &rhs) const { return value < rhs.value; } \
_base value; \
+ typedef _base BaseType; \
};
///
diff --git a/include/llvm/Support/raw_sha1_ostream.h b/include/llvm/Support/raw_sha1_ostream.h
new file mode 100644
index 000000000000..329ef9fd069b
--- /dev/null
+++ b/include/llvm/Support/raw_sha1_ostream.h
@@ -0,0 +1,47 @@
+//==- raw_sha1_ostream.h - raw_ostream that compute SHA1 --*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the raw_sha1_ostream class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_RAW_SHA1_OSTREAM_H
+#define LLVM_SUPPORT_RAW_SHA1_OSTREAM_H
+
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/SHA1.h"
+#include "llvm/ADT/ArrayRef.h"
+
+namespace llvm {
+
+/// A raw_ostream that hash the content using the sha1 algorithm.
+class raw_sha1_ostream : public raw_ostream {
+ SHA1 State;
+
+ /// See raw_ostream::write_impl.
+ void write_impl(const char *Ptr, size_t Size) override {
+ State.update(ArrayRef<uint8_t>((const uint8_t *)Ptr, Size));
+ }
+
+public:
+ /// Return the current SHA1 hash for the content of the stream
+ StringRef sha1() {
+ flush();
+ return State.result();
+ }
+
+ /// Reset the internal state to start over from scratch.
+ void resetHash() { State.init(); }
+
+ uint64_t current_pos() const override { return 0; }
+};
+
+} // end llvm namespace
+
+#endif
diff --git a/include/llvm/Support/thread.h b/include/llvm/Support/thread.h
index 2d130418a57f..9c45418df55c 100644
--- a/include/llvm/Support/thread.h
+++ b/include/llvm/Support/thread.h
@@ -57,6 +57,7 @@ struct thread {
thread(const thread &) = delete;
void join() {}
+ static unsigned hardware_concurrency() { return 1; };
};
}
diff --git a/include/llvm/Support/type_traits.h b/include/llvm/Support/type_traits.h
index 88385c3fae1e..7706ff527197 100644
--- a/include/llvm/Support/type_traits.h
+++ b/include/llvm/Support/type_traits.h
@@ -17,6 +17,8 @@
#include <type_traits>
#include <utility>
+#include "llvm/Support/Compiler.h"
+
#ifndef __has_feature
#define LLVM_DEFINED_HAS_FEATURE
#define __has_feature(x) 0
@@ -54,11 +56,12 @@ struct isPodLike<std::pair<T, U> > {
};
/// \brief Metafunction that determines whether the given type is either an
-/// integral type or an enumeration type.
+/// integral type or an enumeration type, including enum classes.
///
/// Note that this accepts potentially more integral types than is_integral
-/// because it is based on merely being convertible implicitly to an integral
-/// type.
+/// because it is based on being implicitly convertible to an integral type.
+/// Also note that enum classes aren't implicitly convertible to integral types,
+/// the value may therefore need to be explicitly converted before being used.
template <typename T> class is_integral_or_enum {
typedef typename std::remove_reference<T>::type UnderlyingT;
@@ -67,7 +70,8 @@ public:
!std::is_class<UnderlyingT>::value && // Filter conversion operators.
!std::is_pointer<UnderlyingT>::value &&
!std::is_floating_point<UnderlyingT>::value &&
- std::is_convertible<UnderlyingT, unsigned long long>::value;
+ (std::is_enum<UnderlyingT>::value ||
+ std::is_convertible<UnderlyingT, unsigned long long>::value);
};
/// \brief If T is a pointer, just return it. If it is not, return T&.
diff --git a/include/llvm/TableGen/Record.h b/include/llvm/TableGen/Record.h
index 4c1ef4013dda..393cafa7924a 100644
--- a/include/llvm/TableGen/Record.h
+++ b/include/llvm/TableGen/Record.h
@@ -22,6 +22,7 @@
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SMLoc.h"
+#include "llvm/Support/TrailingObjects.h"
#include "llvm/Support/raw_ostream.h"
#include <map>
@@ -43,6 +44,7 @@ public:
enum RecTyKind {
BitRecTyKind,
BitsRecTyKind,
+ CodeRecTyKind,
IntRecTyKind,
StringRecTyKind,
ListRecTyKind,
@@ -64,11 +66,11 @@ public:
void print(raw_ostream &OS) const { OS << getAsString(); }
void dump() const;
- /// typeIsConvertibleTo - Return true if all values of 'this' type can be
- /// converted to the specified type.
+ /// Return true if all values of 'this' type can be converted to the specified
+ /// type.
virtual bool typeIsConvertibleTo(const RecTy *RHS) const;
- /// getListTy - Returns the type representing list<this>.
+ /// Returns the type representing list<this>.
ListRecTy *getListTy();
};
@@ -77,7 +79,7 @@ inline raw_ostream &operator<<(raw_ostream &OS, const RecTy &Ty) {
return OS;
}
-/// BitRecTy - 'bit' - Represent a single bit
+/// 'bit' - Represent a single bit
///
class BitRecTy : public RecTy {
static BitRecTy Shared;
@@ -95,7 +97,7 @@ public:
bool typeIsConvertibleTo(const RecTy *RHS) const override;
};
-/// BitsRecTy - 'bits<n>' - Represent a fixed number of bits
+/// 'bits<n>' - Represent a fixed number of bits
///
class BitsRecTy : public RecTy {
unsigned Size;
@@ -115,7 +117,23 @@ public:
bool typeIsConvertibleTo(const RecTy *RHS) const override;
};
-/// IntRecTy - 'int' - Represent an integer value of no particular size
+/// 'code' - Represent a code fragment
+///
+class CodeRecTy : public RecTy {
+ static CodeRecTy Shared;
+ CodeRecTy() : RecTy(CodeRecTyKind) {}
+
+public:
+ static bool classof(const RecTy *RT) {
+ return RT->getRecTyKind() == CodeRecTyKind;
+ }
+
+ static CodeRecTy *get() { return &Shared; }
+
+ std::string getAsString() const override { return "code"; }
+};
+
+/// 'int' - Represent an integer value of no particular size
///
class IntRecTy : public RecTy {
static IntRecTy Shared;
@@ -133,7 +151,7 @@ public:
bool typeIsConvertibleTo(const RecTy *RHS) const override;
};
-/// StringRecTy - 'string' - Represent an string value
+/// 'string' - Represent an string value
///
class StringRecTy : public RecTy {
static StringRecTy Shared;
@@ -141,7 +159,8 @@ class StringRecTy : public RecTy {
public:
static bool classof(const RecTy *RT) {
- return RT->getRecTyKind() == StringRecTyKind;
+ return RT->getRecTyKind() == StringRecTyKind ||
+ RT->getRecTyKind() == CodeRecTyKind;
}
static StringRecTy *get() { return &Shared; }
@@ -149,7 +168,7 @@ public:
std::string getAsString() const override;
};
-/// ListRecTy - 'list<Ty>' - Represent a list of values, all of which must be of
+/// 'list<Ty>' - Represent a list of values, all of which must be of
/// the specified type.
///
class ListRecTy : public RecTy {
@@ -170,7 +189,7 @@ public:
bool typeIsConvertibleTo(const RecTy *RHS) const override;
};
-/// DagRecTy - 'dag' - Represent a dag fragment
+/// 'dag' - Represent a dag fragment
///
class DagRecTy : public RecTy {
static DagRecTy Shared;
@@ -186,7 +205,7 @@ public:
std::string getAsString() const override;
};
-/// RecordRecTy - '[classname]' - Represent an instance of a class, such as:
+/// '[classname]' - Represent an instance of a class, such as:
/// (R32 X = EAX).
///
class RecordRecTy : public RecTy {
@@ -208,7 +227,7 @@ public:
bool typeIsConvertibleTo(const RecTy *RHS) const override;
};
-/// resolveTypes - Find a common type that T1 and T2 convert to.
+/// Find a common type that T1 and T2 convert to.
/// Return 0 if no such type exists.
///
RecTy *resolveTypes(RecTy *T1, RecTy *T2);
@@ -236,6 +255,7 @@ protected:
IK_BitInit,
IK_FirstTypedInit,
IK_BitsInit,
+ IK_CodeInit,
IK_DagInit,
IK_DefInit,
IK_FieldInit,
@@ -272,30 +292,30 @@ protected:
public:
virtual ~Init() {}
- /// isComplete - This virtual method should be overridden by values that may
+ /// This virtual method should be overridden by values that may
/// not be completely specified yet.
virtual bool isComplete() const { return true; }
- /// print - Print out this value.
+ /// Print out this value.
void print(raw_ostream &OS) const { OS << getAsString(); }
- /// getAsString - Convert this value to a string form.
+ /// Convert this value to a string form.
virtual std::string getAsString() const = 0;
- /// getAsUnquotedString - Convert this value to a string form,
+ /// Convert this value to a string form,
/// without adding quote markers. This primaruly affects
/// StringInits where we will not surround the string value with
/// quotes.
virtual std::string getAsUnquotedString() const { return getAsString(); }
- /// dump - Debugging method that may be called through a debugger, just
+ /// Debugging method that may be called through a debugger, just
/// invokes print on stderr.
void dump() const;
- /// convertInitializerTo - This virtual function converts to the appropriate
+ /// This virtual function converts to the appropriate
/// Init based on the passed in type.
virtual Init *convertInitializerTo(RecTy *Ty) const = 0;
- /// convertInitializerBitRange - This method is used to implement the bitrange
+ /// This method is used to implement the bitrange
/// selection operator. Given an initializer, it selects the specified bits
/// out, returning them as a new init of bits type. If it is not legal to use
/// the bit subscript operator on this initializer, return null.
@@ -305,7 +325,7 @@ public:
return nullptr;
}
- /// convertInitListSlice - This method is used to implement the list slice
+ /// This method is used to implement the list slice
/// selection operator. Given an initializer, it selects the specified list
/// elements, returning them as a new init of list type. If it is not legal
/// to take a slice of this, return null.
@@ -315,7 +335,7 @@ public:
return nullptr;
}
- /// getFieldType - This method is used to implement the FieldInit class.
+ /// This method is used to implement the FieldInit class.
/// Implementors of this method should return the type of the named field if
/// they are of record type.
///
@@ -323,7 +343,7 @@ public:
return nullptr;
}
- /// getFieldInit - This method complements getFieldType to return the
+ /// This method complements getFieldType to return the
/// initializer for the specified field. If getFieldType returns non-null
/// this method should return non-null, otherwise it returns null.
///
@@ -332,7 +352,7 @@ public:
return nullptr;
}
- /// resolveReferences - This method is used by classes that refer to other
+ /// This method is used by classes that refer to other
/// variables which may not be defined at the time the expression is formed.
/// If a value is set for the variable later, this method will be called on
/// users of the value to allow the value to propagate out.
@@ -341,15 +361,15 @@ public:
return const_cast<Init *>(this);
}
- /// getBit - This method is used to return the initializer for the specified
+ /// This method is used to return the initializer for the specified
/// bit.
virtual Init *getBit(unsigned Bit) const = 0;
- /// getBitVar - This method is used to retrieve the initializer for bit
+ /// This method is used to retrieve the initializer for bit
/// reference. For non-VarBitInit, it simply returns itself.
virtual Init *getBitVar() const { return const_cast<Init*>(this); }
- /// getBitNum - This method is used to retrieve the bit number of a bit
+ /// This method is used to retrieve the bit number of a bit
/// reference. For non-VarBitInit, it simply returns 0.
virtual unsigned getBitNum() const { return 0; }
};
@@ -358,7 +378,7 @@ inline raw_ostream &operator<<(raw_ostream &OS, const Init &I) {
I.print(OS); return OS;
}
-/// TypedInit - This is the common super-class of types that have a specific,
+/// This is the common super-class of types that have a specific,
/// explicit, type.
///
class TypedInit : public Init {
@@ -390,20 +410,20 @@ public:
Init *
convertInitListSlice(const std::vector<unsigned> &Elements) const override;
- /// getFieldType - This method is used to implement the FieldInit class.
+ /// This method is used to implement the FieldInit class.
/// Implementors of this method should return the type of the named field if
/// they are of record type.
///
RecTy *getFieldType(const std::string &FieldName) const override;
- /// resolveListElementReference - This method is used to implement
+ /// This method is used to implement
/// VarListElementInit::resolveReferences. If the list element is resolvable
/// now, we return the resolved value, otherwise we return null.
virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
unsigned Elt) const = 0;
};
-/// UnsetInit - ? - Represents an uninitialized value
+/// '?' - Represents an uninitialized value
///
class UnsetInit : public Init {
UnsetInit() : Init(IK_UnsetInit) {}
@@ -426,7 +446,7 @@ public:
std::string getAsString() const override { return "?"; }
};
-/// BitInit - true/false - Represent a concrete initializer for a bit.
+/// 'true'/'false' - Represent a concrete initializer for a bit.
///
class BitInit : public Init {
bool Value;
@@ -453,20 +473,23 @@ public:
std::string getAsString() const override { return Value ? "1" : "0"; }
};
-/// BitsInit - { a, b, c } - Represents an initializer for a BitsRecTy value.
+/// '{ a, b, c }' - Represents an initializer for a BitsRecTy value.
/// It contains a vector of bits, whose size is determined by the type.
///
-class BitsInit : public TypedInit, public FoldingSetNode {
- std::vector<Init*> Bits;
+class BitsInit final : public TypedInit, public FoldingSetNode,
+ public TrailingObjects<BitsInit, Init *> {
+ unsigned NumBits;
- BitsInit(ArrayRef<Init *> Range)
- : TypedInit(IK_BitsInit, BitsRecTy::get(Range.size())),
- Bits(Range.begin(), Range.end()) {}
+ BitsInit(unsigned N)
+ : TypedInit(IK_BitsInit, BitsRecTy::get(N)), NumBits(N) {}
BitsInit(const BitsInit &Other) = delete;
BitsInit &operator=(const BitsInit &Other) = delete;
public:
+ // Do not use sized deallocation due to trailing objects.
+ void operator delete(void *p) { ::operator delete(p); }
+
static bool classof(const Init *I) {
return I->getKind() == IK_BitsInit;
}
@@ -474,7 +497,7 @@ public:
void Profile(FoldingSetNodeID &ID) const;
- unsigned getNumBits() const { return Bits.size(); }
+ unsigned getNumBits() const { return NumBits; }
Init *convertInitializerTo(RecTy *Ty) const override;
Init *
@@ -492,7 +515,7 @@ public:
}
std::string getAsString() const override;
- /// resolveListElementReference - This method is used to implement
+ /// This method is used to implement
/// VarListElementInit::resolveReferences. If the list element is resolvable
/// now, we return the resolved value, otherwise we return null.
Init *resolveListElementReference(Record &R, const RecordVal *RV,
@@ -503,12 +526,12 @@ public:
Init *resolveReferences(Record &R, const RecordVal *RV) const override;
Init *getBit(unsigned Bit) const override {
- assert(Bit < Bits.size() && "Bit index out of range!");
- return Bits[Bit];
+ assert(Bit < NumBits && "Bit index out of range!");
+ return getTrailingObjects<Init *>()[Bit];
}
};
-/// IntInit - 7 - Represent an initialization by a literal integer value.
+/// '7' - Represent an initialization by a literal integer value.
///
class IntInit : public TypedInit {
int64_t Value;
@@ -533,7 +556,7 @@ public:
std::string getAsString() const override;
- /// resolveListElementReference - This method is used to implement
+ /// This method is used to implement
/// VarListElementInit::resolveReferences. If the list element is resolvable
/// now, we return the resolved value, otherwise we return null.
Init *resolveListElementReference(Record &R, const RecordVal *RV,
@@ -546,13 +569,13 @@ public:
}
};
-/// StringInit - "foo" - Represent an initialization by a string value.
+/// "foo" - Represent an initialization by a string value.
///
class StringInit : public TypedInit {
std::string Value;
explicit StringInit(StringRef V)
- : TypedInit(IK_StringInit, StringRecTy::get()), Value(V) {}
+ : TypedInit(IK_StringInit, StringRecTy::get()), Value(V) {}
StringInit(const StringInit &Other) = delete;
StringInit &operator=(const StringInit &Other) = delete;
@@ -568,6 +591,7 @@ public:
Init *convertInitializerTo(RecTy *Ty) const override;
std::string getAsString() const override { return "\"" + Value + "\""; }
+
std::string getAsUnquotedString() const override { return Value; }
/// resolveListElementReference - This method is used to implement
@@ -583,23 +607,65 @@ public:
}
};
-/// ListInit - [AL, AH, CL] - Represent a list of defs
+class CodeInit : public TypedInit {
+ std::string Value;
+
+ explicit CodeInit(StringRef V)
+ : TypedInit(IK_CodeInit, static_cast<RecTy *>(CodeRecTy::get())),
+ Value(V) {}
+
+ CodeInit(const StringInit &Other) = delete;
+ CodeInit &operator=(const StringInit &Other) = delete;
+
+public:
+ static bool classof(const Init *I) {
+ return I->getKind() == IK_CodeInit;
+ }
+ static CodeInit *get(StringRef);
+
+ const std::string &getValue() const { return Value; }
+
+ Init *convertInitializerTo(RecTy *Ty) const override;
+
+ std::string getAsString() const override {
+ return "[{" + Value + "}]";
+ }
+
+ std::string getAsUnquotedString() const override { return Value; }
+
+ /// This method is used to implement
+ /// VarListElementInit::resolveReferences. If the list element is resolvable
+ /// now, we return the resolved value, otherwise we return null.
+ Init *resolveListElementReference(Record &R, const RecordVal *RV,
+ unsigned Elt) const override {
+ llvm_unreachable("Illegal element reference off string");
+ }
+
+ Init *getBit(unsigned Bit) const override {
+ llvm_unreachable("Illegal bit reference off string");
+ }
+};
+
+/// [AL, AH, CL] - Represent a list of defs
///
-class ListInit : public TypedInit, public FoldingSetNode {
- std::vector<Init*> Values;
+class ListInit final : public TypedInit, public FoldingSetNode,
+ public TrailingObjects<BitsInit, Init *> {
+ unsigned NumValues;
public:
- typedef std::vector<Init*>::const_iterator const_iterator;
+ typedef Init *const *const_iterator;
private:
- explicit ListInit(ArrayRef<Init *> Range, RecTy *EltTy)
- : TypedInit(IK_ListInit, ListRecTy::get(EltTy)),
- Values(Range.begin(), Range.end()) {}
+ explicit ListInit(unsigned N, RecTy *EltTy)
+ : TypedInit(IK_ListInit, ListRecTy::get(EltTy)), NumValues(N) {}
ListInit(const ListInit &Other) = delete;
ListInit &operator=(const ListInit &Other) = delete;
public:
+ // Do not use sized deallocation due to trailing objects.
+ void operator delete(void *p) { ::operator delete(p); }
+
static bool classof(const Init *I) {
return I->getKind() == IK_ListInit;
}
@@ -608,8 +674,8 @@ public:
void Profile(FoldingSetNodeID &ID) const;
Init *getElement(unsigned i) const {
- assert(i < Values.size() && "List element index out of range!");
- return Values[i];
+ assert(i < NumValues && "List element index out of range!");
+ return getTrailingObjects<Init *>()[i];
}
Record *getElementAsRecord(unsigned i) const;
@@ -619,7 +685,7 @@ public:
Init *convertInitializerTo(RecTy *Ty) const override;
- /// resolveReferences - This method is used by classes that refer to other
+ /// This method is used by classes that refer to other
/// variables which may not be defined at the time they expression is formed.
/// If a value is set for the variable later, this method will be called on
/// users of the value to allow the value to propagate out.
@@ -628,15 +694,17 @@ public:
std::string getAsString() const override;
- ArrayRef<Init*> getValues() const { return Values; }
+ ArrayRef<Init*> getValues() const {
+ return makeArrayRef(getTrailingObjects<Init *>(), NumValues);
+ }
- const_iterator begin() const { return Values.begin(); }
- const_iterator end () const { return Values.end(); }
+ const_iterator begin() const { return getTrailingObjects<Init *>(); }
+ const_iterator end () const { return begin() + NumValues; }
- size_t size () const { return Values.size(); }
- bool empty() const { return Values.empty(); }
+ size_t size () const { return NumValues; }
+ bool empty() const { return NumValues == 0; }
- /// resolveListElementReference - This method is used to implement
+ /// This method is used to implement
/// VarListElementInit::resolveReferences. If the list element is resolvable
/// now, we return the resolved value, otherwise we return null.
Init *resolveListElementReference(Record &R, const RecordVal *RV,
@@ -647,7 +715,7 @@ public:
}
};
-/// OpInit - Base class for operators
+/// Base class for operators
///
class OpInit : public TypedInit {
OpInit(const OpInit &Other) = delete;
@@ -678,9 +746,9 @@ public:
Init *getBit(unsigned Bit) const override;
};
-/// UnOpInit - !op (X) - Transform an init.
+/// !op (X) - Transform an init.
///
-class UnOpInit : public OpInit {
+class UnOpInit : public OpInit, public FoldingSetNode {
public:
enum UnaryOp : uint8_t { CAST, HEAD, TAIL, EMPTY };
@@ -699,6 +767,8 @@ public:
}
static UnOpInit *get(UnaryOp opc, Init *lhs, RecTy *Type);
+ void Profile(FoldingSetNodeID &ID) const;
+
// Clone - Clone this operator, replacing arguments with the new list
OpInit *clone(std::vector<Init *> &Operands) const override {
assert(Operands.size() == 1 &&
@@ -724,9 +794,9 @@ public:
std::string getAsString() const override;
};
-/// BinOpInit - !op (X, Y) - Combine two inits.
+/// !op (X, Y) - Combine two inits.
///
-class BinOpInit : public OpInit {
+class BinOpInit : public OpInit, public FoldingSetNode {
public:
enum BinaryOp : uint8_t { ADD, AND, SHL, SRA, SRL, LISTCONCAT,
STRCONCAT, CONCAT, EQ };
@@ -747,6 +817,8 @@ public:
static BinOpInit *get(BinaryOp opc, Init *lhs, Init *rhs,
RecTy *Type);
+ void Profile(FoldingSetNodeID &ID) const;
+
// Clone - Clone this operator, replacing arguments with the new list
OpInit *clone(std::vector<Init *> &Operands) const override {
assert(Operands.size() == 2 &&
@@ -776,9 +848,9 @@ public:
std::string getAsString() const override;
};
-/// TernOpInit - !op (X, Y, Z) - Combine two inits.
+/// !op (X, Y, Z) - Combine two inits.
///
-class TernOpInit : public OpInit {
+class TernOpInit : public OpInit, public FoldingSetNode {
public:
enum TernaryOp : uint8_t { SUBST, FOREACH, IF };
@@ -800,6 +872,8 @@ public:
Init *mhs, Init *rhs,
RecTy *Type);
+ void Profile(FoldingSetNodeID &ID) const;
+
// Clone - Clone this operator, replacing arguments with the new list
OpInit *clone(std::vector<Init *> &Operands) const override {
assert(Operands.size() == 3 &&
@@ -834,7 +908,7 @@ public:
std::string getAsString() const override;
};
-/// VarInit - 'Opcode' - Represent a reference to an entire variable object.
+/// 'Opcode' - Represent a reference to an entire variable object.
///
class VarInit : public TypedInit {
Init *VarName;
@@ -865,7 +939,7 @@ public:
Init *getFieldInit(Record &R, const RecordVal *RV,
const std::string &FieldName) const override;
- /// resolveReferences - This method is used by classes that refer to other
+ /// This method is used by classes that refer to other
/// variables which may not be defined at the time they expression is formed.
/// If a value is set for the variable later, this method will be called on
/// users of the value to allow the value to propagate out.
@@ -877,7 +951,7 @@ public:
std::string getAsString() const override { return getName(); }
};
-/// VarBitInit - Opcode{0} - Represent access to one bit of a variable or field.
+/// Opcode{0} - Represent access to one bit of a variable or field.
///
class VarBitInit : public Init {
TypedInit *TI;
@@ -914,7 +988,7 @@ public:
}
};
-/// VarListElementInit - List[4] - Represent access to one element of a var or
+/// List[4] - Represent access to one element of a var or
/// field.
class VarListElementInit : public TypedInit {
TypedInit *TI;
@@ -940,7 +1014,7 @@ public:
TypedInit *getVariable() const { return TI; }
unsigned getElementNum() const { return Element; }
- /// resolveListElementReference - This method is used to implement
+ /// This method is used to implement
/// VarListElementInit::resolveReferences. If the list element is resolvable
/// now, we return the resolved value, otherwise we return null.
Init *resolveListElementReference(Record &R, const RecordVal *RV,
@@ -952,7 +1026,7 @@ public:
Init *getBit(unsigned Bit) const override;
};
-/// DefInit - AL - Represent a reference to a 'def' in the description
+/// AL - Represent a reference to a 'def' in the description
///
class DefInit : public TypedInit {
Record *Def;
@@ -985,7 +1059,7 @@ public:
llvm_unreachable("Illegal bit reference off def");
}
- /// resolveListElementReference - This method is used to implement
+ /// This method is used to implement
/// VarListElementInit::resolveReferences. If the list element is resolvable
/// now, we return the resolved value, otherwise we return null.
Init *resolveListElementReference(Record &R, const RecordVal *RV,
@@ -994,7 +1068,7 @@ public:
}
};
-/// FieldInit - X.Y - Represent a reference to a subfield of a variable
+/// X.Y - Represent a reference to a subfield of a variable
///
class FieldInit : public TypedInit {
Init *Rec; // Record we are referring to
@@ -1026,7 +1100,7 @@ public:
}
};
-/// DagInit - (v a, b) - Represent a DAG tree value. DAG inits are required
+/// (v a, b) - Represent a DAG tree value. DAG inits are required
/// to have at least one value then a (possibly empty) list of arguments. Each
/// argument can have a name associated with it.
///
@@ -1148,21 +1222,22 @@ inline raw_ostream &operator<<(raw_ostream &OS, const RecordVal &RV) {
class Record {
static unsigned LastID;
- // Unique record ID.
- unsigned ID;
Init *Name;
// Location where record was instantiated, followed by the location of
// multiclass prototypes used.
SmallVector<SMLoc, 4> Locs;
- std::vector<Init *> TemplateArgs;
- std::vector<RecordVal> Values;
- std::vector<Record *> SuperClasses;
- std::vector<SMRange> SuperClassRanges;
+ SmallVector<Init *, 0> TemplateArgs;
+ SmallVector<RecordVal, 0> Values;
+ SmallVector<std::pair<Record *, SMRange>, 0> SuperClasses;
// Tracks Record instances. Not owned by Record.
RecordKeeper &TrackedRecords;
std::unique_ptr<DefInit> TheInit;
+
+ // Unique record ID.
+ unsigned ID;
+
bool IsAnonymous;
// Class-instance values can be used by other defs. For example, Struct<i>
@@ -1184,8 +1259,8 @@ public:
// Constructs a record.
explicit Record(Init *N, ArrayRef<SMLoc> locs, RecordKeeper &records,
bool Anonymous = false) :
- ID(LastID++), Name(N), Locs(locs.begin(), locs.end()),
- TrackedRecords(records), IsAnonymous(Anonymous), ResolveFirst(false) {
+ Name(N), Locs(locs.begin(), locs.end()), TrackedRecords(records),
+ ID(LastID++), IsAnonymous(Anonymous), ResolveFirst(false) {
init();
}
explicit Record(const std::string &N, ArrayRef<SMLoc> locs,
@@ -1197,11 +1272,10 @@ public:
// ID number. Don't copy TheInit either since it's owned by the original
// record. All other fields can be copied normally.
Record(const Record &O) :
- ID(LastID++), Name(O.Name), Locs(O.Locs), TemplateArgs(O.TemplateArgs),
+ Name(O.Name), Locs(O.Locs), TemplateArgs(O.TemplateArgs),
Values(O.Values), SuperClasses(O.SuperClasses),
- SuperClassRanges(O.SuperClassRanges), TrackedRecords(O.TrackedRecords),
- IsAnonymous(O.IsAnonymous),
- ResolveFirst(O.ResolveFirst) { }
+ TrackedRecords(O.TrackedRecords), ID(LastID++),
+ IsAnonymous(O.IsAnonymous), ResolveFirst(O.ResolveFirst) { }
static unsigned getNewUID() { return LastID++; }
@@ -1227,8 +1301,9 @@ public:
return TemplateArgs;
}
ArrayRef<RecordVal> getValues() const { return Values; }
- ArrayRef<Record *> getSuperClasses() const { return SuperClasses; }
- ArrayRef<SMRange> getSuperClassRanges() const { return SuperClassRanges; }
+ ArrayRef<std::pair<Record *, SMRange>> getSuperClasses() const {
+ return SuperClasses;
+ }
bool isTemplateArg(Init *Name) const {
for (Init *TA : TemplateArgs)
@@ -1290,31 +1365,35 @@ public:
}
bool isSubClassOf(const Record *R) const {
- for (const Record *SC : SuperClasses)
- if (SC == R)
+ for (const auto &SCPair : SuperClasses)
+ if (SCPair.first == R)
return true;
return false;
}
bool isSubClassOf(StringRef Name) const {
- for (const Record *SC : SuperClasses)
- if (SC->getNameInitAsString() == Name)
+ for (const auto &SCPair : SuperClasses) {
+ if (const auto *SI = dyn_cast<StringInit>(SCPair.first->getNameInit())) {
+ if (SI->getValue() == Name)
+ return true;
+ } else if (SCPair.first->getNameInitAsString() == Name) {
return true;
+ }
+ }
return false;
}
void addSuperClass(Record *R, SMRange Range) {
assert(!isSubClassOf(R) && "Already subclassing record!");
- SuperClasses.push_back(R);
- SuperClassRanges.push_back(Range);
+ SuperClasses.push_back(std::make_pair(R, Range));
}
- /// resolveReferences - If there are any field references that refer to fields
+ /// If there are any field references that refer to fields
/// that have been filled in, we can propagate the values now.
///
void resolveReferences() { resolveReferencesTo(nullptr); }
- /// resolveReferencesTo - If anything in this record refers to RV, replace the
+ /// If anything in this record refers to RV, replace the
/// reference to RV with the RHS of RV. If RV is null, we resolve all
/// possible references.
void resolveReferencesTo(const RecordVal *RV);
@@ -1341,7 +1420,7 @@ public:
// High-level methods useful to tablegen back-ends
//
- /// getValueInit - Return the initializer for a value with the specified name,
+ /// Return the initializer for a value with the specified name,
/// or throw an exception if the field does not exist.
///
Init *getValueInit(StringRef FieldName) const;
@@ -1351,67 +1430,67 @@ public:
return isa<UnsetInit>(getValueInit(FieldName));
}
- /// getValueAsString - This method looks up the specified field and returns
+ /// This method looks up the specified field and returns
/// its value as a string, throwing an exception if the field does not exist
/// or if the value is not a string.
///
std::string getValueAsString(StringRef FieldName) const;
- /// getValueAsBitsInit - This method looks up the specified field and returns
+ /// This method looks up the specified field and returns
/// its value as a BitsInit, throwing an exception if the field does not exist
/// or if the value is not the right type.
///
BitsInit *getValueAsBitsInit(StringRef FieldName) const;
- /// getValueAsListInit - This method looks up the specified field and returns
+ /// This method looks up the specified field and returns
/// its value as a ListInit, throwing an exception if the field does not exist
/// or if the value is not the right type.
///
ListInit *getValueAsListInit(StringRef FieldName) const;
- /// getValueAsListOfDefs - This method looks up the specified field and
+ /// This method looks up the specified field and
/// returns its value as a vector of records, throwing an exception if the
/// field does not exist or if the value is not the right type.
///
std::vector<Record*> getValueAsListOfDefs(StringRef FieldName) const;
- /// getValueAsListOfInts - This method looks up the specified field and
+ /// This method looks up the specified field and
/// returns its value as a vector of integers, throwing an exception if the
/// field does not exist or if the value is not the right type.
///
std::vector<int64_t> getValueAsListOfInts(StringRef FieldName) const;
- /// getValueAsListOfStrings - This method looks up the specified field and
+ /// This method looks up the specified field and
/// returns its value as a vector of strings, throwing an exception if the
/// field does not exist or if the value is not the right type.
///
std::vector<std::string> getValueAsListOfStrings(StringRef FieldName) const;
- /// getValueAsDef - This method looks up the specified field and returns its
+ /// This method looks up the specified field and returns its
/// value as a Record, throwing an exception if the field does not exist or if
/// the value is not the right type.
///
Record *getValueAsDef(StringRef FieldName) const;
- /// getValueAsBit - This method looks up the specified field and returns its
+ /// This method looks up the specified field and returns its
/// value as a bit, throwing an exception if the field does not exist or if
/// the value is not the right type.
///
bool getValueAsBit(StringRef FieldName) const;
- /// getValueAsBitOrUnset - This method looks up the specified field and
+ /// This method looks up the specified field and
/// returns its value as a bit. If the field is unset, sets Unset to true and
/// returns false.
///
bool getValueAsBitOrUnset(StringRef FieldName, bool &Unset) const;
- /// getValueAsInt - This method looks up the specified field and returns its
+ /// This method looks up the specified field and returns its
/// value as an int64_t, throwing an exception if the field does not exist or
/// if the value is not the right type.
///
int64_t getValueAsInt(StringRef FieldName) const;
- /// getValueAsDag - This method looks up the specified field and returns its
+ /// This method looks up the specified field and returns its
/// value as an Dag, throwing an exception if the field does not exist or if
/// the value is not the right type.
///
@@ -1463,16 +1542,16 @@ public:
//===--------------------------------------------------------------------===//
// High-level helper methods, useful for tablegen backends...
- /// getAllDerivedDefinitions - This method returns all concrete definitions
- /// that derive from the specified class name. If a class with the specified
- /// name does not exist, an exception is thrown.
- std::vector<Record*>
+ /// This method returns all concrete definitions
+ /// that derive from the specified class name. A class with the specified
+ /// name must exist.
+ std::vector<Record *>
getAllDerivedDefinitions(const std::string &ClassName) const;
void dump() const;
};
-/// LessRecord - Sorting predicate to sort record pointers by name.
+/// Sorting predicate to sort record pointers by name.
///
struct LessRecord {
bool operator()(const Record *Rec1, const Record *Rec2) const {
@@ -1480,7 +1559,7 @@ struct LessRecord {
}
};
-/// LessRecordByID - Sorting predicate to sort record pointers by their
+/// Sorting predicate to sort record pointers by their
/// unique ID. If you just need a deterministic order, use this, since it
/// just compares two `unsigned`; the other sorting predicates require
/// string manipulation.
@@ -1490,7 +1569,7 @@ struct LessRecordByID {
}
};
-/// LessRecordFieldName - Sorting predicate to sort record pointers by their
+/// Sorting predicate to sort record pointers by their
/// name field.
///
struct LessRecordFieldName {
@@ -1580,12 +1659,12 @@ struct LessRecordRegister {
raw_ostream &operator<<(raw_ostream &OS, const RecordKeeper &RK);
-/// QualifyName - Return an Init with a qualifier prefix referring
+/// Return an Init with a qualifier prefix referring
/// to CurRec's name.
Init *QualifyName(Record &CurRec, MultiClass *CurMultiClass,
Init *Name, const std::string &Scoper);
-/// QualifyName - Return an Init with a qualifier prefix referring
+/// Return an Init with a qualifier prefix referring
/// to CurRec's name.
Init *QualifyName(Record &CurRec, MultiClass *CurMultiClass,
const std::string &Name, const std::string &Scoper);
diff --git a/include/llvm/TableGen/SearchableTable.td b/include/llvm/TableGen/SearchableTable.td
new file mode 100644
index 000000000000..12aaf6000c31
--- /dev/null
+++ b/include/llvm/TableGen/SearchableTable.td
@@ -0,0 +1,41 @@
+//===- SearchableTable.td ----------------------------------*- tablegen -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the key top-level classes needed to produce a reasonably
+// generic table that can be binary-searched via int and string entries.
+//
+// Each table must instantiate "Mappingkind", listing the fields that should be
+// included and fields that shoould be searchable. Only two kinds of fields are
+// searchable at the moment: "strings" (which are compared case-insensitively),
+// and "bits".
+//
+// For each "MappingKind" the generated header will create GET_MAPPINGKIND_DECL
+// and GET_MAPPINGKIND_IMPL guards.
+//
+// Inside the DECL guard will be a set of function declarations:
+// "lookup{InstanceClass}By{SearchableField}", returning "const {InstanceClass}
+// *" and accepting either a StringRef or a uintN_t. Additionally, if
+// EnumNameField is still defined, there will be an "enum {InstanceClass}Values"
+// allowing C++ code to reference either the primary data table's entries (if
+// EnumValueField is not defined) or some other field (e.g. encoding) if it is.
+//
+// Inside the IMPL guard will be a primary data table "{InstanceClass}sList" and
+// as many searchable indexes as requested
+// ("{InstanceClass}sBy{SearchableField}"). Additionally implementations of the
+// lookup function will be provided.
+//
+// See AArch64SystemOperands.td and its generated header for example uses.
+//
+//===----------------------------------------------------------------------===//
+
+class SearchableTable {
+ list<string> SearchableFields;
+ string EnumNameField = "Name";
+ string EnumValueField;
+}
diff --git a/include/llvm/TableGen/StringToOffsetTable.h b/include/llvm/TableGen/StringToOffsetTable.h
index e3277036dc76..e5b61ed1195e 100644
--- a/include/llvm/TableGen/StringToOffsetTable.h
+++ b/include/llvm/TableGen/StringToOffsetTable.h
@@ -76,6 +76,26 @@ public:
}
O << "\"";
}
+
+ /// Emit the string using character literals. MSVC has a limitation that
+ /// string literals cannot be longer than 64K.
+ void EmitCharArray(raw_ostream &O) {
+ assert(AggregateString.find(')') == std::string::npos &&
+ "can't emit raw string with closing parens");
+ int Count = 0;
+ O << ' ';
+ for (char C : AggregateString) {
+ O << " \'";
+ O.write_escaped(StringRef(&C, 1));
+ O << "\',";
+ Count++;
+ if (Count > 14) {
+ O << "\n ";
+ Count = 0;
+ }
+ }
+ O << '\n';
+ }
};
} // end namespace llvm
diff --git a/include/llvm/Target/GenericOpcodes.td b/include/llvm/Target/GenericOpcodes.td
new file mode 100644
index 000000000000..b4d95508f0a5
--- /dev/null
+++ b/include/llvm/Target/GenericOpcodes.td
@@ -0,0 +1,46 @@
+//===-- GenericOpcodes.td - Opcodes used with GlobalISel ---*- tablegen -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the generic opcodes used with GlobalISel.
+// After instruction selection, these opcodes should not appear.
+//
+//===----------------------------------------------------------------------===//
+
+//------------------------------------------------------------------------------
+// Binary ops.
+//------------------------------------------------------------------------------
+// Generic addition.
+def G_ADD : Instruction {
+ let OutOperandList = (outs unknown:$dst);
+ let InOperandList = (ins unknown:$src1, unknown:$src2);
+ let hasSideEffects = 0;
+ let isCommutable = 1;
+}
+
+// Generic bitwise or.
+def G_OR : Instruction {
+ let OutOperandList = (outs unknown:$dst);
+ let InOperandList = (ins unknown:$src1, unknown:$src2);
+ let hasSideEffects = 0;
+ let isCommutable = 1;
+}
+
+//------------------------------------------------------------------------------
+// Branches.
+//------------------------------------------------------------------------------
+// Generic unconditional branch.
+def G_BR : Instruction {
+ let OutOperandList = (outs);
+ let InOperandList = (ins unknown:$src1);
+ let hasSideEffects = 0;
+ let isBranch = 1;
+ let isTerminator = 1;
+}
+
+// TODO: Add the other generic opcodes.
diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td
index c869341c384f..c71435a2564c 100644
--- a/include/llvm/Target/Target.td
+++ b/include/llvm/Target/Target.td
@@ -427,6 +427,11 @@ class Instruction {
// Is this instruction a pseudo instruction for use by the assembler parser.
bit isAsmParserOnly = 0;
+ // This instruction is not expected to be queried for scheduling latencies
+ // and therefore needs no scheduling information even for a complete
+ // scheduling model.
+ bit hasNoSchedulingInfo = 0;
+
InstrItinClass Itinerary = NoItinerary;// Execution steps used for scheduling.
// Scheduling information from TargetSchedule.td.
@@ -605,6 +610,22 @@ class AsmOperandClass {
// match failure error message. By default, use a generic "invalid operand"
// diagnostic. The target AsmParser maps these codes to text.
string DiagnosticType = "";
+
+ /// Set to 1 if this operand is optional and not always required. Typically,
+ /// the AsmParser will emit an error when it finishes parsing an
+ /// instruction if it hasn't matched all the operands yet. However, this
+ /// error will be suppressed if all of the remaining unmatched operands are
+ /// marked as IsOptional.
+ ///
+ /// Optional arguments must be at the end of the operand list.
+ bit IsOptional = 0;
+
+ /// The name of the method on the target specific asm parser that returns the
+ /// default operand for this optional operand. This method is only used if
+ /// IsOptional == 1. If not set, this will default to "defaultFooOperands",
+ /// where Foo is the AsmOperandClass name. The method signature should be:
+ /// std::unique_ptr<MCParsedAsmOperand> defaultFooOperands() const;
+ string DefaultMethod = ?;
}
def ImmAsmOperand : AsmOperandClass {
@@ -756,9 +777,10 @@ class InstrInfo {
// Standard Pseudo Instructions.
// This list must match TargetOpcodes.h and CodeGenTarget.cpp.
// Only these instructions are allowed in the TargetOpcode namespace.
-let isCodeGenOnly = 1, isPseudo = 1, Namespace = "TargetOpcode" in {
+let isCodeGenOnly = 1, isPseudo = 1, hasNoSchedulingInfo = 1,
+ Namespace = "TargetOpcode" in {
def PHI : Instruction {
- let OutOperandList = (outs);
+ let OutOperandList = (outs unknown:$dst);
let InOperandList = (ins variable_ops);
let AsmString = "PHINODE";
}
@@ -848,6 +870,7 @@ def COPY : Instruction {
let AsmString = "";
let hasSideEffects = 0;
let isAsCheapAsAMove = 1;
+ let hasNoSchedulingInfo = 0;
}
def BUNDLE : Instruction {
let OutOperandList = (outs);
@@ -912,7 +935,36 @@ def FAULTING_LOAD_OP : Instruction {
let InOperandList = (ins variable_ops);
let usesCustomInserter = 1;
let mayLoad = 1;
+ let isTerminator = 1;
+ let isBranch = 1;
}
+def PATCHABLE_OP : Instruction {
+ let OutOperandList = (outs unknown:$dst);
+ let InOperandList = (ins variable_ops);
+ let usesCustomInserter = 1;
+ let mayLoad = 1;
+ let mayStore = 1;
+ let hasSideEffects = 1;
+}
+def PATCHABLE_FUNCTION_ENTER : Instruction {
+ let OutOperandList = (outs);
+ let InOperandList = (ins);
+ let AsmString = "# XRay Function Enter.";
+ let usesCustomInserter = 1;
+ let hasSideEffects = 0;
+}
+def PATCHABLE_RET : Instruction {
+ let OutOperandList = (outs unknown:$dst);
+ let InOperandList = (ins variable_ops);
+ let AsmString = "# XRay Function Exit.";
+ let usesCustomInserter = 1;
+ let hasSideEffects = 1;
+ let isReturn = 1;
+}
+
+// Generic opcodes used in GlobalISel.
+include "llvm/Target/GenericOpcodes.td"
+
}
//===----------------------------------------------------------------------===//
@@ -937,6 +989,14 @@ class AsmParser {
// written register name matcher
bit ShouldEmitMatchRegisterName = 1;
+ // Set to true if the target needs a generated 'alternative register name'
+ // matcher.
+ //
+ // This generates a function which can be used to lookup registers from
+ // their aliases. This function will fail when called on targets where
+ // several registers share the same alias (i.e. not a 1:1 mapping).
+ bit ShouldEmitMatchRegisterAltName = 0;
+
// HasMnemonicFirst - Set to false if target instructions don't always
// start with a mnemonic as the first token.
bit HasMnemonicFirst = 1;
diff --git a/include/llvm/Target/TargetCallingConv.h b/include/llvm/Target/TargetCallingConv.h
index 0c6c1f1468c4..19d8917f17d3 100644
--- a/include/llvm/Target/TargetCallingConv.h
+++ b/include/llvm/Target/TargetCallingConv.h
@@ -17,8 +17,7 @@
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/MathExtras.h"
-#include <string>
-#include <limits.h>
+#include <climits>
namespace llvm {
@@ -48,6 +47,10 @@ namespace ISD {
static const uint64_t InAllocaOffs = 12;
static const uint64_t SplitEnd = 1ULL<<13; ///< Last part of a split
static const uint64_t SplitEndOffs = 13;
+ static const uint64_t SwiftSelf = 1ULL<<14; ///< Swift self parameter
+ static const uint64_t SwiftSelfOffs = 14;
+ static const uint64_t SwiftError = 1ULL<<15; ///< Swift error parameter
+ static const uint64_t SwiftErrorOffs = 15;
static const uint64_t OrigAlign = 0x1FULL<<27;
static const uint64_t OrigAlignOffs = 27;
static const uint64_t ByValSize = 0x3fffffffULL<<32; ///< Struct size
@@ -60,6 +63,7 @@ namespace ISD {
static const uint64_t One = 1ULL; ///< 1 of this type, for shifts
uint64_t Flags;
+
public:
ArgFlagsTy() : Flags(0) { }
@@ -81,6 +85,12 @@ namespace ISD {
bool isInAlloca() const { return Flags & InAlloca; }
void setInAlloca() { Flags |= One << InAllocaOffs; }
+ bool isSwiftSelf() const { return Flags & SwiftSelf; }
+ void setSwiftSelf() { Flags |= One << SwiftSelfOffs; }
+
+ bool isSwiftError() const { return Flags & SwiftError; }
+ void setSwiftError() { Flags |= One << SwiftErrorOffs; }
+
bool isNest() const { return Flags & Nest; }
void setNest() { Flags |= One << NestOffs; }
@@ -195,8 +205,8 @@ namespace ISD {
ArgVT = argvt;
}
};
-}
+} // end namespace ISD
} // end llvm namespace
-#endif
+#endif // LLVM_TARGET_TARGETCALLINGCONV_H
diff --git a/include/llvm/Target/TargetCallingConv.td b/include/llvm/Target/TargetCallingConv.td
index 2e766c448b34..3d8639dfe1da 100644
--- a/include/llvm/Target/TargetCallingConv.td
+++ b/include/llvm/Target/TargetCallingConv.td
@@ -42,6 +42,16 @@ class CCIf<string predicate, CCAction A> : CCPredicateAction<A> {
class CCIfByVal<CCAction A> : CCIf<"ArgFlags.isByVal()", A> {
}
+/// CCIfSwiftSelf - If the current argument has swiftself parameter attribute,
+/// apply Action A.
+class CCIfSwiftSelf<CCAction A> : CCIf<"ArgFlags.isSwiftSelf()", A> {
+}
+
+/// CCIfSwiftError - If the current argument has swifterror parameter attribute,
+/// apply Action A.
+class CCIfSwiftError<CCAction A> : CCIf<"ArgFlags.isSwiftError()", A> {
+}
+
/// CCIfConsecutiveRegs - If the current argument has InConsecutiveRegs
/// parameter attribute, apply Action A.
class CCIfConsecutiveRegs<CCAction A> : CCIf<"ArgFlags.isInConsecutiveRegs()", A> {
diff --git a/include/llvm/Target/TargetFrameLowering.h b/include/llvm/Target/TargetFrameLowering.h
index cadd07d71f12..98065aca16f3 100644
--- a/include/llvm/Target/TargetFrameLowering.h
+++ b/include/llvm/Target/TargetFrameLowering.h
@@ -75,9 +75,9 @@ public:
///
int alignSPAdjust(int SPAdj) const {
if (SPAdj < 0) {
- SPAdj = -RoundUpToAlignment(-SPAdj, StackAlignment);
+ SPAdj = -alignTo(-SPAdj, StackAlignment);
} else {
- SPAdj = RoundUpToAlignment(SPAdj, StackAlignment);
+ SPAdj = alignTo(SPAdj, StackAlignment);
}
return SPAdj;
}
@@ -151,6 +151,13 @@ public:
return false;
}
+ /// Returns true if the stack slot holes in the fixed and callee-save stack
+ /// area should be used when allocating other stack locations to reduce stack
+ /// size.
+ virtual bool enableStackSlotScavenging(const MachineFunction &MF) const {
+ return false;
+ }
+
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
/// the function.
virtual void emitPrologue(MachineFunction &MF,
@@ -239,15 +246,17 @@ public:
virtual int getFrameIndexReference(const MachineFunction &MF, int FI,
unsigned &FrameReg) const;
- /// Same as above, except that the 'base register' will always be RSP, not
- /// RBP on x86. This is generally used for emitting statepoint or EH tables
- /// that use offsets from RSP.
- /// TODO: This should really be a parameterizable choice.
- virtual int getFrameIndexReferenceFromSP(const MachineFunction &MF, int FI,
- unsigned &FrameReg) const {
- // default to calling normal version, we override this on x86 only
- llvm_unreachable("unimplemented for non-x86");
- return 0;
+ /// Same as \c getFrameIndexReference, except that the stack pointer (as
+ /// opposed to the frame pointer) will be the preferred value for \p
+ /// FrameReg. This is generally used for emitting statepoint or EH tables that
+ /// 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,
+ unsigned &FrameReg,
+ bool IgnoreSPUpdates) const {
+ // Always safe to dispatch to getFrameIndexReference.
+ return getFrameIndexReference(MF, FI, FrameReg);
}
/// This method determines which of the registers reported by
@@ -273,14 +282,13 @@ public:
report_fatal_error("WinEH not implemented for this target");
}
- /// eliminateCallFramePseudoInstr - This method is called during prolog/epilog
- /// code insertion to eliminate call frame setup and destroy pseudo
- /// instructions (but only if the Target is using them). It is responsible
- /// for eliminating these instructions, replacing them with concrete
- /// instructions. This method need only be implemented if using call frame
- /// setup/destroy pseudo instructions.
- ///
- virtual void
+ /// This method is called during prolog/epilog code insertion to eliminate
+ /// call frame setup and destroy pseudo instructions (but only if the Target
+ /// is using them). It is responsible for eliminating these instructions,
+ /// replacing them with concrete instructions. This method need only be
+ /// implemented if using call frame setup/destroy pseudo instructions.
+ /// Returns an iterator pointing to the instruction after the replaced one.
+ virtual MachineBasicBlock::iterator
eliminateCallFramePseudoInstr(MachineFunction &MF,
MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI) const {
@@ -288,6 +296,18 @@ public:
"target!");
}
+
+ /// Order the symbols in the local stack frame.
+ /// The list of objects that we want to order is in \p objectsToAllocate as
+ /// indices into the MachineFrameInfo. The array can be reordered in any way
+ /// upon return. The contents of the array, however, may not be modified (i.e.
+ /// only their order may be changed).
+ /// By default, just maintain the original order.
+ virtual void
+ orderFrameObjects(const MachineFunction &MF,
+ SmallVectorImpl<int> &objectsToAllocate) const {
+ }
+
/// Check whether or not the given \p MBB can be used as a prologue
/// for the target.
/// The prologue will be inserted first in this basic block.
@@ -311,6 +331,20 @@ public:
virtual bool canUseAsEpilogue(const MachineBasicBlock &MBB) const {
return true;
}
+
+ /// Check if given function is safe for not having callee saved registers.
+ /// This is used when interprocedural register allocation is enabled.
+ static bool isSafeForNoCSROpt(const Function *F) {
+ if (!F->hasLocalLinkage() || F->hasAddressTaken() ||
+ !F->hasFnAttribute(Attribute::NoRecurse))
+ return false;
+ // Function should not be optimized as tail call.
+ for (const User *U : F->users())
+ if (auto CS = ImmutableCallSite(U))
+ if (CS.isTailCall())
+ return false;
+ return true;
+ }
};
} // End llvm namespace
diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h
index 0cebcf1c6b5d..e0b9a22ed5d0 100644
--- a/include/llvm/Target/TargetInstrInfo.h
+++ b/include/llvm/Target/TargetInstrInfo.h
@@ -21,6 +21,7 @@
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/Support/BranchProbability.h"
#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/CodeGen/LiveIntervalAnalysis.h"
namespace llvm {
@@ -45,7 +46,6 @@ class DFAPacketizer;
template<class T> class SmallVectorImpl;
-
//---------------------------------------------------------------------------
///
/// TargetInstrInfo - Interface to description of machine instruction set
@@ -55,10 +55,11 @@ class TargetInstrInfo : public MCInstrInfo {
void operator=(const TargetInstrInfo &) = delete;
public:
TargetInstrInfo(unsigned CFSetupOpcode = ~0u, unsigned CFDestroyOpcode = ~0u,
- unsigned CatchRetOpcode = ~0u)
+ unsigned CatchRetOpcode = ~0u, unsigned ReturnOpcode = ~0u)
: CallFrameSetupOpcode(CFSetupOpcode),
CallFrameDestroyOpcode(CFDestroyOpcode),
- CatchRetOpcode(CatchRetOpcode) {}
+ CatchRetOpcode(CatchRetOpcode),
+ ReturnOpcode(ReturnOpcode) {}
virtual ~TargetInstrInfo();
@@ -78,10 +79,10 @@ public:
/// This means the only allowed uses are constants and unallocatable physical
/// registers so that the instructions result is independent of the place
/// in the function.
- bool isTriviallyReMaterializable(const MachineInstr *MI,
+ bool isTriviallyReMaterializable(const MachineInstr &MI,
AliasAnalysis *AA = nullptr) const {
- return MI->getOpcode() == TargetOpcode::IMPLICIT_DEF ||
- (MI->getDesc().isRematerializable() &&
+ return MI.getOpcode() == TargetOpcode::IMPLICIT_DEF ||
+ (MI.getDesc().isRematerializable() &&
(isReallyTriviallyReMaterializable(MI, AA) ||
isReallyTriviallyReMaterializableGeneric(MI, AA)));
}
@@ -94,7 +95,7 @@ protected:
/// than producing a value, or if it requres any address registers that are
/// not always available.
/// Requirements must be check as stated in isTriviallyReMaterializable() .
- virtual bool isReallyTriviallyReMaterializable(const MachineInstr *MI,
+ virtual bool isReallyTriviallyReMaterializable(const MachineInstr &MI,
AliasAnalysis *AA) const {
return false;
}
@@ -114,8 +115,7 @@ protected:
/// Do not call this method for a non-commutable instruction.
/// Even though the instruction is commutable, the method may still
/// fail to commute the operands, null pointer is returned in such cases.
- virtual MachineInstr *commuteInstructionImpl(MachineInstr *MI,
- bool NewMI,
+ virtual MachineInstr *commuteInstructionImpl(MachineInstr &MI, bool NewMI,
unsigned OpIdx1,
unsigned OpIdx2) const;
@@ -139,7 +139,7 @@ private:
/// set and the target hook isReallyTriviallyReMaterializable returns false,
/// this function does target-independent tests to determine if the
/// instruction is really trivially rematerializable.
- bool isReallyTriviallyReMaterializableGeneric(const MachineInstr *MI,
+ bool isReallyTriviallyReMaterializableGeneric(const MachineInstr &MI,
AliasAnalysis *AA) const;
public:
@@ -152,12 +152,13 @@ public:
unsigned getCallFrameDestroyOpcode() const { return CallFrameDestroyOpcode; }
unsigned getCatchReturnOpcode() const { return CatchRetOpcode; }
+ unsigned getReturnOpcode() const { return ReturnOpcode; }
/// Returns the actual stack pointer adjustment made by an instruction
/// as part of a call sequence. By default, only call frame setup/destroy
/// instructions adjust the stack, but targets may want to override this
/// to enable more fine-grained adjustment, or adjust by a different value.
- virtual int getSPAdjust(const MachineInstr *MI) const;
+ virtual int getSPAdjust(const MachineInstr &MI) const;
/// Return true if the instruction is a "coalescable" extension instruction.
/// That is, it's like a copy where it's legal for the source to overlap the
@@ -175,14 +176,14 @@ public:
/// the destination along with the FrameIndex of the loaded stack slot. If
/// not, return 0. This predicate must return 0 if the instruction has
/// any side effects other than loading from the stack slot.
- virtual unsigned isLoadFromStackSlot(const MachineInstr *MI,
+ virtual unsigned isLoadFromStackSlot(const MachineInstr &MI,
int &FrameIndex) const {
return 0;
}
/// Check for post-frame ptr elimination stack locations as well.
/// This uses a heuristic so it isn't reliable for correctness.
- virtual unsigned isLoadFromStackSlotPostFE(const MachineInstr *MI,
+ virtual unsigned isLoadFromStackSlotPostFE(const MachineInstr &MI,
int &FrameIndex) const {
return 0;
}
@@ -193,7 +194,7 @@ public:
/// If not, return false. Unlike isLoadFromStackSlot, this returns true for
/// any instructions that loads from the stack. This is just a hint, as some
/// cases may be missed.
- virtual bool hasLoadFromStackSlot(const MachineInstr *MI,
+ virtual bool hasLoadFromStackSlot(const MachineInstr &MI,
const MachineMemOperand *&MMO,
int &FrameIndex) const;
@@ -202,14 +203,14 @@ public:
/// the source reg along with the FrameIndex of the loaded stack slot. If
/// not, return 0. This predicate must return 0 if the instruction has
/// any side effects other than storing to the stack slot.
- virtual unsigned isStoreToStackSlot(const MachineInstr *MI,
+ virtual unsigned isStoreToStackSlot(const MachineInstr &MI,
int &FrameIndex) const {
return 0;
}
/// Check for post-frame ptr elimination stack locations as well.
/// This uses a heuristic, so it isn't reliable for correctness.
- virtual unsigned isStoreToStackSlotPostFE(const MachineInstr *MI,
+ virtual unsigned isStoreToStackSlotPostFE(const MachineInstr &MI,
int &FrameIndex) const {
return 0;
}
@@ -220,14 +221,14 @@ public:
/// If not, return false. Unlike isStoreToStackSlot,
/// this returns true for any instructions that stores to the
/// stack. This is just a hint, as some cases may be missed.
- virtual bool hasStoreToStackSlot(const MachineInstr *MI,
+ virtual bool hasStoreToStackSlot(const MachineInstr &MI,
const MachineMemOperand *&MMO,
int &FrameIndex) const;
/// Return true if the specified machine instruction
/// is a copy of one stack slot to another and has no other effect.
/// Provide the identity of the two frame indices.
- virtual bool isStackSlotCopy(const MachineInstr *MI, int &DestFrameIndex,
+ virtual bool isStackSlotCopy(const MachineInstr &MI, int &DestFrameIndex,
int &SrcFrameIndex) const {
return false;
}
@@ -253,8 +254,20 @@ public:
///
/// Targets for different archs need to override this, and different
/// micro-architectures can also be finely tuned inside.
- virtual bool isAsCheapAsAMove(const MachineInstr *MI) const {
- return MI->isAsCheapAsAMove();
+ virtual bool isAsCheapAsAMove(const MachineInstr &MI) const {
+ return MI.isAsCheapAsAMove();
+ }
+
+ /// Return true if the instruction should be sunk by MachineSink.
+ ///
+ /// MachineSink determines on its own whether the instruction is safe to sink;
+ /// this gives the target a hook to override the default behavior with regards
+ /// to which instructions should be sunk.
+ /// The default behavior is to not sink insert_subreg, subreg_to_reg, and
+ /// reg_sequence. These are meant to be close to the source to make it easier
+ /// to coalesce.
+ virtual bool shouldSink(const MachineInstr &MI) const {
+ return !MI.isInsertSubreg() && !MI.isSubregToReg() && !MI.isRegSequence();
}
/// Re-issue the specified 'original' instruction at the
@@ -263,9 +276,8 @@ public:
/// DestReg:SubIdx. Any existing subreg index is preserved or composed with
/// SubIdx.
virtual void reMaterialize(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI,
- unsigned DestReg, unsigned SubIdx,
- const MachineInstr *Orig,
+ MachineBasicBlock::iterator MI, unsigned DestReg,
+ unsigned SubIdx, const MachineInstr &Orig,
const TargetRegisterInfo &TRI) const;
/// Create a duplicate of the Orig instruction in MF. This is like
@@ -273,7 +285,7 @@ public:
/// that are required to be unique.
///
/// The instruction must be duplicable as indicated by isNotDuplicable().
- virtual MachineInstr *duplicate(MachineInstr *Orig,
+ virtual MachineInstr *duplicate(MachineInstr &Orig,
MachineFunction &MF) const;
/// This method must be implemented by targets that
@@ -286,9 +298,9 @@ public:
/// This method returns a null pointer if the transformation cannot be
/// performed, otherwise it returns the last new instruction.
///
- virtual MachineInstr *
- convertToThreeAddress(MachineFunction::iterator &MFI,
- MachineBasicBlock::iterator &MBBI, LiveVariables *LV) const {
+ virtual MachineInstr *convertToThreeAddress(MachineFunction::iterator &MFI,
+ MachineInstr &MI,
+ LiveVariables *LV) const {
return nullptr;
}
@@ -315,8 +327,7 @@ public:
/// Even though the instruction is commutable, the method may still
/// fail to commute the operands, null pointer is returned in such cases.
MachineInstr *
- commuteInstruction(MachineInstr *MI,
- bool NewMI = false,
+ commuteInstruction(MachineInstr &MI, bool NewMI = false,
unsigned OpIdx1 = CommuteAnyOperandIndex,
unsigned OpIdx2 = CommuteAnyOperandIndex) const;
@@ -337,7 +348,7 @@ public:
/// findCommutedOpIndices(MI, Op1, Op2);
/// can be interpreted as a query asking to find an operand that would be
/// commutable with the operand#1.
- virtual bool findCommutedOpIndices(MachineInstr *MI, unsigned &SrcOpIdx1,
+ virtual bool findCommutedOpIndices(MachineInstr &MI, unsigned &SrcOpIdx1,
unsigned &SrcOpIdx2) const;
/// A pair composed of a register and a sub-register index.
@@ -424,8 +435,8 @@ public:
/// are deemed identical except for defs. If this function is called when the
/// IR is still in SSA form, the caller can pass the MachineRegisterInfo for
/// aggressive checks.
- virtual bool produceSameValue(const MachineInstr *MI0,
- const MachineInstr *MI1,
+ virtual bool produceSameValue(const MachineInstr &MI0,
+ const MachineInstr &MI1,
const MachineRegisterInfo *MRI = nullptr) const;
/// Analyze the branching code at the end of MBB, returning
@@ -453,7 +464,9 @@ public:
/// If AllowModify is true, then this routine is allowed to modify the basic
/// block (e.g. delete instructions after the unconditional branch).
///
- virtual bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
+ /// The CFG information in MBB.Predecessors and MBB.Successors must be valid
+ /// before calling this function.
+ virtual bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
MachineBasicBlock *&FBB,
SmallVectorImpl<MachineOperand> &Cond,
bool AllowModify = false) const {
@@ -499,7 +512,7 @@ public:
/// If AllowModify is true, then this routine is allowed to modify the basic
/// block (e.g. delete instructions after the unconditional branch).
///
- virtual bool AnalyzeBranchPredicate(MachineBasicBlock &MBB,
+ virtual bool analyzeBranchPredicate(MachineBasicBlock &MBB,
MachineBranchPredicate &MBP,
bool AllowModify = false) const {
return true;
@@ -522,10 +535,13 @@ public:
/// cases where AnalyzeBranch doesn't apply because there was no original
/// branch to analyze. At least this much must be implemented, else tail
/// merging needs to be disabled.
+ ///
+ /// The CFG information in MBB.Predecessors and MBB.Successors must be valid
+ /// before calling this function.
virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
MachineBasicBlock *FBB,
ArrayRef<MachineOperand> Cond,
- DebugLoc DL) const {
+ const DebugLoc &DL) const {
llvm_unreachable("Target didn't implement TargetInstrInfo::InsertBranch!");
}
@@ -672,7 +688,7 @@ public:
/// @param TrueReg Virtual register to copy when Cond is true.
/// @param FalseReg Virtual register to copy when Cons is false.
virtual void insertSelect(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator I, DebugLoc DL,
+ MachineBasicBlock::iterator I, const DebugLoc &DL,
unsigned DstReg, ArrayRef<MachineOperand> Cond,
unsigned TrueReg, unsigned FalseReg) const {
llvm_unreachable("Target didn't implement TargetInstrInfo::insertSelect!");
@@ -696,11 +712,11 @@ public:
/// @param FalseOp Operand number of the value selected when Cond is false.
/// @param Optimizable Returned as true if MI is optimizable.
/// @returns False on success.
- virtual bool analyzeSelect(const MachineInstr *MI,
+ virtual bool analyzeSelect(const MachineInstr &MI,
SmallVectorImpl<MachineOperand> &Cond,
unsigned &TrueOp, unsigned &FalseOp,
bool &Optimizable) const {
- assert(MI && MI->getDesc().isSelect() && "MI must be a select instruction");
+ assert(MI.getDesc().isSelect() && "MI must be a select instruction");
return true;
}
@@ -719,7 +735,7 @@ public:
/// MI. Has to be updated with any newly created MI or deleted ones.
/// @param PreferFalse Try to optimize FalseOp instead of TrueOp.
/// @returns Optimized instruction or NULL.
- virtual MachineInstr *optimizeSelect(MachineInstr *MI,
+ virtual MachineInstr *optimizeSelect(MachineInstr &MI,
SmallPtrSetImpl<MachineInstr *> &NewMIs,
bool PreferFalse = false) const {
// This function must be implemented if Optimizable is ever set.
@@ -735,7 +751,7 @@ public:
/// careful implementation when multiple copy instructions are required for
/// large registers. See for example the ARM target.
virtual void copyPhysReg(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI, DebugLoc DL,
+ MachineBasicBlock::iterator MI, const DebugLoc &DL,
unsigned DestReg, unsigned SrcReg,
bool KillSrc) const {
llvm_unreachable("Target didn't implement TargetInstrInfo::copyPhysReg!");
@@ -772,9 +788,7 @@ public:
/// into real instructions. The target can edit MI in place, or it can insert
/// new instructions and erase MI. The function should return true if
/// anything was changed.
- virtual bool expandPostRAPseudo(MachineBasicBlock::iterator MI) const {
- return false;
- }
+ virtual bool expandPostRAPseudo(MachineInstr &MI) const { return false; }
/// Attempt to fold a load or store of the specified stack
/// slot into the specified machine instruction for the specified operand(s).
@@ -782,14 +796,15 @@ public:
/// operand folded, otherwise NULL is returned.
/// The new instruction is inserted before MI, and the client is responsible
/// for removing the old instruction.
- MachineInstr *foldMemoryOperand(MachineBasicBlock::iterator MI,
- ArrayRef<unsigned> Ops, int FrameIndex) const;
+ MachineInstr *foldMemoryOperand(MachineInstr &MI, ArrayRef<unsigned> Ops,
+ int FrameIndex,
+ LiveIntervals *LIS = nullptr) const;
/// Same as the previous version except it allows folding of any load and
/// store from / to any address, not just from a specific stack slot.
- MachineInstr *foldMemoryOperand(MachineBasicBlock::iterator MI,
- ArrayRef<unsigned> Ops,
- MachineInstr *LoadMI) const;
+ MachineInstr *foldMemoryOperand(MachineInstr &MI, ArrayRef<unsigned> Ops,
+ MachineInstr &LoadMI,
+ LiveIntervals *LIS = nullptr) const;
/// Return true when there is potentially a faster code sequence
/// for an instruction chain ending in \p Root. All potential patterns are
@@ -802,6 +817,11 @@ public:
MachineInstr &Root,
SmallVectorImpl<MachineCombinerPattern> &Patterns) const;
+ /// Return true when a code sequence can improve throughput. It
+ /// should be called only for instructions in loops.
+ /// \param Pattern - combiner pattern
+ virtual bool isThroughputPattern(MachineCombinerPattern Pattern) const;
+
/// Return true if the input \P Inst is part of a chain of dependent ops
/// that are suitable for reassociation, otherwise return false.
/// If the instruction's operands must be commuted to have a previous
@@ -850,8 +870,7 @@ public:
virtual void setSpecialOperandAttr(MachineInstr &OldMI1, MachineInstr &OldMI2,
MachineInstr &NewMI1,
MachineInstr &NewMI2) const {
- return;
- };
+ }
/// Return true when a target supports MachineCombiner.
virtual bool useMachineCombiner() const { return false; }
@@ -862,9 +881,11 @@ protected:
/// take care of adding a MachineMemOperand to the newly created instruction.
/// The instruction and any auxiliary instructions necessary will be inserted
/// at InsertPt.
- virtual MachineInstr *foldMemoryOperandImpl(
- MachineFunction &MF, MachineInstr *MI, ArrayRef<unsigned> Ops,
- MachineBasicBlock::iterator InsertPt, int FrameIndex) const {
+ virtual MachineInstr *
+ foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI,
+ ArrayRef<unsigned> Ops,
+ MachineBasicBlock::iterator InsertPt, int FrameIndex,
+ LiveIntervals *LIS = nullptr) const {
return nullptr;
}
@@ -874,8 +895,9 @@ protected:
/// The instruction and any auxiliary instructions necessary will be inserted
/// at InsertPt.
virtual MachineInstr *foldMemoryOperandImpl(
- MachineFunction &MF, MachineInstr *MI, ArrayRef<unsigned> Ops,
- MachineBasicBlock::iterator InsertPt, MachineInstr *LoadMI) const {
+ MachineFunction &MF, MachineInstr &MI, ArrayRef<unsigned> Ops,
+ MachineBasicBlock::iterator InsertPt, MachineInstr &LoadMI,
+ LiveIntervals *LIS = nullptr) const {
return nullptr;
}
@@ -926,9 +948,10 @@ public:
/// unfoldMemoryOperand - Separate a single instruction which folded a load or
/// a store or a load and a store into two or more instruction. If this is
/// possible, returns true as well as the new instructions by reference.
- virtual bool unfoldMemoryOperand(MachineFunction &MF, MachineInstr *MI,
- unsigned Reg, bool UnfoldLoad, bool UnfoldStore,
- SmallVectorImpl<MachineInstr*> &NewMIs) const{
+ virtual bool
+ unfoldMemoryOperand(MachineFunction &MF, MachineInstr &MI, unsigned Reg,
+ bool UnfoldLoad, bool UnfoldStore,
+ SmallVectorImpl<MachineInstr *> &NewMIs) const {
return false;
}
@@ -974,24 +997,26 @@ public:
/// Get the base register and byte offset of an instruction that reads/writes
/// memory.
- virtual bool getMemOpBaseRegImmOfs(MachineInstr *MemOp, unsigned &BaseReg,
- unsigned &Offset,
+ virtual bool getMemOpBaseRegImmOfs(MachineInstr &MemOp, unsigned &BaseReg,
+ int64_t &Offset,
const TargetRegisterInfo *TRI) const {
return false;
}
virtual bool enableClusterLoads() const { return false; }
- virtual bool shouldClusterLoads(MachineInstr *FirstLdSt,
- MachineInstr *SecondLdSt,
- unsigned NumLoads) const {
+ virtual bool enableClusterStores() const { return false; }
+
+ virtual bool shouldClusterMemOps(MachineInstr &FirstLdSt,
+ MachineInstr &SecondLdSt,
+ unsigned NumLoads) const {
return false;
}
/// Can this target fuse the given instructions if they are scheduled
/// adjacent.
- virtual bool shouldScheduleAdjacent(MachineInstr* First,
- MachineInstr *Second) const {
+ virtual bool shouldScheduleAdjacent(MachineInstr &First,
+ MachineInstr &Second) const {
return false;
}
@@ -1012,19 +1037,18 @@ public:
/// Returns true if the instruction is already predicated.
- virtual bool isPredicated(const MachineInstr *MI) const {
+ virtual bool isPredicated(const MachineInstr &MI) const {
return false;
}
/// Returns true if the instruction is a
/// terminator instruction that has not been predicated.
- virtual bool isUnpredicatedTerminator(const MachineInstr *MI) const;
+ virtual bool isUnpredicatedTerminator(const MachineInstr &MI) const;
/// Convert the instruction into a predicated instruction.
/// It returns true if the operation was successful.
- virtual
- bool PredicateInstruction(MachineInstr *MI,
- ArrayRef<MachineOperand> Pred) const;
+ virtual bool PredicateInstruction(MachineInstr &MI,
+ ArrayRef<MachineOperand> Pred) const;
/// Returns true if the first specified predicate
/// subsumes the second, e.g. GE subsumes GT.
@@ -1037,7 +1061,7 @@ 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,
+ virtual bool DefinesPredicate(MachineInstr &MI,
std::vector<MachineOperand> &Pred) const {
return false;
}
@@ -1045,8 +1069,8 @@ public:
/// Return true if the specified instruction can be predicated.
/// By default, this returns true for every instruction with a
/// PredicateOperand.
- virtual bool isPredicable(MachineInstr *MI) const {
- return MI->getDesc().isPredicable();
+ virtual bool isPredicable(MachineInstr &MI) const {
+ return MI.getDesc().isPredicable();
}
/// Return true if it's safe to move a machine
@@ -1057,7 +1081,7 @@ public:
/// Test if the given instruction should be considered a scheduling boundary.
/// This primarily includes labels and terminators.
- virtual bool isSchedulingBoundary(const MachineInstr *MI,
+ virtual bool isSchedulingBoundary(const MachineInstr &MI,
const MachineBasicBlock *MBB,
const MachineFunction &MF) const;
@@ -1084,6 +1108,13 @@ public:
CreateTargetPostRAHazardRecognizer(const InstrItineraryData*,
const ScheduleDAG *DAG) const;
+ /// Allocate and return a hazard recognizer to use for by non-scheduling
+ /// passes.
+ virtual ScheduleHazardRecognizer*
+ CreateTargetPostRAHazardRecognizer(const MachineFunction &MF) const {
+ return nullptr;
+ }
+
/// Provide a global flag for disabling the PreRA hazard recognizer that
/// targets may choose to honor.
bool usePreRAHazardRecognizer() const;
@@ -1092,22 +1123,20 @@ public:
/// in SrcReg and SrcReg2 if having two register operands, and the value it
/// compares against in CmpValue. Return true if the comparison instruction
/// can be analyzed.
- virtual bool analyzeCompare(const MachineInstr *MI,
- unsigned &SrcReg, unsigned &SrcReg2,
- int &Mask, int &Value) const {
+ virtual bool analyzeCompare(const MachineInstr &MI, unsigned &SrcReg,
+ unsigned &SrcReg2, int &Mask, int &Value) const {
return false;
}
/// See if the comparison instruction can be converted
/// into something more efficient. E.g., on ARM most instructions can set the
/// flags register, obviating the need for a separate CMP.
- virtual bool optimizeCompareInstr(MachineInstr *CmpInstr,
- unsigned SrcReg, unsigned SrcReg2,
- int Mask, int Value,
+ virtual bool optimizeCompareInstr(MachineInstr &CmpInstr, unsigned SrcReg,
+ unsigned SrcReg2, int Mask, int Value,
const MachineRegisterInfo *MRI) const {
return false;
}
- virtual bool optimizeCondBranch(MachineInstr *MI) const { return false; }
+ virtual bool optimizeCondBranch(MachineInstr &MI) const { return false; }
/// Try to remove the load by folding it to a register operand at the use.
/// We fold the load instructions if and only if the
@@ -1116,10 +1145,10 @@ public:
/// defined by the load we are trying to fold. DefMI returns the machine
/// instruction that defines FoldAsLoadDefReg, and the function returns
/// the machine instruction generated due to folding.
- virtual MachineInstr* optimizeLoadInstr(MachineInstr *MI,
- const MachineRegisterInfo *MRI,
- unsigned &FoldAsLoadDefReg,
- MachineInstr *&DefMI) const {
+ virtual MachineInstr *optimizeLoadInstr(MachineInstr &MI,
+ const MachineRegisterInfo *MRI,
+ unsigned &FoldAsLoadDefReg,
+ MachineInstr *&DefMI) const {
return nullptr;
}
@@ -1129,7 +1158,7 @@ public:
/// then the caller may assume that DefMI has been erased from its parent
/// block. The caller may assume that it will not be erased by this
/// function otherwise.
- virtual bool FoldImmediate(MachineInstr *UseMI, MachineInstr *DefMI,
+ virtual bool FoldImmediate(MachineInstr &UseMI, MachineInstr &DefMI,
unsigned Reg, MachineRegisterInfo *MRI) const {
return false;
}
@@ -1139,7 +1168,7 @@ public:
/// IssueWidth is the number of microops that can be dispatched each
/// cycle. An instruction with zero microops takes no dispatch resources.
virtual unsigned getNumMicroOps(const InstrItineraryData *ItinData,
- const MachineInstr *MI) const;
+ const MachineInstr &MI) const;
/// Return true for pseudo instructions that don't consume any
/// machine resources in their current form. These are common cases that the
@@ -1162,35 +1191,44 @@ public:
/// by a target. Use computeOperandLatency to get the best estimate of
/// latency.
virtual int getOperandLatency(const InstrItineraryData *ItinData,
- const MachineInstr *DefMI, unsigned DefIdx,
- const MachineInstr *UseMI,
+ const MachineInstr &DefMI, unsigned DefIdx,
+ const MachineInstr &UseMI,
unsigned UseIdx) const;
- /// Compute and return the latency of the given data
- /// dependent def and use when the operand indices are already known.
+ /// Compute and return the latency of the given data dependent def and use
+ /// when the operand indices are already known. UseMI may be \c nullptr for
+ /// an unknown use.
+ ///
+ /// FindMin may be set to get the minimum vs. expected latency. Minimum
+ /// latency is used for scheduling groups, while expected latency is for
+ /// instruction cost and critical path.
+ ///
+ /// Depending on the subtarget's itinerary properties, this may or may not
+ /// need to call getOperandLatency(). For most subtargets, we don't need
+ /// DefIdx or UseIdx to compute min latency.
unsigned computeOperandLatency(const InstrItineraryData *ItinData,
- const MachineInstr *DefMI, unsigned DefIdx,
- const MachineInstr *UseMI, unsigned UseIdx)
- const;
+ const MachineInstr &DefMI, unsigned DefIdx,
+ const MachineInstr *UseMI,
+ unsigned UseIdx) const;
/// Compute the instruction latency of a given instruction.
/// If the instruction has higher cost when predicated, it's returned via
/// PredCost.
virtual unsigned getInstrLatency(const InstrItineraryData *ItinData,
- const MachineInstr *MI,
+ const MachineInstr &MI,
unsigned *PredCost = nullptr) const;
- virtual unsigned getPredicationCost(const MachineInstr *MI) const;
+ virtual unsigned getPredicationCost(const MachineInstr &MI) const;
virtual int getInstrLatency(const InstrItineraryData *ItinData,
SDNode *Node) const;
- /// Return the default expected latency for a def based on it's opcode.
+ /// Return the default expected latency for a def based on its opcode.
unsigned defaultDefLatency(const MCSchedModel &SchedModel,
- const MachineInstr *DefMI) const;
+ const MachineInstr &DefMI) const;
int computeDefOperandLatency(const InstrItineraryData *ItinData,
- const MachineInstr *DefMI) const;
+ const MachineInstr &DefMI) const;
/// Return true if this opcode has high latency to its result.
virtual bool isHighLatencyDef(int opc) const { return false; }
@@ -1200,23 +1238,23 @@ public:
/// it 'high'. This is used by optimization passes such as machine LICM to
/// determine whether it makes sense to hoist an instruction out even in a
/// high register pressure situation.
- virtual
- bool hasHighOperandLatency(const TargetSchedModel &SchedModel,
- const MachineRegisterInfo *MRI,
- const MachineInstr *DefMI, unsigned DefIdx,
- const MachineInstr *UseMI, unsigned UseIdx) const {
+ virtual bool hasHighOperandLatency(const TargetSchedModel &SchedModel,
+ const MachineRegisterInfo *MRI,
+ const MachineInstr &DefMI, unsigned DefIdx,
+ const MachineInstr &UseMI,
+ unsigned UseIdx) const {
return false;
}
/// Compute operand latency of a def of 'Reg'. Return true
/// if the target considered it 'low'.
- virtual
- bool hasLowDefLatency(const TargetSchedModel &SchedModel,
- const MachineInstr *DefMI, unsigned DefIdx) const;
+ virtual bool hasLowDefLatency(const TargetSchedModel &SchedModel,
+ const MachineInstr &DefMI,
+ unsigned DefIdx) const;
/// Perform target-specific instruction verification.
- virtual
- bool verifyInstruction(const MachineInstr *MI, StringRef &ErrInfo) const {
+ virtual bool verifyInstruction(const MachineInstr &MI,
+ StringRef &ErrInfo) const {
return true;
}
@@ -1240,7 +1278,7 @@ public:
/// execution domain.
///
virtual std::pair<uint16_t, uint16_t>
- getExecutionDomain(const MachineInstr *MI) const {
+ getExecutionDomain(const MachineInstr &MI) const {
return std::make_pair(0, 0);
}
@@ -1248,8 +1286,7 @@ public:
///
/// The bit (1 << Domain) must be set in the mask returned from
/// getExecutionDomain(MI).
- virtual void setExecutionDomain(MachineInstr *MI, unsigned Domain) const {}
-
+ virtual void setExecutionDomain(MachineInstr &MI, unsigned Domain) const {}
/// Returns the preferred minimum clearance
/// before an instruction with an unwanted partial register update.
@@ -1291,7 +1328,7 @@ public:
/// allows the target to insert a dependency breaking instruction.
///
virtual unsigned
- getPartialRegUpdateClearance(const MachineInstr *MI, unsigned OpNum,
+ getPartialRegUpdateClearance(const MachineInstr &MI, unsigned OpNum,
const TargetRegisterInfo *TRI) const {
// The default implementation returns 0 for no partial register dependency.
return 0;
@@ -1311,7 +1348,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;
@@ -1334,9 +1371,8 @@ public:
/// An <imp-kill> operand should be added to MI if an instruction was
/// inserted. This ties the instructions together in the post-ra scheduler.
///
- virtual void
- breakPartialRegDependency(MachineBasicBlock::iterator MI, unsigned OpNum,
- const TargetRegisterInfo *TRI) const {}
+ virtual void breakPartialRegDependency(MachineInstr &MI, unsigned OpNum,
+ const TargetRegisterInfo *TRI) const {}
/// Create machine specific model for scheduling.
virtual DFAPacketizer *
@@ -1349,11 +1385,11 @@ public:
// memory addresses. This function returns true if two MIs access different
// memory addresses and false otherwise.
virtual bool
- areMemAccessesTriviallyDisjoint(MachineInstr *MIa, MachineInstr *MIb,
+ areMemAccessesTriviallyDisjoint(MachineInstr &MIa, MachineInstr &MIb,
AliasAnalysis *AA = nullptr) const {
- assert(MIa && (MIa->mayLoad() || MIa->mayStore()) &&
+ assert((MIa.mayLoad() || MIa.mayStore()) &&
"MIa must load from or modify a memory location");
- assert(MIb && (MIb->mayLoad() || MIb->mayStore()) &&
+ assert((MIb.mayLoad() || MIb.mayStore()) &&
"MIb must load from or modify a memory location");
return false;
}
@@ -1406,6 +1442,7 @@ public:
private:
unsigned CallFrameSetupOpcode, CallFrameDestroyOpcode;
unsigned CatchRetOpcode;
+ unsigned ReturnOpcode;
};
/// \brief Provide DenseMapInfo for TargetInstrInfo::RegSubRegPair.
@@ -1435,6 +1472,6 @@ struct DenseMapInfo<TargetInstrInfo::RegSubRegPair> {
}
};
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_TARGET_TARGETINSTRINFO_H
diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h
index 304da4f87519..d21d3215860e 100644
--- a/include/llvm/Target/TargetLowering.h
+++ b/include/llvm/Target/TargetLowering.h
@@ -41,8 +41,10 @@
#include <vector>
namespace llvm {
+ class BranchProbability;
class CallInst;
class CCState;
+ class CCValAssign;
class FastISel;
class FunctionLoweringInfo;
class ImmutableCallSite;
@@ -52,6 +54,7 @@ namespace llvm {
class MachineInstr;
class MachineJumpTableInfo;
class MachineLoop;
+ class MachineRegisterInfo;
class Mangler;
class MCContext;
class MCExpr;
@@ -235,6 +238,11 @@ public:
return false;
}
+ /// Return true if the target can handle a standalone remainder operation.
+ virtual bool hasStandaloneRem(EVT VT) const {
+ return true;
+ }
+
/// Return true if sqrt(x) is as cheap or cheaper than 1 / rsqrt(x)
bool isFsqrtCheap() const {
return FsqrtIsCheap;
@@ -259,18 +267,41 @@ public:
return PredictableSelectIsExpensive;
}
- /// isLoadBitCastBeneficial() - Return true if the following transform
- /// is beneficial.
+ /// If a branch or a select condition is skewed in one direction by more than
+ /// this factor, it is very likely to be predicted correctly.
+ virtual BranchProbability getPredictableBranchThreshold() const;
+
+ /// Return true if the following transform is beneficial:
/// fold (conv (load x)) -> (load (conv*)x)
/// On architectures that don't natively support some vector loads
/// efficiently, casting the load to a smaller vector of larger types and
/// loading is more efficient, however, this can be undone by optimizations in
/// dag combiner.
- virtual bool isLoadBitCastBeneficial(EVT /* Load */,
- EVT /* Bitcast */) const {
+ virtual bool isLoadBitCastBeneficial(EVT LoadVT,
+ EVT BitcastVT) const {
+ // Don't do if we could do an indexed load on the original type, but not on
+ // the new one.
+ if (!LoadVT.isSimple() || !BitcastVT.isSimple())
+ return true;
+
+ MVT LoadMVT = LoadVT.getSimpleVT();
+
+ // Don't bother doing this if it's just going to be promoted again later, as
+ // doing so might interfere with other combines.
+ if (getOperationAction(ISD::LOAD, LoadMVT) == Promote &&
+ getTypeToPromoteTo(ISD::LOAD, LoadMVT) == BitcastVT.getSimpleVT())
+ return false;
+
return true;
}
+ /// Return true if the following transform is beneficial:
+ /// (store (y (conv x)), y*)) -> (store x, (x*))
+ virtual bool isStoreBitCastBeneficial(EVT StoreVT, EVT BitcastVT) const {
+ // Default to the same logic as loads.
+ return isLoadBitCastBeneficial(StoreVT, BitcastVT);
+ }
+
/// Return true if it is expected to be cheaper to do a store of a non-zero
/// vector constant with the given size and type for the address space than to
/// store the individual scalar element constants.
@@ -290,6 +321,14 @@ public:
return false;
}
+ /// Return true if it is safe to transform an integer-domain bitwise operation
+ /// into the equivalent floating-point operation. This should be set to true
+ /// if the target has IEEE-754-compliant fabs/fneg operations for the input
+ /// type.
+ virtual bool hasBitPreservingFPLogic(EVT VT) const {
+ return false;
+ }
+
/// \brief Return if the target supports combining a
/// chain like:
/// \code
@@ -305,6 +344,22 @@ public:
return MaskAndBranchFoldingIsLegal;
}
+ /// Return true if the target should transform:
+ /// (X & Y) == Y ---> (~X & Y) == 0
+ /// (X & Y) != Y ---> (~X & Y) != 0
+ ///
+ /// This may be profitable if the target has a bitwise and-not operation that
+ /// sets comparison flags. A target may want to limit the transformation based
+ /// on the type of Y or if Y is a constant.
+ ///
+ /// Note that the transform will not occur if Y is known to be a power-of-2
+ /// because a mask and compare of a single bit can be handled by inverting the
+ /// predicate, for example:
+ /// (X & 8) == 8 ---> (X & 8) != 0
+ virtual bool hasAndNotCompare(SDValue Y) const {
+ return false;
+ }
+
/// \brief Return true if the target wants to use the optimization that
/// turns ext(promotableInst1(...(promotableInstN(load)))) into
/// promotedInst1(...(promotedInstN(ext(load)))).
@@ -571,6 +626,23 @@ public:
getOperationAction(Op, VT) == Promote);
}
+ /// 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 {
+ return (VT == MVT::Other || isTypeLegal(VT)) &&
+ (getOperationAction(Op, VT) == Legal ||
+ getOperationAction(Op, VT) == Custom ||
+ getOperationAction(Op, VT) == Promote);
+ }
+
+ /// Return true if the specified operation is illegal but has a custom lowering
+ /// on that type. This is used to help guide high-level lowering
+ /// decisions.
+ bool isOperationCustom(unsigned Op, EVT VT) const {
+ return (!isTypeLegal(VT) && getOperationAction(Op, VT) == Custom);
+ }
+
/// Return true if the specified operation is illegal on this target or
/// unlikely to be made legal with custom lowering. This is used to help guide
/// high-level lowering decisions.
@@ -594,21 +666,20 @@ public:
unsigned MemI = (unsigned) MemVT.getSimpleVT().SimpleTy;
assert(ExtType < ISD::LAST_LOADEXT_TYPE && ValI < MVT::LAST_VALUETYPE &&
MemI < MVT::LAST_VALUETYPE && "Table isn't big enough!");
- return LoadExtActions[ValI][MemI][ExtType];
+ unsigned Shift = 4 * ExtType;
+ return (LegalizeAction)((LoadExtActions[ValI][MemI] >> Shift) & 0xf);
}
/// Return true if the specified load with extension is legal on this target.
bool isLoadExtLegal(unsigned ExtType, EVT ValVT, EVT MemVT) const {
- return ValVT.isSimple() && MemVT.isSimple() &&
- getLoadExtAction(ExtType, ValVT, MemVT) == Legal;
+ return getLoadExtAction(ExtType, ValVT, MemVT) == Legal;
}
/// Return true if the specified load with extension is legal or custom
/// on this target.
bool isLoadExtLegalOrCustom(unsigned ExtType, EVT ValVT, EVT MemVT) const {
- return ValVT.isSimple() && MemVT.isSimple() &&
- (getLoadExtAction(ExtType, ValVT, MemVT) == Legal ||
- getLoadExtAction(ExtType, ValVT, MemVT) == Custom);
+ return getLoadExtAction(ExtType, ValVT, MemVT) == Legal ||
+ getLoadExtAction(ExtType, ValVT, MemVT) == Custom;
}
/// Return how this store with truncation should be treated: either it is
@@ -626,8 +697,15 @@ public:
/// Return true if the specified store with truncation is legal on this
/// target.
bool isTruncStoreLegal(EVT ValVT, EVT MemVT) const {
- return isTypeLegal(ValVT) && MemVT.isSimple() &&
- getTruncStoreAction(ValVT.getSimpleVT(), MemVT.getSimpleVT()) == Legal;
+ return isTypeLegal(ValVT) && getTruncStoreAction(ValVT, MemVT) == Legal;
+ }
+
+ /// Return true if the specified store with truncation has solution on this
+ /// target.
+ bool isTruncStoreLegalOrCustom(EVT ValVT, EVT MemVT) const {
+ return isTypeLegal(ValVT) &&
+ (getTruncStoreAction(ValVT, MemVT) == Legal ||
+ getTruncStoreAction(ValVT, MemVT) == Custom);
}
/// Return how the indexed load should be treated: either it is legal, needs
@@ -672,7 +750,7 @@ public:
LegalizeAction
getCondCodeAction(ISD::CondCode CC, MVT VT) const {
assert((unsigned)CC < array_lengthof(CondCodeActions) &&
- ((unsigned)VT.SimpleTy >> 4) < array_lengthof(CondCodeActions[0]) &&
+ ((unsigned)VT.SimpleTy >> 3) < array_lengthof(CondCodeActions[0]) &&
"Table isn't big enough!");
// See setCondCodeAction for how this is encoded.
uint32_t Shift = 4 * (VT.SimpleTy & 0x7);
@@ -960,6 +1038,10 @@ public:
return 0;
}
+ virtual bool needsFixedCatchObjects() const {
+ report_fatal_error("Funclet EH is not implemented for this target");
+ }
+
/// Returns the target's jmp_buf size in bytes (if never set, the default is
/// 200)
unsigned getJumpBufSize() const {
@@ -992,19 +1074,26 @@ public:
return PrefLoopAlignment;
}
- /// Return whether the DAG builder should automatically insert fences and
- /// reduce ordering for atomics.
- bool getInsertFencesForAtomic() const {
- return InsertFencesForAtomic;
- }
+ /// If the target has a standard location for the stack protector guard,
+ /// returns the address of that location. Otherwise, returns nullptr.
+ /// DEPRECATED: please override useLoadStackGuardNode and customize
+ /// LOAD_STACK_GUARD, or customize @llvm.stackguard().
+ virtual Value *getIRStackGuard(IRBuilder<> &IRB) const;
- /// Return true if the target stores stack protector cookies at a fixed offset
- /// in some non-standard address space, and populates the address space and
- /// offset as appropriate.
- virtual bool getStackCookieLocation(unsigned &/*AddressSpace*/,
- unsigned &/*Offset*/) const {
- return false;
- }
+ /// Inserts necessary declarations for SSP (stack protection) purpose.
+ /// Should be used only when getIRStackGuard returns nullptr.
+ virtual void insertSSPDeclarations(Module &M) const;
+
+ /// Return the variable that's previously inserted by insertSSPDeclarations,
+ /// if any, otherwise return nullptr. Should be used only when
+ /// getIRStackGuard returns nullptr.
+ virtual Value *getSDagStackGuard(const Module &M) const;
+
+ /// If the target has a standard stack protection check function that
+ /// performs validation and error handling, returns the function. Otherwise,
+ /// returns nullptr. Must be previously inserted by insertSSPDeclarations.
+ /// Should be used only when getIRStackGuard returns nullptr.
+ virtual Value *getSSPStackGuardCheck(const Module &M) const;
/// If the target has a standard location for the unsafe stack pointer,
/// returns the address of that location. Otherwise, returns nullptr.
@@ -1041,6 +1130,30 @@ public:
/// \name Helpers for atomic expansion.
/// @{
+ /// Returns the maximum atomic operation size (in bits) supported by
+ /// the backend. Atomic operations greater than this size (as well
+ /// as ones that are not naturally aligned), will be expanded by
+ /// AtomicExpandPass into an __atomic_* library call.
+ unsigned getMaxAtomicSizeInBitsSupported() const {
+ return MaxAtomicSizeInBitsSupported;
+ }
+
+ /// Returns the size of the smallest cmpxchg or ll/sc instruction
+ /// the backend supports. Any smaller operations are widened in
+ /// AtomicExpandPass.
+ ///
+ /// Note that *unlike* operations above the maximum size, atomic ops
+ /// are still natively supported below the minimum; they just
+ /// require a more complex expansion.
+ unsigned getMinCmpXchgSizeInBits() const { return MinCmpXchgSizeInBits; }
+
+ /// Whether AtomicExpandPass should automatically insert fences and reduce
+ /// ordering for this atomic. This should be true for most architectures with
+ /// weak memory ordering. Defaults to false.
+ virtual bool shouldInsertFencesForAtomic(const Instruction *I) const {
+ return false;
+ }
+
/// Perform a load-linked operation on Addr, returning a "Value *" with the
/// corresponding pointee type. This may entail some non-trivial operations to
/// truncate or reconstruct types that will be illegal in the backend. See
@@ -1059,12 +1172,12 @@ public:
/// Inserts in the IR a target-specific intrinsic specifying a fence.
/// It is called by AtomicExpandPass before expanding an
- /// AtomicRMW/AtomicCmpXchg/AtomicStore/AtomicLoad.
+ /// AtomicRMW/AtomicCmpXchg/AtomicStore/AtomicLoad
+ /// if shouldInsertFencesForAtomic returns true.
/// RMW and CmpXchg set both IsStore and IsLoad to true.
/// This function should either return a nullptr, or a pointer to an IR-level
/// Instruction*. Even complex fence sequences can be represented by a
/// single Instruction* through an intrinsic to be lowered later.
- /// Backends with !getInsertFencesForAtomic() should keep a no-op here.
/// Backends should override this method to produce target-specific intrinsic
/// for their fences.
/// FIXME: Please note that the default implementation here in terms of
@@ -1090,10 +1203,7 @@ public:
virtual Instruction *emitLeadingFence(IRBuilder<> &Builder,
AtomicOrdering Ord, bool IsStore,
bool IsLoad) const {
- if (!getInsertFencesForAtomic())
- return nullptr;
-
- if (isAtLeastRelease(Ord) && IsStore)
+ if (isReleaseOrStronger(Ord) && IsStore)
return Builder.CreateFence(Ord);
else
return nullptr;
@@ -1102,10 +1212,7 @@ public:
virtual Instruction *emitTrailingFence(IRBuilder<> &Builder,
AtomicOrdering Ord, bool IsStore,
bool IsLoad) const {
- if (!getInsertFencesForAtomic())
- return nullptr;
-
- if (isAtLeastAcquire(Ord))
+ if (isAcquireOrStronger(Ord))
return Builder.CreateFence(Ord);
else
return nullptr;
@@ -1166,6 +1273,14 @@ public:
return nullptr;
}
+ /// Returns how the platform's atomic operations are extended (ZERO_EXTEND,
+ /// SIGN_EXTEND, or ANY_EXTEND).
+ virtual ISD::NodeType getExtendForAtomicOps() const {
+ return ISD::ZERO_EXTEND;
+ }
+
+ /// @}
+
/// Returns true if we should normalize
/// select(N0&N1, X, Y) => select(N0, select(N1, X, Y), Y) and
/// select(N0|N1, X, Y) => select(N0, select(N1, X, Y, Y)) if it is likely
@@ -1324,7 +1439,10 @@ protected:
LegalizeAction Action) {
assert(ExtType < ISD::LAST_LOADEXT_TYPE && ValVT.isValid() &&
MemVT.isValid() && "Table isn't big enough!");
- LoadExtActions[(unsigned)ValVT.SimpleTy][MemVT.SimpleTy][ExtType] = Action;
+ assert((unsigned)Action < 0x10 && "too many bits for bitfield array");
+ unsigned Shift = 4 * ExtType;
+ LoadExtActions[ValVT.SimpleTy][MemVT.SimpleTy] &= ~((uint16_t)0xF << Shift);
+ LoadExtActions[ValVT.SimpleTy][MemVT.SimpleTy] |= (uint16_t)Action << Shift;
}
/// Indicate that the specified truncating store does not work with the
@@ -1386,6 +1504,13 @@ protected:
PromoteToType[std::make_pair(Opc, OrigVT.SimpleTy)] = DestVT.SimpleTy;
}
+ /// Convenience method to set an operation to Promote and specify the type
+ /// in a single call.
+ void setOperationPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT) {
+ setOperationAction(Opc, OrigVT, Promote);
+ AddPromotedToType(Opc, OrigVT, DestVT);
+ }
+
/// Targets should invoke this method for each target independent node that
/// they want to provide a custom DAG combiner for by implementing the
/// PerformDAGCombine virtual method.
@@ -1430,10 +1555,17 @@ protected:
MinStackArgumentAlignment = Align;
}
- /// Set if the DAG builder should automatically insert fences and reduce the
- /// order of atomic memory operations to Monotonic.
- void setInsertFencesForAtomic(bool fence) {
- InsertFencesForAtomic = fence;
+ /// Set the maximum atomic operation size supported by the
+ /// backend. Atomic operations greater than this size (as well as
+ /// ones that are not naturally aligned), will be expanded by
+ /// AtomicExpandPass into an __atomic_* library call.
+ void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits) {
+ MaxAtomicSizeInBitsSupported = SizeInBits;
+ }
+
+ // Sets the minimum cmpxchg or ll/sc size supported by the backend.
+ void setMinCmpXchgSizeInBits(unsigned SizeInBits) {
+ MinCmpXchgSizeInBits = SizeInBits;
}
public:
@@ -1845,10 +1977,13 @@ private:
/// The preferred loop alignment.
unsigned PrefLoopAlignment;
- /// Whether the DAG builder should automatically insert fences and reduce
- /// ordering for atomics. (This will be set for for most architectures with
- /// weak memory ordering.)
- bool InsertFencesForAtomic;
+ /// Size in bits of the maximum atomics size the backend supports.
+ /// Accesses larger than this will be expanded by AtomicExpandPass.
+ unsigned MaxAtomicSizeInBitsSupported;
+
+ /// Size in bits of the minimum cmpxchg or ll/sc operation the
+ /// backend supports.
+ unsigned MinCmpXchgSizeInBits;
/// If set to a physical register, this specifies the register that
/// llvm.savestack/llvm.restorestack should save and restore.
@@ -1889,9 +2024,9 @@ private:
/// For each load extension type and each value type, keep a LegalizeAction
/// that indicates how instruction selection should deal with a load of a
- /// specific value type and extension type.
- LegalizeAction LoadExtActions[MVT::LAST_VALUETYPE][MVT::LAST_VALUETYPE]
- [ISD::LAST_LOADEXT_TYPE];
+ /// specific value type and extension type. Uses 4-bits to store the action
+ /// for each of the 4 load ext types.
+ uint16_t LoadExtActions[MVT::LAST_VALUETYPE][MVT::LAST_VALUETYPE];
/// For each value type pair keep a LegalizeAction that indicates whether a
/// truncating store of a specific value type and truncating type is legal.
@@ -2026,7 +2161,7 @@ protected:
/// Replace/modify any TargetFrameIndex operands with a targte-dependent
/// sequence of memory operands that is recognized by PrologEpilogInserter.
- MachineBasicBlock *emitPatchPoint(MachineInstr *MI,
+ MachineBasicBlock *emitPatchPoint(MachineInstr &MI,
MachineBasicBlock *MBB) const;
};
@@ -2043,6 +2178,8 @@ public:
/// NOTE: The TargetMachine owns TLOF.
explicit TargetLowering(const TargetMachine &TM);
+ bool isPositionIndependent() const;
+
/// Returns true by value, base pointer and offset pointer and addressing mode
/// by reference if the node's address can be legally represented as
/// pre-indexed load / store address.
@@ -2092,18 +2229,26 @@ public:
bool isInTailCallPosition(SelectionDAG &DAG, SDNode *Node,
SDValue &Chain) const;
- void softenSetCCOperands(SelectionDAG &DAG, EVT VT,
- SDValue &NewLHS, SDValue &NewRHS,
- ISD::CondCode &CCCode, SDLoc DL) const;
+ void softenSetCCOperands(SelectionDAG &DAG, EVT VT, SDValue &NewLHS,
+ SDValue &NewRHS, ISD::CondCode &CCCode,
+ const SDLoc &DL) const;
/// Returns a pair of (return value, chain).
/// It is an error to pass RTLIB::UNKNOWN_LIBCALL as \p LC.
std::pair<SDValue, SDValue> makeLibCall(SelectionDAG &DAG, RTLIB::Libcall LC,
EVT RetVT, ArrayRef<SDValue> Ops,
- bool isSigned, SDLoc dl,
+ bool isSigned, const SDLoc &dl,
bool doesNotReturn = false,
bool isReturnValueUsed = true) 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<CCValAssign> &ArgLocs,
+ const SmallVectorImpl<SDValue> &OutVals) const;
+
//===--------------------------------------------------------------------===//
// TargetLowering Optimization Methods
//
@@ -2141,7 +2286,7 @@ public:
/// uses isZExtFree and ZERO_EXTEND for the widening cast, but it could be
/// generalized for targets with other types of implicit widening casts.
bool ShrinkDemandedOp(SDValue Op, unsigned BitWidth, const APInt &Demanded,
- SDLoc dl);
+ const SDLoc &dl);
};
/// Look at Op. At this point, we know that only the DemandedMask bits of the
@@ -2204,11 +2349,14 @@ public:
/// from getBooleanContents().
bool isConstFalseVal(const SDNode *N) const;
+ /// Return if \p N is a True value when extended to \p VT.
+ bool isExtendedTrueVal(const ConstantSDNode *N, EVT VT, bool Signed) const;
+
/// Try to simplify a setcc built with the specified operands and cc. If it is
/// unable to simplify it, return a null SDValue.
- SDValue SimplifySetCC(EVT VT, SDValue N0, SDValue N1,
- ISD::CondCode Cond, bool foldBooleans,
- DAGCombinerInfo &DCI, SDLoc dl) const;
+ SDValue SimplifySetCC(EVT VT, SDValue N0, SDValue N1, ISD::CondCode Cond,
+ bool foldBooleans, DAGCombinerInfo &DCI,
+ const SDLoc &dl) const;
/// Returns true (and the GlobalValue and the offset) if the node is a
/// GlobalAddress + offset.
@@ -2263,6 +2411,12 @@ public:
return false;
}
+ /// Return true if the target supports swifterror attribute. It optimizes
+ /// loads and stores to reading and writing a specific register.
+ virtual bool supportSwiftError() const {
+ return false;
+ }
+
/// Return true if the target supports that a subset of CSRs for the given
/// machine function is handled explicitly via copies.
virtual bool supportSplitCSR(MachineFunction *MF) const {
@@ -2302,12 +2456,10 @@ public:
/// should fill in the InVals array with legal-type argument values, and
/// return the resulting token chain value.
///
- virtual SDValue
- LowerFormalArguments(SDValue /*Chain*/, CallingConv::ID /*CallConv*/,
- bool /*isVarArg*/,
- const SmallVectorImpl<ISD::InputArg> &/*Ins*/,
- SDLoc /*dl*/, SelectionDAG &/*DAG*/,
- SmallVectorImpl<SDValue> &/*InVals*/) const {
+ virtual SDValue LowerFormalArguments(
+ SDValue /*Chain*/, CallingConv::ID /*CallConv*/, bool /*isVarArg*/,
+ const SmallVectorImpl<ISD::InputArg> & /*Ins*/, const SDLoc & /*dl*/,
+ SelectionDAG & /*DAG*/, SmallVectorImpl<SDValue> & /*InVals*/) const {
llvm_unreachable("Not Implemented");
}
@@ -2322,11 +2474,14 @@ public:
bool isByVal : 1;
bool isInAlloca : 1;
bool isReturned : 1;
+ bool isSwiftSelf : 1;
+ bool isSwiftError : 1;
uint16_t Alignment;
ArgListEntry() : isSExt(false), isZExt(false), isInReg(false),
isSRet(false), isNest(false), isByVal(false), isInAlloca(false),
- isReturned(false), Alignment(0) { }
+ isReturned(false), isSwiftSelf(false), isSwiftError(false),
+ Alignment(0) { }
void setAttributes(ImmutableCallSite *CS, unsigned AttrIdx);
};
@@ -2345,6 +2500,7 @@ public:
bool IsInReg : 1;
bool DoesNotReturn : 1;
bool IsReturnValueUsed : 1;
+ bool IsConvergent : 1;
// IsTailCall should be modified by implementations of
// TargetLowering::LowerCall that perform tail call conversions.
@@ -2361,14 +2517,16 @@ public:
SmallVector<ISD::OutputArg, 32> Outs;
SmallVector<SDValue, 32> OutVals;
SmallVector<ISD::InputArg, 32> Ins;
+ SmallVector<SDValue, 4> InVals;
CallLoweringInfo(SelectionDAG &DAG)
- : RetTy(nullptr), RetSExt(false), RetZExt(false), IsVarArg(false),
- IsInReg(false), DoesNotReturn(false), IsReturnValueUsed(true),
- IsTailCall(false), NumFixedArgs(-1), CallConv(CallingConv::C),
- DAG(DAG), CS(nullptr), IsPatchPoint(false) {}
+ : RetTy(nullptr), RetSExt(false), RetZExt(false), IsVarArg(false),
+ IsInReg(false), DoesNotReturn(false), IsReturnValueUsed(true),
+ IsConvergent(false), IsTailCall(false), NumFixedArgs(-1),
+ CallConv(CallingConv::C), DAG(DAG), CS(nullptr), IsPatchPoint(false) {
+ }
- CallLoweringInfo &setDebugLoc(SDLoc dl) {
+ CallLoweringInfo &setDebugLoc(const SDLoc &dl) {
DL = dl;
return *this;
}
@@ -2379,13 +2537,11 @@ public:
}
CallLoweringInfo &setCallee(CallingConv::ID CC, Type *ResultType,
- SDValue Target, ArgListTy &&ArgsList,
- unsigned FixedArgs = -1) {
+ SDValue Target, ArgListTy &&ArgsList) {
RetTy = ResultType;
Callee = Target;
CallConv = CC;
- NumFixedArgs =
- (FixedArgs == static_cast<unsigned>(-1) ? Args.size() : FixedArgs);
+ NumFixedArgs = Args.size();
Args = std::move(ArgsList);
return *this;
}
@@ -2396,7 +2552,10 @@ public:
RetTy = ResultType;
IsInReg = Call.paramHasAttr(0, Attribute::InReg);
- DoesNotReturn = Call.doesNotReturn();
+ DoesNotReturn =
+ Call.doesNotReturn() ||
+ (!Call.isInvoke() &&
+ isa<UnreachableInst>(Call.getInstruction()->getNextNode()));
IsVarArg = FTy->isVarArg();
IsReturnValueUsed = !Call.getInstruction()->use_empty();
RetSExt = Call.paramHasAttr(0, Attribute::SExt);
@@ -2438,6 +2597,11 @@ public:
return *this;
}
+ CallLoweringInfo &setConvergent(bool Value = true) {
+ IsConvergent = Value;
+ return *this;
+ }
+
CallLoweringInfo &setSExtResult(bool Value = true) {
RetSExt = Value;
return *this;
@@ -2494,12 +2658,12 @@ public:
/// This hook must be implemented to lower outgoing return values, described
/// by the Outs array, into the specified DAG. The implementation should
/// return the resulting token chain value.
- virtual SDValue
- LowerReturn(SDValue /*Chain*/, CallingConv::ID /*CallConv*/,
- bool /*isVarArg*/,
- const SmallVectorImpl<ISD::OutputArg> &/*Outs*/,
- const SmallVectorImpl<SDValue> &/*OutVals*/,
- SDLoc /*dl*/, SelectionDAG &/*DAG*/) const {
+ virtual SDValue LowerReturn(SDValue /*Chain*/, CallingConv::ID /*CallConv*/,
+ bool /*isVarArg*/,
+ const SmallVectorImpl<ISD::OutputArg> & /*Outs*/,
+ const SmallVectorImpl<SDValue> & /*OutVals*/,
+ const SDLoc & /*dl*/,
+ SelectionDAG & /*DAG*/) const {
llvm_unreachable("Not Implemented");
}
@@ -2534,12 +2698,12 @@ public:
}
/// Return the type that should be used to zero or sign extend a
- /// zeroext/signext integer argument or return value. FIXME: Most C calling
- /// convention requires the return type to be promoted, but this is not true
- /// all the time, e.g. i1 on x86-64. It is also not necessary for non-C
- /// calling conventions. The frontend should handle this and include all of
- /// the necessary information.
- virtual EVT getTypeForExtArgOrReturn(LLVMContext &Context, EVT VT,
+ /// zeroext/signext integer return value. FIXME: Some C calling conventions
+ /// require the return type to be promoted, but this is not true all the time,
+ /// e.g. i1/i8/i16 on x86/x86_64. It is also not necessary for non-C calling
+ /// conventions. The frontend should handle this and include all of the
+ /// necessary information.
+ virtual EVT getTypeForExtReturn(LLVMContext &Context, EVT VT,
ISD::NodeType /*ExtendKind*/) const {
EVT MinVT = getRegisterType(Context, MVT::i32);
return VT.bitsLT(MinVT) ? MinVT : VT;
@@ -2567,7 +2731,7 @@ public:
/// which allows a CPU to reuse the result of a previous load indefinitely,
/// even if a cache-coherent store is performed by another CPU. The default
/// implementation does nothing.
- virtual SDValue prepareVolatileOrAtomicLoad(SDValue Chain, SDLoc DL,
+ virtual SDValue prepareVolatileOrAtomicLoad(SDValue Chain, const SDLoc &DL,
SelectionDAG &DAG) const {
return Chain;
}
@@ -2840,6 +3004,25 @@ public:
/// \returns True, if the expansion was successful, false otherwise
bool expandFP_TO_SINT(SDNode *N, SDValue &Result, SelectionDAG &DAG) const;
+ /// Turn load of vector type into a load of the individual elements.
+ /// \param LD load to expand
+ /// \returns MERGE_VALUEs of the scalar loads with their chains.
+ SDValue scalarizeVectorLoad(LoadSDNode *LD, SelectionDAG &DAG) const;
+
+ // Turn a store of a vector type into stores of the individual elements.
+ /// \param ST Store with a vector value type
+ /// \returns MERGE_VALUs of the individual store chains.
+ SDValue scalarizeVectorStore(StoreSDNode *ST, SelectionDAG &DAG) const;
+
+ /// Expands an unaligned load to 2 half-size loads for an integer, and
+ /// possibly more for vectors.
+ std::pair<SDValue, SDValue> expandUnalignedLoad(LoadSDNode *LD,
+ SelectionDAG &DAG) const;
+
+ /// Expands an unaligned store to 2 half-size stores for integer values, and
+ /// possibly more for vectors.
+ SDValue expandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG) const;
+
//===--------------------------------------------------------------------===//
// Instruction Emitting Hooks
//
@@ -2853,14 +3036,14 @@ public:
/// As long as the returned basic block is different (i.e., we created a new
/// one), the custom inserter is free to modify the rest of \p MBB.
virtual MachineBasicBlock *
- EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const;
+ EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const;
/// This method should be implemented by targets that mark instructions with
/// the 'hasPostISelHook' flag. These instructions must be adjusted after
/// instruction selection by target hooks. e.g. To fill in optional defs for
/// ARM 's' setting instructions.
- virtual void
- AdjustInstrPostInstrSelection(MachineInstr *MI, SDNode *Node) const;
+ virtual void AdjustInstrPostInstrSelection(MachineInstr &MI,
+ SDNode *Node) const;
/// If this function returns true, SelectionDAGBuilder emits a
/// LOAD_STACK_GUARD node when it is lowering Intrinsic::stackprotector.
@@ -2871,6 +3054,11 @@ public:
/// Lower TLS global address SDNode for target independent emulated TLS model.
virtual SDValue LowerToTLSEmulatedModel(const GlobalAddressSDNode *GA,
SelectionDAG &DAG) const;
+
+private:
+ SDValue simplifySetCCWithAnd(EVT VT, SDValue N0, SDValue N1,
+ ISD::CondCode Cond, DAGCombinerInfo &DCI,
+ const SDLoc &DL) const;
};
/// Given an LLVM IR type and return type attributes, compute the return value
diff --git a/include/llvm/Target/TargetLoweringObjectFile.h b/include/llvm/Target/TargetLoweringObjectFile.h
index cb52698c58b9..189eff4f3953 100644
--- a/include/llvm/Target/TargetLoweringObjectFile.h
+++ b/include/llvm/Target/TargetLoweringObjectFile.h
@@ -71,7 +71,8 @@ public:
/// placed in.
virtual MCSection *getSectionForConstant(const DataLayout &DL,
SectionKind Kind,
- const Constant *C) const;
+ const Constant *C,
+ unsigned &Align) const;
/// Classify the specified global variable into a set of target independent
/// categories embodied in SectionKind.
@@ -154,8 +155,8 @@ public:
virtual const MCExpr *getDebugThreadLocalSymbol(const MCSymbol *Sym) const;
virtual const MCExpr *
- getExecutableRelativeSymbol(const ConstantExpr *CE, Mangler &Mang,
- const TargetMachine &TM) const {
+ lowerRelativeReference(const GlobalValue *LHS, const GlobalValue *RHS,
+ Mangler &Mang, const TargetMachine &TM) const {
return nullptr;
}
diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h
index 74e91b5790cb..563fef96acfc 100644
--- a/include/llvm/Target/TargetMachine.h
+++ b/include/llvm/Target/TargetMachine.h
@@ -29,15 +29,14 @@ class InstrItineraryData;
class GlobalValue;
class Mangler;
class MachineFunctionInitializer;
+class MachineModuleInfo;
class MCAsmInfo;
-class MCCodeGenInfo;
class MCContext;
class MCInstrInfo;
class MCRegisterInfo;
class MCSubtargetInfo;
class MCSymbol;
class Target;
-class DataLayout;
class TargetLibraryInfo;
class TargetFrameLowering;
class TargetIRAnalysis;
@@ -45,7 +44,6 @@ class TargetIntrinsicInfo;
class TargetLowering;
class TargetPassConfig;
class TargetRegisterInfo;
-class TargetSelectionDAGInfo;
class TargetSubtargetInfo;
class TargetTransformInfo;
class formatted_raw_ostream;
@@ -90,9 +88,9 @@ protected: // Can only create subclasses.
std::string TargetCPU;
std::string TargetFS;
- /// Low level target information such as relocation model. Non-const to
- /// allow resetting optimization level per-function.
- MCCodeGenInfo *CodeGenInfo;
+ Reloc::Model RM = Reloc::Static;
+ CodeModel::Model CMModel = CodeModel::Default;
+ CodeGenOpt::Level OptLevel = CodeGenOpt::Default;
/// Contains target specific asm information.
const MCAsmInfo *AsmInfo;
@@ -104,11 +102,6 @@ protected: // Can only create subclasses.
unsigned RequireStructuredCFG : 1;
unsigned O0WantsFastISel : 1;
- /// This API is here to support the C API, deprecated in 3.7 release.
- /// This should never be used outside of legacy existing client.
- const DataLayout &getDataLayout() const { return DL; }
- friend struct C_API_PRIVATE_ACCESS;
-
public:
mutable TargetOptions Options;
@@ -181,6 +174,10 @@ public:
/// target default.
CodeModel::Model getCodeModel() const;
+ bool isPositionIndependent() const;
+
+ bool shouldAssumeDSOLocal(const Module &M, const GlobalValue *GV) const;
+
/// Returns the TLS model which should be used for the given global variable.
TLSModel::Model getTLSModel(const GlobalValue *GV) const;
@@ -188,7 +185,7 @@ public:
CodeGenOpt::Level getOptLevel() const;
/// \brief Overrides the optimization level.
- void setOptLevel(CodeGenOpt::Level Level) const;
+ void setOptLevel(CodeGenOpt::Level Level);
void setFastISel(bool Enable) { Options.EnableFastISel = Enable; }
bool getO0WantsFastISel() { return O0WantsFastISel; }
@@ -223,6 +220,11 @@ public:
/// uses this to answer queries about the IR.
virtual TargetIRAnalysis getTargetIRAnalysis();
+ /// Add target-specific function passes that should be run as early as
+ /// possible in the optimization pipeline. Most TargetMachines have no such
+ /// passes.
+ virtual void addEarlyAsPossiblePasses(PassManagerBase &) {}
+
/// These enums are meant to be passed into addPassesToEmitFile to indicate
/// what type of file to emit, and returned by it to indicate what type of
/// file could actually be made.
@@ -265,6 +267,12 @@ public:
void getNameWithPrefix(SmallVectorImpl<char> &Name, const GlobalValue *GV,
Mangler &Mang, bool MayAlwaysUsePrivate = false) const;
MCSymbol *getSymbol(const GlobalValue *GV, Mangler &Mang) const;
+
+ /// True if the target uses physical regs at Prolog/Epilog insertion
+ /// time. If true (most machines), all vregs must be allocated before
+ /// PEI. If false (virtual-register machines), then callee-save register
+ /// spilling and scavenging are not needed or used.
+ virtual bool usesPhysRegsForPEI() const { return true; }
};
/// This class describes a target machine that is implemented with the LLVM
@@ -304,6 +312,13 @@ public:
bool addPassesToEmitMC(PassManagerBase &PM, MCContext *&Ctx,
raw_pwrite_stream &OS,
bool DisableVerify = true) override;
+
+ /// Add MachineModuleInfo pass to pass manager.
+ MachineModuleInfo &addMachineModuleInfo(PassManagerBase &PM) const;
+
+ /// Add MachineFunctionAnalysis pass to pass manager.
+ void addMachineFunctionAnalysis(PassManagerBase &PM,
+ MachineFunctionInitializer *MFInitializer) const;
};
} // End llvm namespace
diff --git a/include/llvm/Target/TargetOpcodes.def b/include/llvm/Target/TargetOpcodes.def
new file mode 100644
index 000000000000..abab6c7a2a7c
--- /dev/null
+++ b/include/llvm/Target/TargetOpcodes.def
@@ -0,0 +1,177 @@
+//===-- llvm/Target/TargetOpcodes.def - Target Indep Opcodes ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the target independent instruction opcodes.
+//
+//===----------------------------------------------------------------------===//
+
+// NOTE: NO INCLUDE GUARD DESIRED!
+
+/// HANDLE_TARGET_OPCODE defines an opcode and its associated enum value.
+///
+#ifndef HANDLE_TARGET_OPCODE
+#define HANDLE_TARGET_OPCODE(OPC, NUM)
+#endif
+
+/// HANDLE_TARGET_OPCODE_MARKER defines an alternative identifier for an opcode.
+///
+#ifndef HANDLE_TARGET_OPCODE_MARKER
+#define HANDLE_TARGET_OPCODE_MARKER(IDENT, OPC)
+#endif
+
+/// Every instruction defined here must also appear in Target.td.
+///
+HANDLE_TARGET_OPCODE(PHI, 0)
+HANDLE_TARGET_OPCODE(INLINEASM, 1)
+HANDLE_TARGET_OPCODE(CFI_INSTRUCTION, 2)
+HANDLE_TARGET_OPCODE(EH_LABEL, 3)
+HANDLE_TARGET_OPCODE(GC_LABEL, 4)
+
+/// KILL - This instruction is a noop that is used only to adjust the
+/// liveness of registers. This can be useful when dealing with
+/// sub-registers.
+HANDLE_TARGET_OPCODE(KILL, 5)
+
+/// EXTRACT_SUBREG - This instruction takes two operands: a register
+/// that has subregisters, and a subregister index. It returns the
+/// extracted subregister value. This is commonly used to implement
+/// truncation operations on target architectures which support it.
+HANDLE_TARGET_OPCODE(EXTRACT_SUBREG, 6)
+
+/// INSERT_SUBREG - This instruction takes three operands: a register that
+/// has subregisters, a register providing an insert value, and a
+/// subregister index. It returns the value of the first register with the
+/// value of the second register inserted. The first register is often
+/// defined by an IMPLICIT_DEF, because it is commonly used to implement
+/// anyext operations on target architectures which support it.
+HANDLE_TARGET_OPCODE(INSERT_SUBREG, 7)
+
+/// IMPLICIT_DEF - This is the MachineInstr-level equivalent of undef.
+HANDLE_TARGET_OPCODE(IMPLICIT_DEF, 8)
+
+/// SUBREG_TO_REG - This instruction is similar to INSERT_SUBREG except that
+/// the first operand is an immediate integer constant. This constant is
+/// often zero, because it is commonly used to assert that the instruction
+/// defining the register implicitly clears the high bits.
+HANDLE_TARGET_OPCODE(SUBREG_TO_REG, 9)
+
+/// COPY_TO_REGCLASS - This instruction is a placeholder for a plain
+/// register-to-register copy into a specific register class. This is only
+/// used between instruction selection and MachineInstr creation, before
+/// virtual registers have been created for all the instructions, and it's
+/// only needed in cases where the register classes implied by the
+/// instructions are insufficient. It is emitted as a COPY MachineInstr.
+HANDLE_TARGET_OPCODE(COPY_TO_REGCLASS, 10)
+
+/// DBG_VALUE - a mapping of the llvm.dbg.value intrinsic
+HANDLE_TARGET_OPCODE(DBG_VALUE, 11)
+
+/// REG_SEQUENCE - This variadic instruction is used to form a register that
+/// represents a consecutive sequence of sub-registers. It's used as a
+/// register coalescing / allocation aid and must be eliminated before code
+/// emission.
+// In SDNode form, the first operand encodes the register class created by
+// the REG_SEQUENCE, while each subsequent pair names a vreg + subreg index
+// pair. Once it has been lowered to a MachineInstr, the regclass operand
+// is no longer present.
+/// e.g. v1027 = REG_SEQUENCE v1024, 3, v1025, 4, v1026, 5
+/// After register coalescing references of v1024 should be replace with
+/// v1027:3, v1025 with v1027:4, etc.
+HANDLE_TARGET_OPCODE(REG_SEQUENCE, 12)
+
+/// COPY - Target-independent register copy. This instruction can also be
+/// used to copy between subregisters of virtual registers.
+HANDLE_TARGET_OPCODE(COPY, 13)
+
+/// BUNDLE - This instruction represents an instruction bundle. Instructions
+/// which immediately follow a BUNDLE instruction which are marked with
+/// 'InsideBundle' flag are inside the bundle.
+HANDLE_TARGET_OPCODE(BUNDLE, 14)
+
+/// Lifetime markers.
+HANDLE_TARGET_OPCODE(LIFETIME_START, 15)
+HANDLE_TARGET_OPCODE(LIFETIME_END, 16)
+
+/// A Stackmap instruction captures the location of live variables at its
+/// position in the instruction stream. It is followed by a shadow of bytes
+/// that must lie within the function and not contain another stackmap.
+HANDLE_TARGET_OPCODE(STACKMAP, 17)
+
+/// Patchable call instruction - this instruction represents a call to a
+/// constant address, followed by a series of NOPs. It is intended to
+/// support optimizations for dynamic languages (such as javascript) that
+/// rewrite calls to runtimes with more efficient code sequences.
+/// This also implies a stack map.
+HANDLE_TARGET_OPCODE(PATCHPOINT, 18)
+
+/// This pseudo-instruction loads the stack guard value. Targets which need
+/// to prevent the stack guard value or address from being spilled to the
+/// stack should override TargetLowering::emitLoadStackGuardNode and
+/// additionally expand this pseudo after register allocation.
+HANDLE_TARGET_OPCODE(LOAD_STACK_GUARD, 19)
+
+/// Call instruction with associated vm state for deoptimization and list
+/// of live pointers for relocation by the garbage collector. It is
+/// intended to support garbage collection with fully precise relocating
+/// collectors and deoptimizations in either the callee or caller.
+HANDLE_TARGET_OPCODE(STATEPOINT, 20)
+
+/// Instruction that records the offset of a local stack allocation passed to
+/// llvm.localescape. It has two arguments: the symbol for the label and the
+/// frame index of the local stack allocation.
+HANDLE_TARGET_OPCODE(LOCAL_ESCAPE, 21)
+
+/// Loading instruction that may page fault, bundled with associated
+/// information on how to handle such a page fault. It is intended to support
+/// "zero cost" null checks in managed languages by allowing LLVM to fold
+/// comparisons into existing memory operations.
+HANDLE_TARGET_OPCODE(FAULTING_LOAD_OP, 22)
+
+/// Wraps a machine instruction to add patchability constraints. An
+/// instruction wrapped in PATCHABLE_OP has to either have a minimum
+/// size or be preceded with a nop of that size. The first operand is
+/// an immediate denoting the minimum size of the instruction, the
+/// second operand is an immediate denoting the opcode of the original
+/// instruction. The rest of the operands are the operands of the
+/// original instruction.
+HANDLE_TARGET_OPCODE(PATCHABLE_OP, 23)
+
+/// This is a marker instruction which gets translated into a nop sled, useful
+/// for inserting instrumentation instructions at runtime.
+HANDLE_TARGET_OPCODE(PATCHABLE_FUNCTION_ENTER, 24)
+
+/// Wraps a return instruction and its operands to enable adding nop sleds
+/// either before or after the return. The nop sleds are useful for inserting
+/// instrumentation instructions at runtime.
+HANDLE_TARGET_OPCODE(PATCHABLE_RET, 25)
+
+/// The following generic opcodes are not supposed to appear after ISel.
+/// This is something we might want to relax, but for now, this is convenient
+/// to produce diagnostics.
+
+/// Generic ADD instruction. This is an integer add.
+HANDLE_TARGET_OPCODE(G_ADD, 26)
+HANDLE_TARGET_OPCODE_MARKER(PRE_ISEL_GENERIC_OPCODE_START, G_ADD)
+
+/// Generic Bitwise-OR instruction.
+HANDLE_TARGET_OPCODE(G_OR, 27)
+
+/// Generic BRANCH instruction. This is an unconditional branch.
+HANDLE_TARGET_OPCODE(G_BR, 28)
+
+// TODO: Add more generic opcodes as we move along.
+
+/// Marker for the end of the generic opcode.
+/// This is used to check if an opcode is in the range of the
+/// generic opcodes.
+HANDLE_TARGET_OPCODE_MARKER(PRE_ISEL_GENERIC_OPCODE_END, G_BR)
+
+/// BUILTIN_OP_END - This must be the last enum value in this list.
+/// The target-specific post-isel opcode values start here.
+HANDLE_TARGET_OPCODE_MARKER(GENERIC_OP_END, PRE_ISEL_GENERIC_OPCODE_END)
diff --git a/include/llvm/Target/TargetOpcodes.h b/include/llvm/Target/TargetOpcodes.h
index db37bdb62582..f851fc27527b 100644
--- a/include/llvm/Target/TargetOpcodes.h
+++ b/include/llvm/Target/TargetOpcodes.h
@@ -18,122 +18,20 @@ namespace llvm {
/// Invariant opcodes: All instruction sets have these as their low opcodes.
///
-/// Every instruction defined here must also appear in Target.td and the order
-/// must be the same as in CodeGenTarget.cpp.
-///
namespace TargetOpcode {
enum {
- PHI = 0,
- INLINEASM = 1,
- CFI_INSTRUCTION = 2,
- EH_LABEL = 3,
- GC_LABEL = 4,
-
- /// KILL - This instruction is a noop that is used only to adjust the
- /// liveness of registers. This can be useful when dealing with
- /// sub-registers.
- KILL = 5,
-
- /// EXTRACT_SUBREG - This instruction takes two operands: a register
- /// that has subregisters, and a subregister index. It returns the
- /// extracted subregister value. This is commonly used to implement
- /// truncation operations on target architectures which support it.
- EXTRACT_SUBREG = 6,
-
- /// INSERT_SUBREG - This instruction takes three operands: a register that
- /// has subregisters, a register providing an insert value, and a
- /// subregister index. It returns the value of the first register with the
- /// value of the second register inserted. The first register is often
- /// defined by an IMPLICIT_DEF, because it is commonly used to implement
- /// anyext operations on target architectures which support it.
- INSERT_SUBREG = 7,
-
- /// IMPLICIT_DEF - This is the MachineInstr-level equivalent of undef.
- IMPLICIT_DEF = 8,
-
- /// SUBREG_TO_REG - This instruction is similar to INSERT_SUBREG except that
- /// the first operand is an immediate integer constant. This constant is
- /// often zero, because it is commonly used to assert that the instruction
- /// defining the register implicitly clears the high bits.
- SUBREG_TO_REG = 9,
-
- /// COPY_TO_REGCLASS - This instruction is a placeholder for a plain
- /// register-to-register copy into a specific register class. This is only
- /// used between instruction selection and MachineInstr creation, before
- /// virtual registers have been created for all the instructions, and it's
- /// only needed in cases where the register classes implied by the
- /// instructions are insufficient. It is emitted as a COPY MachineInstr.
- COPY_TO_REGCLASS = 10,
-
- /// DBG_VALUE - a mapping of the llvm.dbg.value intrinsic
- DBG_VALUE = 11,
-
- /// REG_SEQUENCE - This variadic instruction is used to form a register that
- /// represents a consecutive sequence of sub-registers. It's used as a
- /// register coalescing / allocation aid and must be eliminated before code
- /// emission.
- // In SDNode form, the first operand encodes the register class created by
- // the REG_SEQUENCE, while each subsequent pair names a vreg + subreg index
- // pair. Once it has been lowered to a MachineInstr, the regclass operand
- // is no longer present.
- /// e.g. v1027 = REG_SEQUENCE v1024, 3, v1025, 4, v1026, 5
- /// After register coalescing references of v1024 should be replace with
- /// v1027:3, v1025 with v1027:4, etc.
- REG_SEQUENCE = 12,
-
- /// COPY - Target-independent register copy. This instruction can also be
- /// used to copy between subregisters of virtual registers.
- COPY = 13,
-
- /// BUNDLE - This instruction represents an instruction bundle. Instructions
- /// which immediately follow a BUNDLE instruction which are marked with
- /// 'InsideBundle' flag are inside the bundle.
- BUNDLE = 14,
-
- /// Lifetime markers.
- LIFETIME_START = 15,
- LIFETIME_END = 16,
-
- /// A Stackmap instruction captures the location of live variables at its
- /// position in the instruction stream. It is followed by a shadow of bytes
- /// that must lie within the function and not contain another stackmap.
- STACKMAP = 17,
-
- /// Patchable call instruction - this instruction represents a call to a
- /// constant address, followed by a series of NOPs. It is intended to
- /// support optimizations for dynamic languages (such as javascript) that
- /// rewrite calls to runtimes with more efficient code sequences.
- /// This also implies a stack map.
- PATCHPOINT = 18,
-
- /// This pseudo-instruction loads the stack guard value. Targets which need
- /// to prevent the stack guard value or address from being spilled to the
- /// stack should override TargetLowering::emitLoadStackGuardNode and
- /// additionally expand this pseudo after register allocation.
- LOAD_STACK_GUARD = 19,
-
- /// Call instruction with associated vm state for deoptimization and list
- /// of live pointers for relocation by the garbage collector. It is
- /// intended to support garbage collection with fully precise relocating
- /// collectors and deoptimizations in either the callee or caller.
- STATEPOINT = 20,
-
- /// Instruction that records the offset of a local stack allocation passed to
- /// llvm.localescape. It has two arguments: the symbol for the label and the
- /// frame index of the local stack allocation.
- LOCAL_ESCAPE = 21,
-
- /// Loading instruction that may page fault, bundled with associated
- /// information on how to handle such a page fault. It is intended to support
- /// "zero cost" null checks in managed languages by allowing LLVM to fold
- /// comparisons into existing memory operations.
- FAULTING_LOAD_OP = 22,
-
- /// BUILTIN_OP_END - This must be the last enum value in this list.
- /// The target-specific post-isel opcode values start here.
- GENERIC_OP_END = FAULTING_LOAD_OP,
+#define HANDLE_TARGET_OPCODE(OPC, NUM) OPC = NUM,
+#define HANDLE_TARGET_OPCODE_MARKER(IDENT, OPC) IDENT = OPC,
+#include "llvm/Target/TargetOpcodes.def"
};
} // end namespace TargetOpcode
+
+/// Check whether the given Opcode is a generic opcode that is not supposed
+/// to appear after ISel.
+static inline bool isPreISelGenericOpcode(unsigned Opcode) {
+ return Opcode >= TargetOpcode::PRE_ISEL_GENERIC_OPCODE_START &&
+ Opcode <= TargetOpcode::PRE_ISEL_GENERIC_OPCODE_END;
+}
} // end namespace llvm
#endif
diff --git a/include/llvm/Target/TargetOptions.h b/include/llvm/Target/TargetOptions.h
index d98d0fa0ed5f..57873b4bd0b4 100644
--- a/include/llvm/Target/TargetOptions.h
+++ b/include/llvm/Target/TargetOptions.h
@@ -17,12 +17,11 @@
#include "llvm/Target/TargetRecip.h"
#include "llvm/MC/MCTargetOptions.h"
-#include <string>
+#include "llvm/MC/MCAsmInfo.h"
namespace llvm {
class MachineFunction;
class Module;
- class StringRef;
namespace FloatABI {
enum ABIType {
@@ -97,14 +96,16 @@ namespace llvm {
UnsafeFPMath(false), NoInfsFPMath(false), NoNaNsFPMath(false),
HonorSignDependentRoundingFPMathOption(false), NoZerosInBSS(false),
GuaranteedTailCallOpt(false), StackAlignmentOverride(0),
- EnableFastISel(false), PositionIndependentExecutable(false),
- UseInitArray(false), DisableIntegratedAS(false),
- CompressDebugSections(false), FunctionSections(false),
+ StackSymbolOrdering(true), EnableFastISel(false), UseInitArray(false),
+ DisableIntegratedAS(false), CompressDebugSections(false),
+ RelaxELFRelocations(false), FunctionSections(false),
DataSections(false), UniqueSectionNames(true), TrapUnreachable(false),
- EmulatedTLS(false), FloatABIType(FloatABI::Default),
+ EmulatedTLS(false), EnableIPRA(false),
+ FloatABIType(FloatABI::Default),
AllowFPOpFusion(FPOpFusion::Standard), Reciprocals(TargetRecip()),
JTType(JumpTable::Single), ThreadModel(ThreadModel::POSIX),
- EABIVersion(EABI::Default), DebuggerTuning(DebuggerKind::Default) {}
+ EABIVersion(EABI::Default), DebuggerTuning(DebuggerKind::Default),
+ ExceptionModel(ExceptionHandling::None) {}
/// PrintMachineCode - This flag is enabled when the -print-machineinstrs
/// option is specified on the command line, and should enable debugging
@@ -169,17 +170,17 @@ namespace llvm {
/// StackAlignmentOverride - Override default stack alignment for target.
unsigned StackAlignmentOverride;
+ /// StackSymbolOrdering - When true, this will allow CodeGen to order
+ /// the local stack symbols (for code size, code locality, or any other
+ /// heuristics). When false, the local symbols are left in whatever order
+ /// they were generated. Default is true.
+ unsigned StackSymbolOrdering : 1;
+
/// EnableFastISel - This flag enables fast-path instruction selection
/// which trades away generated code quality in favor of reducing
/// compile time.
unsigned EnableFastISel : 1;
- /// PositionIndependentExecutable - This flag indicates whether the code
- /// will eventually be linked into a single executable, despite the PIC
- /// relocation model being in use. It's value is undefined (and irrelevant)
- /// if the relocation model is anything other than PIC.
- unsigned PositionIndependentExecutable : 1;
-
/// UseInitArray - Use .init_array instead of .ctors for static
/// constructors.
unsigned UseInitArray : 1;
@@ -190,6 +191,8 @@ namespace llvm {
/// Compress DWARF debug sections.
unsigned CompressDebugSections : 1;
+ unsigned RelaxELFRelocations : 1;
+
/// Emit functions into separate sections.
unsigned FunctionSections : 1;
@@ -205,6 +208,9 @@ namespace llvm {
/// function in the runtime library..
unsigned EmulatedTLS : 1;
+ /// This flag enables InterProcedural Register Allocation (IPRA).
+ unsigned EnableIPRA : 1;
+
/// FloatABIType - This setting is set by -float-abi=xxx option is specfied
/// on the command line. This setting may either be Default, Soft, or Hard.
/// Default selects the target's default behavior. Soft selects the ABI for
@@ -248,6 +254,9 @@ namespace llvm {
/// Which debugger to tune for.
DebuggerKind DebuggerTuning;
+ /// What exception model to use
+ ExceptionHandling ExceptionModel;
+
/// Machine level options.
MCTargetOptions MCOptions;
};
@@ -267,7 +276,6 @@ inline bool operator==(const TargetOptions &LHS,
ARE_EQUAL(GuaranteedTailCallOpt) &&
ARE_EQUAL(StackAlignmentOverride) &&
ARE_EQUAL(EnableFastISel) &&
- ARE_EQUAL(PositionIndependentExecutable) &&
ARE_EQUAL(UseInitArray) &&
ARE_EQUAL(TrapUnreachable) &&
ARE_EQUAL(EmulatedTLS) &&
@@ -278,7 +286,9 @@ inline bool operator==(const TargetOptions &LHS,
ARE_EQUAL(ThreadModel) &&
ARE_EQUAL(EABIVersion) &&
ARE_EQUAL(DebuggerTuning) &&
- ARE_EQUAL(MCOptions);
+ ARE_EQUAL(ExceptionModel) &&
+ ARE_EQUAL(MCOptions) &&
+ ARE_EQUAL(EnableIPRA);
#undef ARE_EQUAL
}
diff --git a/include/llvm/Target/TargetRecip.h b/include/llvm/Target/TargetRecip.h
index 210d49324848..309b96079131 100644
--- a/include/llvm/Target/TargetRecip.h
+++ b/include/llvm/Target/TargetRecip.h
@@ -18,9 +18,10 @@
#define LLVM_TARGET_TARGETRECIP_H
#include "llvm/ADT/StringRef.h"
-#include <vector>
-#include <string>
+#include <cstdint>
#include <map>
+#include <string>
+#include <vector>
namespace llvm {
@@ -68,6 +69,6 @@ private:
void parseIndividualParams(const std::vector<std::string> &Args);
};
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_TARGET_TARGETRECIP_H
diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h
index fccaad4705d5..e5a6c8ed2f2d 100644
--- a/include/llvm/Target/TargetRegisterInfo.h
+++ b/include/llvm/Target/TargetRegisterInfo.h
@@ -21,7 +21,6 @@
#include "llvm/CodeGen/MachineValueType.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/MC/MCRegisterInfo.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Printable.h"
#include <cassert>
#include <functional>
@@ -71,6 +70,9 @@ public:
const uint8_t AllocationPriority;
/// Whether the class supports two (or more) disjunct subregister indices.
const bool HasDisjunctSubRegs;
+ /// Whether a combination of subregisters can cover every register in the
+ /// class. See also the CoveredBySubRegs description in Target.td.
+ const bool CoveredBySubRegs;
const sc_iterator SuperClasses;
ArrayRef<MCPhysReg> (*OrderFunc)(const MachineFunction&);
@@ -161,8 +163,21 @@ public:
}
/// Returns a bit vector of subclasses, including this one.
- /// The vector is indexed by class IDs, see hasSubClassEq() above for how to
- /// use it.
+ /// The vector is indexed by class IDs.
+ ///
+ /// To use it, consider the returned array as a chunk of memory that
+ /// contains an array of bits of size NumRegClasses. Each 32-bit chunk
+ /// contains a bitset of the ID of the subclasses in big-endian style.
+
+ /// I.e., the representation of the memory from left to right at the
+ /// bit level looks like:
+ /// [31 30 ... 1 0] [ 63 62 ... 33 32] ...
+ /// [ XXX NumRegClasses NumRegClasses - 1 ... ]
+ /// Where the number represents the class ID and XXX bits that
+ /// should be ignored.
+ ///
+ /// See the implementation of hasSubClassEq for an example of how it
+ /// can be used.
const uint32_t *getSubClassMask() const {
return SubClassMask;
}
@@ -212,7 +227,7 @@ public:
/// Returns the combination of all lane masks of register in this class.
/// The lane masks of the registers are the combination of all lane masks
- /// of their subregisters.
+ /// of their subregisters. Returns 1 if there are no subregisters.
LaneBitmask getLaneMask() const {
return LaneMask;
}
@@ -457,9 +472,13 @@ public:
/// Return a register mask that clobbers everything.
virtual const uint32_t *getNoPreservedMask() const {
- llvm_unreachable("target does not provide no presered mask");
+ llvm_unreachable("target does not provide no preserved mask");
}
+ /// Return true if all bits that are set in mask \p mask0 are also set in
+ /// \p mask1.
+ bool regmaskSubsetEqual(const uint32_t *mask0, const uint32_t *mask1) const;
+
/// Return all the call-preserved register masks defined for this target.
virtual ArrayRef<const uint32_t *> getRegMasks() const = 0;
virtual ArrayRef<const char *> getRegMaskNames() const = 0;
@@ -548,6 +567,20 @@ public:
return composeSubRegIndexLaneMaskImpl(IdxA, Mask);
}
+ /// Transform a lanemask given for a virtual register to the corresponding
+ /// lanemask before using subregister with index \p IdxA.
+ /// This is the reverse of composeSubRegIndexLaneMask(), assuming Mask is a
+ /// valie lane mask (no invalid bits set) the following holds:
+ /// X0 = composeSubRegIndexLaneMask(Idx, Mask)
+ /// X1 = reverseComposeSubRegIndexLaneMask(Idx, X0)
+ /// => X1 == Mask
+ LaneBitmask reverseComposeSubRegIndexLaneMask(unsigned IdxA,
+ LaneBitmask LaneMask) const {
+ if (!IdxA)
+ return LaneMask;
+ return reverseComposeSubRegIndexLaneMaskImpl(IdxA, LaneMask);
+ }
+
/// Debugging helper: dump register in human readable form to dbgs() stream.
static void dumpReg(unsigned Reg, unsigned SubRegIndex = 0,
const TargetRegisterInfo* TRI = nullptr);
@@ -564,6 +597,11 @@ protected:
llvm_unreachable("Target has no sub-registers");
}
+ virtual LaneBitmask reverseComposeSubRegIndexLaneMaskImpl(unsigned,
+ LaneBitmask) const {
+ llvm_unreachable("Target has no sub-registers");
+ }
+
public:
/// Find a common super-register class if it exists.
///
@@ -863,6 +901,17 @@ public:
int SPAdj, unsigned FIOperandNum,
RegScavenger *RS = nullptr) const = 0;
+ /// Return the assembly name for \p Reg.
+ virtual StringRef getRegAsmName(unsigned Reg) const {
+ // FIXME: We are assuming that the assembly name is equal to the TableGen
+ // name converted to lower case
+ //
+ // The TableGen name is the name of the definition for this register in the
+ // target's tablegen files. For example, the TableGen name of
+ // def EAX : Register <...>; is "EAX"
+ return StringRef(getName(Reg));
+ }
+
//===--------------------------------------------------------------------===//
/// Subtarget Hooks
@@ -926,8 +975,9 @@ public:
/// Returns the current sub-register index.
unsigned getSubReg() const { return SubReg; }
- /// Returns the bit mask if register classes that getSubReg() projects into
+ /// Returns the bit mask of register classes that getSubReg() projects into
/// RC.
+ /// See TargetRegisterClass::getSubClassMask() for how to use it.
const uint32_t *getMask() const { return Mask; }
/// Advance iterator to the next entry.
@@ -940,6 +990,97 @@ public:
}
};
+//===----------------------------------------------------------------------===//
+// BitMaskClassIterator
+//===----------------------------------------------------------------------===//
+/// This class encapuslates the logic to iterate over bitmask returned by
+/// the various RegClass related APIs.
+/// E.g., this class can be used to iterate over the subclasses provided by
+/// TargetRegisterClass::getSubClassMask or SuperRegClassIterator::getMask.
+class BitMaskClassIterator {
+ /// Total number of register classes.
+ const unsigned NumRegClasses;
+ /// Base index of CurrentChunk.
+ /// In other words, the number of bit we read to get at the
+ /// beginning of that chunck.
+ unsigned Base;
+ /// Adjust base index of CurrentChunk.
+ /// Base index + how many bit we read within CurrentChunk.
+ unsigned Idx;
+ /// Current register class ID.
+ unsigned ID;
+ /// Mask we are iterating over.
+ const uint32_t *Mask;
+ /// Current chunk of the Mask we are traversing.
+ uint32_t CurrentChunk;
+
+ /// Move ID to the next set bit.
+ void moveToNextID() {
+ // If the current chunk of memory is empty, move to the next one,
+ // while making sure we do not go pass the number of register
+ // classes.
+ while (!CurrentChunk) {
+ // Move to the next chunk.
+ Base += 32;
+ if (Base >= NumRegClasses) {
+ ID = NumRegClasses;
+ return;
+ }
+ CurrentChunk = *++Mask;
+ Idx = Base;
+ }
+ // Otherwise look for the first bit set from the right
+ // (representation of the class ID is big endian).
+ // See getSubClassMask for more details on the representation.
+ unsigned Offset = countTrailingZeros(CurrentChunk);
+ // Add the Offset to the adjusted base number of this chunk: Idx.
+ // This is the ID of the register class.
+ ID = Idx + Offset;
+
+ // Consume the zeros, if any, and the bit we just read
+ // so that we are at the right spot for the next call.
+ // Do not do Offset + 1 because Offset may be 31 and 32
+ // will be UB for the shift, though in that case we could
+ // have make the chunk being equal to 0, but that would
+ // have introduced a if statement.
+ moveNBits(Offset);
+ moveNBits(1);
+ }
+
+ /// Move \p NumBits Bits forward in CurrentChunk.
+ void moveNBits(unsigned NumBits) {
+ assert(NumBits < 32 && "Undefined behavior spotted!");
+ // Consume the bit we read for the next call.
+ CurrentChunk >>= NumBits;
+ // Adjust the base for the chunk.
+ Idx += NumBits;
+ }
+
+public:
+ /// Create a BitMaskClassIterator that visits all the register classes
+ /// represented by \p Mask.
+ ///
+ /// \pre \p Mask != nullptr
+ BitMaskClassIterator(const uint32_t *Mask, const TargetRegisterInfo &TRI)
+ : NumRegClasses(TRI.getNumRegClasses()), Base(0), Idx(0), ID(0),
+ Mask(Mask), CurrentChunk(*Mask) {
+ // Move to the first ID.
+ moveToNextID();
+ }
+
+ /// Returns true if this iterator is still pointing at a valid entry.
+ bool isValid() const { return getID() != NumRegClasses; }
+
+ /// Returns the current register class ID.
+ unsigned getID() const { return ID; }
+
+ /// Advance iterator to the next entry.
+ void operator++() {
+ assert(isValid() && "Cannot move iterator past end.");
+ moveToNextID();
+ }
+};
+
// This is useful when building IndexedMaps keyed on virtual registers
struct VirtReg2IndexFunctor : public std::unary_function<unsigned, unsigned> {
unsigned operator()(unsigned Reg) const {
diff --git a/include/llvm/Target/TargetSchedule.td b/include/llvm/Target/TargetSchedule.td
index 89db37ca859b..74b98ac5f6c5 100644
--- a/include/llvm/Target/TargetSchedule.td
+++ b/include/llvm/Target/TargetSchedule.td
@@ -13,7 +13,7 @@
// The SchedMachineModel is defined by subtargets for three categories of data:
// 1. Basic properties for coarse grained instruction cost model.
// 2. Scheduler Read/Write resources for simple per-opcode cost model.
-// 3. Instruction itineraties for detailed reservation tables.
+// 3. Instruction itineraries for detailed reservation tables.
//
// (1) Basic properties are defined by the SchedMachineModel
// class. Target hooks allow subtargets to associate opcodes with
@@ -55,6 +55,8 @@ include "llvm/Target/TargetItinerary.td"
class Instruction; // Forward def
+class Predicate; // Forward def
+
// DAG operator that interprets the DAG args as Instruction defs.
def instrs;
@@ -76,8 +78,6 @@ def instregex;
// See MCSchedule.h for detailed comments.
class SchedMachineModel {
int IssueWidth = -1; // Max micro-ops that may be scheduled per cycle.
- int MinLatency = -1; // Determines which instructions are allowed in a group.
- // (-1) inorder (0) ooo, (1): inorder +var latencies.
int MicroOpBufferSize = -1; // Max micro-ops that can be buffered.
int LoopMicroOpBufferSize = -1; // Max micro-ops that can be buffered for
// optimized loop dispatch/execution.
@@ -99,11 +99,26 @@ class SchedMachineModel {
// resulting from changes to the instruction definitions.
bit CompleteModel = 1;
+ // A processor may only implement part of published ISA, due to either new ISA
+ // extensions, (e.g. Pentium 4 doesn't have AVX) or implementation
+ // (ARM/MIPS/PowerPC/SPARC soft float cores).
+ //
+ // For a processor which doesn't support some feature(s), the schedule model
+ // can use:
+ //
+ // let<Predicate> UnsupportedFeatures = [HaveA,..,HaveY];
+ //
+ // to skip the checks for scheduling information when building LLVM for
+ // instructions which have any of the listed predicates in their Predicates
+ // field.
+ list<Predicate> UnsupportedFeatures = [];
+
bit NoModel = 0; // Special tag to indicate missing machine model.
}
def NoSchedModel : SchedMachineModel {
let NoModel = 1;
+ let CompleteModel = 0;
}
// Define a kind of processor resource that may be common across
@@ -392,6 +407,8 @@ class InstRW<list<SchedReadWrite> rw, dag instrlist> {
list<SchedReadWrite> OperandReadWrites = rw;
dag Instrs = instrlist;
SchedMachineModel SchedModel = ?;
+ // Allow a subtarget to mark some instructions as unsupported.
+ bit Unsupported = 0;
}
// Map a set of itinerary classes to SchedReadWrite resources. This is
diff --git a/include/llvm/Target/TargetSelectionDAG.td b/include/llvm/Target/TargetSelectionDAG.td
index 565473658404..88375f77e230 100644
--- a/include/llvm/Target/TargetSelectionDAG.td
+++ b/include/llvm/Target/TargetSelectionDAG.td
@@ -116,6 +116,9 @@ def SDTIntBinOp : SDTypeProfile<1, 2, [ // add, and, or, xor, udiv, etc.
def SDTIntShiftOp : SDTypeProfile<1, 2, [ // shl, sra, srl
SDTCisSameAs<0, 1>, SDTCisInt<0>, SDTCisInt<2>
]>;
+def SDTIntSatNoShOp : SDTypeProfile<1, 2, [ // ssat with no shift
+ SDTCisSameAs<0, 1>, SDTCisInt<2>
+]>;
def SDTIntBinHiLoOp : SDTypeProfile<2, 2, [ // mulhi, mullo, sdivrem, udivrem
SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisSameAs<0, 3>,SDTCisInt<0>
]>;
@@ -167,7 +170,7 @@ def SDTSelect : SDTypeProfile<1, 3, [ // select
]>;
def SDTVSelect : SDTypeProfile<1, 3, [ // vselect
- SDTCisInt<1>, SDTCisSameAs<0, 2>, SDTCisSameAs<2, 3>
+ SDTCisInt<1>, SDTCisSameAs<0, 2>, SDTCisSameAs<2, 3>, SDTCisSameNumEltsAs<0, 1>
]>;
def SDTSelectCC : SDTypeProfile<1, 5, [ // select_cc
@@ -300,7 +303,9 @@ def SDNPWantParent : SDNodeProperty; // ComplexPattern gets the parent
//===----------------------------------------------------------------------===//
// Selection DAG Pattern Operations
-class SDPatternOperator;
+class SDPatternOperator {
+ list<SDNodeProperty> Properties = [];
+}
//===----------------------------------------------------------------------===//
// Selection DAG Node definitions.
@@ -310,7 +315,7 @@ class SDNode<string opcode, SDTypeProfile typeprof,
: SDPatternOperator {
string Opcode = opcode;
string SDClass = sdclass;
- list<SDNodeProperty> Properties = props;
+ let Properties = props;
SDTypeProfile TypeProfile = typeprof;
}
@@ -391,10 +396,14 @@ def subc : SDNode<"ISD::SUBC" , SDTIntBinOp,
[SDNPOutGlue]>;
def sube : SDNode<"ISD::SUBE" , SDTIntBinOp,
[SDNPOutGlue, SDNPInGlue]>;
-def smin : SDNode<"ISD::SMIN" , SDTIntBinOp>;
-def smax : SDNode<"ISD::SMAX" , SDTIntBinOp>;
-def umin : SDNode<"ISD::UMIN" , SDTIntBinOp>;
-def umax : SDNode<"ISD::UMAX" , SDTIntBinOp>;
+def smin : SDNode<"ISD::SMIN" , SDTIntBinOp,
+ [SDNPCommutative, SDNPAssociative]>;
+def smax : SDNode<"ISD::SMAX" , SDTIntBinOp,
+ [SDNPCommutative, SDNPAssociative]>;
+def umin : SDNode<"ISD::UMIN" , SDTIntBinOp,
+ [SDNPCommutative, SDNPAssociative]>;
+def umax : SDNode<"ISD::UMAX" , SDTIntBinOp,
+ [SDNPCommutative, SDNPAssociative]>;
def sext_inreg : SDNode<"ISD::SIGN_EXTEND_INREG", SDTExtInreg>;
def bitreverse : SDNode<"ISD::BITREVERSE" , SDTIntUnaryOp>;
@@ -421,11 +430,14 @@ def frem : SDNode<"ISD::FREM" , SDTFPBinOp>;
def fma : SDNode<"ISD::FMA" , SDTFPTernaryOp>;
def fmad : SDNode<"ISD::FMAD" , SDTFPTernaryOp>;
def fabs : SDNode<"ISD::FABS" , SDTFPUnaryOp>;
-def fminnum : SDNode<"ISD::FMINNUM" , SDTFPBinOp>;
-def fmaxnum : SDNode<"ISD::FMAXNUM" , SDTFPBinOp>;
+def fminnum : SDNode<"ISD::FMINNUM" , SDTFPBinOp,
+ [SDNPCommutative, SDNPAssociative]>;
+def fmaxnum : SDNode<"ISD::FMAXNUM" , SDTFPBinOp,
+ [SDNPCommutative, SDNPAssociative]>;
def fminnan : SDNode<"ISD::FMINNAN" , SDTFPBinOp>;
def fmaxnan : SDNode<"ISD::FMAXNAN" , SDTFPBinOp>;
def fgetsign : SDNode<"ISD::FGETSIGN" , SDTFPToIntOp>;
+def fcanonicalize : SDNode<"ISD::FCANONICALIZE", SDTFPUnaryOp>;
def fneg : SDNode<"ISD::FNEG" , SDTFPUnaryOp>;
def fsqrt : SDNode<"ISD::FSQRT" , SDTFPUnaryOp>;
def fsin : SDNode<"ISD::FSIN" , SDTFPUnaryOp>;
@@ -944,6 +956,18 @@ def unalignednontemporalstore : PatFrag<(ops node:$val, node:$ptr),
return St->getAlignment() < St->getMemoryVT().getStoreSize();
}]>;
+// nontemporal load fragments.
+def nontemporalload : PatFrag<(ops node:$ptr),
+ (load node:$ptr), [{
+ return cast<LoadSDNode>(N)->isNonTemporal();
+}]>;
+
+def alignednontemporalload : PatFrag<(ops node:$ptr),
+ (nontemporalload node:$ptr), [{
+ LoadSDNode *Ld = cast<LoadSDNode>(N);
+ return Ld->getAlignment() >= Ld->getMemoryVT().getStoreSize();
+}]>;
+
// setcc convenience fragments.
def setoeq : PatFrag<(ops node:$lhs, node:$rhs),
(setcc node:$lhs, node:$rhs, SETOEQ)>;
diff --git a/include/llvm/Target/TargetSubtargetInfo.h b/include/llvm/Target/TargetSubtargetInfo.h
index d50aa4932f8f..b929070484f9 100644
--- a/include/llvm/Target/TargetSubtargetInfo.h
+++ b/include/llvm/Target/TargetSubtargetInfo.h
@@ -16,14 +16,18 @@
#include "llvm/CodeGen/PBQPRAConstraint.h"
#include "llvm/CodeGen/SchedulerRegistry.h"
+#include "llvm/CodeGen/ScheduleDAGMutation.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/CodeGen.h"
+#include <vector>
namespace llvm {
+class CallLowering;
class DataLayout;
class MachineFunction;
class MachineInstr;
+class RegisterBankInfo;
class SDep;
class SUnit;
class TargetFrameLowering;
@@ -32,7 +36,7 @@ class TargetLowering;
class TargetRegisterClass;
class TargetRegisterInfo;
class TargetSchedModel;
-class TargetSelectionDAGInfo;
+class SelectionDAGTargetInfo;
struct MachineSchedPolicy;
template <typename T> class SmallVectorImpl;
@@ -71,6 +75,7 @@ public:
// -- Pipelines and scheduling information
// -- Stack frame information
// -- Selection DAG lowering information
+ // -- Call lowering information
//
// N.B. These objects may change during compilation. It's not safe to cache
// them between functions.
@@ -79,9 +84,10 @@ public:
return nullptr;
}
virtual const TargetLowering *getTargetLowering() const { return nullptr; }
- virtual const TargetSelectionDAGInfo *getSelectionDAGInfo() const {
+ virtual const SelectionDAGTargetInfo *getSelectionDAGInfo() const {
return nullptr;
}
+ virtual const CallLowering *getCallLowering() const { return nullptr; }
/// Target can subclass this hook to select a different DAG scheduler.
virtual RegisterScheduler::FunctionPassCtor
getDAGScheduler(CodeGenOpt::Level) const {
@@ -89,11 +95,14 @@ public:
}
/// getRegisterInfo - If register information is available, return it. If
- /// not, return null. This is kept separate from RegInfo until RegInfo has
- /// details of graph coloring register allocation removed from it.
+ /// not, return null.
///
virtual const TargetRegisterInfo *getRegisterInfo() const { return nullptr; }
+ /// If the information for the register banks is available, return it.
+ /// Otherwise return nullptr.
+ virtual const RegisterBankInfo *getRegBankInfo() const { return nullptr; }
+
/// getInstrItineraryData - Returns instruction itinerary data for the target
/// or specific subtarget.
///
@@ -144,7 +153,6 @@ public:
/// scheduling heuristics (no custom MachineSchedStrategy) to make
/// changes to the generic scheduling policy.
virtual void overrideSchedPolicy(MachineSchedPolicy &Policy,
- MachineInstr *begin, MachineInstr *end,
unsigned NumRegionInstrs) const {}
// \brief Perform target specific adjustments to the latency of a schedule
@@ -162,6 +170,12 @@ public:
return CriticalPathRCs.clear();
}
+ // \brief Provide an ordered list of schedule DAG mutations for the post-RA
+ // scheduler.
+ virtual void getPostRAMutations(
+ std::vector<std::unique_ptr<ScheduleDAGMutation>> &Mutations) const {
+ }
+
// For use with PostRAScheduling: get the minimum optimization level needed
// to enable post-RA scheduling.
virtual CodeGenOpt::Level getOptLevelToEnablePostRAScheduler() const {
diff --git a/include/llvm/Transforms/GCOVProfiler.h b/include/llvm/Transforms/GCOVProfiler.h
new file mode 100644
index 000000000000..f6521901a33e
--- /dev/null
+++ b/include/llvm/Transforms/GCOVProfiler.h
@@ -0,0 +1,31 @@
+//===- Transforms/GCOVProfiler.h - GCOVProfiler pass ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file provides the interface for the GCOV style profiler pass.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_GCOVPROFILER_H
+#define LLVM_TRANSFORMS_GCOVPROFILER_H
+
+#include "llvm/IR/PassManager.h"
+#include "llvm/Transforms/Instrumentation.h"
+
+namespace llvm {
+/// The gcov-style instrumentation pass
+class GCOVProfilerPass : public PassInfoMixin<GCOVProfilerPass> {
+public:
+ GCOVProfilerPass(const GCOVOptions &Options = GCOVOptions::getDefault()) : GCOVOpts(Options) { }
+ PreservedAnalyses run(Module &M, AnalysisManager<Module> &AM);
+
+private:
+ GCOVOptions GCOVOpts;
+};
+
+} // End llvm namespace
+#endif
diff --git a/include/llvm/Transforms/IPO.h b/include/llvm/Transforms/IPO.h
index 78d2fadc5190..f6731884870c 100644
--- a/include/llvm/Transforms/IPO.h
+++ b/include/llvm/Transforms/IPO.h
@@ -15,12 +15,13 @@
#ifndef LLVM_TRANSFORMS_IPO_H
#define LLVM_TRANSFORMS_IPO_H
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringRef.h"
+#include <functional>
+#include <vector>
namespace llvm {
-class FunctionInfoIndex;
+class StringRef;
+class ModuleSummaryIndex;
class ModulePass;
class Pass;
class Function;
@@ -88,7 +89,7 @@ ModulePass *createGVExtractionPass(std::vector<GlobalValue*>& GVs, bool
//===----------------------------------------------------------------------===//
/// This pass performs iterative function importing from other modules.
-Pass *createFunctionImportPass(const FunctionInfoIndex *Index = nullptr);
+Pass *createFunctionImportPass(const ModuleSummaryIndex *Index = nullptr);
//===----------------------------------------------------------------------===//
/// createFunctionInliningPass - Return a new pass object that uses a heuristic
@@ -119,14 +120,17 @@ Pass *createPruneEHPass();
/// createInternalizePass - This pass loops over all of the functions in the
/// input module, internalizing all globals (functions and variables) it can.
////
-/// The symbols in \p ExportList are never internalized.
+/// Before internalizing a symbol, the callback \p MustPreserveGV is invoked and
+/// gives to the client the ability to prevent internalizing specific symbols.
///
/// The symbol in DSOList are internalized if it is safe to drop them from
/// the symbol table.
///
/// Note that commandline options that are used with the above function are not
/// used now!
-ModulePass *createInternalizePass(ArrayRef<const char *> ExportList);
+ModulePass *
+createInternalizePass(std::function<bool(const GlobalValue &)> MustPreserveGV);
+
/// createInternalizePass - Same as above, but with an empty exportList.
ModulePass *createInternalizePass();
@@ -183,15 +187,6 @@ ModulePass *createBlockExtractorPass();
ModulePass *createStripDeadPrototypesPass();
//===----------------------------------------------------------------------===//
-/// createPostOrderFunctionAttrsPass - This pass walks SCCs of the call graph
-/// in post-order to deduce and propagate function attributes. It can discover
-/// functions that do not access memory, or only read memory, and give them the
-/// readnone/readonly attribute. It also discovers function arguments that are
-/// not captured by the function and marks them with the nocapture attribute.
-///
-Pass *createPostOrderFunctionAttrsPass();
-
-//===----------------------------------------------------------------------===//
/// createReversePostOrderFunctionAttrsPass - This pass walks SCCs of the call
/// graph in RPO to deduce and propagate function attributes. Currently it
/// only handles synthesizing norecurse attributes.
@@ -219,13 +214,17 @@ ModulePass *createMetaRenamerPass();
/// manager.
ModulePass *createBarrierNoopPass();
-/// \brief This pass lowers bitset metadata and the llvm.bitset.test intrinsic
-/// to bitsets.
-ModulePass *createLowerBitSetsPass();
+/// \brief This pass lowers type metadata and the llvm.type.test intrinsic to
+/// bitsets.
+ModulePass *createLowerTypeTestsPass();
/// \brief This pass export CFI checks for use by external modules.
ModulePass *createCrossDSOCFIPass();
+/// \brief This pass implements whole-program devirtualization using type
+/// metadata.
+ModulePass *createWholeProgramDevirtPass();
+
//===----------------------------------------------------------------------===//
// SampleProfilePass - Loads sample profile data from disk and generates
// IR metadata to reflect the profile.
diff --git a/include/llvm/Transforms/IPO/ConstantMerge.h b/include/llvm/Transforms/IPO/ConstantMerge.h
new file mode 100644
index 000000000000..1d4da43f6a7b
--- /dev/null
+++ b/include/llvm/Transforms/IPO/ConstantMerge.h
@@ -0,0 +1,35 @@
+//===- ConstantMerge.h - Merge duplicate global constants -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interface to a pass that merges duplicate global
+// constants together into a single constant that is shared. This is useful
+// because some passes (ie TraceValues) insert a lot of string constants into
+// the program, regardless of whether or not an existing string is available.
+//
+// Algorithm: ConstantMerge is designed to build up a map of available constants
+// and eliminate duplicates when it is initialized.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_IPO_CONSTANTMERGE_H
+#define LLVM_TRANSFORMS_IPO_CONSTANTMERGE_H
+
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+/// A pass that merges duplicate global constants into a single constant.
+class ConstantMergePass : public PassInfoMixin<ConstantMergePass> {
+public:
+ PreservedAnalyses run(Module &M, ModuleAnalysisManager &);
+};
+}
+
+#endif // LLVM_TRANSFORMS_IPO_CONSTANTMERGE_H
diff --git a/include/llvm/Transforms/IPO/CrossDSOCFI.h b/include/llvm/Transforms/IPO/CrossDSOCFI.h
new file mode 100644
index 000000000000..409604a7f330
--- /dev/null
+++ b/include/llvm/Transforms/IPO/CrossDSOCFI.h
@@ -0,0 +1,28 @@
+//===-- CrossDSOCFI.cpp - Externalize this module's CFI checks --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass exports all llvm.bitset's found in the module in the form of a
+// __cfi_check function, which can be used to verify cross-DSO call targets.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_IPO_CROSSDSOCFI_H
+#define LLVM_TRANSFORMS_IPO_CROSSDSOCFI_H
+
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+class CrossDSOCFIPass : public PassInfoMixin<CrossDSOCFIPass> {
+public:
+ PreservedAnalyses run(Module &M, AnalysisManager<Module> &AM);
+};
+}
+#endif // LLVM_TRANSFORMS_IPO_CROSSDSOCFI_H
+
diff --git a/include/llvm/Transforms/IPO/DeadArgumentElimination.h b/include/llvm/Transforms/IPO/DeadArgumentElimination.h
new file mode 100644
index 000000000000..e179afa956f6
--- /dev/null
+++ b/include/llvm/Transforms/IPO/DeadArgumentElimination.h
@@ -0,0 +1,133 @@
+//===- DeadArgumentElimination.h - Eliminate Dead Args ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass deletes dead arguments from internal functions. Dead argument
+// elimination removes arguments which are directly dead, as well as arguments
+// only passed into function calls as dead arguments of other functions. This
+// pass also deletes dead return values in a similar way.
+//
+// This pass is often useful as a cleanup pass to run after aggressive
+// interprocedural passes, which add possibly-dead arguments or return values.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_IPO_DEADARGUMENTELIMINATION_H
+#define LLVM_TRANSFORMS_IPO_DEADARGUMENTELIMINATION_H
+
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+
+#include <map>
+#include <set>
+#include <string>
+
+namespace llvm {
+
+/// Eliminate dead arguments (and return values) from functions.
+class DeadArgumentEliminationPass
+ : public PassInfoMixin<DeadArgumentEliminationPass> {
+public:
+ /// Struct that represents (part of) either a return value or a function
+ /// argument. Used so that arguments and return values can be used
+ /// interchangeably.
+ struct RetOrArg {
+ RetOrArg(const Function *F, unsigned Idx, bool IsArg)
+ : F(F), Idx(Idx), IsArg(IsArg) {}
+ const Function *F;
+ unsigned Idx;
+ bool IsArg;
+
+ /// Make RetOrArg comparable, so we can put it into a map.
+ bool operator<(const RetOrArg &O) const {
+ return std::tie(F, Idx, IsArg) < std::tie(O.F, O.Idx, O.IsArg);
+ }
+
+ /// Make RetOrArg comparable, so we can easily iterate the multimap.
+ bool operator==(const RetOrArg &O) const {
+ return F == O.F && Idx == O.Idx && IsArg == O.IsArg;
+ }
+
+ std::string getDescription() const {
+ return (Twine(IsArg ? "Argument #" : "Return value #") + Twine(Idx) +
+ " of function " + F->getName())
+ .str();
+ }
+ };
+
+ /// Liveness enum - During our initial pass over the program, we determine
+ /// that things are either alive or maybe alive. We don't mark anything
+ /// explicitly dead (even if we know they are), since anything not alive
+ /// with no registered uses (in Uses) will never be marked alive and will
+ /// thus become dead in the end.
+ enum Liveness { Live, MaybeLive };
+
+ /// Convenience wrapper
+ RetOrArg CreateRet(const Function *F, unsigned Idx) {
+ return RetOrArg(F, Idx, false);
+ }
+ /// Convenience wrapper
+ RetOrArg CreateArg(const Function *F, unsigned Idx) {
+ return RetOrArg(F, Idx, true);
+ }
+
+ typedef std::multimap<RetOrArg, RetOrArg> UseMap;
+ /// This maps a return value or argument to any MaybeLive return values or
+ /// arguments it uses. This allows the MaybeLive values to be marked live
+ /// when any of its users is marked live.
+ /// For example (indices are left out for clarity):
+ /// - Uses[ret F] = ret G
+ /// This means that F calls G, and F returns the value returned by G.
+ /// - Uses[arg F] = ret G
+ /// This means that some function calls G and passes its result as an
+ /// argument to F.
+ /// - Uses[ret F] = arg F
+ /// This means that F returns one of its own arguments.
+ /// - Uses[arg F] = arg G
+ /// This means that G calls F and passes one of its own (G's) arguments
+ /// directly to F.
+ UseMap Uses;
+
+ typedef std::set<RetOrArg> LiveSet;
+ typedef std::set<const Function *> LiveFuncSet;
+
+ /// This set contains all values that have been determined to be live.
+ LiveSet LiveValues;
+ /// This set contains all values that are cannot be changed in any way.
+ LiveFuncSet LiveFunctions;
+
+ typedef SmallVector<RetOrArg, 5> UseVector;
+
+ /// This allows this pass to do double-duty as the dead arg hacking pass
+ /// (used only by bugpoint).
+ bool ShouldHackArguments = false;
+
+public:
+ DeadArgumentEliminationPass(bool ShouldHackArguments_ = false)
+ : ShouldHackArguments(ShouldHackArguments_) {}
+ PreservedAnalyses run(Module &M, ModuleAnalysisManager &);
+
+private:
+ Liveness MarkIfNotLive(RetOrArg Use, UseVector &MaybeLiveUses);
+ Liveness SurveyUse(const Use *U, UseVector &MaybeLiveUses,
+ unsigned RetValNum = -1U);
+ Liveness SurveyUses(const Value *V, UseVector &MaybeLiveUses);
+
+ void SurveyFunction(const Function &F);
+ void MarkValue(const RetOrArg &RA, Liveness L,
+ const UseVector &MaybeLiveUses);
+ void MarkLive(const RetOrArg &RA);
+ void MarkLive(const Function &F);
+ void PropagateLiveness(const RetOrArg &RA);
+ bool RemoveDeadStuffFromFunction(Function *F);
+ bool DeleteDeadVarargs(Function &Fn);
+ bool RemoveDeadArgumentsFromCallers(Function &Fn);
+};
+}
+
+#endif // LLVM_TRANSFORMS_IPO_DEADARGUMENTELIMINATION_H
diff --git a/include/llvm/Transforms/IPO/ElimAvailExtern.h b/include/llvm/Transforms/IPO/ElimAvailExtern.h
new file mode 100644
index 000000000000..88a0e9bd8ce0
--- /dev/null
+++ b/include/llvm/Transforms/IPO/ElimAvailExtern.h
@@ -0,0 +1,31 @@
+//===- ElimAvailExtern.h - Optimize Global Variables ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This transform is designed to eliminate available external global
+// definitions from the program, turning them into declarations.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_IPO_ELIMAVAILEXTERN_H
+#define LLVM_TRANSFORMS_IPO_ELIMAVAILEXTERN_H
+
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+/// A pass that transforms external global definitions into declarations.
+class EliminateAvailableExternallyPass
+ : public PassInfoMixin<EliminateAvailableExternallyPass> {
+public:
+ PreservedAnalyses run(Module &M, ModuleAnalysisManager &);
+};
+}
+
+#endif // LLVM_TRANSFORMS_IPO_ELIMAVAILEXTERN_H
diff --git a/include/llvm/Transforms/IPO/ForceFunctionAttrs.h b/include/llvm/Transforms/IPO/ForceFunctionAttrs.h
index 0ff4afe79b0c..ff8a6546f059 100644
--- a/include/llvm/Transforms/IPO/ForceFunctionAttrs.h
+++ b/include/llvm/Transforms/IPO/ForceFunctionAttrs.h
@@ -21,10 +21,8 @@ namespace llvm {
/// Pass which forces specific function attributes into the IR, primarily as
/// a debugging tool.
-class ForceFunctionAttrsPass {
-public:
- static StringRef name() { return "ForceFunctionAttrsPass"; }
- PreservedAnalyses run(Module &M);
+struct ForceFunctionAttrsPass : PassInfoMixin<ForceFunctionAttrsPass> {
+ PreservedAnalyses run(Module &M, ModuleAnalysisManager &);
};
/// Create a legacy pass manager instance of a pass to force function attrs.
diff --git a/include/llvm/Transforms/IPO/FunctionAttrs.h b/include/llvm/Transforms/IPO/FunctionAttrs.h
new file mode 100644
index 000000000000..c44cc43fc0f6
--- /dev/null
+++ b/include/llvm/Transforms/IPO/FunctionAttrs.h
@@ -0,0 +1,57 @@
+//===-- FunctionAttrs.h - Compute function attrs --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// Provides passes for computing function attributes based on interprocedural
+/// analyses.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_IPO_FUNCTIONATTRS_H
+#define LLVM_TRANSFORMS_IPO_FUNCTIONATTRS_H
+
+#include "llvm/Analysis/LazyCallGraph.h"
+#include "llvm/Analysis/CGSCCPassManager.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+/// Computes function attributes in post-order over the call graph.
+///
+/// By operating in post-order, this pass computes precise attributes for
+/// called functions prior to processsing their callers. This "bottom-up"
+/// approach allows powerful interprocedural inference of function attributes
+/// like memory access patterns, etc. It can discover functions that do not
+/// access memory, or only read memory, and give them the readnone/readonly
+/// attribute. It also discovers function arguments that are not captured by
+/// the function and marks them with the nocapture attribute.
+struct PostOrderFunctionAttrsPass : PassInfoMixin<PostOrderFunctionAttrsPass> {
+ PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM);
+};
+
+/// Create a legacy pass manager instance of a pass to compute function attrs
+/// in post-order.
+Pass *createPostOrderFunctionAttrsLegacyPass();
+
+/// A pass to do RPO deduction and propagation of function attributes.
+///
+/// This pass provides a general RPO or "top down" propagation of
+/// function attributes. For a few (rare) cases, we can deduce significantly
+/// more about function attributes by working in RPO, so this pass
+/// provides the compliment to the post-order pass above where the majority of
+/// deduction is performed.
+// FIXME: Currently there is no RPO CGSCC pass structure to slide into and so
+// this is a boring module pass, but eventually it should be an RPO CGSCC pass
+// when such infrastructure is available.
+class ReversePostOrderFunctionAttrsPass
+ : public PassInfoMixin<ReversePostOrderFunctionAttrsPass> {
+public:
+ PreservedAnalyses run(Module &M, AnalysisManager<Module> &AM);
+};
+}
+
+#endif // LLVM_TRANSFORMS_IPO_FUNCTIONATTRS_H
diff --git a/include/llvm/Transforms/IPO/FunctionImport.h b/include/llvm/Transforms/IPO/FunctionImport.h
index d7707790a017..ba5db2b5c739 100644
--- a/include/llvm/Transforms/IPO/FunctionImport.h
+++ b/include/llvm/Transforms/IPO/FunctionImport.h
@@ -11,33 +11,113 @@
#define LLVM_FUNCTIONIMPORT_H
#include "llvm/ADT/StringMap.h"
+#include "llvm/IR/GlobalValue.h"
+#include "llvm/IR/ModuleSummaryIndex.h"
+
#include <functional>
+#include <map>
+#include <unordered_set>
+#include <utility>
namespace llvm {
class LLVMContext;
+class GlobalValueSummary;
class Module;
-class FunctionInfoIndex;
/// The function importer is automatically importing function from other modules
/// based on the provided summary informations.
class FunctionImporter {
+public:
+ /// Set of functions to import from a source module. Each entry is a map
+ /// containing all the functions to import for a source module.
+ /// The keys is the GUID identifying a function to import, and the value
+ /// is the threshold applied when deciding to import it.
+ typedef std::map<GlobalValue::GUID, unsigned> FunctionsToImportTy;
- /// The summaries index used to trigger importing.
- const FunctionInfoIndex &Index;
+ /// The map contains an entry for every module to import from, the key being
+ /// the module identifier to pass to the ModuleLoader. The value is the set of
+ /// functions to import.
+ typedef StringMap<FunctionsToImportTy> ImportMapTy;
- /// Factory function to load a Module for a given identifier
- std::function<std::unique_ptr<Module>(StringRef Identifier)> ModuleLoader;
+ /// The set contains an entry for every global value the module exports.
+ typedef std::unordered_set<GlobalValue::GUID> ExportSetTy;
-public:
/// Create a Function Importer.
FunctionImporter(
- const FunctionInfoIndex &Index,
+ const ModuleSummaryIndex &Index,
std::function<std::unique_ptr<Module>(StringRef Identifier)> ModuleLoader)
- : Index(Index), ModuleLoader(ModuleLoader) {}
+ : Index(Index), ModuleLoader(std::move(ModuleLoader)) {}
+
+ /// Import functions in Module \p M based on the supplied import list.
+ /// \p ForceImportReferencedDiscardableSymbols will set the ModuleLinker in
+ /// a mode where referenced discarable symbols in the source modules will be
+ /// imported as well even if they are not present in the ImportList.
+ bool importFunctions(Module &M, const ImportMapTy &ImportList,
+ bool ForceImportReferencedDiscardableSymbols = false);
- /// Import functions in Module \p M based on the summary informations.
- bool importFunctions(Module &M);
+private:
+ /// The summaries index used to trigger importing.
+ const ModuleSummaryIndex &Index;
+
+ /// Factory function to load a Module for a given identifier
+ std::function<std::unique_ptr<Module>(StringRef Identifier)> ModuleLoader;
};
+
+/// Compute all the imports and exports for every module in the Index.
+///
+/// \p ModuleToDefinedGVSummaries contains for each Module a map
+/// (GUID -> Summary) for every global defined in the module.
+///
+/// \p ImportLists will be populated with an entry for every Module we are
+/// importing into. This entry is itself a map that can be passed to
+/// FunctionImporter::importFunctions() above (see description there).
+///
+/// \p ExportLists contains for each Module the set of globals (GUID) that will
+/// be imported by another module, or referenced by such a function. I.e. this
+/// is the set of globals that need to be promoted/renamed appropriately.
+void ComputeCrossModuleImport(
+ const ModuleSummaryIndex &Index,
+ const StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries,
+ StringMap<FunctionImporter::ImportMapTy> &ImportLists,
+ StringMap<FunctionImporter::ExportSetTy> &ExportLists);
+
+/// Compute all the imports for the given module using the Index.
+///
+/// \p ImportList will be populated with a map that can be passed to
+/// FunctionImporter::importFunctions() above (see description there).
+void ComputeCrossModuleImportForModule(
+ StringRef ModulePath, const ModuleSummaryIndex &Index,
+ FunctionImporter::ImportMapTy &ImportList);
+
+/// Compute the set of summaries needed for a ThinLTO backend compilation of
+/// \p ModulePath.
+//
+/// This includes summaries from that module (in case any global summary based
+/// optimizations were recorded) and from any definitions in other modules that
+/// should be imported.
+//
+/// \p ModuleToSummariesForIndex will be populated with the needed summaries
+/// from each required module path. Use a std::map instead of StringMap to get
+/// stable order for bitcode emission.
+void gatherImportedSummariesForModule(
+ StringRef ModulePath,
+ const StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries,
+ const StringMap<FunctionImporter::ImportMapTy> &ImportLists,
+ std::map<std::string, GVSummaryMapTy> &ModuleToSummariesForIndex);
+
+std::error_code
+EmitImportsFiles(StringRef ModulePath, StringRef OutputFilename,
+ const StringMap<FunctionImporter::ImportMapTy> &ImportLists);
+
+/// Resolve WeakForLinker values in \p TheModule based on the information
+/// recorded in the summaries during global summary-based analysis.
+void thinLTOResolveWeakForLinkerModule(Module &TheModule,
+ const GVSummaryMapTy &DefinedGlobals);
+
+/// Internalize \p TheModule based on the information recorded in the summaries
+/// during global summary-based analysis.
+void thinLTOInternalizeModule(Module &TheModule,
+ const GVSummaryMapTy &DefinedGlobals);
}
#endif // LLVM_FUNCTIONIMPORT_H
diff --git a/include/llvm/Transforms/IPO/GlobalDCE.h b/include/llvm/Transforms/IPO/GlobalDCE.h
new file mode 100644
index 000000000000..57e174c2a37f
--- /dev/null
+++ b/include/llvm/Transforms/IPO/GlobalDCE.h
@@ -0,0 +1,46 @@
+//===-- GlobalDCE.h - DCE unreachable internal functions ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This transform is designed to eliminate unreachable internal globals from the
+// program. It uses an aggressive algorithm, searching out globals that are
+// known to be alive. After it finds all of the globals which are needed, it
+// deletes whatever is left over. This allows it to delete recursive chunks of
+// the program which are unreachable.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_IPO_GLOBALDCE_H
+#define LLVM_TRANSFORMS_IPO_GLOBALDCE_H
+
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+#include <unordered_map>
+
+namespace llvm {
+
+/// Pass to remove unused function declarations.
+class GlobalDCEPass : public PassInfoMixin<GlobalDCEPass> {
+public:
+ PreservedAnalyses run(Module &M, ModuleAnalysisManager &);
+
+private:
+ SmallPtrSet<GlobalValue*, 32> AliveGlobals;
+ SmallPtrSet<Constant *, 8> SeenConstants;
+ std::unordered_multimap<Comdat *, GlobalValue *> ComdatMembers;
+
+ /// Mark the specific global value as needed, and
+ /// recursively mark anything that it uses as also needed.
+ void GlobalIsNeeded(GlobalValue *GV);
+ void MarkUsedGlobalsAsNeeded(Constant *C);
+ bool RemoveUnusedGlobalValue(GlobalValue &GV);
+};
+
+}
+
+#endif // LLVM_TRANSFORMS_IPO_GLOBALDCE_H
diff --git a/include/llvm/Transforms/IPO/GlobalOpt.h b/include/llvm/Transforms/IPO/GlobalOpt.h
new file mode 100644
index 000000000000..5a25a6db4390
--- /dev/null
+++ b/include/llvm/Transforms/IPO/GlobalOpt.h
@@ -0,0 +1,32 @@
+//===- GlobalOpt.h - Optimize Global Variables ------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass transforms simple global variables that never have their address
+// taken. If obviously true, it marks read/write globals as constant, deletes
+// variables only stored to, etc.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_IPO_GLOBALOPT_H
+#define LLVM_TRANSFORMS_IPO_GLOBALOPT_H
+
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+/// Optimize globals that never have their address taken.
+class GlobalOptPass : public PassInfoMixin<GlobalOptPass> {
+public:
+ PreservedAnalyses run(Module &M, AnalysisManager<Module> &AM);
+};
+
+}
+
+#endif // LLVM_TRANSFORMS_IPO_GLOBALOPT_H
diff --git a/include/llvm/Transforms/IPO/InferFunctionAttrs.h b/include/llvm/Transforms/IPO/InferFunctionAttrs.h
index 80afc02c62ae..f5cbf9eb0613 100644
--- a/include/llvm/Transforms/IPO/InferFunctionAttrs.h
+++ b/include/llvm/Transforms/IPO/InferFunctionAttrs.h
@@ -23,10 +23,8 @@ namespace llvm {
/// A pass which infers function attributes from the names and signatures of
/// function declarations in a module.
-class InferFunctionAttrsPass {
-public:
- static StringRef name() { return "InferFunctionAttrsPass"; }
- PreservedAnalyses run(Module &M, AnalysisManager<Module> *AM);
+struct InferFunctionAttrsPass : PassInfoMixin<InferFunctionAttrsPass> {
+ PreservedAnalyses run(Module &M, AnalysisManager<Module> &AM);
};
/// Create a legacy pass manager instance of a pass to infer function
diff --git a/include/llvm/Transforms/IPO/InlinerPass.h b/include/llvm/Transforms/IPO/InlinerPass.h
index 58ef0cbbfb5d..59e10608a9ba 100644
--- a/include/llvm/Transforms/IPO/InlinerPass.h
+++ b/include/llvm/Transforms/IPO/InlinerPass.h
@@ -24,6 +24,7 @@ class AssumptionCacheTracker;
class CallSite;
class DataLayout;
class InlineCost;
+class ProfileSummaryInfo;
template <class PtrType, unsigned SmallSize> class SmallPtrSet;
/// Inliner - This class contains all of the helper code which is used to
@@ -31,7 +32,7 @@ template <class PtrType, unsigned SmallSize> class SmallPtrSet;
///
struct Inliner : public CallGraphSCCPass {
explicit Inliner(char &ID);
- explicit Inliner(char &ID, int Threshold, bool InsertLifetime);
+ explicit Inliner(char &ID, bool InsertLifetime);
/// getAnalysisUsage - For this class, we declare that we require and preserve
/// the call graph. If the derived class implements this method, it should
@@ -47,18 +48,6 @@ struct Inliner : public CallGraphSCCPass {
// processing to avoid breaking the SCC traversal.
bool doFinalization(CallGraph &CG) override;
- /// This method returns the value specified by the -inline-threshold value,
- /// specified on the command line. This is typically not directly needed.
- ///
- unsigned getInlineThreshold() const { return InlineThreshold; }
-
- /// Calculate the inline threshold for given Caller. This threshold is lower
- /// if the caller is marked with OptimizeForSize and -inline-threshold is not
- /// given on the comand line. It is higher if the callee is marked with the
- /// inlinehint attribute.
- ///
- unsigned getInlineThreshold(CallSite CS) const;
-
/// getInlineCost - This method must be implemented by the subclass to
/// determine the cost of inlining the specified call site. If the cost
/// returned is greater than the current inline threshold, the call site is
@@ -74,19 +63,30 @@ struct Inliner : public CallGraphSCCPass {
/// deal with that subset of the functions.
bool removeDeadFunctions(CallGraph &CG, bool AlwaysInlineOnly = false);
-private:
- // InlineThreshold - Cache the value here for easy access.
- unsigned InlineThreshold;
+ /// This function performs the main work of the pass. The default
+ /// of Inlinter::runOnSCC() calls skipSCC() before calling this method, but
+ /// derived classes which cannot be skipped can override that method and
+ /// call this function unconditionally.
+ bool inlineCalls(CallGraphSCC &SCC);
+private:
// InsertLifetime - Insert @llvm.lifetime intrinsics.
bool InsertLifetime;
/// shouldInline - Return true if the inliner should attempt to
/// inline at the given CallSite.
bool shouldInline(CallSite CS);
+ /// Return true if inlining of CS can block the caller from being
+ /// inlined which is proved to be more beneficial. \p IC is the
+ /// estimated inline cost associated with callsite \p CS.
+ /// \p TotalAltCost will be set to the estimated cost of inlining the caller
+ /// if \p CS is suppressed for inlining.
+ bool shouldBeDeferred(Function *Caller, CallSite CS, InlineCost IC,
+ int &TotalAltCost);
protected:
AssumptionCacheTracker *ACT;
+ ProfileSummaryInfo *PSI;
};
} // End llvm namespace
diff --git a/include/llvm/Transforms/IPO/Internalize.h b/include/llvm/Transforms/IPO/Internalize.h
new file mode 100644
index 000000000000..ba1b06877d3a
--- /dev/null
+++ b/include/llvm/Transforms/IPO/Internalize.h
@@ -0,0 +1,79 @@
+//====- Internalize.h - Internalization API ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass loops over all of the functions and variables in the input module.
+// If the function or variable does not need to be preserved according to the
+// client supplied callback, it is marked as internal.
+//
+// This transformation would not be legal in a regular compilation, but it gets
+// extra information from the linker about what is safe.
+//
+// For example: Internalizing a function with external linkage. Only if we are
+// told it is only used from within this module, it is safe to do it.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_IPO_INTERNALIZE_H
+#define LLVM_TRANSFORMS_IPO_INTERNALIZE_H
+
+#include "llvm/ADT/StringSet.h"
+#include "llvm/IR/GlobalValue.h"
+#include "llvm/IR/PassManager.h"
+#include <functional>
+#include <set>
+
+namespace llvm {
+class Module;
+class CallGraph;
+
+/// A pass that internalizes all functions and variables other than those that
+/// must be preserved according to \c MustPreserveGV.
+class InternalizePass : public PassInfoMixin<InternalizePass> {
+ /// Client supplied callback to control wheter a symbol must be preserved.
+ const std::function<bool(const GlobalValue &)> MustPreserveGV;
+ /// Set of symbols private to the compiler that this pass should not touch.
+ StringSet<> AlwaysPreserved;
+
+ /// Return false if we're allowed to internalize this GV.
+ bool shouldPreserveGV(const GlobalValue &GV);
+ /// Internalize GV if it is possible to do so, i.e. it is not externally
+ /// visible and is not a member of an externally visible comdat.
+ bool maybeInternalize(GlobalValue &GV,
+ const std::set<const Comdat *> &ExternalComdats);
+ /// If GV is part of a comdat and is externally visible, keep track of its
+ /// comdat so that we don't internalize any of its members.
+ void checkComdatVisibility(GlobalValue &GV,
+ std::set<const Comdat *> &ExternalComdats);
+
+public:
+ InternalizePass();
+ InternalizePass(std::function<bool(const GlobalValue &)> MustPreserveGV)
+ : MustPreserveGV(std::move(MustPreserveGV)) {}
+
+ /// Run the internalizer on \p TheModule, returns true if any changes was
+ /// made.
+ ///
+ /// If the CallGraph \p CG is supplied, it will be updated when
+ /// internalizing a function (by removing any edge from the "external node")
+ bool internalizeModule(Module &TheModule, CallGraph *CG = nullptr);
+
+ PreservedAnalyses run(Module &M, AnalysisManager<Module> &AM);
+};
+
+/// Helper function to internalize functions and variables in a Module.
+inline bool
+internalizeModule(Module &TheModule,
+ std::function<bool(const GlobalValue &)> MustPreserveGV,
+ CallGraph *CG = nullptr) {
+ return InternalizePass(std::move(MustPreserveGV))
+ .internalizeModule(TheModule, CG);
+}
+} // end namespace llvm
+
+#endif // LLVM_TRANSFORMS_IPO_INTERNALIZE_H
diff --git a/include/llvm/Transforms/IPO/LowerBitSets.h b/include/llvm/Transforms/IPO/LowerTypeTests.h
index e5fb7b98fcb3..93d4fb94e2c4 100644
--- a/include/llvm/Transforms/IPO/LowerBitSets.h
+++ b/include/llvm/Transforms/IPO/LowerTypeTests.h
@@ -1,4 +1,4 @@
-//===- LowerBitSets.h - Bitset lowering pass --------------------*- C++ -*-===//
+//===- LowerTypeTests.h - type metadata lowering pass -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,18 +7,21 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines parts of the bitset lowering pass implementation that may
-// be usefully unit tested.
+// This file defines parts of the type test lowering pass implementation that
+// may be usefully unit tested.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_TRANSFORMS_IPO_LOWERBITSETS_H
-#define LLVM_TRANSFORMS_IPO_LOWERBITSETS_H
+#ifndef LLVM_TRANSFORMS_IPO_LOWERTYPETESTS_H
+#define LLVM_TRANSFORMS_IPO_LOWERTYPETESTS_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
-#include <stdint.h>
+#include <cstdint>
+#include <cstring>
#include <limits>
#include <set>
#include <vector>
@@ -30,6 +33,8 @@ class GlobalObject;
class Value;
class raw_ostream;
+namespace lowertypetests {
+
struct BitSetInfo {
// The indices of the set bits in the bitset.
std::set<uint64_t> Bits;
@@ -196,6 +201,13 @@ struct ByteArrayBuilder {
uint64_t &AllocByteOffset, uint8_t &AllocMask);
};
-} // namespace llvm
+} // end namespace lowertypetests
+
+class LowerTypeTestsPass : public PassInfoMixin<LowerTypeTestsPass> {
+public:
+ PreservedAnalyses run(Module &M, AnalysisManager<Module> &AM);
+};
+
+} // end namespace llvm
-#endif
+#endif // LLVM_TRANSFORMS_IPO_LOWERTYPETESTS_H
diff --git a/include/llvm/Transforms/IPO/PartialInlining.h b/include/llvm/Transforms/IPO/PartialInlining.h
new file mode 100644
index 000000000000..48eb1e30a191
--- /dev/null
+++ b/include/llvm/Transforms/IPO/PartialInlining.h
@@ -0,0 +1,32 @@
+//===- PartialInlining.h - Inline parts of functions --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass performs partial inlining, typically by inlining an if statement
+// that surrounds the body of the function.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_IPO_PARTIALINLINING_H
+#define LLVM_TRANSFORMS_IPO_PARTIALINLINING_H
+
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+/// Pass to remove unused function declarations.
+class PartialInlinerPass : public PassInfoMixin<PartialInlinerPass> {
+public:
+ PreservedAnalyses run(Module &M, ModuleAnalysisManager &);
+
+private:
+ Function *unswitchFunction(Function *F);
+};
+}
+#endif // LLVM_TRANSFORMS_IPO_PARTIALINLINING_H
diff --git a/include/llvm/Transforms/IPO/PassManagerBuilder.h b/include/llvm/Transforms/IPO/PassManagerBuilder.h
index a4e7bce8ef4a..4f483deeefe5 100644
--- a/include/llvm/Transforms/IPO/PassManagerBuilder.h
+++ b/include/llvm/Transforms/IPO/PassManagerBuilder.h
@@ -15,11 +15,13 @@
#ifndef LLVM_TRANSFORMS_IPO_PASSMANAGERBUILDER_H
#define LLVM_TRANSFORMS_IPO_PASSMANAGERBUILDER_H
+#include <functional>
#include <memory>
+#include <string>
#include <vector>
namespace llvm {
-class FunctionInfoIndex;
+class ModuleSummaryIndex;
class Pass;
class TargetLibraryInfoImpl;
class TargetMachine;
@@ -58,8 +60,9 @@ class PassManagerBuilder {
public:
/// Extensions are passed the builder itself (so they can see how it is
/// configured) as well as the pass manager to add stuff to.
- typedef void (*ExtensionFn)(const PassManagerBuilder &Builder,
- legacy::PassManagerBase &PM);
+ typedef std::function<void(const PassManagerBuilder &Builder,
+ legacy::PassManagerBase &PM)>
+ ExtensionFn;
enum ExtensionPointTy {
/// EP_EarlyAsPossible - This extension point allows adding passes before
/// any other transformations, allowing them to see the code as it is coming
@@ -116,8 +119,8 @@ public:
/// added to the per-module passes.
Pass *Inliner;
- /// The function summary index to use for function importing.
- const FunctionInfoIndex *FunctionIndex;
+ /// The module summary index to use for function importing.
+ const ModuleSummaryIndex *ModuleSummary;
bool DisableTailCalls;
bool DisableUnitAtATime;
@@ -132,10 +135,17 @@ public:
bool VerifyOutput;
bool MergeFunctions;
bool PrepareForLTO;
+ bool PrepareForThinLTO;
+ bool PerformThinLTO;
+
+ /// Profile data file name that the instrumentation will be written to.
+ std::string PGOInstrGen;
+ /// Path of the profile data file.
+ std::string PGOInstrUse;
private:
/// ExtensionList - This is list of all of the extensions that are registered.
- std::vector<std::pair<ExtensionPointTy, ExtensionFn> > Extensions;
+ std::vector<std::pair<ExtensionPointTy, ExtensionFn>> Extensions;
public:
PassManagerBuilder();
@@ -152,6 +162,9 @@ private:
void addInitialAliasAnalysisPasses(legacy::PassManagerBase &PM) const;
void addLTOOptimizationPasses(legacy::PassManagerBase &PM);
void addLateLTOOptimizationPasses(legacy::PassManagerBase &PM);
+ void addPGOInstrPasses(legacy::PassManagerBase &MPM);
+ void addFunctionSimplificationPasses(legacy::PassManagerBase &MPM);
+ void addInstructionCombiningPass(legacy::PassManagerBase &MPM) const;
public:
/// populateFunctionPassManager - This fills in the function pass manager,
@@ -162,6 +175,7 @@ public:
/// populateModulePassManager - This sets up the primary pass manager.
void populateModulePassManager(legacy::PassManagerBase &MPM);
void populateLTOPassManager(legacy::PassManagerBase &PM);
+ void populateThinLTOPassManager(legacy::PassManagerBase &PM);
};
/// Registers a function for adding a standard set of passes. This should be
@@ -171,7 +185,7 @@ public:
struct RegisterStandardPasses {
RegisterStandardPasses(PassManagerBuilder::ExtensionPointTy Ty,
PassManagerBuilder::ExtensionFn Fn) {
- PassManagerBuilder::addGlobalExtension(Ty, Fn);
+ PassManagerBuilder::addGlobalExtension(Ty, std::move(Fn));
}
};
diff --git a/include/llvm/Transforms/IPO/SCCP.h b/include/llvm/Transforms/IPO/SCCP.h
new file mode 100644
index 000000000000..fab731342144
--- /dev/null
+++ b/include/llvm/Transforms/IPO/SCCP.h
@@ -0,0 +1,34 @@
+//===- SCCP.h - Sparse Conditional Constant Propagation ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass implements interprocedural sparse conditional constant
+// propagation and merging.
+//
+// Specifically, this:
+// * Assumes values are constant unless proven otherwise
+// * Assumes BasicBlocks are dead unless proven otherwise
+// * Proves values to be constant, and replaces them with constants
+// * Proves conditional branches to be unconditional
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_IPO_SCCP_H
+#define LLVM_TRANSFORMS_IPO_SCCP_H
+
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+/// Pass to perform interprocedural constant propagation.
+class IPSCCPPass : public PassInfoMixin<IPSCCPPass> {
+public:
+ PreservedAnalyses run(Module &M, AnalysisManager<Module> &AM);
+};
+}
+#endif // LLVM_TRANSFORMS_IPO_SCCP_H
diff --git a/include/llvm/Transforms/IPO/StripDeadPrototypes.h b/include/llvm/Transforms/IPO/StripDeadPrototypes.h
index 9dddd12871c4..5a05cd75c9d5 100644
--- a/include/llvm/Transforms/IPO/StripDeadPrototypes.h
+++ b/include/llvm/Transforms/IPO/StripDeadPrototypes.h
@@ -23,10 +23,8 @@
namespace llvm {
/// Pass to remove unused function declarations.
-class StripDeadPrototypesPass {
-public:
- static StringRef name() { return "StripDeadPrototypesPass"; }
- PreservedAnalyses run(Module &M);
+struct StripDeadPrototypesPass : PassInfoMixin<StripDeadPrototypesPass> {
+ PreservedAnalyses run(Module &M, ModuleAnalysisManager &);
};
}
diff --git a/include/llvm/Transforms/IPO/WholeProgramDevirt.h b/include/llvm/Transforms/IPO/WholeProgramDevirt.h
new file mode 100644
index 000000000000..2bd20c95702c
--- /dev/null
+++ b/include/llvm/Transforms/IPO/WholeProgramDevirt.h
@@ -0,0 +1,223 @@
+//===- WholeProgramDevirt.h - Whole-program devirt pass ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines parts of the whole-program devirtualization pass
+// implementation that may be usefully unit tested.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_IPO_WHOLEPROGRAMDEVIRT_H
+#define LLVM_TRANSFORMS_IPO_WHOLEPROGRAMDEVIRT_H
+
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+#include <cassert>
+#include <cstdint>
+#include <utility>
+#include <vector>
+
+namespace llvm {
+
+template <typename T> class ArrayRef;
+template <typename T> class MutableArrayRef;
+class Function;
+class GlobalVariable;
+
+namespace wholeprogramdevirt {
+
+// A bit vector that keeps track of which bits are used. We use this to
+// pack constant values compactly before and after each virtual table.
+struct AccumBitVector {
+ std::vector<uint8_t> Bytes;
+
+ // Bits in BytesUsed[I] are 1 if matching bit in Bytes[I] is used, 0 if not.
+ std::vector<uint8_t> BytesUsed;
+
+ std::pair<uint8_t *, uint8_t *> getPtrToData(uint64_t Pos, uint8_t Size) {
+ if (Bytes.size() < Pos + Size) {
+ Bytes.resize(Pos + Size);
+ BytesUsed.resize(Pos + Size);
+ }
+ return std::make_pair(Bytes.data() + Pos, BytesUsed.data() + Pos);
+ }
+
+ // Set little-endian value Val with size Size at bit position Pos,
+ // and mark bytes as used.
+ void setLE(uint64_t Pos, uint64_t Val, uint8_t Size) {
+ assert(Pos % 8 == 0);
+ auto DataUsed = getPtrToData(Pos / 8, Size);
+ for (unsigned I = 0; I != Size; ++I) {
+ DataUsed.first[I] = Val >> (I * 8);
+ assert(!DataUsed.second[I]);
+ DataUsed.second[I] = 0xff;
+ }
+ }
+
+ // Set big-endian value Val with size Size at bit position Pos,
+ // and mark bytes as used.
+ void setBE(uint64_t Pos, uint64_t Val, uint8_t Size) {
+ assert(Pos % 8 == 0);
+ auto DataUsed = getPtrToData(Pos / 8, Size);
+ for (unsigned I = 0; I != Size; ++I) {
+ DataUsed.first[Size - I - 1] = Val >> (I * 8);
+ assert(!DataUsed.second[Size - I - 1]);
+ DataUsed.second[Size - I - 1] = 0xff;
+ }
+ }
+
+ // Set bit at bit position Pos to b and mark bit as used.
+ void setBit(uint64_t Pos, bool b) {
+ auto DataUsed = getPtrToData(Pos / 8, 1);
+ if (b)
+ *DataUsed.first |= 1 << (Pos % 8);
+ assert(!(*DataUsed.second & (1 << Pos % 8)));
+ *DataUsed.second |= 1 << (Pos % 8);
+ }
+};
+
+// The bits that will be stored before and after a particular vtable.
+struct VTableBits {
+ // The vtable global.
+ GlobalVariable *GV;
+
+ // Cache of the vtable's size in bytes.
+ uint64_t ObjectSize = 0;
+
+ // The bit vector that will be laid out before the vtable. Note that these
+ // bytes are stored in reverse order until the globals are rebuilt. This means
+ // that any values in the array must be stored using the opposite endianness
+ // from the target.
+ AccumBitVector Before;
+
+ // The bit vector that will be laid out after the vtable.
+ AccumBitVector After;
+};
+
+// Information about a member of a particular type identifier.
+struct TypeMemberInfo {
+ // The VTableBits for the vtable.
+ VTableBits *Bits;
+
+ // The offset in bytes from the start of the vtable (i.e. the address point).
+ uint64_t Offset;
+
+ bool operator<(const TypeMemberInfo &other) const {
+ return Bits < other.Bits || (Bits == other.Bits && Offset < other.Offset);
+ }
+};
+
+// A virtual call target, i.e. an entry in a particular vtable.
+struct VirtualCallTarget {
+ VirtualCallTarget(Function *Fn, const TypeMemberInfo *TM);
+
+ // For testing only.
+ VirtualCallTarget(const TypeMemberInfo *TM, bool IsBigEndian)
+ : Fn(nullptr), TM(TM), IsBigEndian(IsBigEndian) {}
+
+ // The function stored in the vtable.
+ Function *Fn;
+
+ // A pointer to the type identifier member through which the pointer to Fn is
+ // accessed.
+ const TypeMemberInfo *TM;
+
+ // When doing virtual constant propagation, this stores the return value for
+ // the function when passed the currently considered argument list.
+ uint64_t RetVal;
+
+ // Whether the target is big endian.
+ bool IsBigEndian;
+
+ // The minimum byte offset before the address point. This covers the bytes in
+ // the vtable object before the address point (e.g. RTTI, access-to-top,
+ // vtables for other base classes) and is equal to the offset from the start
+ // of the vtable object to the address point.
+ uint64_t minBeforeBytes() const { return TM->Offset; }
+
+ // The minimum byte offset after the address point. This covers the bytes in
+ // the vtable object after the address point (e.g. the vtable for the current
+ // class and any later base classes) and is equal to the size of the vtable
+ // object minus the offset from the start of the vtable object to the address
+ // point.
+ uint64_t minAfterBytes() const { return TM->Bits->ObjectSize - TM->Offset; }
+
+ // The number of bytes allocated (for the vtable plus the byte array) before
+ // the address point.
+ uint64_t allocatedBeforeBytes() const {
+ return minBeforeBytes() + TM->Bits->Before.Bytes.size();
+ }
+
+ // The number of bytes allocated (for the vtable plus the byte array) after
+ // the address point.
+ uint64_t allocatedAfterBytes() const {
+ return minAfterBytes() + TM->Bits->After.Bytes.size();
+ }
+
+ // Set the bit at position Pos before the address point to RetVal.
+ void setBeforeBit(uint64_t Pos) {
+ assert(Pos >= 8 * minBeforeBytes());
+ TM->Bits->Before.setBit(Pos - 8 * minBeforeBytes(), RetVal);
+ }
+
+ // Set the bit at position Pos after the address point to RetVal.
+ void setAfterBit(uint64_t Pos) {
+ assert(Pos >= 8 * minAfterBytes());
+ TM->Bits->After.setBit(Pos - 8 * minAfterBytes(), RetVal);
+ }
+
+ // Set the bytes at position Pos before the address point to RetVal.
+ // Because the bytes in Before are stored in reverse order, we use the
+ // opposite endianness to the target.
+ void setBeforeBytes(uint64_t Pos, uint8_t Size) {
+ assert(Pos >= 8 * minBeforeBytes());
+ if (IsBigEndian)
+ TM->Bits->Before.setLE(Pos - 8 * minBeforeBytes(), RetVal, Size);
+ else
+ TM->Bits->Before.setBE(Pos - 8 * minBeforeBytes(), RetVal, Size);
+ }
+
+ // Set the bytes at position Pos after the address point to RetVal.
+ void setAfterBytes(uint64_t Pos, uint8_t Size) {
+ assert(Pos >= 8 * minAfterBytes());
+ if (IsBigEndian)
+ TM->Bits->After.setBE(Pos - 8 * minAfterBytes(), RetVal, Size);
+ else
+ TM->Bits->After.setLE(Pos - 8 * minAfterBytes(), RetVal, Size);
+ }
+};
+
+// Find the minimum offset that we may store a value of size Size bits at. If
+// IsAfter is set, look for an offset before the object, otherwise look for an
+// offset after the object.
+uint64_t findLowestOffset(ArrayRef<VirtualCallTarget> Targets, bool IsAfter,
+ uint64_t Size);
+
+// Set the stored value in each of Targets to VirtualCallTarget::RetVal at the
+// given allocation offset before the vtable address. Stores the computed
+// byte/bit offset to OffsetByte/OffsetBit.
+void setBeforeReturnValues(MutableArrayRef<VirtualCallTarget> Targets,
+ uint64_t AllocBefore, unsigned BitWidth,
+ int64_t &OffsetByte, uint64_t &OffsetBit);
+
+// Set the stored value in each of Targets to VirtualCallTarget::RetVal at the
+// given allocation offset after the vtable address. Stores the computed
+// byte/bit offset to OffsetByte/OffsetBit.
+void setAfterReturnValues(MutableArrayRef<VirtualCallTarget> Targets,
+ uint64_t AllocAfter, unsigned BitWidth,
+ int64_t &OffsetByte, uint64_t &OffsetBit);
+
+} // end namespace wholeprogramdevirt
+
+struct WholeProgramDevirtPass : public PassInfoMixin<WholeProgramDevirtPass> {
+ PreservedAnalyses run(Module &M, ModuleAnalysisManager &);
+};
+
+} // end namespace llvm
+
+#endif // LLVM_TRANSFORMS_IPO_WHOLEPROGRAMDEVIRT_H
diff --git a/include/llvm/Transforms/InstCombine/InstCombine.h b/include/llvm/Transforms/InstCombine/InstCombine.h
index f48ec13107bc..d70b847c6892 100644
--- a/include/llvm/Transforms/InstCombine/InstCombine.h
+++ b/include/llvm/Transforms/InstCombine/InstCombine.h
@@ -24,23 +24,47 @@
namespace llvm {
-class InstCombinePass {
+class InstCombinePass : public PassInfoMixin<InstCombinePass> {
InstCombineWorklist Worklist;
+ bool ExpensiveCombines;
public:
static StringRef name() { return "InstCombinePass"; }
// Explicitly define constructors for MSVC.
- InstCombinePass() {}
- InstCombinePass(InstCombinePass &&Arg) : Worklist(std::move(Arg.Worklist)) {}
+ InstCombinePass(bool ExpensiveCombines = true)
+ : ExpensiveCombines(ExpensiveCombines) {}
+ InstCombinePass(InstCombinePass &&Arg)
+ : Worklist(std::move(Arg.Worklist)),
+ ExpensiveCombines(Arg.ExpensiveCombines) {}
InstCombinePass &operator=(InstCombinePass &&RHS) {
Worklist = std::move(RHS.Worklist);
+ ExpensiveCombines = RHS.ExpensiveCombines;
return *this;
}
- PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM);
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
};
+/// \brief The legacy pass manager's instcombine pass.
+///
+/// This is a basic whole-function wrapper around the instcombine utility. It
+/// will try to combine all instructions in the function.
+class InstructionCombiningPass : public FunctionPass {
+ InstCombineWorklist Worklist;
+ const bool ExpensiveCombines;
+
+public:
+ static char ID; // Pass identification, replacement for typeid
+
+ InstructionCombiningPass(bool ExpensiveCombines = true)
+ : FunctionPass(ID), ExpensiveCombines(ExpensiveCombines) {
+ initializeInstructionCombiningPassPass(*PassRegistry::getPassRegistry());
+ }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override;
+ bool runOnFunction(Function &F) override;
+};
}
#endif
diff --git a/include/llvm/Transforms/InstCombine/InstCombineWorklist.h b/include/llvm/Transforms/InstCombine/InstCombineWorklist.h
index 5d2b2d000009..32af035d07d4 100644
--- a/include/llvm/Transforms/InstCombine/InstCombineWorklist.h
+++ b/include/llvm/Transforms/InstCombine/InstCombineWorklist.h
@@ -11,6 +11,7 @@
#define LLVM_TRANSFORMS_INSTCOMBINE_INSTCOMBINEWORKLIST_H
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/Instruction.h"
#include "llvm/Support/Compiler.h"
@@ -63,7 +64,7 @@ public:
void AddInitialGroup(ArrayRef<Instruction *> List) {
assert(Worklist.empty() && "Worklist must be empty to add initial group");
Worklist.reserve(List.size()+16);
- WorklistMap.resize(List.size());
+ WorklistMap.reserve(List.size());
DEBUG(dbgs() << "IC: ADDING: " << List.size() << " instrs to worklist\n");
unsigned Idx = 0;
for (Instruction *I : reverse(List)) {
diff --git a/include/llvm/Transforms/InstrProfiling.h b/include/llvm/Transforms/InstrProfiling.h
new file mode 100644
index 000000000000..9ac6d63b96ae
--- /dev/null
+++ b/include/llvm/Transforms/InstrProfiling.h
@@ -0,0 +1,105 @@
+//===- Transforms/InstrProfiling.h - Instrumentation passes ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file provides the interface for LLVM's PGO Instrumentation lowering
+/// pass.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_INSTRPROFILING_H
+#define LLVM_TRANSFORMS_INSTRPROFILING_H
+
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/ProfileData/InstrProf.h"
+#include "llvm/Transforms/Instrumentation.h"
+
+namespace llvm {
+
+/// Instrumenation based profiling lowering pass. This pass lowers
+/// the profile instrumented code generated by FE or the IR based
+/// instrumentation pass.
+class InstrProfiling : public PassInfoMixin<InstrProfiling> {
+public:
+ InstrProfiling() {}
+ InstrProfiling(const InstrProfOptions &Options) : Options(Options) {}
+
+ PreservedAnalyses run(Module &M, AnalysisManager<Module> &AM);
+ bool run(Module &M);
+
+private:
+ InstrProfOptions Options;
+ Module *M;
+ struct PerFunctionProfileData {
+ uint32_t NumValueSites[IPVK_Last + 1];
+ GlobalVariable *RegionCounters;
+ GlobalVariable *DataVar;
+ PerFunctionProfileData() : RegionCounters(nullptr), DataVar(nullptr) {
+ memset(NumValueSites, 0, sizeof(uint32_t) * (IPVK_Last + 1));
+ }
+ };
+ DenseMap<GlobalVariable *, PerFunctionProfileData> ProfileDataMap;
+ std::vector<Value *> UsedVars;
+ std::vector<GlobalVariable *> ReferencedNames;
+ GlobalVariable *NamesVar;
+ size_t NamesSize;
+
+ bool isMachO() const;
+
+ /// Get the section name for the counter variables.
+ StringRef getCountersSection() const;
+
+ /// Get the section name for the name variables.
+ StringRef getNameSection() const;
+
+ /// Get the section name for the profile data variables.
+ StringRef getDataSection() const;
+
+ /// Get the section name for the coverage mapping data.
+ StringRef getCoverageSection() const;
+
+ /// Count the number of instrumented value sites for the function.
+ void computeNumValueSiteCounts(InstrProfValueProfileInst *Ins);
+
+ /// Replace instrprof_value_profile with a call to runtime library.
+ void lowerValueProfileInst(InstrProfValueProfileInst *Ins);
+
+ /// Replace instrprof_increment with an increment of the appropriate value.
+ void lowerIncrement(InstrProfIncrementInst *Inc);
+
+ /// Force emitting of name vars for unused functions.
+ void lowerCoverageData(GlobalVariable *CoverageNamesVar);
+
+ /// Get the region counters for an increment, creating them if necessary.
+ ///
+ /// If the counter array doesn't yet exist, the profile data variables
+ /// referring to them will also be created.
+ GlobalVariable *getOrCreateRegionCounters(InstrProfIncrementInst *Inc);
+
+ /// Emit the section with compressed function names.
+ void emitNameData();
+
+ /// Emit value nodes section for value profiling.
+ void emitVNodes();
+
+ /// Emit runtime registration functions for each profile data variable.
+ void emitRegistration();
+
+ /// Emit the necessary plumbing to pull in the runtime initialization.
+ void emitRuntimeHook();
+
+ /// Add uses of our data variables and runtime hook.
+ void emitUses();
+
+ /// Create a static initializer for our data, on platforms that need it,
+ /// and for any profile output file that was specified.
+ void emitInitialization();
+};
+
+} // End llvm namespace
+#endif
diff --git a/include/llvm/Transforms/Instrumentation.h b/include/llvm/Transforms/Instrumentation.h
index 38dfeb04ace3..09eef7e0750e 100644
--- a/include/llvm/Transforms/Instrumentation.h
+++ b/include/llvm/Transforms/Instrumentation.h
@@ -80,9 +80,10 @@ ModulePass *createGCOVProfilerPass(const GCOVOptions &Options =
GCOVOptions::getDefault());
// PGO Instrumention
-ModulePass *createPGOInstrumentationGenPass();
+ModulePass *createPGOInstrumentationGenLegacyPass();
ModulePass *
-createPGOInstrumentationUsePass(StringRef Filename = StringRef(""));
+createPGOInstrumentationUseLegacyPass(StringRef Filename = StringRef(""));
+ModulePass *createPGOIndirectCallPromotionLegacyPass(bool InLTO = false);
/// Options for the frontend instrumentation based profiling pass.
struct InstrProfOptions {
@@ -96,12 +97,13 @@ struct InstrProfOptions {
};
/// Insert frontend instrumentation based profiling.
-ModulePass *createInstrProfilingPass(
+ModulePass *createInstrProfilingLegacyPass(
const InstrProfOptions &Options = InstrProfOptions());
// Insert AddressSanitizer (address sanity checking) instrumentation
FunctionPass *createAddressSanitizerFunctionPass(bool CompileKernel = false,
- bool Recover = false);
+ bool Recover = false,
+ bool UseAfterScope = false);
ModulePass *createAddressSanitizerModulePass(bool CompileKernel = false,
bool Recover = false);
@@ -116,11 +118,25 @@ ModulePass *createDataFlowSanitizerPass(
const std::vector<std::string> &ABIListFiles = std::vector<std::string>(),
void *(*getArgTLS)() = nullptr, void *(*getRetValTLS)() = nullptr);
+// Options for EfficiencySanitizer sub-tools.
+struct EfficiencySanitizerOptions {
+ EfficiencySanitizerOptions() : ToolType(ESAN_None) {}
+ enum Type {
+ ESAN_None = 0,
+ ESAN_CacheFrag,
+ ESAN_WorkingSet,
+ } ToolType;
+};
+
+// Insert EfficiencySanitizer instrumentation.
+ModulePass *createEfficiencySanitizerPass(
+ const EfficiencySanitizerOptions &Options = EfficiencySanitizerOptions());
+
// Options for sanitizer coverage instrumentation.
struct SanitizerCoverageOptions {
SanitizerCoverageOptions()
: CoverageType(SCK_None), IndirectCalls(false), TraceBB(false),
- TraceCmp(false), Use8bitCounters(false) {}
+ TraceCmp(false), Use8bitCounters(false), TracePC(false) {}
enum Type {
SCK_None = 0,
@@ -132,6 +148,7 @@ struct SanitizerCoverageOptions {
bool TraceBB;
bool TraceCmp;
bool Use8bitCounters;
+ bool TracePC;
};
// Insert SanitizerCoverage instrumentation.
@@ -150,10 +167,6 @@ inline ModulePass *createDataFlowSanitizerPassForJIT(
// checking on loads, stores, and other memory intrinsics.
FunctionPass *createBoundsCheckingPass();
-/// \brief This pass splits the stack into a safe stack and an unsafe stack to
-/// protect against stack-based overflow vulnerabilities.
-FunctionPass *createSafeStackPass(const TargetMachine *TM = nullptr);
-
/// \brief Calculate what to divide by to scale counts.
///
/// Given the maximum count, calculate a divisor that will scale all the
diff --git a/include/llvm/Transforms/PGOInstrumentation.h b/include/llvm/Transforms/PGOInstrumentation.h
new file mode 100644
index 000000000000..f6b5639e5aad
--- /dev/null
+++ b/include/llvm/Transforms/PGOInstrumentation.h
@@ -0,0 +1,48 @@
+//===- Transforms/PGOInstrumentation.h - PGO gen/use passes ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file provides the interface for IR based instrumentation passes (
+/// (profile-gen, and profile-use).
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_PGOINSTRUMENTATION_H
+#define LLVM_TRANSFORMS_PGOINSTRUMENTATION_H
+
+#include "llvm/IR/PassManager.h"
+#include "llvm/Transforms/Instrumentation.h"
+
+namespace llvm {
+
+/// The instrumentation (profile-instr-gen) pass for IR based PGO.
+class PGOInstrumentationGen : public PassInfoMixin<PGOInstrumentationGen> {
+public:
+ PreservedAnalyses run(Module &M, AnalysisManager<Module> &AM);
+};
+
+/// The profile annotation (profile-instr-use) pass for IR based PGO.
+class PGOInstrumentationUse : public PassInfoMixin<PGOInstrumentationUse> {
+public:
+ PreservedAnalyses run(Module &M, AnalysisManager<Module> &AM);
+ PGOInstrumentationUse(std::string Filename = "");
+
+private:
+ std::string ProfileFileName;
+};
+
+/// The indirect function call promotion pass.
+class PGOIndirectCallPromotion : public PassInfoMixin<PGOIndirectCallPromotion> {
+public:
+ PGOIndirectCallPromotion(bool IsInLTO = false) : InLTO(IsInLTO) {}
+ PreservedAnalyses run(Module &M, AnalysisManager<Module> &AM);
+private:
+ bool InLTO;
+};
+
+} // End llvm namespace
+#endif
diff --git a/include/llvm/Transforms/SampleProfile.h b/include/llvm/Transforms/SampleProfile.h
new file mode 100644
index 000000000000..0fdfa2f85e54
--- /dev/null
+++ b/include/llvm/Transforms/SampleProfile.h
@@ -0,0 +1,27 @@
+//===- Transforms/SampleProfile.h - SamplePGO pass--------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file provides the interface for the sampled PGO loader pass.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SAMPLEPROFILE_H
+#define LLVM_TRANSFORMS_SAMPLEPROFILE_H
+
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+/// The sample profiler data loader pass.
+class SampleProfileLoaderPass : public PassInfoMixin<SampleProfileLoaderPass> {
+public:
+ PreservedAnalyses run(Module &M, AnalysisManager<Module> &AM);
+};
+
+} // End llvm namespace
+#endif
diff --git a/include/llvm/Transforms/Scalar.h b/include/llvm/Transforms/Scalar.h
index 9173de1112f3..167cc94ec81f 100644
--- a/include/llvm/Transforms/Scalar.h
+++ b/include/llvm/Transforms/Scalar.h
@@ -15,7 +15,6 @@
#ifndef LLVM_TRANSFORMS_SCALAR_H
#define LLVM_TRANSFORMS_SCALAR_H
-#include "llvm/ADT/StringRef.h"
#include <functional>
namespace llvm {
@@ -82,6 +81,16 @@ FunctionPass *createDeadStoreEliminationPass();
//
FunctionPass *createAggressiveDCEPass();
+
+//===----------------------------------------------------------------------===//
+//
+// GuardWidening - An optimization over the @llvm.experimental.guard intrinsic
+// that (optimistically) combines multiple guards into one to have fewer checks
+// at runtime.
+//
+FunctionPass *createGuardWideningPass();
+
+
//===----------------------------------------------------------------------===//
//
// BitTrackingDCE - This pass uses a bit-tracking DCE algorithm in order to
@@ -97,17 +106,6 @@ FunctionPass *createSROAPass();
//===----------------------------------------------------------------------===//
//
-// ScalarReplAggregates - Break up alloca's of aggregates into multiple allocas
-// if possible.
-//
-FunctionPass *createScalarReplAggregatesPass(signed Threshold = -1,
- bool UseDomTree = true,
- signed StructMemberThreshold = -1,
- signed ArrayElementThreshold = -1,
- signed ScalarLoadThreshold = -1);
-
-//===----------------------------------------------------------------------===//
-//
// InductiveRangeCheckElimination - Transform loops to elide range checks on
// linear functions of the induction variable.
//
@@ -132,7 +130,7 @@ Pass *createIndVarSimplifyPass();
// into:
// %Z = add int 2, %X
//
-FunctionPass *createInstructionCombiningPass();
+FunctionPass *createInstructionCombiningPass(bool ExpensiveCombines = true);
//===----------------------------------------------------------------------===//
//
@@ -156,16 +154,6 @@ Pass *createLoopStrengthReducePass();
//===----------------------------------------------------------------------===//
//
-// GlobalMerge - This pass merges internal (by default) globals into structs
-// to enable reuse of a base pointer by indexed addressing modes.
-// It can also be configured to focus on size optimizations only.
-//
-Pass *createGlobalMergePass(const TargetMachine *TM, unsigned MaximalOffset,
- bool OnlyOptimizeForSize = false,
- bool MergeExternalByDefault = false);
-
-//===----------------------------------------------------------------------===//
-//
// LoopUnswitch - This pass is a simple loop unswitching pass.
//
Pass *createLoopUnswitchPass(bool OptimizeForSize = false);
@@ -205,6 +193,12 @@ Pass *createLoopIdiomPass();
//===----------------------------------------------------------------------===//
//
+// LoopVersioningLICM - This pass is a loop versioning pass for LICM.
+//
+Pass *createLoopVersioningLICMPass();
+
+//===----------------------------------------------------------------------===//
+//
// PromoteMemoryToRegister - This pass is used to promote memory references to
// be register references. A simple example of the transformation performed by
// this pass is:
@@ -262,7 +256,10 @@ FunctionPass *createFlattenCFGPass();
//
// CFG Structurization - Remove irreducible control flow
//
-Pass *createStructurizeCFGPass();
+///
+/// When \p SkipUniformRegions is true the structizer will not structurize
+/// regions that only contain uniform branches.
+Pass *createStructurizeCFGPass(bool SkipUniformRegions = false);
//===----------------------------------------------------------------------===//
//
@@ -329,17 +326,17 @@ FunctionPass *createEarlyCSEPass();
//===----------------------------------------------------------------------===//
//
-// MergedLoadStoreMotion - This pass merges loads and stores in diamonds. Loads
-// are hoisted into the header, while stores sink into the footer.
+// GVNHoist - This pass performs a simple and fast GVN pass over the dominator
+// tree to hoist common expressions from sibling branches.
//
-FunctionPass *createMergedLoadStoreMotionPass();
+FunctionPass *createGVNHoistPass();
//===----------------------------------------------------------------------===//
//
-// GVN - This pass performs global value numbering and redundant load
-// elimination cotemporaneously.
+// MergedLoadStoreMotion - This pass merges loads and stores in diamonds. Loads
+// are hoisted into the header, while stores sink into the footer.
//
-FunctionPass *createGVNPass(bool NoLoads = false);
+FunctionPass *createMergedLoadStoreMotionPass();
//===----------------------------------------------------------------------===//
//
@@ -382,6 +379,12 @@ Pass *createLowerAtomicPass();
//===----------------------------------------------------------------------===//
//
+// LowerGuardIntrinsic - Lower guard intrinsics to normal control flow.
+//
+Pass *createLowerGuardIntrinsicPass();
+
+//===----------------------------------------------------------------------===//
+//
// ValuePropagation - Propagate CFG-derived value information
//
Pass *createCorrelatedValuePropagationPass();
@@ -432,6 +435,10 @@ createSeparateConstOffsetFromGEPPass(const TargetMachine *TM = nullptr,
//
FunctionPass *createSpeculativeExecutionPass();
+// Same as createSpeculativeExecutionPass, but does nothing unless
+// TargetTransformInfo::hasBranchDivergence() is true.
+FunctionPass *createSpeculativeExecutionIfHasBranchDivergencePass();
+
//===----------------------------------------------------------------------===//
//
// LoadCombine - Combine loads into bigger loads.
@@ -478,7 +485,10 @@ FunctionPass *createNaryReassociatePass();
//
// LoopDistribute - Distribute loops.
//
-FunctionPass *createLoopDistributePass();
+// ProcessAllLoopsByDefault instructs the pass to look for distribution
+// opportunities in all loops unless -enable-loop-distribute or the
+// llvm.loop.distribute.enable metadata data override this default.
+FunctionPass *createLoopDistributePass(bool ProcessAllLoopsByDefault);
//===----------------------------------------------------------------------===//
//
@@ -486,6 +496,28 @@ FunctionPass *createLoopDistributePass();
//
FunctionPass *createLoopLoadEliminationPass();
+//===----------------------------------------------------------------------===//
+//
+// LoopSimplifyCFG - This pass performs basic CFG simplification on loops,
+// primarily to help other loop passes.
+//
+Pass *createLoopSimplifyCFGPass();
+
+//===----------------------------------------------------------------------===//
+//
+// LoopVersioning - Perform loop multi-versioning.
+//
+FunctionPass *createLoopVersioningPass();
+
+//===----------------------------------------------------------------------===//
+//
+// LoopDataPrefetch - Perform data prefetching in loops.
+//
+FunctionPass *createLoopDataPrefetchPass();
+
+///===---------------------------------------------------------------------===//
+ModulePass *createNameAnonFunctionPass();
+
} // End llvm namespace
#endif
diff --git a/include/llvm/Transforms/Scalar/ADCE.h b/include/llvm/Transforms/Scalar/ADCE.h
index f9bc7b77c14a..b9b7e1c0c99f 100644
--- a/include/llvm/Transforms/Scalar/ADCE.h
+++ b/include/llvm/Transforms/Scalar/ADCE.h
@@ -28,10 +28,8 @@ namespace llvm {
/// instructions are dead until proven otherwise. This allows it to eliminate
/// dead computations that other DCE passes do not catch, particularly involving
/// loop computations.
-class ADCEPass {
-public:
- static StringRef name() { return "ADCEPass"; }
- PreservedAnalyses run(Function &F);
+struct ADCEPass : PassInfoMixin<ADCEPass> {
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &);
};
}
diff --git a/include/llvm/Transforms/Scalar/AlignmentFromAssumptions.h b/include/llvm/Transforms/Scalar/AlignmentFromAssumptions.h
new file mode 100644
index 000000000000..f75dc4dc331d
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/AlignmentFromAssumptions.h
@@ -0,0 +1,51 @@
+//===---- AlignmentFromAssumptions.h ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a ScalarEvolution-based transformation to set
+// the alignments of load, stores and memory intrinsics based on the truth
+// expressions of assume intrinsics. The primary motivation is to handle
+// complex alignment assumptions that apply to vector loads and stores that
+// appear after vectorization and unrolling.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_ALIGNMENTFROMASSUMPTIONS_H
+#define LLVM_TRANSFORMS_SCALAR_ALIGNMENTFROMASSUMPTIONS_H
+
+#include "llvm/Analysis/ScalarEvolution.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+struct AlignmentFromAssumptionsPass
+ : public PassInfoMixin<AlignmentFromAssumptionsPass> {
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+
+ // Glue for old PM.
+ bool runImpl(Function &F, AssumptionCache &AC, ScalarEvolution *SE_,
+ DominatorTree *DT_);
+
+ // For memory transfers, we need a common alignment for both the source and
+ // destination. If we have a new alignment for only one operand of a transfer
+ // instruction, save it in these maps. If we reach the other operand through
+ // another assumption later, then we may change the alignment at that point.
+ DenseMap<MemTransferInst *, unsigned> NewDestAlignments, NewSrcAlignments;
+
+ ScalarEvolution *SE = nullptr;
+ DominatorTree *DT = nullptr;
+
+ bool extractAlignmentInfo(CallInst *I, Value *&AAPtr, const SCEV *&AlignSCEV,
+ const SCEV *&OffSCEV);
+ bool processAssumption(CallInst *I);
+};
+}
+
+#endif // LLVM_TRANSFORMS_SCALAR_ALIGNMENTFROMASSUMPTIONS_H
diff --git a/include/llvm/Transforms/Scalar/BDCE.h b/include/llvm/Transforms/Scalar/BDCE.h
new file mode 100644
index 000000000000..d7d2730a8033
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/BDCE.h
@@ -0,0 +1,31 @@
+//===---- BDCE.cpp - Bit-tracking dead code elimination ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Bit-Tracking Dead Code Elimination pass. Some
+// instructions (shifts, some ands, ors, etc.) kill some of their input bits.
+// We track these dead bits and remove instructions that compute only these
+// dead bits.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_BDCE_H
+#define LLVM_TRANSFORMS_SCALAR_BDCE_H
+
+#include "llvm/IR/Function.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+// The Bit-Tracking Dead Code Elimination pass.
+struct BDCEPass : PassInfoMixin<BDCEPass> {
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+};
+}
+
+#endif // LLVM_TRANSFORMS_SCALAR_BDCE_H
diff --git a/include/llvm/Transforms/Scalar/ConstantHoisting.h b/include/llvm/Transforms/Scalar/ConstantHoisting.h
new file mode 100644
index 000000000000..3e2b3327a9fe
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/ConstantHoisting.h
@@ -0,0 +1,149 @@
+//===-- ConstantHoisting.h - Prepare code for expensive constants ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass identifies expensive constants to hoist and coalesces them to
+// better prepare it for SelectionDAG-based code generation. This works around
+// the limitations of the basic-block-at-a-time approach.
+//
+// First it scans all instructions for integer constants and calculates its
+// cost. If the constant can be folded into the instruction (the cost is
+// TCC_Free) or the cost is just a simple operation (TCC_BASIC), then we don't
+// consider it expensive and leave it alone. This is the default behavior and
+// the default implementation of getIntImmCost will always return TCC_Free.
+//
+// If the cost is more than TCC_BASIC, then the integer constant can't be folded
+// into the instruction and it might be beneficial to hoist the constant.
+// Similar constants are coalesced to reduce register pressure and
+// materialization code.
+//
+// When a constant is hoisted, it is also hidden behind a bitcast to force it to
+// be live-out of the basic block. Otherwise the constant would be just
+// duplicated and each basic block would have its own copy in the SelectionDAG.
+// The SelectionDAG recognizes such constants as opaque and doesn't perform
+// certain transformations on them, which would create a new expensive constant.
+//
+// This optimization is only applied to integer constants in instructions and
+// simple (this means not nested) constant cast expressions. For example:
+// %0 = load i64* inttoptr (i64 big_constant to i64*)
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_CONSTANTHOISTING_H
+#define LLVM_TRANSFORMS_SCALAR_CONSTANTHOISTING_H
+
+#include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+/// A private "module" namespace for types and utilities used by
+/// ConstantHoisting. These are implementation details and should not be used by
+/// clients.
+namespace consthoist {
+/// \brief Keeps track of the user of a constant and the operand index where the
+/// constant is used.
+struct ConstantUser {
+ Instruction *Inst;
+ unsigned OpndIdx;
+
+ ConstantUser(Instruction *Inst, unsigned Idx) : Inst(Inst), OpndIdx(Idx) { }
+};
+
+typedef SmallVector<ConstantUser, 8> ConstantUseListType;
+
+/// \brief Keeps track of a constant candidate and its uses.
+struct ConstantCandidate {
+ ConstantUseListType Uses;
+ ConstantInt *ConstInt;
+ unsigned CumulativeCost;
+
+ ConstantCandidate(ConstantInt *ConstInt)
+ : ConstInt(ConstInt), CumulativeCost(0) { }
+
+ /// \brief Add the user to the use list and update the cost.
+ void addUser(Instruction *Inst, unsigned Idx, unsigned Cost) {
+ CumulativeCost += Cost;
+ Uses.push_back(ConstantUser(Inst, Idx));
+ }
+};
+
+/// \brief This represents a constant that has been rebased with respect to a
+/// base constant. The difference to the base constant is recorded in Offset.
+struct RebasedConstantInfo {
+ ConstantUseListType Uses;
+ Constant *Offset;
+
+ RebasedConstantInfo(ConstantUseListType &&Uses, Constant *Offset)
+ : Uses(std::move(Uses)), Offset(Offset) { }
+};
+
+typedef SmallVector<RebasedConstantInfo, 4> RebasedConstantListType;
+
+/// \brief A base constant and all its rebased constants.
+struct ConstantInfo {
+ ConstantInt *BaseConstant;
+ RebasedConstantListType RebasedConstants;
+};
+}
+
+class ConstantHoistingPass : public PassInfoMixin<ConstantHoistingPass> {
+public:
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+
+ // Glue for old PM.
+ bool runImpl(Function &F, TargetTransformInfo &TTI, DominatorTree &DT,
+ BasicBlock &Entry);
+
+ void releaseMemory() {
+ ConstantVec.clear();
+ ClonedCastMap.clear();
+ ConstCandVec.clear();
+ }
+
+private:
+ typedef DenseMap<ConstantInt *, unsigned> ConstCandMapType;
+ typedef std::vector<consthoist::ConstantCandidate> ConstCandVecType;
+
+ const TargetTransformInfo *TTI;
+ DominatorTree *DT;
+ BasicBlock *Entry;
+
+ /// Keeps track of constant candidates found in the function.
+ ConstCandVecType ConstCandVec;
+
+ /// Keep track of cast instructions we already cloned.
+ SmallDenseMap<Instruction *, Instruction *> ClonedCastMap;
+
+ /// These are the final constants we decided to hoist.
+ SmallVector<consthoist::ConstantInfo, 8> ConstantVec;
+
+ Instruction *findMatInsertPt(Instruction *Inst, unsigned Idx = ~0U) const;
+ Instruction *findConstantInsertionPoint(
+ const consthoist::ConstantInfo &ConstInfo) const;
+ void collectConstantCandidates(ConstCandMapType &ConstCandMap,
+ Instruction *Inst, unsigned Idx,
+ ConstantInt *ConstInt);
+ void collectConstantCandidates(ConstCandMapType &ConstCandMap,
+ Instruction *Inst);
+ void collectConstantCandidates(Function &Fn);
+ void findAndMakeBaseConstant(ConstCandVecType::iterator S,
+ ConstCandVecType::iterator E);
+ unsigned maximizeConstantsInRange(ConstCandVecType::iterator S,
+ ConstCandVecType::iterator E,
+ ConstCandVecType::iterator &MaxCostItr);
+ void findBaseConstants();
+ void emitBaseConstants(Instruction *Base, Constant *Offset,
+ const consthoist::ConstantUser &ConstUser);
+ bool emitBaseConstants();
+ void deleteDeadCastInst() const;
+ bool optimizeConstants(Function &Fn);
+};
+}
+
+#endif // LLVM_TRANSFORMS_SCALAR_CONSTANTHOISTING_H
diff --git a/include/llvm/Transforms/Scalar/CorrelatedValuePropagation.h b/include/llvm/Transforms/Scalar/CorrelatedValuePropagation.h
new file mode 100644
index 000000000000..38816bbed068
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/CorrelatedValuePropagation.h
@@ -0,0 +1,24 @@
+//===---- CorrelatedValuePropagation.h --------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_CORRELATEDVALUEPROPAGATION_H
+#define LLVM_TRANSFORMS_SCALAR_CORRELATEDVALUEPROPAGATION_H
+
+#include "llvm/IR/Function.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+struct CorrelatedValuePropagationPass
+ : PassInfoMixin<CorrelatedValuePropagationPass> {
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+};
+}
+
+#endif // LLVM_TRANSFORMS_SCALAR_CORRELATEDVALUEPROPAGATION_H
diff --git a/include/llvm/Transforms/Scalar/DCE.h b/include/llvm/Transforms/Scalar/DCE.h
new file mode 100644
index 000000000000..d9f921e1e7c1
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/DCE.h
@@ -0,0 +1,29 @@
+//===- DCE.h - Dead code elimination ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides the interface for the Dead Code Elimination pass.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_DCE_H
+#define LLVM_TRANSFORMS_SCALAR_DCE_H
+
+#include "llvm/IR/Function.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+/// Basic Dead Code Elimination pass.
+class DCEPass : public PassInfoMixin<DCEPass> {
+public:
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
+};
+}
+
+#endif // LLVM_TRANSFORMS_SCALAR_DCE_H
diff --git a/include/llvm/Transforms/Scalar/DeadStoreElimination.h b/include/llvm/Transforms/Scalar/DeadStoreElimination.h
new file mode 100644
index 000000000000..7826e29f178e
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/DeadStoreElimination.h
@@ -0,0 +1,34 @@
+//===- DeadStoreElimination.h - Fast Dead Store Elimination -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a trivial dead store elimination that only considers
+// basic-block local redundant stores.
+//
+// FIXME: This should eventually be extended to be a post-dominator tree
+// traversal. Doing so would be pretty trivial.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_DSE_H
+#define LLVM_TRANSFORMS_SCALAR_DSE_H
+
+#include "llvm/IR/Function.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+/// This class implements a trivial dead store elimination. We consider
+/// only the redundant stores that are local to a single Basic Block.
+class DSEPass : public PassInfoMixin<DSEPass> {
+public:
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &FAM);
+};
+}
+
+#endif // LLVM_TRANSFORMS_SCALAR_DSE_H
diff --git a/include/llvm/Transforms/Scalar/EarlyCSE.h b/include/llvm/Transforms/Scalar/EarlyCSE.h
index e3dd3c050df6..80e3c602a2b8 100644
--- a/include/llvm/Transforms/Scalar/EarlyCSE.h
+++ b/include/llvm/Transforms/Scalar/EarlyCSE.h
@@ -26,12 +26,9 @@ namespace llvm {
/// canonicalize things as it goes. It is intended to be fast and catch obvious
/// cases so that instcombine and other passes are more effective. It is
/// expected that a later pass of GVN will catch the interesting/hard cases.
-class EarlyCSEPass {
-public:
- static StringRef name() { return "EarlyCSEPass"; }
-
+struct EarlyCSEPass : PassInfoMixin<EarlyCSEPass> {
/// \brief Run the pass over the function.
- PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM);
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
};
}
diff --git a/include/llvm/Transforms/Scalar/Float2Int.h b/include/llvm/Transforms/Scalar/Float2Int.h
new file mode 100644
index 000000000000..a8042399fb08
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/Float2Int.h
@@ -0,0 +1,51 @@
+//===-- Float2Int.h - Demote floating point ops to work on integers -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides the Float2Int pass, which aims to demote floating
+// point operations to work on integers, where that is losslessly possible.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_FLOAT2INT_H
+#define LLVM_TRANSFORMS_SCALAR_FLOAT2INT_H
+
+#include "llvm/ADT/EquivalenceClasses.h"
+#include "llvm/ADT/MapVector.h"
+#include "llvm/IR/ConstantRange.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+class Float2IntPass : public PassInfoMixin<Float2IntPass> {
+public:
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+
+ // Glue for old PM.
+ bool runImpl(Function &F);
+
+private:
+ void findRoots(Function &F, SmallPtrSet<Instruction *, 8> &Roots);
+ ConstantRange seen(Instruction *I, ConstantRange R);
+ ConstantRange badRange();
+ ConstantRange unknownRange();
+ ConstantRange validateRange(ConstantRange R);
+ void walkBackwards(const SmallPtrSetImpl<Instruction *> &Roots);
+ void walkForwards();
+ bool validateAndTransform();
+ Value *convert(Instruction *I, Type *ToTy);
+ void cleanup();
+
+ MapVector<Instruction *, ConstantRange> SeenInsts;
+ SmallPtrSet<Instruction *, 8> Roots;
+ EquivalenceClasses<Instruction *> ECs;
+ MapVector<Instruction *, Value *> ConvertedInsts;
+ LLVMContext *Ctx;
+};
+}
+#endif // LLVM_TRANSFORMS_SCALAR_FLOAT2INT_H
diff --git a/include/llvm/Transforms/Scalar/GVN.h b/include/llvm/Transforms/Scalar/GVN.h
new file mode 100644
index 000000000000..3bb5ec392272
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/GVN.h
@@ -0,0 +1,240 @@
+//===- GVN.h - Eliminate redundant values and loads -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file provides the interface for LLVM's Global Value Numbering pass
+/// which eliminates fully redundant instructions. It also does somewhat Ad-Hoc
+/// PRE and dead load elimination.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_GVN_H
+#define LLVM_TRANSFORMS_SCALAR_GVN_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Analysis/AliasAnalysis.h"
+#include "llvm/Analysis/AssumptionCache.h"
+#include "llvm/Analysis/MemoryDependenceAnalysis.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+/// A private "module" namespace for types and utilities used by GVN. These
+/// are implementation details and should not be used by clients.
+namespace gvn LLVM_LIBRARY_VISIBILITY {
+struct AvailableValue;
+struct AvailableValueInBlock;
+class GVNLegacyPass;
+}
+
+/// The core GVN pass object.
+///
+/// FIXME: We should have a good summary of the GVN algorithm implemented by
+/// this particular pass here.
+class GVN : public PassInfoMixin<GVN> {
+public:
+
+ /// \brief Run the pass over the function.
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
+
+ /// This removes the specified instruction from
+ /// our various maps and marks it for deletion.
+ void markInstructionForDeletion(Instruction *I) {
+ VN.erase(I);
+ InstrsToErase.push_back(I);
+ }
+
+ DominatorTree &getDominatorTree() const { return *DT; }
+ AliasAnalysis *getAliasAnalysis() const { return VN.getAliasAnalysis(); }
+ MemoryDependenceResults &getMemDep() const { return *MD; }
+
+ struct Expression;
+
+ /// This class holds the mapping between values and value numbers. It is used
+ /// as an efficient mechanism to determine the expression-wise equivalence of
+ /// two values.
+ class ValueTable {
+ DenseMap<Value *, uint32_t> valueNumbering;
+ DenseMap<Expression, uint32_t> expressionNumbering;
+ AliasAnalysis *AA;
+ MemoryDependenceResults *MD;
+ DominatorTree *DT;
+
+ uint32_t nextValueNumber;
+
+ Expression createExpr(Instruction *I);
+ Expression createCmpExpr(unsigned Opcode, CmpInst::Predicate Predicate,
+ Value *LHS, Value *RHS);
+ Expression createExtractvalueExpr(ExtractValueInst *EI);
+ uint32_t lookupOrAddCall(CallInst *C);
+
+ public:
+ ValueTable();
+ ValueTable(const ValueTable &Arg);
+ ValueTable(ValueTable &&Arg);
+ ~ValueTable();
+
+ uint32_t lookupOrAdd(Value *V);
+ uint32_t lookup(Value *V) const;
+ uint32_t lookupOrAddCmp(unsigned Opcode, CmpInst::Predicate Pred,
+ Value *LHS, Value *RHS);
+ bool exists(Value *V) const;
+ void add(Value *V, uint32_t num);
+ void clear();
+ void erase(Value *v);
+ void setAliasAnalysis(AliasAnalysis *A) { AA = A; }
+ AliasAnalysis *getAliasAnalysis() const { return AA; }
+ void setMemDep(MemoryDependenceResults *M) { MD = M; }
+ void setDomTree(DominatorTree *D) { DT = D; }
+ uint32_t getNextUnusedValueNumber() { return nextValueNumber; }
+ void verifyRemoved(const Value *) const;
+ };
+
+private:
+ friend class gvn::GVNLegacyPass;
+ friend struct DenseMapInfo<Expression>;
+
+ MemoryDependenceResults *MD;
+ DominatorTree *DT;
+ const TargetLibraryInfo *TLI;
+ AssumptionCache *AC;
+ SetVector<BasicBlock *> DeadBlocks;
+
+ ValueTable VN;
+
+ /// A mapping from value numbers to lists of Value*'s that
+ /// have that value number. Use findLeader to query it.
+ struct LeaderTableEntry {
+ Value *Val;
+ const BasicBlock *BB;
+ LeaderTableEntry *Next;
+ };
+ DenseMap<uint32_t, LeaderTableEntry> LeaderTable;
+ BumpPtrAllocator TableAllocator;
+
+ // Block-local map of equivalent values to their leader, does not
+ // propagate to any successors. Entries added mid-block are applied
+ // to the remaining instructions in the block.
+ SmallMapVector<llvm::Value *, llvm::Constant *, 4> ReplaceWithConstMap;
+ SmallVector<Instruction *, 8> InstrsToErase;
+
+ typedef SmallVector<NonLocalDepResult, 64> LoadDepVect;
+ typedef SmallVector<gvn::AvailableValueInBlock, 64> AvailValInBlkVect;
+ typedef SmallVector<BasicBlock *, 64> UnavailBlkVect;
+
+ bool runImpl(Function &F, AssumptionCache &RunAC, DominatorTree &RunDT,
+ const TargetLibraryInfo &RunTLI, AAResults &RunAA,
+ MemoryDependenceResults *RunMD);
+
+ /// Push a new Value to the LeaderTable onto the list for its value number.
+ void addToLeaderTable(uint32_t N, Value *V, const BasicBlock *BB) {
+ LeaderTableEntry &Curr = LeaderTable[N];
+ if (!Curr.Val) {
+ Curr.Val = V;
+ Curr.BB = BB;
+ return;
+ }
+
+ LeaderTableEntry *Node = TableAllocator.Allocate<LeaderTableEntry>();
+ Node->Val = V;
+ Node->BB = BB;
+ Node->Next = Curr.Next;
+ Curr.Next = Node;
+ }
+
+ /// Scan the list of values corresponding to a given
+ /// value number, and remove the given instruction if encountered.
+ void removeFromLeaderTable(uint32_t N, Instruction *I, BasicBlock *BB) {
+ LeaderTableEntry *Prev = nullptr;
+ LeaderTableEntry *Curr = &LeaderTable[N];
+
+ while (Curr && (Curr->Val != I || Curr->BB != BB)) {
+ Prev = Curr;
+ Curr = Curr->Next;
+ }
+
+ if (!Curr)
+ return;
+
+ if (Prev) {
+ Prev->Next = Curr->Next;
+ } else {
+ if (!Curr->Next) {
+ Curr->Val = nullptr;
+ Curr->BB = nullptr;
+ } else {
+ LeaderTableEntry *Next = Curr->Next;
+ Curr->Val = Next->Val;
+ Curr->BB = Next->BB;
+ Curr->Next = Next->Next;
+ }
+ }
+ }
+
+ // List of critical edges to be split between iterations.
+ SmallVector<std::pair<TerminatorInst *, unsigned>, 4> toSplit;
+
+ // Helper functions of redundant load elimination
+ bool processLoad(LoadInst *L);
+ bool processNonLocalLoad(LoadInst *L);
+ bool processAssumeIntrinsic(IntrinsicInst *II);
+ /// Given a local dependency (Def or Clobber) determine if a value is
+ /// available for the load. Returns true if an value is known to be
+ /// available and populates Res. Returns false otherwise.
+ bool AnalyzeLoadAvailability(LoadInst *LI, MemDepResult DepInfo,
+ Value *Address, gvn::AvailableValue &Res);
+ /// Given a list of non-local dependencies, determine if a value is
+ /// available for the load in each specified block. If it is, add it to
+ /// ValuesPerBlock. If not, add it to UnavailableBlocks.
+ void AnalyzeLoadAvailability(LoadInst *LI, LoadDepVect &Deps,
+ AvailValInBlkVect &ValuesPerBlock,
+ UnavailBlkVect &UnavailableBlocks);
+ bool PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock,
+ UnavailBlkVect &UnavailableBlocks);
+
+ // Other helper routines
+ bool processInstruction(Instruction *I);
+ bool processBlock(BasicBlock *BB);
+ void dump(DenseMap<uint32_t, Value *> &d);
+ bool iterateOnFunction(Function &F);
+ bool performPRE(Function &F);
+ bool performScalarPRE(Instruction *I);
+ bool performScalarPREInsertion(Instruction *Instr, BasicBlock *Pred,
+ unsigned int ValNo);
+ Value *findLeader(const BasicBlock *BB, uint32_t num);
+ void cleanupGlobalSets();
+ void verifyRemoved(const Instruction *I) const;
+ bool splitCriticalEdges();
+ BasicBlock *splitCriticalEdges(BasicBlock *Pred, BasicBlock *Succ);
+ bool replaceOperandsWithConsts(Instruction *I) const;
+ bool propagateEquality(Value *LHS, Value *RHS, const BasicBlockEdge &Root,
+ bool DominatesByEdge);
+ bool processFoldableCondBr(BranchInst *BI);
+ void addDeadBlock(BasicBlock *BB);
+ void assignValNumForDeadCode();
+};
+
+/// Create a legacy GVN pass. This also allows parameterizing whether or not
+/// loads are eliminated by the pass.
+FunctionPass *createGVNPass(bool NoLoads = false);
+
+/// \brief A simple and fast domtree-based GVN pass to hoist common expressions
+/// from sibling branches.
+struct GVNHoistPass : PassInfoMixin<GVNHoistPass> {
+ /// \brief Run the pass over the function.
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
+};
+
+}
+
+#endif
diff --git a/include/llvm/Transforms/Scalar/GuardWidening.h b/include/llvm/Transforms/Scalar/GuardWidening.h
new file mode 100644
index 000000000000..201065cbdfb5
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/GuardWidening.h
@@ -0,0 +1,32 @@
+//===- GuardWidening.h - ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Guard widening is an optimization over the @llvm.experimental.guard intrinsic
+// that (optimistically) combines multiple guards into one to have fewer checks
+// at runtime.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef LLVM_TRANSFORMS_SCALAR_GUARD_WIDENING_H
+#define LLVM_TRANSFORMS_SCALAR_GUARD_WIDENING_H
+
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+class Function;
+
+struct GuardWideningPass : public PassInfoMixin<GuardWideningPass> {
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
+};
+}
+
+
+#endif // LLVM_TRANSFORMS_SCALAR_GUARD_WIDENING_H
diff --git a/include/llvm/Transforms/Scalar/IndVarSimplify.h b/include/llvm/Transforms/Scalar/IndVarSimplify.h
new file mode 100644
index 000000000000..325bcc7bed8f
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/IndVarSimplify.h
@@ -0,0 +1,29 @@
+//===- IndVarSimplify.h - Induction Variable Simplification -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides the interface for the Induction Variable
+// Simplification pass.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_INDVARSIMPLIFY_H
+#define LLVM_TRANSFORMS_SCALAR_INDVARSIMPLIFY_H
+
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+class IndVarSimplifyPass : public PassInfoMixin<IndVarSimplifyPass> {
+public:
+ PreservedAnalyses run(Loop &L, AnalysisManager<Loop> &AM);
+};
+}
+
+#endif // LLVM_TRANSFORMS_SCALAR_INDVARSIMPLIFY_H
diff --git a/include/llvm/Transforms/Scalar/JumpThreading.h b/include/llvm/Transforms/Scalar/JumpThreading.h
new file mode 100644
index 000000000000..e38bdd03ac06
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/JumpThreading.h
@@ -0,0 +1,141 @@
+//===- JumpThreading.h - thread control through conditional BBs -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// See the comments on JumpThreadingPass.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_JUMPTHREADING_H
+#define LLVM_TRANSFORMS_SCALAR_JUMPTHREADING_H
+
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/Analysis/BlockFrequencyInfo.h"
+#include "llvm/Analysis/BlockFrequencyInfoImpl.h"
+#include "llvm/Analysis/BranchProbabilityInfo.h"
+#include "llvm/Analysis/LazyValueInfo.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/ValueHandle.h"
+
+namespace llvm {
+
+/// A private "module" namespace for types and utilities used by
+/// JumpThreading.
+/// These are implementation details and should not be used by clients.
+namespace jumpthreading {
+// These are at global scope so static functions can use them too.
+typedef SmallVectorImpl<std::pair<Constant *, BasicBlock *>> PredValueInfo;
+typedef SmallVector<std::pair<Constant *, BasicBlock *>, 8> PredValueInfoTy;
+
+// This is used to keep track of what kind of constant we're currently hoping
+// to find.
+enum ConstantPreference { WantInteger, WantBlockAddress };
+}
+
+/// This pass performs 'jump threading', which looks at blocks that have
+/// multiple predecessors and multiple successors. If one or more of the
+/// predecessors of the block can be proven to always jump to one of the
+/// successors, we forward the edge from the predecessor to the successor by
+/// duplicating the contents of this block.
+///
+/// An example of when this can occur is code like this:
+///
+/// if () { ...
+/// X = 4;
+/// }
+/// if (X < 3) {
+///
+/// In this case, the unconditional branch at the end of the first if can be
+/// revectored to the false side of the second if.
+///
+class JumpThreadingPass : public PassInfoMixin<JumpThreadingPass> {
+ TargetLibraryInfo *TLI;
+ LazyValueInfo *LVI;
+ std::unique_ptr<BlockFrequencyInfo> BFI;
+ std::unique_ptr<BranchProbabilityInfo> BPI;
+ bool HasProfileData = false;
+#ifdef NDEBUG
+ SmallPtrSet<const BasicBlock *, 16> LoopHeaders;
+#else
+ SmallSet<AssertingVH<const BasicBlock>, 16> LoopHeaders;
+#endif
+ DenseSet<std::pair<Value *, BasicBlock *>> RecursionSet;
+
+ unsigned BBDupThreshold;
+
+ // RAII helper for updating the recursion stack.
+ struct RecursionSetRemover {
+ DenseSet<std::pair<Value *, BasicBlock *>> &TheSet;
+ std::pair<Value *, BasicBlock *> ThePair;
+
+ RecursionSetRemover(DenseSet<std::pair<Value *, BasicBlock *>> &S,
+ std::pair<Value *, BasicBlock *> P)
+ : TheSet(S), ThePair(P) {}
+
+ ~RecursionSetRemover() { TheSet.erase(ThePair); }
+ };
+
+public:
+ JumpThreadingPass(int T = -1);
+ // Hack for MSVC 2013 which seems like it can't synthesize this.
+ JumpThreadingPass(JumpThreadingPass &&Other)
+ : TLI(Other.TLI), LVI(Other.LVI), BFI(std::move(Other.BFI)),
+ BPI(std::move(Other.BPI)), HasProfileData(Other.HasProfileData),
+ LoopHeaders(std::move(Other.LoopHeaders)),
+ RecursionSet(std::move(Other.RecursionSet)),
+ BBDupThreshold(Other.BBDupThreshold) {}
+
+ // Glue for old PM.
+ bool runImpl(Function &F, TargetLibraryInfo *TLI_, LazyValueInfo *LVI_,
+ bool HasProfileData_, std::unique_ptr<BlockFrequencyInfo> BFI_,
+ std::unique_ptr<BranchProbabilityInfo> BPI_);
+
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
+
+ void releaseMemory() {
+ BFI.reset();
+ BPI.reset();
+ }
+
+ void FindLoopHeaders(Function &F);
+ bool ProcessBlock(BasicBlock *BB);
+ bool ThreadEdge(BasicBlock *BB, const SmallVectorImpl<BasicBlock *> &PredBBs,
+ BasicBlock *SuccBB);
+ bool DuplicateCondBranchOnPHIIntoPred(
+ BasicBlock *BB, const SmallVectorImpl<BasicBlock *> &PredBBs);
+
+ bool
+ ComputeValueKnownInPredecessors(Value *V, BasicBlock *BB,
+ jumpthreading::PredValueInfo &Result,
+ jumpthreading::ConstantPreference Preference,
+ Instruction *CxtI = nullptr);
+ bool ProcessThreadableEdges(Value *Cond, BasicBlock *BB,
+ jumpthreading::ConstantPreference Preference,
+ Instruction *CxtI = nullptr);
+
+ bool ProcessBranchOnPHI(PHINode *PN);
+ bool ProcessBranchOnXOR(BinaryOperator *BO);
+ bool ProcessImpliedCondition(BasicBlock *BB);
+
+ bool SimplifyPartiallyRedundantLoad(LoadInst *LI);
+ bool TryToUnfoldSelect(CmpInst *CondCmp, BasicBlock *BB);
+ bool TryToUnfoldSelectInCurrBB(BasicBlock *BB);
+
+private:
+ BasicBlock *SplitBlockPreds(BasicBlock *BB, ArrayRef<BasicBlock *> Preds,
+ const char *Suffix);
+ void UpdateBlockFreqAndEdgeWeight(BasicBlock *PredBB, BasicBlock *BB,
+ BasicBlock *NewBB, BasicBlock *SuccBB);
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/include/llvm/Transforms/Scalar/LICM.h b/include/llvm/Transforms/Scalar/LICM.h
new file mode 100644
index 000000000000..a050a43d6179
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/LICM.h
@@ -0,0 +1,48 @@
+//===- LICM.h - Loop Invariant Code Motion Pass -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass performs loop invariant code motion, attempting to remove as much
+// code from the body of a loop as possible. It does this by either hoisting
+// code into the preheader block, or by sinking code to the exit blocks if it is
+// safe. This pass also promotes must-aliased memory locations in the loop to
+// live in registers, thus hoisting and sinking "invariant" loads and stores.
+//
+// This pass uses alias analysis for two purposes:
+//
+// 1. Moving loop invariant loads and calls out of loops. If we can determine
+// that a load or call inside of a loop never aliases anything stored to,
+// we can hoist it or sink it like any other instruction.
+// 2. Scalar Promotion of Memory - If there is a store instruction inside of
+// the loop, we try to move the store to happen AFTER the loop instead of
+// inside of the loop. This can only happen if a few conditions are true:
+// A. The pointer stored through is loop invariant
+// B. There are no stores or loads in the loop which _may_ alias the
+// pointer. There are no calls in the loop which mod/ref the pointer.
+// If these conditions are true, we can promote the loads and stores in the
+// loop of the pointer to use a temporary alloca'd variable. We then use
+// the SSAUpdater to construct the appropriate SSA form for the value.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_LICM_H
+#define LLVM_TRANSFORMS_SCALAR_LICM_H
+
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+/// Performs Loop Invariant Code Motion Pass.
+class LICMPass : public PassInfoMixin<LICMPass> {
+public:
+ PreservedAnalyses run(Loop &L, AnalysisManager<Loop> &AM);
+};
+} // end namespace llvm
+
+#endif // LLVM_TRANSFORMS_SCALAR_LICM_H
diff --git a/include/llvm/Transforms/Scalar/LoopDeletion.h b/include/llvm/Transforms/Scalar/LoopDeletion.h
new file mode 100644
index 000000000000..ed5a9833e572
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/LoopDeletion.h
@@ -0,0 +1,38 @@
+//===- LoopDeletion.h - Loop Deletion -------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides the interface for the Loop Deletion Pass.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_LOOPDELETION_H
+#define LLVM_TRANSFORMS_SCALAR_LOOPDELETION_H
+
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/ScalarEvolution.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+class LoopDeletionPass : public PassInfoMixin<LoopDeletionPass> {
+public:
+ LoopDeletionPass() {}
+ PreservedAnalyses run(Loop &L, AnalysisManager<Loop> &AM);
+ bool runImpl(Loop *L, DominatorTree &DT, ScalarEvolution &SE,
+ LoopInfo &loopInfo);
+
+private:
+ bool isLoopDead(Loop *L, ScalarEvolution &SE,
+ SmallVectorImpl<BasicBlock *> &exitingBlocks,
+ SmallVectorImpl<BasicBlock *> &exitBlocks, bool &Changed,
+ BasicBlock *Preheader);
+};
+}
+
+#endif // LLVM_TRANSFORMS_SCALAR_LOOPDELETION_H
diff --git a/include/llvm/Transforms/Scalar/LoopDistribute.h b/include/llvm/Transforms/Scalar/LoopDistribute.h
new file mode 100644
index 000000000000..ddde5954c218
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/LoopDistribute.h
@@ -0,0 +1,30 @@
+//===- LoopDistribute.cpp - Loop Distribution Pass --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Loop Distribution Pass. Its main focus is to
+// distribute loops that cannot be vectorized due to dependence cycles. It
+// tries to isolate the offending dependences into a new loop allowing
+// vectorization of the remaining parts.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_LOOPDISTRIBUTE_H
+#define LLVM_TRANSFORMS_SCALAR_LOOPDISTRIBUTE_H
+
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+class LoopDistributePass : public PassInfoMixin<LoopDistributePass> {
+public:
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+};
+} // end namespace llvm
+
+#endif // LLVM_TRANSFORMS_SCALAR_LOOPDISTRIBUTE_H
diff --git a/include/llvm/Transforms/Scalar/LoopIdiomRecognize.h b/include/llvm/Transforms/Scalar/LoopIdiomRecognize.h
new file mode 100644
index 000000000000..cc66156fba8a
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/LoopIdiomRecognize.h
@@ -0,0 +1,31 @@
+//===- LoopIdiomRecognize.h - Loop Idiom Recognize Pass -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass implements an idiom recognizer that transforms simple loops into a
+// non-loop form. In cases that this kicks in, it can be a significant
+// performance win.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_LOOPIDIOMRECOGNIZE_H
+#define LLVM_TRANSFORMS_SCALAR_LOOPIDIOMRECOGNIZE_H
+
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+/// Performs Loop Idiom Recognize Pass.
+class LoopIdiomRecognizePass : public PassInfoMixin<LoopIdiomRecognizePass> {
+public:
+ PreservedAnalyses run(Loop &L, AnalysisManager<Loop> &AM);
+};
+} // end namespace llvm
+
+#endif // LLVM_TRANSFORMS_SCALAR_LOOPIDIOMRECOGNIZE_H
diff --git a/include/llvm/Transforms/Scalar/LoopInstSimplify.h b/include/llvm/Transforms/Scalar/LoopInstSimplify.h
new file mode 100644
index 000000000000..f67343f40a7c
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/LoopInstSimplify.h
@@ -0,0 +1,29 @@
+//===- LoopInstSimplify.h - Loop Inst Simplify Pass -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass performs lightweight instruction simplification on loop bodies.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_LOOPINSTSIMPLIFY_H
+#define LLVM_TRANSFORMS_SCALAR_LOOPINSTSIMPLIFY_H
+
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+/// Performs Loop Inst Simplify Pass.
+class LoopInstSimplifyPass : public PassInfoMixin<LoopInstSimplifyPass> {
+public:
+ PreservedAnalyses run(Loop &L, AnalysisManager<Loop> &AM);
+};
+} // end namespace llvm
+
+#endif // LLVM_TRANSFORMS_SCALAR_LOOPINSTSIMPLIFY_H
diff --git a/include/llvm/Transforms/Scalar/LoopRotation.h b/include/llvm/Transforms/Scalar/LoopRotation.h
new file mode 100644
index 000000000000..b21c7313dc4b
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/LoopRotation.h
@@ -0,0 +1,30 @@
+//===- LoopRotation.h - Loop Rotation -------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides the interface for the Loop Rotation pass.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_LOOPROTATION_H
+#define LLVM_TRANSFORMS_SCALAR_LOOPROTATION_H
+
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+/// A simple loop rotation transformation.
+class LoopRotatePass : public PassInfoMixin<LoopRotatePass> {
+public:
+ LoopRotatePass();
+ PreservedAnalyses run(Loop &L, AnalysisManager<Loop> &AM);
+};
+}
+
+#endif // LLVM_TRANSFORMS_SCALAR_LOOPROTATION_H
diff --git a/include/llvm/Transforms/Scalar/LoopSimplifyCFG.h b/include/llvm/Transforms/Scalar/LoopSimplifyCFG.h
new file mode 100644
index 000000000000..7609bb26a1a0
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/LoopSimplifyCFG.h
@@ -0,0 +1,32 @@
+//===- LoopSimplifyCFG.cpp - Loop CFG Simplification Pass -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Loop SimplifyCFG Pass. This pass is responsible for
+// basic loop CFG cleanup, primarily to assist other loop passes. If you
+// encounter a noncanonical CFG construct that causes another loop pass to
+// perform suboptimally, this is the place to fix it up.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_LOOPSIMPLIFYCFG_H
+#define LLVM_TRANSFORMS_SCALAR_LOOPSIMPLIFYCFG_H
+
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+/// Performs basic CFG simplifications to assist other loop passes.
+class LoopSimplifyCFGPass : public PassInfoMixin<LoopSimplifyCFGPass> {
+public:
+ PreservedAnalyses run(Loop &L, AnalysisManager<Loop> &AM);
+};
+} // end namespace llvm
+
+#endif // LLVM_TRANSFORMS_SCALAR_LOOPSIMPLIFYCFG_H
diff --git a/include/llvm/Transforms/Scalar/LowerAtomic.h b/include/llvm/Transforms/Scalar/LowerAtomic.h
new file mode 100644
index 000000000000..a4a2e7aafe44
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/LowerAtomic.h
@@ -0,0 +1,29 @@
+//===- LowerAtomic.cpp - Lower atomic intrinsics ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+// This pass lowers atomic intrinsics to non-atomic form for use in a known
+// non-preemptible environment.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_LOWERATOMIC_H
+#define LLVM_TRANSFORMS_SCALAR_LOWERATOMIC_H
+
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+/// A pass that lowers atomic intrinsic into non-atomic intrinsics.
+class LowerAtomicPass : public PassInfoMixin<LowerAtomicPass> {
+public:
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &);
+};
+}
+
+#endif // LLVM_TRANSFORMS_SCALAR_LOWERATOMIC_H
diff --git a/include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h b/include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h
index 40283203f3a3..f688e7f19986 100644
--- a/include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h
+++ b/include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h
@@ -21,10 +21,7 @@
namespace llvm {
-class LowerExpectIntrinsicPass {
-public:
- static StringRef name() { return "LowerExpectIntrinsicPass"; }
-
+struct LowerExpectIntrinsicPass : PassInfoMixin<LowerExpectIntrinsicPass> {
/// \brief Run the pass over the function.
///
/// This will lower all of th expect intrinsic calls in this function into
@@ -32,7 +29,7 @@ public:
/// of the probabilities and frequencies of the CFG. After running this pass,
/// no more expect intrinsics remain, allowing the rest of the optimizer to
/// ignore them.
- PreservedAnalyses run(Function &F);
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &);
};
}
diff --git a/include/llvm/Transforms/Scalar/MemCpyOptimizer.h b/include/llvm/Transforms/Scalar/MemCpyOptimizer.h
new file mode 100644
index 000000000000..4308e44e7c4b
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/MemCpyOptimizer.h
@@ -0,0 +1,68 @@
+//===---- MemCpyOptimizer.h - memcpy optimization ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass performs various transformations related to eliminating memcpy
+// calls, or transforming sets of stores into memset's.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_MEMCPYOPTIMIZER_H
+#define LLVM_TRANSFORMS_SCALAR_MEMCPYOPTIMIZER_H
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Analysis/AliasAnalysis.h"
+#include "llvm/Analysis/AssumptionCache.h"
+#include "llvm/Analysis/GlobalsModRef.h"
+#include "llvm/Analysis/MemoryDependenceAnalysis.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+class MemCpyOptPass : public PassInfoMixin<MemCpyOptPass> {
+ MemoryDependenceResults *MD = nullptr;
+ TargetLibraryInfo *TLI = nullptr;
+ std::function<AliasAnalysis &()> LookupAliasAnalysis;
+ std::function<AssumptionCache &()> LookupAssumptionCache;
+ std::function<DominatorTree &()> LookupDomTree;
+
+public:
+ MemCpyOptPass() {}
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+ // Glue for the old PM.
+ bool runImpl(Function &F, MemoryDependenceResults *MD_,
+ TargetLibraryInfo *TLI_,
+ std::function<AliasAnalysis &()> LookupAliasAnalysis_,
+ std::function<AssumptionCache &()> LookupAssumptionCache_,
+ std::function<DominatorTree &()> LookupDomTree_);
+
+private:
+ // Helper functions
+ bool processStore(StoreInst *SI, BasicBlock::iterator &BBI);
+ bool processMemSet(MemSetInst *SI, BasicBlock::iterator &BBI);
+ bool processMemCpy(MemCpyInst *M);
+ bool processMemMove(MemMoveInst *M);
+ bool performCallSlotOptzn(Instruction *cpy, Value *cpyDst, Value *cpySrc,
+ uint64_t cpyLen, unsigned cpyAlign, CallInst *C);
+ bool processMemCpyMemCpyDependence(MemCpyInst *M, MemCpyInst *MDep);
+ bool processMemSetMemCpyDependence(MemCpyInst *M, MemSetInst *MDep);
+ bool performMemCpyToMemSetOptzn(MemCpyInst *M, MemSetInst *MDep);
+ bool processByValArgument(CallSite CS, unsigned ArgNo);
+ Instruction *tryMergingIntoMemset(Instruction *I, Value *StartPtr,
+ Value *ByteVal);
+
+ bool iterateOnFunction(Function &F);
+};
+}
+
+#endif // LLVM_TRANSFORMS_SCALAR_MEMCPYOPTIMIZER_H
diff --git a/include/llvm/Transforms/Scalar/MergedLoadStoreMotion.h b/include/llvm/Transforms/Scalar/MergedLoadStoreMotion.h
new file mode 100644
index 000000000000..47cfea489243
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/MergedLoadStoreMotion.h
@@ -0,0 +1,39 @@
+//===- MergedLoadStoreMotion.h - merge and hoist/sink load/stores ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//! \file
+//! \brief This pass performs merges of loads and stores on both sides of a
+// diamond (hammock). It hoists the loads and sinks the stores.
+//
+// The algorithm iteratively hoists two loads to the same address out of a
+// diamond (hammock) and merges them into a single load in the header. Similar
+// it sinks and merges two stores to the tail block (footer). The algorithm
+// iterates over the instructions of one side of the diamond and attempts to
+// find a matching load/store on the other side. It hoists / sinks when it
+// thinks it safe to do so. This optimization helps with eg. hiding load
+// latencies, triggering if-conversion, and reducing static code size.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_MERGEDLOADSTOREMOTION_H
+#define LLVM_TRANSFORMS_SCALAR_MERGEDLOADSTOREMOTION_H
+
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+class MergedLoadStoreMotionPass
+ : public PassInfoMixin<MergedLoadStoreMotionPass> {
+public:
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
+};
+
+}
+
+#endif // LLVM_TRANSFORMS_SCALAR_MERGEDLOADSTOREMOTION_H
diff --git a/include/llvm/Transforms/Scalar/PartiallyInlineLibCalls.h b/include/llvm/Transforms/Scalar/PartiallyInlineLibCalls.h
new file mode 100644
index 000000000000..385bbb40db3f
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/PartiallyInlineLibCalls.h
@@ -0,0 +1,30 @@
+//===--- PartiallyInlineLibCalls.h - Partially inline libcalls --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass tries to partially inline the fast path of well-known library
+// functions, such as using square-root instructions for cases where sqrt()
+// does not need to set errno.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_PARTIALLYINLINELIBCALLS_H
+#define LLVM_TRANSFORMS_SCALAR_PARTIALLYINLINELIBCALLS_H
+
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+class PartiallyInlineLibCallsPass
+ : public PassInfoMixin<PartiallyInlineLibCallsPass> {
+public:
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
+};
+}
+
+#endif // LLVM_TRANSFORMS_SCALAR_PARTIALLYINLINELIBCALLS_H
diff --git a/include/llvm/Transforms/Scalar/Reassociate.h b/include/llvm/Transforms/Scalar/Reassociate.h
new file mode 100644
index 000000000000..7b68b4489306
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/Reassociate.h
@@ -0,0 +1,100 @@
+//===- Reassociate.h - Reassociate binary expressions -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass reassociates commutative expressions in an order that is designed
+// to promote better constant propagation, GCSE, LICM, PRE, etc.
+//
+// For example: 4 + (x + 5) -> x + (4 + 5)
+//
+// In the implementation of this algorithm, constants are assigned rank = 0,
+// function arguments are rank = 1, and other values are assigned ranks
+// corresponding to the reverse post order traversal of current function
+// (starting at 2), which effectively gives values in deep loops higher rank
+// than values not in loops.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_REASSOCIATE_H
+#define LLVM_TRANSFORMS_SCALAR_REASSOCIATE_H
+
+#include "llvm/ADT/PostOrderIterator.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Operator.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+/// A private "module" namespace for types and utilities used by Reassociate.
+/// These are implementation details and should not be used by clients.
+namespace reassociate {
+struct ValueEntry {
+ unsigned Rank;
+ Value *Op;
+ ValueEntry(unsigned R, Value *O) : Rank(R), Op(O) {}
+};
+inline bool operator<(const ValueEntry &LHS, const ValueEntry &RHS) {
+ return LHS.Rank > RHS.Rank; // Sort so that highest rank goes to start.
+}
+
+/// \brief Utility class representing a base and exponent pair which form one
+/// factor of some product.
+struct Factor {
+ Value *Base;
+ unsigned Power;
+ Factor(Value *Base, unsigned Power) : Base(Base), Power(Power) {}
+};
+
+class XorOpnd;
+}
+
+/// Reassociate commutative expressions.
+class ReassociatePass : public PassInfoMixin<ReassociatePass> {
+ DenseMap<BasicBlock *, unsigned> RankMap;
+ DenseMap<AssertingVH<Value>, unsigned> ValueRankMap;
+ SetVector<AssertingVH<Instruction>> RedoInsts;
+ bool MadeChange;
+
+public:
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &);
+
+private:
+ void BuildRankMap(Function &F, ReversePostOrderTraversal<Function *> &RPOT);
+ unsigned getRank(Value *V);
+ void canonicalizeOperands(Instruction *I);
+ void ReassociateExpression(BinaryOperator *I);
+ void RewriteExprTree(BinaryOperator *I,
+ SmallVectorImpl<reassociate::ValueEntry> &Ops);
+ Value *OptimizeExpression(BinaryOperator *I,
+ SmallVectorImpl<reassociate::ValueEntry> &Ops);
+ Value *OptimizeAdd(Instruction *I,
+ SmallVectorImpl<reassociate::ValueEntry> &Ops);
+ Value *OptimizeXor(Instruction *I,
+ SmallVectorImpl<reassociate::ValueEntry> &Ops);
+ bool CombineXorOpnd(Instruction *I, reassociate::XorOpnd *Opnd1,
+ APInt &ConstOpnd, Value *&Res);
+ bool CombineXorOpnd(Instruction *I, reassociate::XorOpnd *Opnd1,
+ reassociate::XorOpnd *Opnd2, APInt &ConstOpnd,
+ Value *&Res);
+ bool collectMultiplyFactors(SmallVectorImpl<reassociate::ValueEntry> &Ops,
+ SmallVectorImpl<reassociate::Factor> &Factors);
+ Value *buildMinimalMultiplyDAG(IRBuilder<> &Builder,
+ SmallVectorImpl<reassociate::Factor> &Factors);
+ Value *OptimizeMul(BinaryOperator *I,
+ SmallVectorImpl<reassociate::ValueEntry> &Ops);
+ Value *RemoveFactorFromExpression(Value *V, Value *Factor);
+ void EraseInst(Instruction *I);
+ void RecursivelyEraseDeadInsts(Instruction *I,
+ SetVector<AssertingVH<Instruction>> &Insts);
+ void OptimizeInst(Instruction *I);
+ Instruction *canonicalizeNegConstExpr(Instruction *I);
+};
+}
+
+#endif // LLVM_TRANSFORMS_SCALAR_REASSOCIATE_H
diff --git a/include/llvm/Transforms/Scalar/SCCP.h b/include/llvm/Transforms/Scalar/SCCP.h
new file mode 100644
index 000000000000..0dd90ecbedec
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/SCCP.h
@@ -0,0 +1,36 @@
+//===- SCCP.cpp - Sparse Conditional Constant Propagation -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+// This file implements sparse conditional constant propagation and merging:
+//
+// Specifically, this:
+// * Assumes values are constant unless proven otherwise
+// * Assumes BasicBlocks are dead unless proven otherwise
+// * Proves values to be constant, and replaces them with constants
+// * Proves conditional branches to be unconditional
+//
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_SCCP_H
+#define LLVM_TRANSFORMS_SCALAR_SCCP_H
+
+#include "llvm/IR/Function.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+/// This pass performs function-level constant propagation and merging.
+class SCCPPass : public PassInfoMixin<SCCPPass> {
+public:
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
+};
+}
+
+#endif // LLVM_TRANSFORMS_SCALAR_SCCP_H
diff --git a/include/llvm/Transforms/Scalar/SROA.h b/include/llvm/Transforms/Scalar/SROA.h
index f90cc7b686ba..72e7d63d4df6 100644
--- a/include/llvm/Transforms/Scalar/SROA.h
+++ b/include/llvm/Transforms/Scalar/SROA.h
@@ -26,7 +26,7 @@ namespace llvm {
/// A private "module" namespace for types and utilities used by SROA. These
/// are implementation details and should not be used by clients.
-namespace sroa {
+namespace sroa LLVM_LIBRARY_VISIBILITY {
class AllocaSliceRewriter;
class AllocaSlices;
class Partition;
@@ -51,7 +51,7 @@ class SROALegacyPass;
/// onto insert and extract operations on a vector value, and convert them to
/// this form. By doing so, it will enable promotion of vector aggregates to
/// SSA vector values.
-class SROA {
+class SROA : public PassInfoMixin<SROA> {
LLVMContext *C;
DominatorTree *DT;
AssumptionCache *AC;
@@ -101,10 +101,8 @@ class SROA {
public:
SROA() : C(nullptr), DT(nullptr), AC(nullptr) {}
- static StringRef name() { return "SROA"; }
-
/// \brief Run the pass over the function.
- PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM);
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
private:
friend class sroa::AllocaSliceRewriter;
diff --git a/include/llvm/Transforms/Scalar/SimplifyCFG.h b/include/llvm/Transforms/Scalar/SimplifyCFG.h
index ef28e0f78a4c..53f427a7d19a 100644
--- a/include/llvm/Transforms/Scalar/SimplifyCFG.h
+++ b/include/llvm/Transforms/Scalar/SimplifyCFG.h
@@ -25,12 +25,10 @@ namespace llvm {
/// This pass iteratively simplifies the entire CFG of a function, removing
/// unnecessary control flows and bringing it into the canonical form expected
/// by the rest of the mid-level optimizer.
-class SimplifyCFGPass {
+class SimplifyCFGPass : public PassInfoMixin<SimplifyCFGPass> {
int BonusInstThreshold;
public:
- static StringRef name() { return "SimplifyCFGPass"; }
-
/// \brief Construct a pass with the default thresholds.
SimplifyCFGPass();
@@ -38,7 +36,7 @@ public:
SimplifyCFGPass(int BonusInstThreshold);
/// \brief Run the pass over the function.
- PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM);
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
};
}
diff --git a/include/llvm/Transforms/Scalar/Sink.h b/include/llvm/Transforms/Scalar/Sink.h
new file mode 100644
index 000000000000..1144c62fb20c
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/Sink.h
@@ -0,0 +1,30 @@
+//===-- Sink.h - Code Sinking -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass moves instructions into successor blocks, when possible, so that
+// they aren't executed on paths where their results aren't needed.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_SINK_H
+#define LLVM_TRANSFORMS_SCALAR_SINK_H
+
+#include "llvm/IR/Function.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+/// Move instructions into successor blocks when possible.
+class SinkingPass : public PassInfoMixin<SinkingPass> {
+public:
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
+};
+}
+
+#endif // LLVM_TRANSFORMS_SCALAR_SINK_H
diff --git a/include/llvm/Transforms/Scalar/TailRecursionElimination.h b/include/llvm/Transforms/Scalar/TailRecursionElimination.h
new file mode 100644
index 000000000000..793f9bc152ed
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/TailRecursionElimination.h
@@ -0,0 +1,66 @@
+//===---- TailRecursionElimination.h ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file transforms calls of the current function (self recursion) followed
+// by a return instruction with a branch to the entry of the function, creating
+// a loop. This pass also implements the following extensions to the basic
+// algorithm:
+//
+// 1. Trivial instructions between the call and return do not prevent the
+// transformation from taking place, though currently the analysis cannot
+// support moving any really useful instructions (only dead ones).
+// 2. This pass transforms functions that are prevented from being tail
+// recursive by an associative and commutative expression to use an
+// accumulator variable, thus compiling the typical naive factorial or
+// 'fib' implementation into efficient code.
+// 3. TRE is performed if the function returns void, if the return
+// returns the result returned by the call, or if the function returns a
+// run-time constant on all exits from the function. It is possible, though
+// unlikely, that the return returns something else (like constant 0), and
+// can still be TRE'd. It can be TRE'd if ALL OTHER return instructions in
+// the function return the exact same value.
+// 4. If it can prove that callees do not access their caller stack frame,
+// they are marked as eligible for tail call elimination (by the code
+// generator).
+//
+// There are several improvements that could be made:
+//
+// 1. If the function has any alloca instructions, these instructions will be
+// moved out of the entry block of the function, causing them to be
+// evaluated each time through the tail recursion. Safely keeping allocas
+// in the entry block requires analysis to proves that the tail-called
+// function does not read or write the stack object.
+// 2. Tail recursion is only performed if the call immediately precedes the
+// return instruction. It's possible that there could be a jump between
+// the call and the return.
+// 3. There can be intervening operations between the call and the return that
+// prevent the TRE from occurring. For example, there could be GEP's and
+// stores to memory that will not be read or written by the call. This
+// requires some substantial analysis (such as with DSA) to prove safe to
+// move ahead of the call, but doing so could allow many more TREs to be
+// performed, for example in TreeAdd/TreeAlloc from the treeadd benchmark.
+// 4. The algorithm we use to detect if callees access their caller stack
+// frames is very primitive.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_TAILRECURSIONELIMINATION_H
+#define LLVM_TRANSFORMS_SCALAR_TAILRECURSIONELIMINATION_H
+
+#include "llvm/IR/Function.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+struct TailCallElimPass : PassInfoMixin<TailCallElimPass> {
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+};
+}
+
+#endif // LLVM_TRANSFORMS_SCALAR_TAILRECURSIONELIMINATION_H
diff --git a/include/llvm/Transforms/Utils/AddDiscriminators.h b/include/llvm/Transforms/Utils/AddDiscriminators.h
new file mode 100644
index 000000000000..0b3a8add6278
--- /dev/null
+++ b/include/llvm/Transforms/Utils/AddDiscriminators.h
@@ -0,0 +1,29 @@
+//===- AddDiscriminators.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass adds DWARF discriminators to the IR. Path discriminators are used
+// to decide what CFG path was taken inside sub-graphs whose instructions share
+// the same line and column number information.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_UTILS_ADDDISCRIMINATORS_H
+#define LLVM_TRANSFORMS_UTILS_ADDDISCRIMINATORS_H
+
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+class AddDiscriminatorsPass : public PassInfoMixin<AddDiscriminatorsPass> {
+public:
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
+};
+} // end namespace llvm
+
+#endif // LLVM_TRANSFORMS_UTILS_ADDDISCRIMINATORS_H
diff --git a/include/llvm/Transforms/Utils/BasicBlockUtils.h b/include/llvm/Transforms/Utils/BasicBlockUtils.h
index 13c856dfdc9a..37fd20925cba 100644
--- a/include/llvm/Transforms/Utils/BasicBlockUtils.h
+++ b/include/llvm/Transforms/Utils/BasicBlockUtils.h
@@ -22,7 +22,7 @@
namespace llvm {
-class MemoryDependenceAnalysis;
+class MemoryDependenceResults;
class DominatorTree;
class LoopInfo;
class Instruction;
@@ -31,51 +31,45 @@ class ReturnInst;
class TargetLibraryInfo;
class TerminatorInst;
-/// DeleteDeadBlock - Delete the specified block, which must have no
-/// predecessors.
+/// Delete the specified block, which must have no predecessors.
void DeleteDeadBlock(BasicBlock *BB);
-/// FoldSingleEntryPHINodes - We know that BB has one predecessor. If there are
-/// any single-entry PHI nodes in it, fold them away. This handles the case
-/// when all entries to the PHI nodes in a block are guaranteed equal, such as
-/// when the block has exactly one predecessor.
+/// We know that BB has one predecessor. If there are any single-entry PHI nodes
+/// in it, fold them away. This handles the case when all entries to the PHI
+/// nodes in a block are guaranteed equal, such as when the block has exactly
+/// one predecessor.
void FoldSingleEntryPHINodes(BasicBlock *BB,
- MemoryDependenceAnalysis *MemDep = nullptr);
+ MemoryDependenceResults *MemDep = nullptr);
-/// DeleteDeadPHIs - Examine each PHI in the given block and delete it if it
-/// is dead. Also recursively delete any operands that become dead as
-/// a result. This includes tracing the def-use list from the PHI to see if
-/// it is ultimately unused or if it reaches an unused cycle. Return true
-/// if any PHIs were deleted.
+/// Examine each PHI in the given block and delete it if it is dead. Also
+/// recursively delete any operands that become dead as a result. This includes
+/// tracing the def-use list from the PHI to see if it is ultimately unused or
+/// if it reaches an unused cycle. Return true if any PHIs were deleted.
bool DeleteDeadPHIs(BasicBlock *BB, const TargetLibraryInfo *TLI = nullptr);
-/// MergeBlockIntoPredecessor - Attempts to merge a block into its predecessor,
-/// if possible. The return value indicates success or failure.
+/// Attempts to merge a block into its predecessor, if possible. The return
+/// value indicates success or failure.
bool MergeBlockIntoPredecessor(BasicBlock *BB, DominatorTree *DT = nullptr,
LoopInfo *LI = nullptr,
- MemoryDependenceAnalysis *MemDep = nullptr);
+ MemoryDependenceResults *MemDep = nullptr);
-// ReplaceInstWithValue - Replace all uses of an instruction (specified by BI)
-// with a value, then remove and delete the original instruction.
-//
+/// Replace all uses of an instruction (specified by BI) with a value, then
+/// remove and delete the original instruction.
void ReplaceInstWithValue(BasicBlock::InstListType &BIL,
BasicBlock::iterator &BI, Value *V);
-// ReplaceInstWithInst - Replace the instruction specified by BI with the
-// instruction specified by I. Copies DebugLoc from BI to I, if I doesn't
-// already have a DebugLoc. The original instruction is deleted and BI is
-// updated to point to the new instruction.
-//
+/// Replace the instruction specified by BI with the instruction specified by I.
+/// Copies DebugLoc from BI to I, if I doesn't already have a DebugLoc. The
+/// original instruction is deleted and BI is updated to point to the new
+/// instruction.
void ReplaceInstWithInst(BasicBlock::InstListType &BIL,
BasicBlock::iterator &BI, Instruction *I);
-// ReplaceInstWithInst - Replace the instruction specified by From with the
-// instruction specified by To. Copies DebugLoc from BI to I, if I doesn't
-// already have a DebugLoc.
-//
+/// Replace the instruction specified by From with the instruction specified by
+/// To. Copies DebugLoc from BI to I, if I doesn't already have a DebugLoc.
void ReplaceInstWithInst(Instruction *From, Instruction *To);
-/// \brief Option class for critical edge splitting.
+/// Option class for critical edge splitting.
///
/// This provides a builder interface for overriding the default options used
/// during critical edge splitting.
@@ -107,10 +101,9 @@ struct CriticalEdgeSplittingOptions {
}
};
-/// SplitCriticalEdge - If this edge is a critical edge, insert a new node to
-/// split the critical edge. This will update the analyses passed in through
-/// the option struct. This returns the new block if the edge was split, null
-/// otherwise.
+/// If this edge is a critical edge, insert a new node to split the critical
+/// edge. This will update the analyses passed in through the option struct.
+/// This returns the new block if the edge was split, null otherwise.
///
/// If MergeIdenticalEdges in the options struct is true (not the default),
/// *all* edges from TI to the specified successor will be merged into the same
@@ -137,11 +130,10 @@ SplitCriticalEdge(BasicBlock *BB, succ_iterator SI,
Options);
}
-/// SplitCriticalEdge - If the edge from *PI to BB is not critical, return
-/// false. Otherwise, split all edges between the two blocks and return true.
-/// This updates all of the same analyses as the other SplitCriticalEdge
-/// function. If P is specified, it updates the analyses
-/// described above.
+/// If the edge from *PI to BB is not critical, return false. Otherwise, split
+/// all edges between the two blocks and return true. This updates all of the
+/// same analyses as the other SplitCriticalEdge function. If P is specified, it
+/// updates the analyses described above.
inline bool SplitCriticalEdge(BasicBlock *Succ, pred_iterator PI,
const CriticalEdgeSplittingOptions &Options =
CriticalEdgeSplittingOptions()) {
@@ -153,10 +145,9 @@ inline bool SplitCriticalEdge(BasicBlock *Succ, pred_iterator PI,
return MadeChange;
}
-/// SplitCriticalEdge - If an edge from Src to Dst is critical, split the edge
-/// and return true, otherwise return false. This method requires that there be
-/// an edge between the two blocks. It updates the analyses
-/// passed in the options struct
+/// If an edge from Src to Dst is critical, split the edge and return true,
+/// otherwise return false. This method requires that there be an edge between
+/// the two blocks. It updates the analyses passed in the options struct
inline BasicBlock *
SplitCriticalEdge(BasicBlock *Src, BasicBlock *Dst,
const CriticalEdgeSplittingOptions &Options =
@@ -171,30 +162,28 @@ SplitCriticalEdge(BasicBlock *Src, BasicBlock *Dst,
}
}
-// SplitAllCriticalEdges - Loop over all of the edges in the CFG,
-// breaking critical edges as they are found.
-// Returns the number of broken edges.
+/// Loop over all of the edges in the CFG, breaking critical edges as they are
+/// found. Returns the number of broken edges.
unsigned SplitAllCriticalEdges(Function &F,
const CriticalEdgeSplittingOptions &Options =
CriticalEdgeSplittingOptions());
-/// SplitEdge - Split the edge connecting specified block.
+/// Split the edge connecting specified block.
BasicBlock *SplitEdge(BasicBlock *From, BasicBlock *To,
DominatorTree *DT = nullptr, LoopInfo *LI = nullptr);
-/// SplitBlock - Split the specified block at the specified instruction - every
-/// thing before SplitPt stays in Old and everything starting with SplitPt moves
-/// to a new block. The two blocks are joined by an unconditional branch and
-/// the loop info is updated.
-///
+/// Split the specified block at the specified instruction - everything before
+/// SplitPt stays in Old and everything starting with SplitPt moves to a new
+/// block. The two blocks are joined by an unconditional branch and the loop
+/// info is updated.
BasicBlock *SplitBlock(BasicBlock *Old, Instruction *SplitPt,
DominatorTree *DT = nullptr, LoopInfo *LI = nullptr);
-/// SplitBlockPredecessors - This method introduces at least one new basic block
-/// into the function and moves some of the predecessors of BB to be
-/// predecessors of the new block. The new predecessors are indicated by the
-/// Preds array. The new block is given a suffix of 'Suffix'. Returns new basic
-/// block to which predecessors from Preds are now pointing.
+/// This method introduces at least one new basic block into the function and
+/// moves some of the predecessors of BB to be predecessors of the new block.
+/// The new predecessors are indicated by the Preds array. The new block is
+/// given a suffix of 'Suffix'. Returns new basic block to which predecessors
+/// from Preds are now pointing.
///
/// If BB is a landingpad block then additional basicblock might be introduced.
/// It will have Suffix+".split_lp". See SplitLandingPadPredecessors for more
@@ -211,12 +200,12 @@ BasicBlock *SplitBlockPredecessors(BasicBlock *BB, ArrayRef<BasicBlock *> Preds,
LoopInfo *LI = nullptr,
bool PreserveLCSSA = false);
-/// SplitLandingPadPredecessors - This method transforms the landing pad,
-/// OrigBB, by introducing two new basic blocks into the function. One of those
-/// new basic blocks gets the predecessors listed in Preds. The other basic
-/// block gets the remaining predecessors of OrigBB. The landingpad instruction
-/// OrigBB is clone into both of the new basic blocks. The new blocks are given
-/// the suffixes 'Suffix1' and 'Suffix2', and are returned in the NewBBs vector.
+/// This method transforms the landing pad, OrigBB, by introducing two new basic
+/// blocks into the function. One of those new basic blocks gets the
+/// predecessors listed in Preds. The other basic block gets the remaining
+/// predecessors of OrigBB. The landingpad instruction OrigBB is clone into both
+/// of the new basic blocks. The new blocks are given the suffixes 'Suffix1' and
+/// 'Suffix2', and are returned in the NewBBs vector.
///
/// This currently updates the LLVM IR, DominatorTree, LoopInfo, and LCCSA but
/// no other analyses. In particular, it does not preserve LoopSimplify
@@ -231,19 +220,17 @@ void SplitLandingPadPredecessors(BasicBlock *OrigBB,
LoopInfo *LI = nullptr,
bool PreserveLCSSA = false);
-/// FoldReturnIntoUncondBranch - This method duplicates the specified return
-/// instruction into a predecessor which ends in an unconditional branch. If
-/// the return instruction returns a value defined by a PHI, propagate the
-/// right value into the return. It returns the new return instruction in the
-/// predecessor.
+/// This method duplicates the specified return instruction into a predecessor
+/// which ends in an unconditional branch. If the return instruction returns a
+/// value defined by a PHI, propagate the right value into the return. It
+/// returns the new return instruction in the predecessor.
ReturnInst *FoldReturnIntoUncondBranch(ReturnInst *RI, BasicBlock *BB,
BasicBlock *Pred);
-/// SplitBlockAndInsertIfThen - Split the containing block at the
-/// specified instruction - everything before and including SplitBefore stays
-/// in the old basic block, and everything after SplitBefore is moved to a
-/// new block. The two blocks are connected by a conditional branch
-/// (with value of Cmp being the condition).
+/// Split the containing block at the specified instruction - everything before
+/// and including SplitBefore stays in the old basic block, and everything after
+/// SplitBefore is moved to a new block. The two blocks are connected by a
+/// conditional branch (with value of Cmp being the condition).
/// Before:
/// Head
/// SplitBefore
@@ -259,11 +246,12 @@ ReturnInst *FoldReturnIntoUncondBranch(ReturnInst *RI, BasicBlock *BB,
/// UnreachableInst, otherwise it branches to Tail.
/// Returns the NewBasicBlock's terminator.
///
-/// Updates DT if given.
+/// Updates DT and LI if given.
TerminatorInst *SplitBlockAndInsertIfThen(Value *Cond, Instruction *SplitBefore,
bool Unreachable,
MDNode *BranchWeights = nullptr,
- DominatorTree *DT = nullptr);
+ DominatorTree *DT = nullptr,
+ LoopInfo *LI = nullptr);
/// SplitBlockAndInsertIfThenElse is similar to SplitBlockAndInsertIfThen,
/// but also creates the ElseBlock.
@@ -284,12 +272,14 @@ void SplitBlockAndInsertIfThenElse(Value *Cond, Instruction *SplitBefore,
TerminatorInst **ElseTerm,
MDNode *BranchWeights = nullptr);
-///
-/// GetIfCondition - Check whether BB is the merge point of a if-region.
+/// Check whether BB is the merge point of a if-region.
/// If so, return the boolean condition that determines which entry into
/// BB will be taken. Also, return by references the block that will be
/// entered from if the condition is true, and the block that will be
/// entered if the condition is false.
+///
+/// This does no checking to see if the true/false blocks have large or unsavory
+/// instructions in them.
Value *GetIfCondition(BasicBlock *BB, BasicBlock *&IfTrue,
BasicBlock *&IfFalse);
} // End llvm namespace
diff --git a/include/llvm/Transforms/Utils/BuildLibCalls.h b/include/llvm/Transforms/Utils/BuildLibCalls.h
index 879f295caf0c..2d2a85905d0e 100644
--- a/include/llvm/Transforms/Utils/BuildLibCalls.h
+++ b/include/llvm/Transforms/Utils/BuildLibCalls.h
@@ -22,94 +22,96 @@ namespace llvm {
class DataLayout;
class TargetLibraryInfo;
- /// CastToCStr - Return V if it is an i8*, otherwise cast it to i8*.
- Value *CastToCStr(Value *V, IRBuilder<> &B);
-
- /// EmitStrLen - Emit a call to the strlen function to the builder, for the
- /// specified pointer. Ptr is required to be some pointer type, and the
- /// return value has 'intptr_t' type.
- Value *EmitStrLen(Value *Ptr, IRBuilder<> &B, const DataLayout &DL,
+ /// Analyze the name and prototype of the given function and set any
+ /// applicable attributes.
+ /// If the library function is unavailable, this doesn't modify it.
+ ///
+ /// Returns true if any attributes were set and false otherwise.
+ bool inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI);
+
+ /// Return V if it is an i8*, otherwise cast it to i8*.
+ Value *castToCStr(Value *V, IRBuilder<> &B);
+
+ /// Emit a call to the strlen function to the builder, for the specified
+ /// pointer. Ptr is required to be some pointer type, and the return value has
+ /// 'intptr_t' type.
+ Value *emitStrLen(Value *Ptr, IRBuilder<> &B, const DataLayout &DL,
const TargetLibraryInfo *TLI);
- /// EmitStrNLen - Emit a call to the strnlen function to the builder, for the
- /// specified pointer. Ptr is required to be some pointer type, MaxLen must
- /// be of size_t type, and the return value has 'intptr_t' type.
- Value *EmitStrNLen(Value *Ptr, Value *MaxLen, IRBuilder<> &B,
+ /// Emit a call to the strnlen function to the builder, for the specified
+ /// pointer. Ptr is required to be some pointer type, MaxLen must be of size_t
+ /// type, and the return value has 'intptr_t' type.
+ Value *emitStrNLen(Value *Ptr, Value *MaxLen, IRBuilder<> &B,
const DataLayout &DL, const TargetLibraryInfo *TLI);
- /// EmitStrChr - Emit a call to the strchr function to the builder, for the
- /// specified pointer and character. Ptr is required to be some pointer type,
- /// and the return value has 'i8*' type.
- Value *EmitStrChr(Value *Ptr, char C, IRBuilder<> &B,
+ /// Emit a call to the strchr function to the builder, for the specified
+ /// pointer and character. Ptr is required to be some pointer type, and the
+ /// return value has 'i8*' type.
+ Value *emitStrChr(Value *Ptr, char C, IRBuilder<> &B,
const TargetLibraryInfo *TLI);
- /// EmitStrNCmp - Emit a call to the strncmp function to the builder.
- Value *EmitStrNCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B,
+ /// Emit a call to the strncmp function to the builder.
+ Value *emitStrNCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B,
const DataLayout &DL, const TargetLibraryInfo *TLI);
- /// EmitStrCpy - Emit a call to the strcpy function to the builder, for the
- /// specified pointer arguments.
- Value *EmitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B,
+ /// Emit a call to the strcpy function to the builder, for the specified
+ /// pointer arguments.
+ Value *emitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B,
const TargetLibraryInfo *TLI, StringRef Name = "strcpy");
- /// EmitStrNCpy - Emit a call to the strncpy function to the builder, for the
- /// specified pointer arguments and length.
- Value *EmitStrNCpy(Value *Dst, Value *Src, Value *Len, IRBuilder<> &B,
+ /// Emit a call to the strncpy function to the builder, for the specified
+ /// pointer arguments and length.
+ Value *emitStrNCpy(Value *Dst, Value *Src, Value *Len, IRBuilder<> &B,
const TargetLibraryInfo *TLI, StringRef Name = "strncpy");
- /// EmitMemCpyChk - Emit a call to the __memcpy_chk function to the builder.
- /// This expects that the Len and ObjSize have type 'intptr_t' and Dst/Src
- /// are pointers.
- Value *EmitMemCpyChk(Value *Dst, Value *Src, Value *Len, Value *ObjSize,
+ /// Emit a call to the __memcpy_chk function to the builder. This expects that
+ /// the Len and ObjSize have type 'intptr_t' and Dst/Src are pointers.
+ Value *emitMemCpyChk(Value *Dst, Value *Src, Value *Len, Value *ObjSize,
IRBuilder<> &B, const DataLayout &DL,
const TargetLibraryInfo *TLI);
- /// EmitMemChr - Emit a call to the memchr function. This assumes that Ptr is
- /// a pointer, Val is an i32 value, and Len is an 'intptr_t' value.
- Value *EmitMemChr(Value *Ptr, Value *Val, Value *Len, IRBuilder<> &B,
+ /// Emit a call to the memchr function. This assumes that Ptr is a pointer,
+ /// Val is an i32 value, and Len is an 'intptr_t' value.
+ Value *emitMemChr(Value *Ptr, Value *Val, Value *Len, IRBuilder<> &B,
const DataLayout &DL, const TargetLibraryInfo *TLI);
- /// EmitMemCmp - Emit a call to the memcmp function.
- Value *EmitMemCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B,
+ /// Emit a call to the memcmp function.
+ Value *emitMemCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B,
const DataLayout &DL, const TargetLibraryInfo *TLI);
- /// EmitUnaryFloatFnCall - Emit a call to the unary function named 'Name'
- /// (e.g. 'floor'). This function is known to take a single of type matching
- /// 'Op' and returns one value with the same type. If 'Op' is a long double,
- /// 'l' is added as the suffix of name, if 'Op' is a float, we add a 'f'
- /// suffix.
- Value *EmitUnaryFloatFnCall(Value *Op, StringRef Name, IRBuilder<> &B,
+ /// Emit a call to the unary function named 'Name' (e.g. 'floor'). This
+ /// function is known to take a single of type matching 'Op' and returns one
+ /// value with the same type. If 'Op' is a long double, 'l' is added as the
+ /// suffix of name, if 'Op' is a float, we add a 'f' suffix.
+ Value *emitUnaryFloatFnCall(Value *Op, StringRef Name, IRBuilder<> &B,
const AttributeSet &Attrs);
- /// EmitUnaryFloatFnCall - Emit a call to the binary function named 'Name'
- /// (e.g. 'fmin'). This function is known to take type matching 'Op1' and
- /// 'Op2' and return one value with the same type. If 'Op1/Op2' are long
- /// double, 'l' is added as the suffix of name, if 'Op1/Op2' are float, we
- /// add a 'f' suffix.
- Value *EmitBinaryFloatFnCall(Value *Op1, Value *Op2, StringRef Name,
+ /// Emit a call to the binary function named 'Name' (e.g. 'fmin'). This
+ /// function is known to take type matching 'Op1' and 'Op2' and return one
+ /// value with the same type. If 'Op1/Op2' are long double, 'l' is added as
+ /// the suffix of name, if 'Op1/Op2' are float, we add a 'f' suffix.
+ Value *emitBinaryFloatFnCall(Value *Op1, Value *Op2, StringRef Name,
IRBuilder<> &B, const AttributeSet &Attrs);
- /// EmitPutChar - Emit a call to the putchar function. This assumes that Char
- /// is an integer.
- Value *EmitPutChar(Value *Char, IRBuilder<> &B, const TargetLibraryInfo *TLI);
+ /// Emit a call to the putchar function. This assumes that Char is an integer.
+ Value *emitPutChar(Value *Char, IRBuilder<> &B, const TargetLibraryInfo *TLI);
- /// EmitPutS - Emit a call to the puts function. This assumes that Str is
- /// some pointer.
- Value *EmitPutS(Value *Str, IRBuilder<> &B, const TargetLibraryInfo *TLI);
+ /// Emit a call to the puts function. This assumes that Str is some pointer.
+ Value *emitPutS(Value *Str, IRBuilder<> &B, const TargetLibraryInfo *TLI);
- /// EmitFPutC - Emit a call to the fputc function. This assumes that Char is
- /// an i32, and File is a pointer to FILE.
- Value *EmitFPutC(Value *Char, Value *File, IRBuilder<> &B,
+ /// Emit a call to the fputc function. This assumes that Char is an i32, and
+ /// File is a pointer to FILE.
+ Value *emitFPutC(Value *Char, Value *File, IRBuilder<> &B,
const TargetLibraryInfo *TLI);
- /// EmitFPutS - Emit a call to the puts function. Str is required to be a
- /// pointer and File is a pointer to FILE.
- Value *EmitFPutS(Value *Str, Value *File, IRBuilder<> &B,
+ /// Emit a call to the puts function. Str is required to be a pointer and
+ /// File is a pointer to FILE.
+ Value *emitFPutS(Value *Str, Value *File, IRBuilder<> &B,
const TargetLibraryInfo *TLI);
- /// EmitFWrite - Emit a call to the fwrite function. This assumes that Ptr is
- /// a pointer, Size is an 'intptr_t', and File is a pointer to FILE.
- Value *EmitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilder<> &B,
+ /// Emit a call to the fwrite function. This assumes that Ptr is a pointer,
+ /// Size is an 'intptr_t', and File is a pointer to FILE.
+ Value *emitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilder<> &B,
const DataLayout &DL, const TargetLibraryInfo *TLI);
}
diff --git a/include/llvm/Transforms/Utils/Cloning.h b/include/llvm/Transforms/Utils/Cloning.h
index 4f006f2adeef..c5fb37007090 100644
--- a/include/llvm/Transforms/Utils/Cloning.h
+++ b/include/llvm/Transforms/Utils/Cloning.h
@@ -59,7 +59,7 @@ std::unique_ptr<Module> CloneModule(const Module *M, ValueToValueMapTy &VMap);
/// in place of the global definition.
std::unique_ptr<Module>
CloneModule(const Module *M, ValueToValueMapTy &VMap,
- std::function<bool(const GlobalValue *)> ShouldCloneDefinition);
+ function_ref<bool(const GlobalValue *)> ShouldCloneDefinition);
/// ClonedCodeInfo - This struct can be used to capture information about code
/// being cloned, while it is being cloned.
@@ -114,20 +114,19 @@ BasicBlock *CloneBasicBlock(const BasicBlock *BB, ValueToValueMapTy &VMap,
const Twine &NameSuffix = "", Function *F = nullptr,
ClonedCodeInfo *CodeInfo = nullptr);
-/// CloneFunction - Return a copy of the specified function, but without
-/// embedding the function into another module. Also, any references specified
-/// in the VMap are changed to refer to their mapped value instead of the
-/// original one. If any of the arguments to the function are in the VMap,
-/// the arguments are deleted from the resultant function. The VMap is
-/// updated to include mappings from all of the instructions and basicblocks in
-/// the function from their old to new values. The final argument captures
-/// information about the cloned code if non-null.
+/// CloneFunction - Return a copy of the specified function and add it to that
+/// function's module. Also, any references specified in the VMap are changed
+/// to refer to their mapped value instead of the original one. If any of the
+/// arguments to the function are in the VMap, the arguments are deleted from
+/// the resultant function. The VMap is updated to include mappings from all of
+/// the instructions and basicblocks in the function from their old to new
+/// values. The final argument captures information about the cloned code if
+/// non-null.
///
-/// If ModuleLevelChanges is false, VMap contains no non-identity GlobalValue
-/// mappings, and debug info metadata will not be cloned.
+/// VMap contains no non-identity GlobalValue mappings and debug info metadata
+/// will not be cloned.
///
-Function *CloneFunction(const Function *F, ValueToValueMapTy &VMap,
- bool ModuleLevelChanges,
+Function *CloneFunction(Function *F, ValueToValueMapTy &VMap,
ClonedCodeInfo *CodeInfo = nullptr);
/// Clone OldFunc into NewFunc, transforming the old arguments into references
@@ -221,6 +220,7 @@ bool InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
///
/// Updates LoopInfo and DominatorTree assuming the loop is dominated by block
/// \p LoopDomBB. Insert the new blocks before block specified in \p Before.
+/// Note: Only innermost loops are supported.
Loop *cloneLoopWithPreheader(BasicBlock *Before, BasicBlock *LoopDomBB,
Loop *OrigLoop, ValueToValueMapTy &VMap,
const Twine &NameSuffix, LoopInfo *LI,
diff --git a/include/llvm/Transforms/Utils/CodeExtractor.h b/include/llvm/Transforms/Utils/CodeExtractor.h
index 3a96d955cac2..30dafd045f23 100644
--- a/include/llvm/Transforms/Utils/CodeExtractor.h
+++ b/include/llvm/Transforms/Utils/CodeExtractor.h
@@ -15,10 +15,10 @@
#ifndef LLVM_TRANSFORMS_UTILS_CODEEXTRACTOR_H
#define LLVM_TRANSFORMS_UTILS_CODEEXTRACTOR_H
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SetVector.h"
namespace llvm {
+template <typename T> class ArrayRef;
class BasicBlock;
class DominatorTree;
class Function;
diff --git a/include/llvm/Transforms/Utils/Evaluator.h b/include/llvm/Transforms/Utils/Evaluator.h
new file mode 100644
index 000000000000..07f12f41b3bc
--- /dev/null
+++ b/include/llvm/Transforms/Utils/Evaluator.h
@@ -0,0 +1,119 @@
+//===-- Evaluator.h - LLVM IR evaluator -------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Function evaluator for LLVM IR.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_UTILS_EVALUATOR_H
+#define LLVM_TRANSFORMS_UTILS_EVALUATOR_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Constant.h"
+#include "llvm/IR/GlobalVariable.h"
+
+#include <deque>
+#include <memory>
+
+namespace llvm {
+
+class DataLayout;
+class Function;
+class TargetLibraryInfo;
+
+/// This class evaluates LLVM IR, producing the Constant representing each SSA
+/// instruction. Changes to global variables are stored in a mapping that can
+/// be iterated over after the evaluation is complete. Once an evaluation call
+/// fails, the evaluation object should not be reused.
+class Evaluator {
+public:
+ Evaluator(const DataLayout &DL, const TargetLibraryInfo *TLI)
+ : DL(DL), TLI(TLI) {
+ ValueStack.emplace_back();
+ }
+
+ ~Evaluator() {
+ for (auto &Tmp : AllocaTmps)
+ // If there are still users of the alloca, the program is doing something
+ // silly, e.g. storing the address of the alloca somewhere and using it
+ // later. Since this is undefined, we'll just make it be null.
+ if (!Tmp->use_empty())
+ Tmp->replaceAllUsesWith(Constant::getNullValue(Tmp->getType()));
+ }
+
+ /// Evaluate a call to function F, returning true if successful, false if we
+ /// can't evaluate it. ActualArgs contains the formal arguments for the
+ /// function.
+ bool EvaluateFunction(Function *F, Constant *&RetVal,
+ const SmallVectorImpl<Constant*> &ActualArgs);
+
+ /// Evaluate all instructions in block BB, returning true if successful, false
+ /// if we can't evaluate it. NewBB returns the next BB that control flows
+ /// into, or null upon return.
+ bool EvaluateBlock(BasicBlock::iterator CurInst, BasicBlock *&NextBB);
+
+ Constant *getVal(Value *V) {
+ if (Constant *CV = dyn_cast<Constant>(V)) return CV;
+ Constant *R = ValueStack.back().lookup(V);
+ assert(R && "Reference to an uncomputed value!");
+ return R;
+ }
+
+ void setVal(Value *V, Constant *C) {
+ ValueStack.back()[V] = C;
+ }
+
+ const DenseMap<Constant*, Constant*> &getMutatedMemory() const {
+ return MutatedMemory;
+ }
+
+ const SmallPtrSetImpl<GlobalVariable*> &getInvariants() const {
+ return Invariants;
+ }
+
+private:
+ Constant *ComputeLoadResult(Constant *P);
+
+ /// As we compute SSA register values, we store their contents here. The back
+ /// of the deque contains the current function and the stack contains the
+ /// values in the calling frames.
+ std::deque<DenseMap<Value*, Constant*>> ValueStack;
+
+ /// This is used to detect recursion. In pathological situations we could hit
+ /// exponential behavior, but at least there is nothing unbounded.
+ SmallVector<Function*, 4> CallStack;
+
+ /// For each store we execute, we update this map. Loads check this to get
+ /// the most up-to-date value. If evaluation is successful, this state is
+ /// committed to the process.
+ DenseMap<Constant*, Constant*> MutatedMemory;
+
+ /// To 'execute' an alloca, we create a temporary global variable to represent
+ /// its body. This vector is needed so we can delete the temporary globals
+ /// when we are done.
+ SmallVector<std::unique_ptr<GlobalVariable>, 32> AllocaTmps;
+
+ /// These global variables have been marked invariant by the static
+ /// constructor.
+ SmallPtrSet<GlobalVariable*, 8> Invariants;
+
+ /// These are constants we have checked and know to be simple enough to live
+ /// in a static initializer of a global.
+ SmallPtrSet<Constant*, 8> SimpleConstants;
+
+ const DataLayout &DL;
+ const TargetLibraryInfo *TLI;
+};
+
+}
+
+#endif
diff --git a/include/llvm/Transforms/Utils/FunctionImportUtils.h b/include/llvm/Transforms/Utils/FunctionImportUtils.h
new file mode 100644
index 000000000000..3b94ef60be5d
--- /dev/null
+++ b/include/llvm/Transforms/Utils/FunctionImportUtils.h
@@ -0,0 +1,100 @@
+//===- FunctionImportUtils.h - Importing support utilities -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the FunctionImportGlobalProcessing class which is used
+// to perform the necessary global value handling for function importing.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_UTILS_FUNCTIONIMPORTUTILS_H
+#define LLVM_TRANSFORMS_UTILS_FUNCTIONIMPORTUTILS_H
+
+#include "llvm/ADT/SetVector.h"
+#include "llvm/IR/ModuleSummaryIndex.h"
+
+namespace llvm {
+class Module;
+
+/// Class to handle necessary GlobalValue changes required by ThinLTO
+/// function importing, including linkage changes and any necessary renaming.
+class FunctionImportGlobalProcessing {
+ /// The Module which we are exporting or importing functions from.
+ Module &M;
+
+ /// Module summary index passed in for function importing/exporting handling.
+ const ModuleSummaryIndex &ImportIndex;
+
+ /// Globals to import from this module, all other functions will be
+ /// imported as declarations instead of definitions.
+ DenseSet<const GlobalValue *> *GlobalsToImport;
+
+ /// Set to true if the given ModuleSummaryIndex contains any functions
+ /// from this source module, in which case we must conservatively assume
+ /// that any of its functions may be imported into another module
+ /// as part of a different backend compilation process.
+ bool HasExportedFunctions = false;
+
+ /// Check if we should promote the given local value to global scope.
+ bool doPromoteLocalToGlobal(const GlobalValue *SGV);
+
+ /// Helper methods to check if we are importing from or potentially
+ /// exporting from the current source module.
+ bool isPerformingImport() const { return GlobalsToImport != nullptr; }
+ bool isModuleExporting() const { return HasExportedFunctions; }
+
+ /// If we are importing from the source module, checks if we should
+ /// import SGV as a definition, otherwise import as a declaration.
+ bool doImportAsDefinition(const GlobalValue *SGV);
+
+ /// Get the name for SGV that should be used in the linked destination
+ /// module. Specifically, this handles the case where we need to rename
+ /// a local that is being promoted to global scope.
+ std::string getName(const GlobalValue *SGV);
+
+ /// Process globals so that they can be used in ThinLTO. This includes
+ /// promoting local variables so that they can be reference externally by
+ /// thin lto imported globals and converting strong external globals to
+ /// available_externally.
+ void processGlobalsForThinLTO();
+ void processGlobalForThinLTO(GlobalValue &GV);
+
+ /// Get the new linkage for SGV that should be used in the linked destination
+ /// module. Specifically, for ThinLTO importing or exporting it may need
+ /// to be adjusted.
+ GlobalValue::LinkageTypes getLinkage(const GlobalValue *SGV);
+
+public:
+ FunctionImportGlobalProcessing(
+ Module &M, const ModuleSummaryIndex &Index,
+ DenseSet<const GlobalValue *> *GlobalsToImport = nullptr)
+ : M(M), ImportIndex(Index), GlobalsToImport(GlobalsToImport) {
+ // If we have a ModuleSummaryIndex but no function to import,
+ // then this is the primary module being compiled in a ThinLTO
+ // backend compilation, and we need to see if it has functions that
+ // may be exported to another backend compilation.
+ if (!GlobalsToImport)
+ HasExportedFunctions = ImportIndex.hasExportedFunctions(M);
+ }
+
+ bool run();
+
+ static bool
+ doImportAsDefinition(const GlobalValue *SGV,
+ DenseSet<const GlobalValue *> *GlobalsToImport);
+};
+
+/// Perform in-place global value handling on the given Module for
+/// exported local functions renamed and promoted for ThinLTO.
+bool renameModuleForThinLTO(
+ Module &M, const ModuleSummaryIndex &Index,
+ DenseSet<const GlobalValue *> *GlobalsToImport = nullptr);
+
+} // End llvm namespace
+
+#endif
diff --git a/include/llvm/Transforms/Utils/LCSSA.h b/include/llvm/Transforms/Utils/LCSSA.h
new file mode 100644
index 000000000000..f0277d021541
--- /dev/null
+++ b/include/llvm/Transforms/Utils/LCSSA.h
@@ -0,0 +1,44 @@
+//===- LCSSA.h - Loop-closed SSA transform Pass -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass transforms loops by placing phi nodes at the end of the loops for
+// all values that are live across the loop boundary. For example, it turns
+// the left into the right code:
+//
+// for (...) for (...)
+// if (c) if (c)
+// X1 = ... X1 = ...
+// else else
+// X2 = ... X2 = ...
+// X3 = phi(X1, X2) X3 = phi(X1, X2)
+// ... = X3 + 4 X4 = phi(X3)
+// ... = X4 + 4
+//
+// This is still valid LLVM; the extra phi nodes are purely redundant, and will
+// be trivially eliminated by InstCombine. The major benefit of this
+// transformation is that it makes many other loop optimizations, such as
+// LoopUnswitching, simpler.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_UTILS_LCSSA_H
+#define LLVM_TRANSFORMS_UTILS_LCSSA_H
+
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+/// Converts loops into loop-closed SSA form.
+class LCSSAPass : public PassInfoMixin<LCSSAPass> {
+public:
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
+};
+} // end namespace llvm
+
+#endif // LLVM_TRANSFORMS_UTILS_LCSSA_H
diff --git a/include/llvm/Transforms/Utils/Local.h b/include/llvm/Transforms/Utils/Local.h
index 3ae01657a2ec..43b376cf8068 100644
--- a/include/llvm/Transforms/Utils/Local.h
+++ b/include/llvm/Transforms/Utils/Local.h
@@ -21,6 +21,7 @@
#include "llvm/IR/GetElementPtrTypeIterator.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Operator.h"
+#include "llvm/ADT/SmallPtrSet.h"
namespace llvm {
@@ -29,6 +30,7 @@ class BasicBlock;
class Function;
class BranchInst;
class Instruction;
+class CallInst;
class DbgDeclareInst;
class StoreInst;
class LoadInst;
@@ -50,10 +52,10 @@ template<typename T> class SmallVectorImpl;
// Local constant propagation.
//
-/// ConstantFoldTerminator - If a terminator instruction is predicated on a
-/// constant value, convert it into an unconditional branch to the constant
-/// destination. This is a nontrivial operation because the successors of this
-/// basic block must have their PHI nodes updated.
+/// If a terminator instruction is predicated on a constant value, convert it
+/// into an unconditional branch to the constant destination.
+/// This is a nontrivial operation because the successors of this basic block
+/// must have their PHI nodes updated.
/// Also calls RecursivelyDeleteTriviallyDeadInstructions() on any branch/switch
/// conditions and indirectbr addresses this might make dead if
/// DeleteDeadConditions is true.
@@ -64,29 +66,27 @@ bool ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions = false,
// Local dead code elimination.
//
-/// isInstructionTriviallyDead - Return true if the result produced by the
-/// instruction is not used, and the instruction has no side effects.
-///
+/// Return true if the result produced by the instruction is not used, and the
+/// instruction has no side effects.
bool isInstructionTriviallyDead(Instruction *I,
const TargetLibraryInfo *TLI = nullptr);
-/// RecursivelyDeleteTriviallyDeadInstructions - If the specified value is a
-/// trivially dead instruction, delete it. If that makes any of its operands
-/// trivially dead, delete them too, recursively. Return true if any
-/// instructions were deleted.
+/// If the specified value is a trivially dead instruction, delete it.
+/// If that makes any of its operands trivially dead, delete them too,
+/// recursively. Return true if any instructions were deleted.
bool RecursivelyDeleteTriviallyDeadInstructions(Value *V,
const TargetLibraryInfo *TLI = nullptr);
-/// RecursivelyDeleteDeadPHINode - If the specified value is an effectively
-/// dead PHI node, due to being a def-use chain of single-use nodes that
-/// either forms a cycle or is terminated by a trivially dead instruction,
-/// delete it. If that makes any of its operands trivially dead, delete them
-/// too, recursively. Return true if a change was made.
+/// If the specified value is an effectively dead PHI node, due to being a
+/// def-use chain of single-use nodes that either forms a cycle or is terminated
+/// by a trivially dead instruction, delete it. If that makes any of its
+/// operands trivially dead, delete them too, recursively. Return true if a
+/// change was made.
bool RecursivelyDeleteDeadPHINode(PHINode *PN,
const TargetLibraryInfo *TLI = nullptr);
-/// SimplifyInstructionsInBlock - Scan the specified basic block and try to
-/// simplify any instructions in it and recursively delete dead instructions.
+/// Scan the specified basic block and try to simplify any instructions in it
+/// and recursively delete dead instructions.
///
/// This returns true if it changed the code, note that it can delete
/// instructions in other blocks as well in this block.
@@ -97,9 +97,9 @@ bool SimplifyInstructionsInBlock(BasicBlock *BB,
// Control Flow Graph Restructuring.
//
-/// RemovePredecessorAndSimplify - Like BasicBlock::removePredecessor, this
-/// method is called when we're about to delete Pred as a predecessor of BB. If
-/// BB contains any PHI nodes, this drops the entries in the PHI nodes for Pred.
+/// Like BasicBlock::removePredecessor, this method is called when we're about
+/// to delete Pred as a predecessor of BB. If BB contains any PHI nodes, this
+/// drops the entries in the PHI nodes for Pred.
///
/// Unlike the removePredecessor method, this attempts to simplify uses of PHI
/// nodes that collapse into identity values. For example, if we have:
@@ -110,74 +110,68 @@ bool SimplifyInstructionsInBlock(BasicBlock *BB,
/// recursively fold the 'and' to 0.
void RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred);
-/// MergeBasicBlockIntoOnlyPred - BB is a block with one predecessor and its
-/// predecessor is known to have one successor (BB!). Eliminate the edge
-/// between them, moving the instructions in the predecessor into BB. This
-/// deletes the predecessor block.
-///
+/// BB is a block with one predecessor and its predecessor is known to have one
+/// successor (BB!). Eliminate the edge between them, moving the instructions in
+/// the predecessor into BB. This deletes the predecessor block.
void MergeBasicBlockIntoOnlyPred(BasicBlock *BB, DominatorTree *DT = nullptr);
-/// TryToSimplifyUncondBranchFromEmptyBlock - BB is known to contain an
-/// unconditional branch, and contains no instructions other than PHI nodes,
-/// potential debug intrinsics and the branch. If possible, eliminate BB by
-/// rewriting all the predecessors to branch to the successor block and return
-/// true. If we can't transform, return false.
+/// BB is known to contain an unconditional branch, and contains no instructions
+/// other than PHI nodes, potential debug intrinsics and the branch. If
+/// possible, eliminate BB by rewriting all the predecessors to branch to the
+/// successor block and return true. If we can't transform, return false.
bool TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB);
-/// EliminateDuplicatePHINodes - Check for and eliminate duplicate PHI
-/// nodes in this block. This doesn't try to be clever about PHI nodes
-/// which differ only in the order of the incoming values, but instcombine
-/// orders them so it usually won't matter.
-///
+/// Check for and eliminate duplicate PHI nodes in this block. This doesn't try
+/// to be clever about PHI nodes which differ only in the order of the incoming
+/// values, but instcombine orders them so it usually won't matter.
bool EliminateDuplicatePHINodes(BasicBlock *BB);
-/// SimplifyCFG - This function is used to do simplification of a CFG. For
+/// This function is used to do simplification of a CFG. For
/// example, it adjusts branches to branches to eliminate the extra hop, it
/// eliminates unreachable basic blocks, and does other "peephole" optimization
/// of the CFG. It returns true if a modification was made, possibly deleting
-/// the basic block that was pointed to.
-///
+/// the basic block that was pointed to. LoopHeaders is an optional input
+/// parameter, providing the set of loop header that SimplifyCFG should not
+/// eliminate.
bool SimplifyCFG(BasicBlock *BB, const TargetTransformInfo &TTI,
- unsigned BonusInstThreshold, AssumptionCache *AC = nullptr);
+ unsigned BonusInstThreshold, AssumptionCache *AC = nullptr,
+ SmallPtrSetImpl<BasicBlock *> *LoopHeaders = nullptr);
-/// FlatternCFG - This function is used to flatten a CFG. For
-/// example, it uses parallel-and and parallel-or mode to collapse
-// if-conditions and merge if-regions with identical statements.
-///
+/// This function is used to flatten a CFG. For example, it uses parallel-and
+/// and parallel-or mode to collapse if-conditions and merge if-regions with
+/// identical statements.
bool FlattenCFG(BasicBlock *BB, AliasAnalysis *AA = nullptr);
-/// FoldBranchToCommonDest - If this basic block is ONLY a setcc and a branch,
-/// and if a predecessor branches to us and one of our successors, fold the
-/// setcc into the predecessor and use logical operations to pick the right
-/// destination.
+/// If this basic block is ONLY a setcc and a branch, and if a predecessor
+/// branches to us and one of our successors, fold the setcc into the
+/// predecessor and use logical operations to pick the right destination.
bool FoldBranchToCommonDest(BranchInst *BI, unsigned BonusInstThreshold = 1);
-/// DemoteRegToStack - This function takes a virtual register computed by an
-/// Instruction and replaces it with a slot in the stack frame, allocated via
-/// alloca. This allows the CFG to be changed around without fear of
-/// invalidating the SSA information for the value. It returns the pointer to
-/// the alloca inserted to create a stack slot for X.
-///
+/// This function takes a virtual register computed by an Instruction and
+/// replaces it with a slot in the stack frame, allocated via alloca.
+/// This allows the CFG to be changed around without fear of invalidating the
+/// SSA information for the value. It returns the pointer to the alloca inserted
+/// to create a stack slot for X.
AllocaInst *DemoteRegToStack(Instruction &X,
bool VolatileLoads = false,
Instruction *AllocaPoint = nullptr);
-/// DemotePHIToStack - This function takes a virtual register computed by a phi
-/// node and replaces it with a slot in the stack frame, allocated via alloca.
-/// The phi node is deleted and it returns the pointer to the alloca inserted.
+/// This function takes a virtual register computed by a phi node and replaces
+/// it with a slot in the stack frame, allocated via alloca. The phi node is
+/// deleted and it returns the pointer to the alloca inserted.
AllocaInst *DemotePHIToStack(PHINode *P, Instruction *AllocaPoint = nullptr);
-/// getOrEnforceKnownAlignment - If the specified pointer has an alignment that
-/// we can determine, return it, otherwise return 0. If PrefAlign is specified,
-/// and it is more than the alignment of the ultimate object, see if we can
-/// increase the alignment of the ultimate object, making this check succeed.
+/// If the specified pointer has an alignment that we can determine, return it,
+/// otherwise return 0. If PrefAlign is specified, and it is more than the
+/// alignment of the ultimate object, see if we can increase the alignment of
+/// the ultimate object, making this check succeed.
unsigned getOrEnforceKnownAlignment(Value *V, unsigned PrefAlign,
const DataLayout &DL,
const Instruction *CxtI = nullptr,
AssumptionCache *AC = nullptr,
const DominatorTree *DT = nullptr);
-/// getKnownAlignment - Try to infer an alignment for the specified pointer.
+/// Try to infer an alignment for the specified pointer.
static inline unsigned getKnownAlignment(Value *V, const DataLayout &DL,
const Instruction *CxtI = nullptr,
AssumptionCache *AC = nullptr,
@@ -185,9 +179,9 @@ static inline unsigned getKnownAlignment(Value *V, const DataLayout &DL,
return getOrEnforceKnownAlignment(V, 0, DL, CxtI, AC, DT);
}
-/// EmitGEPOffset - Given a getelementptr instruction/constantexpr, emit the
-/// code necessary to compute the offset from the base pointer (without adding
-/// in the base pointer). Return the result as a signed integer of intptr size.
+/// Given a getelementptr instruction/constantexpr, emit the code necessary to
+/// compute the offset from the base pointer (without adding in the base
+/// pointer). Return the result as a signed integer of intptr size.
/// When NoAssumptions is true, no assumptions about index computation not
/// overflowing is made.
template <typename IRBuilderTy>
@@ -264,15 +258,14 @@ bool ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI,
bool ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI,
LoadInst *LI, DIBuilder &Builder);
-/// LowerDbgDeclare - Lowers llvm.dbg.declare intrinsics into appropriate set
-/// of llvm.dbg.value intrinsics.
+/// Lowers llvm.dbg.declare intrinsics into appropriate set of
+/// llvm.dbg.value intrinsics.
bool LowerDbgDeclare(Function &F);
-/// FindAllocaDbgDeclare - Finds the llvm.dbg.declare intrinsic corresponding to
-/// an alloca, if any.
+/// Finds the llvm.dbg.declare intrinsic corresponding to an alloca, if any.
DbgDeclareInst *FindAllocaDbgDeclare(Value *V);
-/// \brief Replaces llvm.dbg.declare instruction when the address it describes
+/// Replaces llvm.dbg.declare instruction when the address it describes
/// is replaced with a new value. If Deref is true, an additional DW_OP_deref is
/// prepended to the expression. If Offset is non-zero, a constant displacement
/// is added to the expression (after the optional Deref). Offset can be
@@ -281,7 +274,7 @@ bool replaceDbgDeclare(Value *Address, Value *NewAddress,
Instruction *InsertBefore, DIBuilder &Builder,
bool Deref, int Offset);
-/// \brief Replaces llvm.dbg.declare instruction when the alloca it describes
+/// Replaces llvm.dbg.declare instruction when the alloca it describes
/// is replaced with a new value. If Deref is true, an additional DW_OP_deref is
/// prepended to the expression. If Offset is non-zero, a constant displacement
/// is added to the expression (after the optional Deref). Offset can be
@@ -289,39 +282,51 @@ bool replaceDbgDeclare(Value *Address, Value *NewAddress,
bool replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress,
DIBuilder &Builder, bool Deref, int Offset = 0);
-/// \brief Insert an unreachable instruction before the specified
+/// Replaces multiple llvm.dbg.value instructions when the alloca it describes
+/// is replaced with a new value. If Offset is non-zero, a constant displacement
+/// is added to the expression (after the mandatory Deref). Offset can be
+/// negative. New llvm.dbg.value instructions are inserted at the locations of
+/// the instructions they replace.
+void replaceDbgValueForAlloca(AllocaInst *AI, Value *NewAllocaAddress,
+ DIBuilder &Builder, int Offset = 0);
+
+/// Remove all instructions from a basic block other than it's terminator
+/// and any present EH pad instructions.
+unsigned removeAllNonTerminatorAndEHPadInstructions(BasicBlock *BB);
+
+/// Insert an unreachable instruction before the specified
/// instruction, making it and the rest of the code in the block dead.
-void changeToUnreachable(Instruction *I, bool UseLLVMTrap);
+unsigned changeToUnreachable(Instruction *I, bool UseLLVMTrap);
/// Replace 'BB's terminator with one that does not have an unwind successor
-/// block. Rewrites `invoke` to `call`, etc. Updates any PHIs in unwind
+/// block. Rewrites `invoke` to `call`, etc. Updates any PHIs in unwind
/// successor.
///
/// \param BB Block whose terminator will be replaced. Its terminator must
/// have an unwind successor.
void removeUnwindEdge(BasicBlock *BB);
-/// \brief Remove all blocks that can not be reached from the function's entry.
+/// Remove all blocks that can not be reached from the function's entry.
///
/// Returns true if any basic block was removed.
bool removeUnreachableBlocks(Function &F, LazyValueInfo *LVI = nullptr);
-/// \brief Combine the metadata of two instructions so that K can replace J
+/// Combine the metadata of two instructions so that K can replace J
///
/// Metadata not listed as known via KnownIDs is removed
void combineMetadata(Instruction *K, const Instruction *J, ArrayRef<unsigned> KnownIDs);
-/// \brief Replace each use of 'From' with 'To' if that use is dominated by
+/// Replace each use of 'From' with 'To' if that use is dominated by
/// the given edge. Returns the number of replacements made.
unsigned replaceDominatedUsesWith(Value *From, Value *To, DominatorTree &DT,
const BasicBlockEdge &Edge);
-/// \brief Replace each use of 'From' with 'To' if that use is dominated by
-/// the given BasicBlock. Returns the number of replacements made.
+/// Replace each use of 'From' with 'To' if that use is dominated by
+/// the end of the given BasicBlock. Returns the number of replacements made.
unsigned replaceDominatedUsesWith(Value *From, Value *To, DominatorTree &DT,
const BasicBlock *BB);
-/// \brief Return true if the CallSite CS calls a gc leaf function.
+/// Return true if the CallSite CS calls a gc leaf function.
///
/// A leaf function is a function that does not safepoint the thread during its
/// execution. During a call or invoke to such a function, the callers stack
@@ -335,7 +340,7 @@ bool callsGCLeafFunction(ImmutableCallSite CS);
// Intrinsic pattern matching
//
-/// Try and match a bitreverse or bswap idiom.
+/// Try and match a bswap or bitreverse idiom.
///
/// If an idiom is matched, an intrinsic call is inserted before \c I. Any added
/// instructions are returned in \c InsertedInsts. They will all have been added
@@ -346,10 +351,21 @@ bool callsGCLeafFunction(ImmutableCallSite CS);
/// to BW / 4 nodes to be searched, so is significantly faster.
///
/// This function returns true on a successful match or false otherwise.
-bool recognizeBitReverseOrBSwapIdiom(
+bool recognizeBSwapOrBitReverseIdiom(
Instruction *I, bool MatchBSwaps, bool MatchBitReversals,
SmallVectorImpl<Instruction *> &InsertedInsts);
+//===----------------------------------------------------------------------===//
+// Sanitizer utilities
+//
+
+/// Given a CallInst, check if it calls a string function known to CodeGen,
+/// and mark it with NoBuiltin if so. To be used by sanitizers that intend
+/// to intercept string functions and want to avoid converting them to target
+/// specific instructions.
+void maybeMarkSanitizerLibraryCallNoBuiltin(CallInst *CI,
+ const TargetLibraryInfo *TLI);
+
} // End llvm namespace
#endif
diff --git a/include/llvm/Transforms/Utils/LoopSimplify.h b/include/llvm/Transforms/Utils/LoopSimplify.h
new file mode 100644
index 000000000000..7cf89eaeb939
--- /dev/null
+++ b/include/llvm/Transforms/Utils/LoopSimplify.h
@@ -0,0 +1,65 @@
+//===- LoopSimplify.h - Loop Canonicalization Pass --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass performs several transformations to transform natural loops into a
+// simpler form, which makes subsequent analyses and transformations simpler and
+// more effective.
+//
+// Loop pre-header insertion guarantees that there is a single, non-critical
+// entry edge from outside of the loop to the loop header. This simplifies a
+// number of analyses and transformations, such as LICM.
+//
+// Loop exit-block insertion guarantees that all exit blocks from the loop
+// (blocks which are outside of the loop that have predecessors inside of the
+// loop) only have predecessors from inside of the loop (and are thus dominated
+// by the loop header). This simplifies transformations such as store-sinking
+// that are built into LICM.
+//
+// This pass also guarantees that loops will have exactly one backedge.
+//
+// Indirectbr instructions introduce several complications. If the loop
+// contains or is entered by an indirectbr instruction, it may not be possible
+// to transform the loop and make these guarantees. Client code should check
+// that these conditions are true before relying on them.
+//
+// Note that the simplifycfg pass will clean up blocks which are split out but
+// end up being unnecessary, so usage of this pass should not pessimize
+// generated code.
+//
+// This pass obviously modifies the CFG, but updates loop information and
+// dominator information.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_TRANSFORMS_UTILS_LOOPSIMPLIFY_H
+#define LLVM_TRANSFORMS_UTILS_LOOPSIMPLIFY_H
+
+#include "llvm/Analysis/AssumptionCache.h"
+#include "llvm/Analysis/ScalarEvolution.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+/// This pass is responsible for loop canonicalization.
+class LoopSimplifyPass : public PassInfoMixin<LoopSimplifyPass> {
+public:
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
+};
+
+/// \brief Simplify each loop in a loop nest recursively.
+///
+/// This takes a potentially un-simplified loop L (and its children) and turns
+/// it into a simplified loop nest with preheaders and single backedges. It will
+/// update \c AliasAnalysis and \c ScalarEvolution analyses if they're non-null.
+bool simplifyLoop(Loop *L, DominatorTree *DT, LoopInfo *LI, ScalarEvolution *SE,
+ AssumptionCache *AC, bool PreserveLCSSA);
+
+} // end namespace llvm
+
+#endif // LLVM_TRANSFORMS_UTILS_LOOPSIMPLIFY_H
diff --git a/include/llvm/Transforms/Utils/LoopUtils.h b/include/llvm/Transforms/Utils/LoopUtils.h
index 2cfacb650ff5..89fea10f818a 100644
--- a/include/llvm/Transforms/Utils/LoopUtils.h
+++ b/include/llvm/Transforms/Utils/LoopUtils.h
@@ -30,20 +30,21 @@ class DominatorTree;
class Loop;
class LoopInfo;
class Pass;
+class PredicatedScalarEvolution;
class PredIteratorCache;
class ScalarEvolution;
+class SCEV;
class TargetLibraryInfo;
/// \brief Captures loop safety information.
/// It keep information for loop & its header may throw exception.
-struct LICMSafetyInfo {
- bool MayThrow; // The current loop contains an instruction which
- // may throw.
- bool HeaderMayThrow; // Same as previous, but specific to loop header
+struct LoopSafetyInfo {
+ bool MayThrow; // The current loop contains an instruction which
+ // may throw.
+ bool HeaderMayThrow; // Same as previous, but specific to loop header
// Used to update funclet bundle operands.
DenseMap<BasicBlock *, ColorVector> BlockColors;
- LICMSafetyInfo() : MayThrow(false), HeaderMayThrow(false)
- {}
+ LoopSafetyInfo() : MayThrow(false), HeaderMayThrow(false) {}
};
/// The RecurrenceDescriptor is used to identify recurrences variables in a
@@ -175,6 +176,13 @@ public:
static bool isReductionPHI(PHINode *Phi, Loop *TheLoop,
RecurrenceDescriptor &RedDes);
+ /// Returns true if Phi is a first-order recurrence. A first-order recurrence
+ /// is a non-reduction recurrence relation in which the value of the
+ /// recurrence in the current loop iteration equals a value defined in the
+ /// previous iteration.
+ static bool isFirstOrderRecurrence(PHINode *Phi, Loop *TheLoop,
+ DominatorTree *DT);
+
RecurrenceKind getRecurrenceKind() { return Kind; }
MinMaxRecurrenceKind getMinMaxRecurrenceKind() { return MinMaxKind; }
@@ -261,7 +269,7 @@ public:
public:
/// Default constructor - creates an invalid induction.
InductionDescriptor()
- : StartValue(nullptr), IK(IK_NoInduction), StepValue(nullptr) {}
+ : StartValue(nullptr), IK(IK_NoInduction), Step(nullptr) {}
/// Get the consecutive direction. Returns:
/// 0 - unknown or non-consecutive.
@@ -275,37 +283,59 @@ public:
/// For pointer induction, returns StartValue[Index * StepValue].
/// FIXME: The newly created binary instructions should contain nsw/nuw
/// flags, which can be found from the original scalar operations.
- Value *transform(IRBuilder<> &B, Value *Index) const;
+ Value *transform(IRBuilder<> &B, Value *Index, ScalarEvolution *SE,
+ const DataLayout& DL) const;
Value *getStartValue() const { return StartValue; }
InductionKind getKind() const { return IK; }
- ConstantInt *getStepValue() const { return StepValue; }
-
+ const SCEV *getStep() const { return Step; }
+ ConstantInt *getConstIntStepValue() const;
+
+ /// Returns true if \p Phi is an induction. If \p Phi is an induction,
+ /// the induction descriptor \p D will contain the data describing this
+ /// induction. If by some other means the caller has a better SCEV
+ /// expression for \p Phi than the one returned by the ScalarEvolution
+ /// analysis, it can be passed through \p Expr.
static bool isInductionPHI(PHINode *Phi, ScalarEvolution *SE,
- InductionDescriptor &D);
+ InductionDescriptor &D,
+ const SCEV *Expr = nullptr);
+
+ /// Returns true if \p Phi is an induction, in the context associated with
+ /// the run-time predicate of PSE. If \p Assume is true, this can add further
+ /// SCEV predicates to \p PSE in order to prove that \p Phi is an induction.
+ /// If \p Phi is an induction, \p D will contain the data describing this
+ /// induction.
+ static bool isInductionPHI(PHINode *Phi, PredicatedScalarEvolution &PSE,
+ InductionDescriptor &D, bool Assume = false);
private:
/// Private constructor - used by \c isInductionPHI.
- InductionDescriptor(Value *Start, InductionKind K, ConstantInt *Step);
+ InductionDescriptor(Value *Start, InductionKind K, const SCEV *Step);
/// Start value.
TrackingVH<Value> StartValue;
/// Induction kind.
InductionKind IK;
/// Step value.
- ConstantInt *StepValue;
+ const SCEV *Step;
};
BasicBlock *InsertPreheaderForLoop(Loop *L, DominatorTree *DT, LoopInfo *LI,
bool PreserveLCSSA);
-/// \brief Simplify each loop in a loop nest recursively.
+/// Ensures LCSSA form for every instruction from the Worklist in the scope of
+/// innermost containing loop.
+///
+/// For the given instruction which have uses outside of the loop, an LCSSA PHI
+/// node is inserted and the uses outside the loop are rewritten to use this
+/// node.
+///
+/// LoopInfo and DominatorTree are required and, since the routine makes no
+/// changes to CFG, preserved.
///
-/// This takes a potentially un-simplified loop L (and its children) and turns
-/// it into a simplified loop nest with preheaders and single backedges. It will
-/// update \c AliasAnalysis and \c ScalarEvolution analyses if they're non-null.
-bool simplifyLoop(Loop *L, DominatorTree *DT, LoopInfo *LI, ScalarEvolution *SE,
- AssumptionCache *AC, bool PreserveLCSSA);
+/// Returns true if any modifications are made.
+bool formLCSSAForInstructions(SmallVectorImpl<Instruction *> &Worklist,
+ DominatorTree &DT, LoopInfo &LI);
/// \brief Put loop into LCSSA form.
///
@@ -318,8 +348,7 @@ bool simplifyLoop(Loop *L, DominatorTree *DT, LoopInfo *LI, ScalarEvolution *SE,
/// If ScalarEvolution is passed in, it will be preserved.
///
/// Returns true if any modifications are made to the loop.
-bool formLCSSA(Loop &L, DominatorTree &DT, LoopInfo *LI,
- ScalarEvolution *SE);
+bool formLCSSA(Loop &L, DominatorTree &DT, LoopInfo *LI, ScalarEvolution *SE);
/// \brief Put a loop nest into LCSSA form.
///
@@ -343,7 +372,7 @@ bool formLCSSARecursively(Loop &L, DominatorTree &DT, LoopInfo *LI,
/// It returns changed status.
bool sinkRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *,
TargetLibraryInfo *, Loop *, AliasSetTracker *,
- LICMSafetyInfo *);
+ LoopSafetyInfo *);
/// \brief Walk the specified region of the CFG (defined by all blocks
/// dominated by the specified block, and that are in the current loop) in depth
@@ -354,7 +383,7 @@ bool sinkRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *,
/// loop and loop safety information as arguments. It returns changed status.
bool hoistRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *,
TargetLibraryInfo *, Loop *, AliasSetTracker *,
- LICMSafetyInfo *);
+ LoopSafetyInfo *);
/// \brief Try to promote memory values to scalars by sinking stores out of
/// the loop and moving loads to before the loop. We do this by looping over
@@ -363,20 +392,45 @@ bool hoistRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *,
/// insertion point vector, PredIteratorCache, LoopInfo, DominatorTree, Loop,
/// AliasSet information for all instructions of the loop and loop safety
/// information as arguments. It returns changed status.
-bool promoteLoopAccessesToScalars(AliasSet &, SmallVectorImpl<BasicBlock*> &,
- SmallVectorImpl<Instruction*> &,
+bool promoteLoopAccessesToScalars(AliasSet &, SmallVectorImpl<BasicBlock *> &,
+ SmallVectorImpl<Instruction *> &,
PredIteratorCache &, LoopInfo *,
- DominatorTree *, Loop *, AliasSetTracker *,
- LICMSafetyInfo *);
+ DominatorTree *, const TargetLibraryInfo *,
+ Loop *, AliasSetTracker *, LoopSafetyInfo *);
/// \brief Computes safety information for a loop
/// checks loop body & header for the possibility of may throw
-/// exception, it takes LICMSafetyInfo and loop as argument.
-/// Updates safety information in LICMSafetyInfo argument.
-void computeLICMSafetyInfo(LICMSafetyInfo *, Loop *);
+/// exception, it takes LoopSafetyInfo and loop as argument.
+/// Updates safety information in LoopSafetyInfo argument.
+void computeLoopSafetyInfo(LoopSafetyInfo *, Loop *);
+
+/// Returns true if the instruction in a loop is guaranteed to execute at least
+/// once.
+bool isGuaranteedToExecute(const Instruction &Inst, const DominatorTree *DT,
+ const Loop *CurLoop,
+ const LoopSafetyInfo *SafetyInfo);
/// \brief Returns the instructions that use values defined in the loop.
SmallVector<Instruction *, 8> findDefsUsedOutsideOfLoop(Loop *L);
+
+/// \brief Find string metadata for loop
+///
+/// If it has a value (e.g. {"llvm.distribute", 1} return the value as an
+/// operand or null otherwise. If the string metadata is not found return
+/// Optional's not-a-value.
+Optional<const MDOperand *> findStringMetadataForLoop(Loop *TheLoop,
+ StringRef Name);
+
+/// \brief Set input string into loop metadata by keeping other values intact.
+void addStringMetadataToLoop(Loop *TheLoop, const char *MDString,
+ unsigned V = 0);
+
+/// Helper to consistently add the set of standard passes to a loop pass's \c
+/// AnalysisUsage.
+///
+/// All loop passes should call this as part of implementing their \c
+/// getAnalysisUsage.
+void getLoopAnalysisUsage(AnalysisUsage &AU);
}
#endif
diff --git a/include/llvm/Transforms/Utils/LoopVersioning.h b/include/llvm/Transforms/Utils/LoopVersioning.h
index 3b70594e0b63..0d345a972e10 100644
--- a/include/llvm/Transforms/Utils/LoopVersioning.h
+++ b/include/llvm/Transforms/Utils/LoopVersioning.h
@@ -73,11 +73,30 @@ public:
/// \brief Sets the runtime alias checks for versioning the loop.
void setAliasChecks(
- const SmallVector<RuntimePointerChecking::PointerCheck, 4> Checks);
+ SmallVector<RuntimePointerChecking::PointerCheck, 4> Checks);
/// \brief Sets the runtime SCEV checks for versioning the loop.
void setSCEVChecks(SCEVUnionPredicate Check);
+ /// \brief Annotate memory instructions in the versioned loop with no-alias
+ /// metadata based on the memchecks issued.
+ ///
+ /// This is just wrapper that calls prepareNoAliasMetadata and
+ /// annotateInstWithNoAlias on the instructions of the versioned loop.
+ void annotateLoopWithNoAlias();
+
+ /// \brief Set up the aliasing scopes based on the memchecks. This needs to
+ /// be called before the first call to annotateInstWithNoAlias.
+ void prepareNoAliasMetadata();
+
+ /// \brief Add the noalias annotations to \p VersionedInst.
+ ///
+ /// \p OrigInst is the instruction corresponding to \p VersionedInst in the
+ /// original loop. Initialize the aliasing scopes with
+ /// prepareNoAliasMetadata once before this can be called.
+ void annotateInstWithNoAlias(Instruction *VersionedInst,
+ const Instruction *OrigInst);
+
private:
/// \brief Adds the necessary PHI nodes for the versioned loops based on the
/// loop-defined values used outside of the loop.
@@ -86,6 +105,12 @@ private:
/// that are used outside the loop.
void addPHINodes(const SmallVectorImpl<Instruction *> &DefsUsedOutside);
+ /// \brief Add the noalias annotations to \p I. Initialize the aliasing
+ /// scopes with prepareNoAliasMetadata once before this can be called.
+ void annotateInstWithNoAlias(Instruction *I) {
+ annotateInstWithNoAlias(I, I);
+ }
+
/// \brief The original loop. This becomes the "versioned" one. I.e.,
/// control flows here if pointers in the loop don't alias.
Loop *VersionedLoop;
@@ -103,6 +128,19 @@ private:
/// \brief The set of SCEV checks that we are versioning for.
SCEVUnionPredicate Preds;
+ /// \brief Maps a pointer to the pointer checking group that the pointer
+ /// belongs to.
+ DenseMap<const Value *, const RuntimePointerChecking::CheckingPtrGroup *>
+ PtrToGroup;
+
+ /// \brief The alias scope corresponding to a pointer checking group.
+ DenseMap<const RuntimePointerChecking::CheckingPtrGroup *, MDNode *>
+ GroupToScope;
+
+ /// \brief The list of alias scopes that a pointer checking group can't alias.
+ DenseMap<const RuntimePointerChecking::CheckingPtrGroup *, MDNode *>
+ GroupToNonAliasingScopeList;
+
/// \brief Analyses used.
const LoopAccessInfo &LAI;
LoopInfo *LI;
diff --git a/include/llvm/Transforms/Utils/Mem2Reg.h b/include/llvm/Transforms/Utils/Mem2Reg.h
new file mode 100644
index 000000000000..f3c80edf544d
--- /dev/null
+++ b/include/llvm/Transforms/Utils/Mem2Reg.h
@@ -0,0 +1,28 @@
+//===- Mem2Reg.h - The -mem2reg pass, a wrapper around the Utils lib ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass is a simple pass wrapper around the PromoteMemToReg function call
+// exposed by the Utils library.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_UTILS_MEM2REG_H
+#define LLVM_TRANSFORMS_UTILS_MEM2REG_H
+
+#include "llvm/IR/Function.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+class PromotePass : public PassInfoMixin<PromotePass> {
+public:
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
+};
+}
+
+#endif // LLVM_TRANSFORMS_UTILS_MEM2REG_H \ No newline at end of file
diff --git a/include/llvm/Transforms/Utils/MemorySSA.h b/include/llvm/Transforms/Utils/MemorySSA.h
new file mode 100644
index 000000000000..befc34cb80fc
--- /dev/null
+++ b/include/llvm/Transforms/Utils/MemorySSA.h
@@ -0,0 +1,949 @@
+//===- MemorySSA.h - Build Memory SSA ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// \file
+// \brief This file exposes an interface to building/using memory SSA to
+// walk memory instructions using a use/def graph.
+//
+// Memory SSA class builds an SSA form that links together memory access
+// instructions such as loads, stores, atomics, and calls. Additionally, it does
+// a trivial form of "heap versioning" Every time the memory state changes in
+// the program, we generate a new heap version. It generates MemoryDef/Uses/Phis
+// that are overlayed on top of the existing instructions.
+//
+// As a trivial example,
+// define i32 @main() #0 {
+// entry:
+// %call = call noalias i8* @_Znwm(i64 4) #2
+// %0 = bitcast i8* %call to i32*
+// %call1 = call noalias i8* @_Znwm(i64 4) #2
+// %1 = bitcast i8* %call1 to i32*
+// store i32 5, i32* %0, align 4
+// store i32 7, i32* %1, align 4
+// %2 = load i32* %0, align 4
+// %3 = load i32* %1, align 4
+// %add = add nsw i32 %2, %3
+// ret i32 %add
+// }
+//
+// Will become
+// define i32 @main() #0 {
+// entry:
+// ; 1 = MemoryDef(0)
+// %call = call noalias i8* @_Znwm(i64 4) #3
+// %2 = bitcast i8* %call to i32*
+// ; 2 = MemoryDef(1)
+// %call1 = call noalias i8* @_Znwm(i64 4) #3
+// %4 = bitcast i8* %call1 to i32*
+// ; 3 = MemoryDef(2)
+// store i32 5, i32* %2, align 4
+// ; 4 = MemoryDef(3)
+// store i32 7, i32* %4, align 4
+// ; MemoryUse(3)
+// %7 = load i32* %2, align 4
+// ; MemoryUse(4)
+// %8 = load i32* %4, align 4
+// %add = add nsw i32 %7, %8
+// ret i32 %add
+// }
+//
+// Given this form, all the stores that could ever effect the load at %8 can be
+// gotten by using the MemoryUse associated with it, and walking from use to def
+// until you hit the top of the function.
+//
+// Each def also has a list of users associated with it, so you can walk from
+// both def to users, and users to defs. Note that we disambiguate MemoryUses,
+// but not the RHS of MemoryDefs. You can see this above at %7, which would
+// otherwise be a MemoryUse(4). Being disambiguated means that for a given
+// store, all the MemoryUses on its use lists are may-aliases of that store (but
+// the MemoryDefs on its use list may not be).
+//
+// MemoryDefs are not disambiguated because it would require multiple reaching
+// definitions, which would require multiple phis, and multiple memoryaccesses
+// per instruction.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_UTILS_MEMORYSSA_H
+#define LLVM_TRANSFORMS_UTILS_MEMORYSSA_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/ilist.h"
+#include "llvm/ADT/ilist_node.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/Analysis/AliasAnalysis.h"
+#include "llvm/Analysis/MemoryLocation.h"
+#include "llvm/Analysis/PHITransAddr.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/OperandTraits.h"
+#include "llvm/IR/Type.h"
+#include "llvm/IR/Use.h"
+#include "llvm/IR/User.h"
+#include "llvm/IR/Value.h"
+#include "llvm/Pass.h"
+#include "llvm/PassAnalysisSupport.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <iterator>
+#include <memory>
+#include <utility>
+
+namespace llvm {
+
+class DominatorTree;
+class Function;
+class Instruction;
+class MemoryAccess;
+class LLVMContext;
+class raw_ostream;
+
+template <class T> class memoryaccess_def_iterator_base;
+using memoryaccess_def_iterator = memoryaccess_def_iterator_base<MemoryAccess>;
+using const_memoryaccess_def_iterator =
+ memoryaccess_def_iterator_base<const MemoryAccess>;
+
+// \brief The base for all memory accesses. All memory accesses in a block are
+// linked together using an intrusive list.
+class MemoryAccess : public User, public ilist_node<MemoryAccess> {
+ void *operator new(size_t, unsigned) = delete;
+ void *operator new(size_t) = delete;
+
+public:
+ // Methods for support type inquiry through isa, cast, and
+ // dyn_cast
+ static inline bool classof(const MemoryAccess *) { return true; }
+ static inline bool classof(const Value *V) {
+ unsigned ID = V->getValueID();
+ return ID == MemoryUseVal || ID == MemoryPhiVal || ID == MemoryDefVal;
+ }
+
+ ~MemoryAccess() override;
+
+ BasicBlock *getBlock() const { return Block; }
+
+ virtual void print(raw_ostream &OS) const = 0;
+ virtual void dump() const;
+
+ /// \brief The user iterators for a memory access
+ typedef user_iterator iterator;
+ typedef const_user_iterator const_iterator;
+
+ /// \brief This iterator walks over all of the defs in a given
+ /// MemoryAccess. For MemoryPhi nodes, this walks arguments. For
+ /// MemoryUse/MemoryDef, this walks the defining access.
+ memoryaccess_def_iterator defs_begin();
+ const_memoryaccess_def_iterator defs_begin() const;
+ memoryaccess_def_iterator defs_end();
+ const_memoryaccess_def_iterator defs_end() const;
+
+protected:
+ friend class MemorySSA;
+ friend class MemoryUseOrDef;
+ friend class MemoryUse;
+ friend class MemoryDef;
+ friend class MemoryPhi;
+
+ /// \brief Used internally to give IDs to MemoryAccesses for printing
+ virtual unsigned getID() const = 0;
+
+ MemoryAccess(LLVMContext &C, unsigned Vty, BasicBlock *BB,
+ unsigned NumOperands)
+ : User(Type::getVoidTy(C), Vty, nullptr, NumOperands), Block(BB) {}
+
+private:
+ MemoryAccess(const MemoryAccess &);
+ void operator=(const MemoryAccess &);
+ BasicBlock *Block;
+};
+
+template <>
+struct ilist_traits<MemoryAccess> : public ilist_default_traits<MemoryAccess> {
+ /// See details of the instruction class for why this trick works
+ // FIXME: This downcast is UB. See llvm.org/PR26753.
+ LLVM_NO_SANITIZE("object-size")
+ MemoryAccess *createSentinel() const {
+ return static_cast<MemoryAccess *>(&Sentinel);
+ }
+
+ static void destroySentinel(MemoryAccess *) {}
+
+ MemoryAccess *provideInitialHead() const { return createSentinel(); }
+ MemoryAccess *ensureHead(MemoryAccess *) const { return createSentinel(); }
+ static void noteHead(MemoryAccess *, MemoryAccess *) {}
+
+private:
+ mutable ilist_half_node<MemoryAccess> Sentinel;
+};
+
+inline raw_ostream &operator<<(raw_ostream &OS, const MemoryAccess &MA) {
+ MA.print(OS);
+ return OS;
+}
+
+/// \brief Class that has the common methods + fields of memory uses/defs. It's
+/// a little awkward to have, but there are many cases where we want either a
+/// use or def, and there are many cases where uses are needed (defs aren't
+/// acceptable), and vice-versa.
+///
+/// This class should never be instantiated directly; make a MemoryUse or
+/// MemoryDef instead.
+class MemoryUseOrDef : public MemoryAccess {
+ void *operator new(size_t, unsigned) = delete;
+ void *operator new(size_t) = delete;
+
+public:
+ DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess);
+
+ /// \brief Get the instruction that this MemoryUse represents.
+ Instruction *getMemoryInst() const { return MemoryInst; }
+
+ /// \brief Get the access that produces the memory state used by this Use.
+ MemoryAccess *getDefiningAccess() const { return getOperand(0); }
+
+ static inline bool classof(const MemoryUseOrDef *) { return true; }
+ static inline bool classof(const Value *MA) {
+ return MA->getValueID() == MemoryUseVal || MA->getValueID() == MemoryDefVal;
+ }
+
+protected:
+ friend class MemorySSA;
+
+ MemoryUseOrDef(LLVMContext &C, MemoryAccess *DMA, unsigned Vty,
+ Instruction *MI, BasicBlock *BB)
+ : MemoryAccess(C, Vty, BB, 1), MemoryInst(MI) {
+ setDefiningAccess(DMA);
+ }
+
+ void setDefiningAccess(MemoryAccess *DMA) { setOperand(0, DMA); }
+
+private:
+ Instruction *MemoryInst;
+};
+
+template <>
+struct OperandTraits<MemoryUseOrDef>
+ : public FixedNumOperandTraits<MemoryUseOrDef, 1> {};
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryUseOrDef, MemoryAccess)
+
+/// \brief Represents read-only accesses to memory
+///
+/// In particular, the set of Instructions that will be represented by
+/// MemoryUse's is exactly the set of Instructions for which
+/// AliasAnalysis::getModRefInfo returns "Ref".
+class MemoryUse final : public MemoryUseOrDef {
+ void *operator new(size_t, unsigned) = delete;
+
+public:
+ DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess);
+
+ // allocate space for exactly one operand
+ void *operator new(size_t s) { return User::operator new(s, 1); }
+
+ MemoryUse(LLVMContext &C, MemoryAccess *DMA, Instruction *MI, BasicBlock *BB)
+ : MemoryUseOrDef(C, DMA, MemoryUseVal, MI, BB) {}
+
+ static inline bool classof(const MemoryUse *) { return true; }
+ static inline bool classof(const Value *MA) {
+ return MA->getValueID() == MemoryUseVal;
+ }
+
+ void print(raw_ostream &OS) const override;
+
+protected:
+ friend class MemorySSA;
+
+ unsigned getID() const override {
+ llvm_unreachable("MemoryUses do not have IDs");
+ }
+};
+
+template <>
+struct OperandTraits<MemoryUse> : public FixedNumOperandTraits<MemoryUse, 1> {};
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryUse, MemoryAccess)
+
+/// \brief Represents a read-write access to memory, whether it is a must-alias,
+/// or a may-alias.
+///
+/// In particular, the set of Instructions that will be represented by
+/// MemoryDef's is exactly the set of Instructions for which
+/// AliasAnalysis::getModRefInfo returns "Mod" or "ModRef".
+/// Note that, in order to provide def-def chains, all defs also have a use
+/// associated with them. This use points to the nearest reaching
+/// MemoryDef/MemoryPhi.
+class MemoryDef final : public MemoryUseOrDef {
+ void *operator new(size_t, unsigned) = delete;
+
+public:
+ DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess);
+
+ // allocate space for exactly one operand
+ void *operator new(size_t s) { return User::operator new(s, 1); }
+
+ MemoryDef(LLVMContext &C, MemoryAccess *DMA, Instruction *MI, BasicBlock *BB,
+ unsigned Ver)
+ : MemoryUseOrDef(C, DMA, MemoryDefVal, MI, BB), ID(Ver) {}
+
+ static inline bool classof(const MemoryDef *) { return true; }
+ static inline bool classof(const Value *MA) {
+ return MA->getValueID() == MemoryDefVal;
+ }
+
+ void print(raw_ostream &OS) const override;
+
+protected:
+ friend class MemorySSA;
+
+ // For debugging only. This gets used to give memory accesses pretty numbers
+ // when printing them out
+ unsigned getID() const override { return ID; }
+
+private:
+ const unsigned ID;
+};
+
+template <>
+struct OperandTraits<MemoryDef> : public FixedNumOperandTraits<MemoryDef, 1> {};
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryDef, MemoryAccess)
+
+/// \brief Represents phi nodes for memory accesses.
+///
+/// These have the same semantic as regular phi nodes, with the exception that
+/// only one phi will ever exist in a given basic block.
+/// Guaranteeing one phi per block means guaranteeing there is only ever one
+/// valid reaching MemoryDef/MemoryPHI along each path to the phi node.
+/// This is ensured by not allowing disambiguation of the RHS of a MemoryDef or
+/// a MemoryPhi's operands.
+/// That is, given
+/// if (a) {
+/// store %a
+/// store %b
+/// }
+/// it *must* be transformed into
+/// if (a) {
+/// 1 = MemoryDef(liveOnEntry)
+/// store %a
+/// 2 = MemoryDef(1)
+/// store %b
+/// }
+/// and *not*
+/// if (a) {
+/// 1 = MemoryDef(liveOnEntry)
+/// store %a
+/// 2 = MemoryDef(liveOnEntry)
+/// store %b
+/// }
+/// even if the two stores do not conflict. Otherwise, both 1 and 2 reach the
+/// end of the branch, and if there are not two phi nodes, one will be
+/// disconnected completely from the SSA graph below that point.
+/// Because MemoryUse's do not generate new definitions, they do not have this
+/// issue.
+class MemoryPhi final : public MemoryAccess {
+ void *operator new(size_t, unsigned) = delete;
+ // allocate space for exactly zero operands
+ void *operator new(size_t s) { return User::operator new(s); }
+
+public:
+ /// Provide fast operand accessors
+ DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess);
+
+ MemoryPhi(LLVMContext &C, BasicBlock *BB, unsigned Ver, unsigned NumPreds = 0)
+ : MemoryAccess(C, MemoryPhiVal, BB, 0), ID(Ver), ReservedSpace(NumPreds) {
+ allocHungoffUses(ReservedSpace);
+ }
+
+ // Block iterator interface. This provides access to the list of incoming
+ // basic blocks, which parallels the list of incoming values.
+ typedef BasicBlock **block_iterator;
+ typedef BasicBlock *const *const_block_iterator;
+
+ block_iterator block_begin() {
+ auto *Ref = reinterpret_cast<Use::UserRef *>(op_begin() + ReservedSpace);
+ return reinterpret_cast<block_iterator>(Ref + 1);
+ }
+
+ const_block_iterator block_begin() const {
+ const auto *Ref =
+ reinterpret_cast<const Use::UserRef *>(op_begin() + ReservedSpace);
+ return reinterpret_cast<const_block_iterator>(Ref + 1);
+ }
+
+ block_iterator block_end() { return block_begin() + getNumOperands(); }
+
+ const_block_iterator block_end() const {
+ return block_begin() + getNumOperands();
+ }
+
+ op_range incoming_values() { return operands(); }
+
+ const_op_range incoming_values() const { return operands(); }
+
+ /// \brief Return the number of incoming edges
+ unsigned getNumIncomingValues() const { return getNumOperands(); }
+
+ /// \brief Return incoming value number x
+ MemoryAccess *getIncomingValue(unsigned I) const { return getOperand(I); }
+ void setIncomingValue(unsigned I, MemoryAccess *V) {
+ assert(V && "PHI node got a null value!");
+ setOperand(I, V);
+ }
+ static unsigned getOperandNumForIncomingValue(unsigned I) { return I; }
+ static unsigned getIncomingValueNumForOperand(unsigned I) { return I; }
+
+ /// \brief Return incoming basic block number @p i.
+ BasicBlock *getIncomingBlock(unsigned I) const { return block_begin()[I]; }
+
+ /// \brief Return incoming basic block corresponding
+ /// to an operand of the PHI.
+ BasicBlock *getIncomingBlock(const Use &U) const {
+ assert(this == U.getUser() && "Iterator doesn't point to PHI's Uses?");
+ return getIncomingBlock(unsigned(&U - op_begin()));
+ }
+
+ /// \brief Return incoming basic block corresponding
+ /// to value use iterator.
+ BasicBlock *getIncomingBlock(MemoryAccess::const_user_iterator I) const {
+ return getIncomingBlock(I.getUse());
+ }
+
+ void setIncomingBlock(unsigned I, BasicBlock *BB) {
+ assert(BB && "PHI node got a null basic block!");
+ block_begin()[I] = BB;
+ }
+
+ /// \brief Add an incoming value to the end of the PHI list
+ void addIncoming(MemoryAccess *V, BasicBlock *BB) {
+ if (getNumOperands() == ReservedSpace)
+ growOperands(); // Get more space!
+ // Initialize some new operands.
+ setNumHungOffUseOperands(getNumOperands() + 1);
+ setIncomingValue(getNumOperands() - 1, V);
+ setIncomingBlock(getNumOperands() - 1, BB);
+ }
+
+ /// \brief Return the first index of the specified basic
+ /// block in the value list for this PHI. Returns -1 if no instance.
+ int getBasicBlockIndex(const BasicBlock *BB) const {
+ for (unsigned I = 0, E = getNumOperands(); I != E; ++I)
+ if (block_begin()[I] == BB)
+ return I;
+ return -1;
+ }
+
+ Value *getIncomingValueForBlock(const BasicBlock *BB) const {
+ int Idx = getBasicBlockIndex(BB);
+ assert(Idx >= 0 && "Invalid basic block argument!");
+ return getIncomingValue(Idx);
+ }
+
+ static inline bool classof(const MemoryPhi *) { return true; }
+ static inline bool classof(const Value *V) {
+ return V->getValueID() == MemoryPhiVal;
+ }
+
+ void print(raw_ostream &OS) const override;
+
+protected:
+ friend class MemorySSA;
+ /// \brief this is more complicated than the generic
+ /// User::allocHungoffUses, because we have to allocate Uses for the incoming
+ /// values and pointers to the incoming blocks, all in one allocation.
+ void allocHungoffUses(unsigned N) {
+ User::allocHungoffUses(N, /* IsPhi */ true);
+ }
+
+ /// For debugging only. This gets used to give memory accesses pretty numbers
+ /// when printing them out
+ unsigned getID() const final { return ID; }
+
+private:
+ // For debugging only
+ const unsigned ID;
+ unsigned ReservedSpace;
+
+ /// \brief This grows the operand list in response to a push_back style of
+ /// operation. This grows the number of ops by 1.5 times.
+ void growOperands() {
+ unsigned E = getNumOperands();
+ // 2 op PHI nodes are VERY common, so reserve at least enough for that.
+ ReservedSpace = std::max(E + E / 2, 2u);
+ growHungoffUses(ReservedSpace, /* IsPhi */ true);
+ }
+};
+
+template <> struct OperandTraits<MemoryPhi> : public HungoffOperandTraits<2> {};
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryPhi, MemoryAccess)
+
+class MemorySSAWalker;
+
+/// \brief Encapsulates MemorySSA, including all data associated with memory
+/// accesses.
+class MemorySSA {
+public:
+ MemorySSA(Function &, AliasAnalysis *, DominatorTree *);
+ MemorySSA(MemorySSA &&);
+ ~MemorySSA();
+
+ MemorySSAWalker *getWalker();
+
+ /// \brief Given a memory Mod/Ref'ing instruction, get the MemorySSA
+ /// access associated with it. If passed a basic block gets the memory phi
+ /// node that exists for that block, if there is one. Otherwise, this will get
+ /// a MemoryUseOrDef.
+ MemoryAccess *getMemoryAccess(const Value *) const;
+ MemoryPhi *getMemoryAccess(const BasicBlock *BB) const;
+
+ void dump() const;
+ void print(raw_ostream &) const;
+
+ /// \brief Return true if \p MA represents the live on entry value
+ ///
+ /// Loads and stores from pointer arguments and other global values may be
+ /// defined by memory operations that do not occur in the current function, so
+ /// they may be live on entry to the function. MemorySSA represents such
+ /// memory state by the live on entry definition, which is guaranteed to occur
+ /// before any other memory access in the function.
+ inline bool isLiveOnEntryDef(const MemoryAccess *MA) const {
+ return MA == LiveOnEntryDef.get();
+ }
+
+ inline MemoryAccess *getLiveOnEntryDef() const {
+ return LiveOnEntryDef.get();
+ }
+
+ using AccessList = iplist<MemoryAccess>;
+
+ /// \brief Return the list of MemoryAccess's for a given basic block.
+ ///
+ /// This list is not modifiable by the user.
+ const AccessList *getBlockAccesses(const BasicBlock *BB) const {
+ auto It = PerBlockAccesses.find(BB);
+ return It == PerBlockAccesses.end() ? nullptr : It->second.get();
+ }
+
+ /// \brief Create an empty MemoryPhi in MemorySSA
+ MemoryPhi *createMemoryPhi(BasicBlock *BB);
+
+ enum InsertionPlace { Beginning, End };
+
+ /// \brief Create a MemoryAccess in MemorySSA at a specified point in a block,
+ /// with a specified clobbering definition.
+ ///
+ /// Returns the new MemoryAccess.
+ /// This should be called when a memory instruction is created that is being
+ /// used to replace an existing memory instruction. It will *not* create PHI
+ /// nodes, or verify the clobbering definition. The insertion place is used
+ /// solely to determine where in the memoryssa access lists the instruction
+ /// will be placed. The caller is expected to keep ordering the same as
+ /// instructions.
+ /// It will return the new MemoryAccess.
+ MemoryAccess *createMemoryAccessInBB(Instruction *I, MemoryAccess *Definition,
+ const BasicBlock *BB,
+ InsertionPlace Point);
+ /// \brief Create a MemoryAccess in MemorySSA before or after an existing
+ /// MemoryAccess.
+ ///
+ /// Returns the new MemoryAccess.
+ /// This should be called when a memory instruction is created that is being
+ /// used to replace an existing memory instruction. It will *not* create PHI
+ /// nodes, or verify the clobbering definition. The clobbering definition
+ /// must be non-null.
+ MemoryAccess *createMemoryAccessBefore(Instruction *I,
+ MemoryAccess *Definition,
+ MemoryAccess *InsertPt);
+ MemoryAccess *createMemoryAccessAfter(Instruction *I,
+ MemoryAccess *Definition,
+ MemoryAccess *InsertPt);
+
+ /// \brief Remove a MemoryAccess from MemorySSA, including updating all
+ /// definitions and uses.
+ /// This should be called when a memory instruction that has a MemoryAccess
+ /// associated with it is erased from the program. For example, if a store or
+ /// load is simply erased (not replaced), removeMemoryAccess should be called
+ /// on the MemoryAccess for that store/load.
+ void removeMemoryAccess(MemoryAccess *);
+
+ /// \brief Given two memory accesses in the same basic block, determine
+ /// whether MemoryAccess \p A dominates MemoryAccess \p B.
+ bool locallyDominates(const MemoryAccess *A, const MemoryAccess *B) const;
+
+ /// \brief Verify that MemorySSA is self consistent (IE definitions dominate
+ /// all uses, uses appear in the right places). This is used by unit tests.
+ void verifyMemorySSA() const;
+
+protected:
+ // Used by Memory SSA annotater, dumpers, and wrapper pass
+ friend class MemorySSAAnnotatedWriter;
+ friend class MemorySSAPrinterLegacyPass;
+ void verifyDefUses(Function &F) const;
+ void verifyDomination(Function &F) const;
+ void verifyOrdering(Function &F) const;
+
+private:
+ class CachingWalker;
+ void buildMemorySSA();
+ void verifyUseInDefs(MemoryAccess *, MemoryAccess *) const;
+ using AccessMap = DenseMap<const BasicBlock *, std::unique_ptr<AccessList>>;
+
+ void
+ determineInsertionPoint(const SmallPtrSetImpl<BasicBlock *> &DefiningBlocks);
+ void computeDomLevels(DenseMap<DomTreeNode *, unsigned> &DomLevels);
+ void markUnreachableAsLiveOnEntry(BasicBlock *BB);
+ bool dominatesUse(const MemoryAccess *, const MemoryAccess *) const;
+ MemoryUseOrDef *createNewAccess(Instruction *);
+ MemoryUseOrDef *createDefinedAccess(Instruction *, MemoryAccess *);
+ MemoryAccess *findDominatingDef(BasicBlock *, enum InsertionPlace);
+ void removeFromLookups(MemoryAccess *);
+
+ MemoryAccess *renameBlock(BasicBlock *, MemoryAccess *);
+ void renamePass(DomTreeNode *, MemoryAccess *IncomingVal,
+ SmallPtrSet<BasicBlock *, 16> &Visited);
+ AccessList *getOrCreateAccessList(const BasicBlock *);
+ AliasAnalysis *AA;
+ DominatorTree *DT;
+ Function &F;
+
+ // Memory SSA mappings
+ DenseMap<const Value *, MemoryAccess *> ValueToMemoryAccess;
+ AccessMap PerBlockAccesses;
+ std::unique_ptr<MemoryAccess> LiveOnEntryDef;
+
+ // Memory SSA building info
+ std::unique_ptr<CachingWalker> Walker;
+ unsigned NextID;
+};
+
+// This pass does eager building and then printing of MemorySSA. It is used by
+// the tests to be able to build, dump, and verify Memory SSA.
+class MemorySSAPrinterLegacyPass : public FunctionPass {
+public:
+ MemorySSAPrinterLegacyPass();
+
+ static char ID;
+ bool runOnFunction(Function &) override;
+ void getAnalysisUsage(AnalysisUsage &AU) const override;
+};
+
+/// An analysis that produces \c MemorySSA for a function.
+///
+class MemorySSAAnalysis : public AnalysisInfoMixin<MemorySSAAnalysis> {
+ friend AnalysisInfoMixin<MemorySSAAnalysis>;
+ static char PassID;
+
+public:
+ typedef MemorySSA Result;
+
+ MemorySSA run(Function &F, AnalysisManager<Function> &AM);
+};
+
+/// \brief Printer pass for \c MemorySSA.
+class MemorySSAPrinterPass : public PassInfoMixin<MemorySSAPrinterPass> {
+ raw_ostream &OS;
+
+public:
+ explicit MemorySSAPrinterPass(raw_ostream &OS) : OS(OS) {}
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
+};
+
+/// \brief Verifier pass for \c MemorySSA.
+struct MemorySSAVerifierPass : PassInfoMixin<MemorySSAVerifierPass> {
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
+};
+
+/// \brief Legacy analysis pass which computes \c MemorySSA.
+class MemorySSAWrapperPass : public FunctionPass {
+public:
+ MemorySSAWrapperPass();
+
+ static char ID;
+ bool runOnFunction(Function &) override;
+ void releaseMemory() override;
+ MemorySSA &getMSSA() { return *MSSA; }
+ const MemorySSA &getMSSA() const { return *MSSA; }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override;
+
+ void verifyAnalysis() const override;
+ void print(raw_ostream &OS, const Module *M = nullptr) const override;
+
+private:
+ std::unique_ptr<MemorySSA> MSSA;
+};
+
+/// \brief This is the generic walker interface for walkers of MemorySSA.
+/// Walkers are used to be able to further disambiguate the def-use chains
+/// MemorySSA gives you, or otherwise produce better info than MemorySSA gives
+/// you.
+/// In particular, while the def-use chains provide basic information, and are
+/// guaranteed to give, for example, the nearest may-aliasing MemoryDef for a
+/// MemoryUse as AliasAnalysis considers it, a user mant want better or other
+/// information. In particular, they may want to use SCEV info to further
+/// disambiguate memory accesses, or they may want the nearest dominating
+/// may-aliasing MemoryDef for a call or a store. This API enables a
+/// standardized interface to getting and using that info.
+class MemorySSAWalker {
+public:
+ MemorySSAWalker(MemorySSA *);
+ virtual ~MemorySSAWalker() {}
+
+ using MemoryAccessSet = SmallVector<MemoryAccess *, 8>;
+
+ /// \brief Given a memory Mod/Ref/ModRef'ing instruction, calling this
+ /// will give you the nearest dominating MemoryAccess that Mod's the location
+ /// the instruction accesses (by skipping any def which AA can prove does not
+ /// alias the location(s) accessed by the instruction given).
+ ///
+ /// Note that this will return a single access, and it must dominate the
+ /// Instruction, so if an operand of a MemoryPhi node Mod's the instruction,
+ /// this will return the MemoryPhi, not the operand. This means that
+ /// given:
+ /// if (a) {
+ /// 1 = MemoryDef(liveOnEntry)
+ /// store %a
+ /// } else {
+ /// 2 = MemoryDef(liveOnEntry)
+ /// store %b
+ /// }
+ /// 3 = MemoryPhi(2, 1)
+ /// MemoryUse(3)
+ /// load %a
+ ///
+ /// calling this API on load(%a) will return the MemoryPhi, not the MemoryDef
+ /// in the if (a) branch.
+ virtual MemoryAccess *getClobberingMemoryAccess(const Instruction *) = 0;
+
+ /// \brief Given a potentially clobbering memory access and a new location,
+ /// calling this will give you the nearest dominating clobbering MemoryAccess
+ /// (by skipping non-aliasing def links).
+ ///
+ /// This version of the function is mainly used to disambiguate phi translated
+ /// pointers, where the value of a pointer may have changed from the initial
+ /// memory access. Note that this expects to be handed either a MemoryUse,
+ /// or an already potentially clobbering access. Unlike the above API, if
+ /// given a MemoryDef that clobbers the pointer as the starting access, it
+ /// will return that MemoryDef, whereas the above would return the clobber
+ /// starting from the use side of the memory def.
+ virtual MemoryAccess *getClobberingMemoryAccess(MemoryAccess *,
+ MemoryLocation &) = 0;
+
+ /// \brief Given a memory access, invalidate anything this walker knows about
+ /// that access.
+ /// This API is used by walkers that store information to perform basic cache
+ /// invalidation. This will be called by MemorySSA at appropriate times for
+ /// the walker it uses or returns.
+ virtual void invalidateInfo(MemoryAccess *) {}
+
+protected:
+ friend class MemorySSA; // For updating MSSA pointer in MemorySSA move
+ // constructor.
+ MemorySSA *MSSA;
+};
+
+/// \brief A MemorySSAWalker that does no alias queries, or anything else. It
+/// simply returns the links as they were constructed by the builder.
+class DoNothingMemorySSAWalker final : public MemorySSAWalker {
+public:
+ MemoryAccess *getClobberingMemoryAccess(const Instruction *) override;
+ MemoryAccess *getClobberingMemoryAccess(MemoryAccess *,
+ MemoryLocation &) override;
+};
+
+using MemoryAccessPair = std::pair<MemoryAccess *, MemoryLocation>;
+using ConstMemoryAccessPair = std::pair<const MemoryAccess *, MemoryLocation>;
+
+/// \brief Iterator base class used to implement const and non-const iterators
+/// over the defining accesses of a MemoryAccess.
+template <class T>
+class memoryaccess_def_iterator_base
+ : public iterator_facade_base<memoryaccess_def_iterator_base<T>,
+ std::forward_iterator_tag, T, ptrdiff_t, T *,
+ T *> {
+ using BaseT = typename memoryaccess_def_iterator_base::iterator_facade_base;
+
+public:
+ memoryaccess_def_iterator_base(T *Start) : Access(Start), ArgNo(0) {}
+ memoryaccess_def_iterator_base() : Access(nullptr), ArgNo(0) {}
+ bool operator==(const memoryaccess_def_iterator_base &Other) const {
+ return Access == Other.Access && (!Access || ArgNo == Other.ArgNo);
+ }
+
+ // This is a bit ugly, but for MemoryPHI's, unlike PHINodes, you can't get the
+ // block from the operand in constant time (In a PHINode, the uselist has
+ // both, so it's just subtraction). We provide it as part of the
+ // iterator to avoid callers having to linear walk to get the block.
+ // If the operation becomes constant time on MemoryPHI's, this bit of
+ // abstraction breaking should be removed.
+ BasicBlock *getPhiArgBlock() const {
+ MemoryPhi *MP = dyn_cast<MemoryPhi>(Access);
+ assert(MP && "Tried to get phi arg block when not iterating over a PHI");
+ return MP->getIncomingBlock(ArgNo);
+ }
+ typename BaseT::iterator::pointer operator*() const {
+ assert(Access && "Tried to access past the end of our iterator");
+ // Go to the first argument for phis, and the defining access for everything
+ // else.
+ if (MemoryPhi *MP = dyn_cast<MemoryPhi>(Access))
+ return MP->getIncomingValue(ArgNo);
+ return cast<MemoryUseOrDef>(Access)->getDefiningAccess();
+ }
+ using BaseT::operator++;
+ memoryaccess_def_iterator &operator++() {
+ assert(Access && "Hit end of iterator");
+ if (MemoryPhi *MP = dyn_cast<MemoryPhi>(Access)) {
+ if (++ArgNo >= MP->getNumIncomingValues()) {
+ ArgNo = 0;
+ Access = nullptr;
+ }
+ } else {
+ Access = nullptr;
+ }
+ return *this;
+ }
+
+private:
+ T *Access;
+ unsigned ArgNo;
+};
+
+inline memoryaccess_def_iterator MemoryAccess::defs_begin() {
+ return memoryaccess_def_iterator(this);
+}
+
+inline const_memoryaccess_def_iterator MemoryAccess::defs_begin() const {
+ return const_memoryaccess_def_iterator(this);
+}
+
+inline memoryaccess_def_iterator MemoryAccess::defs_end() {
+ return memoryaccess_def_iterator();
+}
+
+inline const_memoryaccess_def_iterator MemoryAccess::defs_end() const {
+ return const_memoryaccess_def_iterator();
+}
+
+/// \brief GraphTraits for a MemoryAccess, which walks defs in the normal case,
+/// and uses in the inverse case.
+template <> struct GraphTraits<MemoryAccess *> {
+ using NodeType = MemoryAccess;
+ using ChildIteratorType = memoryaccess_def_iterator;
+
+ static NodeType *getEntryNode(NodeType *N) { return N; }
+ static inline ChildIteratorType child_begin(NodeType *N) {
+ return N->defs_begin();
+ }
+ static inline ChildIteratorType child_end(NodeType *N) {
+ return N->defs_end();
+ }
+};
+
+template <> struct GraphTraits<Inverse<MemoryAccess *>> {
+ using NodeType = MemoryAccess;
+ using ChildIteratorType = MemoryAccess::iterator;
+
+ static NodeType *getEntryNode(NodeType *N) { return N; }
+ static inline ChildIteratorType child_begin(NodeType *N) {
+ return N->user_begin();
+ }
+ static inline ChildIteratorType child_end(NodeType *N) {
+ return N->user_end();
+ }
+};
+
+/// \brief Provide an iterator that walks defs, giving both the memory access,
+/// and the current pointer location, updating the pointer location as it
+/// changes due to phi node translation.
+///
+/// This iterator, while somewhat specialized, is what most clients actually
+/// want when walking upwards through MemorySSA def chains. It takes a pair of
+/// <MemoryAccess,MemoryLocation>, and walks defs, properly translating the
+/// memory location through phi nodes for the user.
+class upward_defs_iterator
+ : public iterator_facade_base<upward_defs_iterator,
+ std::forward_iterator_tag,
+ const MemoryAccessPair> {
+ using BaseT = upward_defs_iterator::iterator_facade_base;
+
+public:
+ upward_defs_iterator(const MemoryAccessPair &Info)
+ : DefIterator(Info.first), Location(Info.second),
+ OriginalAccess(Info.first) {
+ CurrentPair.first = nullptr;
+
+ WalkingPhi = Info.first && isa<MemoryPhi>(Info.first);
+ fillInCurrentPair();
+ }
+
+ upward_defs_iterator()
+ : DefIterator(), Location(), OriginalAccess(), WalkingPhi(false) {
+ CurrentPair.first = nullptr;
+ }
+
+ bool operator==(const upward_defs_iterator &Other) const {
+ return DefIterator == Other.DefIterator;
+ }
+
+ BaseT::iterator::reference operator*() const {
+ assert(DefIterator != OriginalAccess->defs_end() &&
+ "Tried to access past the end of our iterator");
+ return CurrentPair;
+ }
+
+ using BaseT::operator++;
+ upward_defs_iterator &operator++() {
+ assert(DefIterator != OriginalAccess->defs_end() &&
+ "Tried to access past the end of the iterator");
+ ++DefIterator;
+ if (DefIterator != OriginalAccess->defs_end())
+ fillInCurrentPair();
+ return *this;
+ }
+
+ BasicBlock *getPhiArgBlock() const { return DefIterator.getPhiArgBlock(); }
+
+private:
+ void fillInCurrentPair() {
+ CurrentPair.first = *DefIterator;
+ if (WalkingPhi && Location.Ptr) {
+ PHITransAddr Translator(
+ const_cast<Value *>(Location.Ptr),
+ OriginalAccess->getBlock()->getModule()->getDataLayout(), nullptr);
+ if (!Translator.PHITranslateValue(OriginalAccess->getBlock(),
+ DefIterator.getPhiArgBlock(), nullptr,
+ false))
+ if (Translator.getAddr() != Location.Ptr) {
+ CurrentPair.second = Location.getWithNewPtr(Translator.getAddr());
+ return;
+ }
+ }
+ CurrentPair.second = Location;
+ }
+
+ MemoryAccessPair CurrentPair;
+ memoryaccess_def_iterator DefIterator;
+ MemoryLocation Location;
+ MemoryAccess *OriginalAccess;
+ bool WalkingPhi;
+};
+
+inline upward_defs_iterator upward_defs_begin(const MemoryAccessPair &Pair) {
+ return upward_defs_iterator(Pair);
+}
+
+inline upward_defs_iterator upward_defs_end() { return upward_defs_iterator(); }
+
+} // end namespace llvm
+
+#endif // LLVM_TRANSFORMS_UTILS_MEMORYSSA_H
diff --git a/include/llvm/Transforms/Utils/ModuleUtils.h b/include/llvm/Transforms/Utils/ModuleUtils.h
index 0f23d34de5db..2eb2b1363b0b 100644
--- a/include/llvm/Transforms/Utils/ModuleUtils.h
+++ b/include/llvm/Transforms/Utils/ModuleUtils.h
@@ -14,12 +14,12 @@
#ifndef LLVM_TRANSFORMS_UTILS_MODULEUTILS_H
#define LLVM_TRANSFORMS_UTILS_MODULEUTILS_H
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include <utility> // for std::pair
namespace llvm {
+template <typename T> class ArrayRef;
class Module;
class Function;
class GlobalValue;
@@ -28,22 +28,17 @@ class Constant;
class StringRef;
class Value;
class Type;
-template <class PtrType> class SmallPtrSetImpl;
/// Append F to the list of global ctors of module M with the given Priority.
/// This wraps the function in the appropriate structure and stores it along
/// side other global constructors. For details see
/// http://llvm.org/docs/LangRef.html#intg_global_ctors
-void appendToGlobalCtors(Module &M, Function *F, int Priority);
+void appendToGlobalCtors(Module &M, Function *F, int Priority,
+ Constant *Data = nullptr);
/// Same as appendToGlobalCtors(), but for global dtors.
-void appendToGlobalDtors(Module &M, Function *F, int Priority);
-
-/// \brief Given "llvm.used" or "llvm.compiler.used" as a global name, collect
-/// the initializer elements of that global in Set and return the global itself.
-GlobalVariable *collectUsedGlobalVariables(Module &M,
- SmallPtrSetImpl<GlobalValue *> &Set,
- bool CompilerUsed);
+void appendToGlobalDtors(Module &M, Function *F, int Priority,
+ Constant *Data = nullptr);
// Validate the result of Module::getOrInsertFunction called for an interface
// function of given sanitizer. If the instrumented module defines a function
@@ -59,6 +54,11 @@ std::pair<Function *, Function *> createSanitizerCtorAndInitFunctions(
Module &M, StringRef CtorName, StringRef InitName,
ArrayRef<Type *> InitArgTypes, ArrayRef<Value *> InitArgs,
StringRef VersionCheckName = StringRef());
+
+/// Rename all the anon functions in the module using a hash computed from
+/// the list of public globals in the module.
+bool nameUnamedFunctions(Module &M);
+
} // End llvm namespace
#endif // LLVM_TRANSFORMS_UTILS_MODULEUTILS_H
diff --git a/include/llvm/Transforms/Utils/PromoteMemToReg.h b/include/llvm/Transforms/Utils/PromoteMemToReg.h
index d0602bf47c92..b548072c413e 100644
--- a/include/llvm/Transforms/Utils/PromoteMemToReg.h
+++ b/include/llvm/Transforms/Utils/PromoteMemToReg.h
@@ -15,10 +15,9 @@
#ifndef LLVM_TRANSFORMS_UTILS_PROMOTEMEMTOREG_H
#define LLVM_TRANSFORMS_UTILS_PROMOTEMEMTOREG_H
-#include "llvm/ADT/ArrayRef.h"
-
namespace llvm {
+template <typename T> class ArrayRef;
class AllocaInst;
class DominatorTree;
class AliasSetTracker;
diff --git a/include/llvm/Transforms/Utils/SSAUpdater.h b/include/llvm/Transforms/Utils/SSAUpdater.h
index 1c7b2c587a36..9f98bac22dc9 100644
--- a/include/llvm/Transforms/Utils/SSAUpdater.h
+++ b/include/llvm/Transforms/Utils/SSAUpdater.h
@@ -14,7 +14,6 @@
#ifndef LLVM_TRANSFORMS_UTILS_SSAUPDATER_H
#define LLVM_TRANSFORMS_UTILS_SSAUPDATER_H
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Compiler.h"
@@ -22,8 +21,9 @@ namespace llvm {
class BasicBlock;
class Instruction;
class LoadInst;
- template<typename T> class SmallVectorImpl;
- template<typename T> class SSAUpdaterTraits;
+ template <typename T> class ArrayRef;
+ template <typename T> class SmallVectorImpl;
+ template <typename T> class SSAUpdaterTraits;
class PHINode;
class Type;
class Use;
diff --git a/include/llvm/Transforms/Utils/SSAUpdaterImpl.h b/include/llvm/Transforms/Utils/SSAUpdaterImpl.h
index 425ecd3cfb5e..b5f4ac82b605 100644
--- a/include/llvm/Transforms/Utils/SSAUpdaterImpl.h
+++ b/include/llvm/Transforms/Utils/SSAUpdaterImpl.h
@@ -17,6 +17,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/Instructions.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Debug.h"
diff --git a/include/llvm/Transforms/Utils/SanitizerStats.h b/include/llvm/Transforms/Utils/SanitizerStats.h
new file mode 100644
index 000000000000..d36e34258a3f
--- /dev/null
+++ b/include/llvm/Transforms/Utils/SanitizerStats.h
@@ -0,0 +1,56 @@
+//===- SanitizerStats.h - Sanitizer statistics gathering -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Declares functions and data structures for sanitizer statistics gathering.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_UTILS_SANITIZERSTATS_H
+#define LLVM_TRANSFORMS_UTILS_SANITIZERSTATS_H
+
+#include "llvm/IR/IRBuilder.h"
+
+namespace llvm {
+
+// Number of bits in data that are used for the sanitizer kind. Needs to match
+// __sanitizer::kKindBits in compiler-rt/lib/stats/stats.h
+enum { kSanitizerStatKindBits = 3 };
+
+enum SanitizerStatKind {
+ SanStat_CFI_VCall,
+ SanStat_CFI_NVCall,
+ SanStat_CFI_DerivedCast,
+ SanStat_CFI_UnrelatedCast,
+ SanStat_CFI_ICall,
+};
+
+struct SanitizerStatReport {
+ SanitizerStatReport(Module *M);
+
+ /// Generates code into B that increments a location-specific counter tagged
+ /// with the given sanitizer kind SK.
+ void create(IRBuilder<> &B, SanitizerStatKind SK);
+
+ /// Finalize module stats array and add global constructor to register it.
+ void finish();
+
+private:
+ Module *M;
+ GlobalVariable *ModuleStatsGV;
+ ArrayType *StatTy;
+ StructType *EmptyModuleStatsTy;
+
+ std::vector<Constant *> Inits;
+ ArrayType *makeModuleStatsArrayTy();
+ StructType *makeModuleStatsTy();
+};
+
+}
+
+#endif
diff --git a/include/llvm/Transforms/Utils/SimplifyIndVar.h b/include/llvm/Transforms/Utils/SimplifyIndVar.h
index 3c55e64537c7..90438ee699fe 100644
--- a/include/llvm/Transforms/Utils/SimplifyIndVar.h
+++ b/include/llvm/Transforms/Utils/SimplifyIndVar.h
@@ -17,7 +17,6 @@
#define LLVM_TRANSFORMS_UTILS_SIMPLIFYINDVAR_H
#include "llvm/IR/ValueHandle.h"
-#include "llvm/Support/CommandLine.h"
namespace llvm {
@@ -34,24 +33,14 @@ class ScalarEvolution;
class IVVisitor {
protected:
const DominatorTree *DT;
- bool ShouldSplitOverflowIntrinsics;
virtual void anchor();
public:
- IVVisitor(): DT(nullptr), ShouldSplitOverflowIntrinsics(false) {}
+ IVVisitor() : DT(nullptr) {}
virtual ~IVVisitor() {}
const DominatorTree *getDomTree() const { return DT; }
-
- bool shouldSplitOverflowInstrinsics() const {
- return ShouldSplitOverflowIntrinsics;
- }
- void setSplitOverflowIntrinsics() {
- ShouldSplitOverflowIntrinsics = true;
- assert(DT && "Splitting overflow intrinsics requires a DomTree.");
- }
-
virtual void visitCast(CastInst *Cast) = 0;
};
diff --git a/include/llvm/Transforms/Utils/SimplifyInstructions.h b/include/llvm/Transforms/Utils/SimplifyInstructions.h
new file mode 100644
index 000000000000..ea491dc50587
--- /dev/null
+++ b/include/llvm/Transforms/Utils/SimplifyInstructions.h
@@ -0,0 +1,31 @@
+//===- SimplifyInstructions.h - Remove redundant instructions ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a utility pass used for testing the InstructionSimplify analysis.
+// The analysis is applied to every instruction, and if it simplifies then the
+// instruction is replaced by the simplification. If you are looking for a pass
+// that performs serious instruction folding, use the instcombine pass instead.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_UTILS_SIMPLIFYINSTRUCTIONS_H
+#define LLVM_TRANSFORMS_UTILS_SIMPLIFYINSTRUCTIONS_H
+
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+/// This pass removes redundant instructions.
+class InstSimplifierPass : public PassInfoMixin<InstSimplifierPass> {
+public:
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
+};
+} // end namespace llvm
+
+#endif // LLVM_TRANSFORMS_UTILS_SIMPLIFYINSTRUCTIONS_H
diff --git a/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/include/llvm/Transforms/Utils/SimplifyLibCalls.h
index fc34f49a1255..92ee24633950 100644
--- a/include/llvm/Transforms/Utils/SimplifyLibCalls.h
+++ b/include/llvm/Transforms/Utils/SimplifyLibCalls.h
@@ -16,11 +16,11 @@
#define LLVM_TRANSFORMS_UTILS_SIMPLIFYLIBCALLS_H
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/IRBuilder.h"
namespace llvm {
+class StringRef;
class Value;
class CallInst;
class DataLayout;
@@ -154,7 +154,7 @@ private:
// Helper methods
Value *emitStrLenMemCpy(Value *Src, Value *Dst, uint64_t Len, IRBuilder<> &B);
- void classifyArgUse(Value *Val, BasicBlock *BB, bool IsFloat,
+ void classifyArgUse(Value *Val, Function *F, bool IsFloat,
SmallVectorImpl<CallInst *> &SinCalls,
SmallVectorImpl<CallInst *> &CosCalls,
SmallVectorImpl<CallInst *> &SinCosCalls);
diff --git a/include/llvm/Transforms/Utils/SplitModule.h b/include/llvm/Transforms/Utils/SplitModule.h
index 7d896d1993d6..b7a3bcf4f86a 100644
--- a/include/llvm/Transforms/Utils/SplitModule.h
+++ b/include/llvm/Transforms/Utils/SplitModule.h
@@ -16,7 +16,7 @@
#ifndef LLVM_TRANSFORMS_UTILS_SPLITMODULE_H
#define LLVM_TRANSFORMS_UTILS_SPLITMODULE_H
-#include <functional>
+#include "llvm/ADT/STLExtras.h"
#include <memory>
namespace llvm {
@@ -36,7 +36,8 @@ class StringRef;
/// each partition.
void SplitModule(
std::unique_ptr<Module> M, unsigned N,
- std::function<void(std::unique_ptr<Module> MPart)> ModuleCallback);
+ function_ref<void(std::unique_ptr<Module> MPart)> ModuleCallback,
+ bool PreserveLocals = false);
} // End llvm namespace
diff --git a/include/llvm/Transforms/Utils/UnrollLoop.h b/include/llvm/Transforms/Utils/UnrollLoop.h
index 710817cddf6a..4d370407591d 100644
--- a/include/llvm/Transforms/Utils/UnrollLoop.h
+++ b/include/llvm/Transforms/Utils/UnrollLoop.h
@@ -16,10 +16,10 @@
#ifndef LLVM_TRANSFORMS_UTILS_UNROLLLOOP_H
#define LLVM_TRANSFORMS_UTILS_UNROLLLOOP_H
-#include "llvm/ADT/StringRef.h"
namespace llvm {
+class StringRef;
class AssumptionCache;
class DominatorTree;
class Loop;
@@ -29,15 +29,16 @@ class MDNode;
class Pass;
class ScalarEvolution;
-bool UnrollLoop(Loop *L, unsigned Count, unsigned TripCount, bool AllowRuntime,
- bool AllowExpensiveTripCount, unsigned TripMultiple,
- LoopInfo *LI, ScalarEvolution *SE, DominatorTree *DT,
- AssumptionCache *AC, bool PreserveLCSSA);
+bool UnrollLoop(Loop *L, unsigned Count, unsigned TripCount, bool Force,
+ bool AllowRuntime, bool AllowExpensiveTripCount,
+ unsigned TripMultiple, LoopInfo *LI, ScalarEvolution *SE,
+ DominatorTree *DT, AssumptionCache *AC, bool PreserveLCSSA);
-bool UnrollRuntimeLoopProlog(Loop *L, unsigned Count,
- bool AllowExpensiveTripCount, LoopInfo *LI,
- ScalarEvolution *SE, DominatorTree *DT,
- bool PreserveLCSSA);
+bool UnrollRuntimeLoopRemainder(Loop *L, unsigned Count,
+ bool AllowExpensiveTripCount,
+ bool UseEpilogRemainder, LoopInfo *LI,
+ ScalarEvolution *SE, DominatorTree *DT,
+ bool PreserveLCSSA);
MDNode *GetUnrollMetadata(MDNode *LoopID, StringRef Name);
}
diff --git a/include/llvm/Transforms/Utils/ValueMapper.h b/include/llvm/Transforms/Utils/ValueMapper.h
index 469022f34c56..de649009612c 100644
--- a/include/llvm/Transforms/Utils/ValueMapper.h
+++ b/include/llvm/Transforms/Utils/ValueMapper.h
@@ -18,117 +18,255 @@
#include "llvm/IR/ValueMap.h"
namespace llvm {
- class Value;
- class Instruction;
- typedef ValueMap<const Value *, WeakVH> ValueToValueMapTy;
-
- /// ValueMapTypeRemapper - This is a class that can be implemented by clients
- /// to remap types when cloning constants and instructions.
- class ValueMapTypeRemapper {
- virtual void anchor(); // Out of line method.
- public:
- virtual ~ValueMapTypeRemapper() {}
-
- /// remapType - The client should implement this method if they want to
- /// remap types while mapping values.
- virtual Type *remapType(Type *SrcTy) = 0;
- };
-
- /// ValueMaterializer - This is a class that can be implemented by clients
- /// to materialize Values on demand.
- class ValueMaterializer {
- virtual void anchor(); // Out of line method.
-
- protected:
- ~ValueMaterializer() = default;
- ValueMaterializer() = default;
- ValueMaterializer(const ValueMaterializer&) = default;
- ValueMaterializer &operator=(const ValueMaterializer&) = default;
-
- public:
- /// The client should implement this method if they want to generate a
- /// mapped Value on demand. For example, if linking lazily.
- virtual Value *materializeDeclFor(Value *V) = 0;
-
- /// If the data being mapped is recursive, the above function can map
- /// just the declaration and this is called to compute the initializer.
- /// It is called after the mapping is recorded, so it doesn't need to worry
- /// about recursion.
- virtual void materializeInitFor(GlobalValue *New, GlobalValue *Old);
-
- /// If the client needs to handle temporary metadata it must implement
- /// these methods.
- virtual Metadata *mapTemporaryMetadata(Metadata *MD) { return nullptr; }
- virtual void replaceTemporaryMetadata(const Metadata *OrigMD,
- Metadata *NewMD) {}
-
- /// The client should implement this method if some metadata need
- /// not be mapped, for example DISubprogram metadata for functions not
- /// linked into the destination module.
- virtual bool isMetadataNeeded(Metadata *MD) { return true; }
- };
-
- /// RemapFlags - These are flags that the value mapping APIs allow.
- enum RemapFlags {
- RF_None = 0,
-
- /// RF_NoModuleLevelChanges - If this flag is set, the remapper knows that
- /// only local values within a function (such as an instruction or argument)
- /// are mapped, not global values like functions and global metadata.
- RF_NoModuleLevelChanges = 1,
-
- /// RF_IgnoreMissingEntries - If this flag is set, the remapper ignores
- /// entries that are not in the value map. If it is unset, it aborts if an
- /// operand is asked to be remapped which doesn't exist in the mapping.
- RF_IgnoreMissingEntries = 2,
-
- /// Instruct the remapper to move distinct metadata instead of duplicating
- /// it when there are module-level changes.
- RF_MoveDistinctMDs = 4,
-
- /// Any global values not in value map are mapped to null instead of
- /// mapping to self. Illegal if RF_IgnoreMissingEntries is also set.
- RF_NullMapMissingGlobalValues = 8,
-
- /// Set when there is still temporary metadata that must be handled,
- /// such as when we are doing function importing and will materialize
- /// and link metadata as a postpass.
- RF_HaveUnmaterializedMetadata = 16,
- };
-
- static inline RemapFlags operator|(RemapFlags LHS, RemapFlags RHS) {
- return RemapFlags(unsigned(LHS)|unsigned(RHS));
- }
-
- Value *MapValue(const Value *V, ValueToValueMapTy &VM,
- RemapFlags Flags = RF_None,
- ValueMapTypeRemapper *TypeMapper = nullptr,
- ValueMaterializer *Materializer = nullptr);
-
- Metadata *MapMetadata(const Metadata *MD, ValueToValueMapTy &VM,
- RemapFlags Flags = RF_None,
- ValueMapTypeRemapper *TypeMapper = nullptr,
- ValueMaterializer *Materializer = nullptr);
-
- /// MapMetadata - provide versions that preserve type safety for MDNodes.
- MDNode *MapMetadata(const MDNode *MD, ValueToValueMapTy &VM,
- RemapFlags Flags = RF_None,
- ValueMapTypeRemapper *TypeMapper = nullptr,
- ValueMaterializer *Materializer = nullptr);
-
- void RemapInstruction(Instruction *I, ValueToValueMapTy &VM,
- RemapFlags Flags = RF_None,
- ValueMapTypeRemapper *TypeMapper = nullptr,
- ValueMaterializer *Materializer = nullptr);
-
- /// MapValue - provide versions that preserve type safety for Constants.
- inline Constant *MapValue(const Constant *V, ValueToValueMapTy &VM,
- RemapFlags Flags = RF_None,
- ValueMapTypeRemapper *TypeMapper = nullptr,
- ValueMaterializer *Materializer = nullptr) {
- return cast<Constant>(MapValue((const Value*)V, VM, Flags, TypeMapper,
- Materializer));
- }
+
+class Value;
+class Instruction;
+typedef ValueMap<const Value *, WeakVH> ValueToValueMapTy;
+
+/// This is a class that can be implemented by clients to remap types when
+/// cloning constants and instructions.
+class ValueMapTypeRemapper {
+ virtual void anchor(); // Out of line method.
+public:
+ virtual ~ValueMapTypeRemapper() {}
+
+ /// The client should implement this method if they want to remap types while
+ /// mapping values.
+ virtual Type *remapType(Type *SrcTy) = 0;
+};
+
+/// This is a class that can be implemented by clients to materialize Values on
+/// demand.
+class ValueMaterializer {
+ virtual void anchor(); // Out of line method.
+
+protected:
+ ~ValueMaterializer() = default;
+ ValueMaterializer() = default;
+ ValueMaterializer(const ValueMaterializer &) = default;
+ ValueMaterializer &operator=(const ValueMaterializer &) = default;
+
+public:
+ /// This method can be implemented to generate a mapped Value on demand. For
+ /// example, if linking lazily. Returns null if the value is not materialized.
+ virtual Value *materialize(Value *V) = 0;
+};
+
+/// These are flags that the value mapping APIs allow.
+enum RemapFlags {
+ RF_None = 0,
+
+ /// If this flag is set, the remapper knows that only local values within a
+ /// function (such as an instruction or argument) are mapped, not global
+ /// values like functions and global metadata.
+ RF_NoModuleLevelChanges = 1,
+
+ /// If this flag is set, the remapper ignores missing function-local entries
+ /// (Argument, Instruction, BasicBlock) that are not in the value map. If it
+ /// is unset, it aborts if an operand is asked to be remapped which doesn't
+ /// exist in the mapping.
+ ///
+ /// There are no such assertions in MapValue(), whose results are almost
+ /// unchanged by this flag. This flag mainly changes the assertion behaviour
+ /// in RemapInstruction().
+ ///
+ /// Since an Instruction's metadata operands (even that point to SSA values)
+ /// aren't guaranteed to be dominated by their definitions, MapMetadata will
+ /// return "!{}" instead of "null" for \a LocalAsMetadata instances whose SSA
+ /// values are unmapped when this flag is set. Otherwise, \a MapValue()
+ /// completely ignores this flag.
+ ///
+ /// \a MapMetadata() always ignores this flag.
+ RF_IgnoreMissingLocals = 2,
+
+ /// Instruct the remapper to move distinct metadata instead of duplicating it
+ /// when there are module-level changes.
+ RF_MoveDistinctMDs = 4,
+
+ /// Any global values not in value map are mapped to null instead of mapping
+ /// to self. Illegal if RF_IgnoreMissingLocals is also set.
+ RF_NullMapMissingGlobalValues = 8,
+};
+
+static inline RemapFlags operator|(RemapFlags LHS, RemapFlags RHS) {
+ return RemapFlags(unsigned(LHS) | unsigned(RHS));
+}
+
+class ValueMapperImpl;
+
+/// Context for (re-)mapping values (and metadata).
+///
+/// A shared context used for mapping and remapping of Value and Metadata
+/// instances using \a ValueToValueMapTy, \a RemapFlags, \a
+/// ValueMapTypeRemapper, and \a ValueMaterializer.
+///
+/// There are a number of top-level entry points:
+/// - \a mapValue() (and \a mapConstant());
+/// - \a mapMetadata() (and \a mapMDNode());
+/// - \a remapInstruction(); and
+/// - \a remapFunction().
+///
+/// The \a ValueMaterializer can be used as a callback, but cannot invoke any
+/// of these top-level functions recursively. Instead, callbacks should use
+/// one of the following to schedule work lazily in the \a ValueMapper
+/// instance:
+/// - \a scheduleMapGlobalInitializer()
+/// - \a scheduleMapAppendingVariable()
+/// - \a scheduleMapGlobalAliasee()
+/// - \a scheduleRemapFunction()
+///
+/// Sometimes a callback needs a diferent mapping context. Such a context can
+/// be registered using \a registerAlternateMappingContext(), which takes an
+/// alternate \a ValueToValueMapTy and \a ValueMaterializer and returns a ID to
+/// pass into the schedule*() functions.
+///
+/// TODO: lib/Linker really doesn't need the \a ValueHandle in the \a
+/// ValueToValueMapTy. We should template \a ValueMapper (and its
+/// implementation classes), and explicitly instantiate on two concrete
+/// instances of \a ValueMap (one as \a ValueToValueMap, and one with raw \a
+/// Value pointers). It may be viable to do away with \a TrackingMDRef in the
+/// \a Metadata side map for the lib/Linker case as well, in which case we'll
+/// need a new template parameter on \a ValueMap.
+///
+/// TODO: Update callers of \a RemapInstruction() and \a MapValue() (etc.) to
+/// use \a ValueMapper directly.
+class ValueMapper {
+ void *pImpl;
+
+ ValueMapper(ValueMapper &&) = delete;
+ ValueMapper(const ValueMapper &) = delete;
+ ValueMapper &operator=(ValueMapper &&) = delete;
+ ValueMapper &operator=(const ValueMapper &) = delete;
+
+public:
+ ValueMapper(ValueToValueMapTy &VM, RemapFlags Flags = RF_None,
+ ValueMapTypeRemapper *TypeMapper = nullptr,
+ ValueMaterializer *Materializer = nullptr);
+ ~ValueMapper();
+
+ /// Register an alternate mapping context.
+ ///
+ /// Returns a MappingContextID that can be used with the various schedule*()
+ /// API to switch in a different value map on-the-fly.
+ unsigned
+ registerAlternateMappingContext(ValueToValueMapTy &VM,
+ ValueMaterializer *Materializer = nullptr);
+
+ /// Add to the current \a RemapFlags.
+ ///
+ /// \note Like the top-level mapping functions, \a addFlags() must be called
+ /// at the top level, not during a callback in a \a ValueMaterializer.
+ void addFlags(RemapFlags Flags);
+
+ Metadata *mapMetadata(const Metadata &MD);
+ MDNode *mapMDNode(const MDNode &N);
+
+ Value *mapValue(const Value &V);
+ Constant *mapConstant(const Constant &C);
+
+ void remapInstruction(Instruction &I);
+ void remapFunction(Function &F);
+
+ void scheduleMapGlobalInitializer(GlobalVariable &GV, Constant &Init,
+ unsigned MappingContextID = 0);
+ void scheduleMapAppendingVariable(GlobalVariable &GV, Constant *InitPrefix,
+ bool IsOldCtorDtor,
+ ArrayRef<Constant *> NewMembers,
+ unsigned MappingContextID = 0);
+ void scheduleMapGlobalAliasee(GlobalAlias &GA, Constant &Aliasee,
+ unsigned MappingContextID = 0);
+ void scheduleRemapFunction(Function &F, unsigned MappingContextID = 0);
+};
+
+/// Look up or compute a value in the value map.
+///
+/// Return a mapped value for a function-local value (Argument, Instruction,
+/// BasicBlock), or compute and memoize a value for a Constant.
+///
+/// 1. If \c V is in VM, return the result.
+/// 2. Else if \c V can be materialized with \c Materializer, do so, memoize
+/// it in \c VM, and return it.
+/// 3. Else if \c V is a function-local value, return nullptr.
+/// 4. Else if \c V is a \a GlobalValue, return \c nullptr or \c V depending
+/// on \a RF_NullMapMissingGlobalValues.
+/// 5. Else if \c V is a \a MetadataAsValue wrapping a LocalAsMetadata,
+/// recurse on the local SSA value, and return nullptr or "metadata !{}" on
+/// missing depending on RF_IgnoreMissingValues.
+/// 6. Else if \c V is a \a MetadataAsValue, rewrap the return of \a
+/// MapMetadata().
+/// 7. Else, compute the equivalent constant, and return it.
+inline Value *MapValue(const Value *V, ValueToValueMapTy &VM,
+ RemapFlags Flags = RF_None,
+ ValueMapTypeRemapper *TypeMapper = nullptr,
+ ValueMaterializer *Materializer = nullptr) {
+ return ValueMapper(VM, Flags, TypeMapper, Materializer).mapValue(*V);
+}
+
+/// Lookup or compute a mapping for a piece of metadata.
+///
+/// Compute and memoize a mapping for \c MD.
+///
+/// 1. If \c MD is mapped, return it.
+/// 2. Else if \a RF_NoModuleLevelChanges or \c MD is an \a MDString, return
+/// \c MD.
+/// 3. Else if \c MD is a \a ConstantAsMetadata, call \a MapValue() and
+/// re-wrap its return (returning nullptr on nullptr).
+/// 4. Else, \c MD is an \a MDNode. These are remapped, along with their
+/// transitive operands. Distinct nodes are duplicated or moved depending
+/// on \a RF_MoveDistinctNodes. Uniqued nodes are remapped like constants.
+///
+/// \note \a LocalAsMetadata is completely unsupported by \a MapMetadata.
+/// Instead, use \a MapValue() with its wrapping \a MetadataAsValue instance.
+inline Metadata *MapMetadata(const Metadata *MD, ValueToValueMapTy &VM,
+ RemapFlags Flags = RF_None,
+ ValueMapTypeRemapper *TypeMapper = nullptr,
+ ValueMaterializer *Materializer = nullptr) {
+ return ValueMapper(VM, Flags, TypeMapper, Materializer).mapMetadata(*MD);
+}
+
+/// Version of MapMetadata with type safety for MDNode.
+inline MDNode *MapMetadata(const MDNode *MD, ValueToValueMapTy &VM,
+ RemapFlags Flags = RF_None,
+ ValueMapTypeRemapper *TypeMapper = nullptr,
+ ValueMaterializer *Materializer = nullptr) {
+ return ValueMapper(VM, Flags, TypeMapper, Materializer).mapMDNode(*MD);
+}
+
+/// Convert the instruction operands from referencing the current values into
+/// those specified by VM.
+///
+/// If \a RF_IgnoreMissingLocals is set and an operand can't be found via \a
+/// MapValue(), use the old value. Otherwise assert that this doesn't happen.
+///
+/// Note that \a MapValue() only returns \c nullptr for SSA values missing from
+/// \c VM.
+inline void RemapInstruction(Instruction *I, ValueToValueMapTy &VM,
+ RemapFlags Flags = RF_None,
+ ValueMapTypeRemapper *TypeMapper = nullptr,
+ ValueMaterializer *Materializer = nullptr) {
+ ValueMapper(VM, Flags, TypeMapper, Materializer).remapInstruction(*I);
+}
+
+/// Remap the operands, metadata, arguments, and instructions of a function.
+///
+/// Calls \a MapValue() on prefix data, prologue data, and personality
+/// function; calls \a MapMetadata() on each attached MDNode; remaps the
+/// argument types using the provided \c TypeMapper; and calls \a
+/// RemapInstruction() on every instruction.
+inline void RemapFunction(Function &F, ValueToValueMapTy &VM,
+ RemapFlags Flags = RF_None,
+ ValueMapTypeRemapper *TypeMapper = nullptr,
+ ValueMaterializer *Materializer = nullptr) {
+ ValueMapper(VM, Flags, TypeMapper, Materializer).remapFunction(F);
+}
+
+/// Version of MapValue with type safety for Constant.
+inline Constant *MapValue(const Constant *V, ValueToValueMapTy &VM,
+ RemapFlags Flags = RF_None,
+ ValueMapTypeRemapper *TypeMapper = nullptr,
+ ValueMaterializer *Materializer = nullptr) {
+ return ValueMapper(VM, Flags, TypeMapper, Materializer).mapConstant(*V);
+}
} // End llvm namespace
diff --git a/include/llvm/Transforms/Vectorize.h b/include/llvm/Transforms/Vectorize.h
index aec3993d68fc..f734e299c6e9 100644
--- a/include/llvm/Transforms/Vectorize.h
+++ b/include/llvm/Transforms/Vectorize.h
@@ -139,6 +139,13 @@ Pass *createSLPVectorizerPass();
bool vectorizeBasicBlock(Pass *P, BasicBlock &BB,
const VectorizeConfig &C = VectorizeConfig());
+//===----------------------------------------------------------------------===//
+//
+// LoadStoreVectorizer - Create vector loads and stores, but leave scalar
+// operations.
+//
+Pass *createLoadStoreVectorizerPass();
+
} // End llvm namespace
#endif
diff --git a/include/llvm/Transforms/Vectorize/LoopVectorize.h b/include/llvm/Transforms/Vectorize/LoopVectorize.h
new file mode 100644
index 000000000000..e6d3e8353307
--- /dev/null
+++ b/include/llvm/Transforms/Vectorize/LoopVectorize.h
@@ -0,0 +1,103 @@
+//===---- LoopVectorize.h ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is the LLVM loop vectorizer. This pass modifies 'vectorizable' loops
+// and generates target-independent LLVM-IR.
+// The vectorizer uses the TargetTransformInfo analysis to estimate the costs
+// of instructions in order to estimate the profitability of vectorization.
+//
+// The loop vectorizer combines consecutive loop iterations into a single
+// 'wide' iteration. After this transformation the index is incremented
+// by the SIMD vector width, and not by one.
+//
+// This pass has three parts:
+// 1. The main loop pass that drives the different parts.
+// 2. LoopVectorizationLegality - A unit that checks for the legality
+// of the vectorization.
+// 3. InnerLoopVectorizer - A unit that performs the actual
+// widening of instructions.
+// 4. LoopVectorizationCostModel - A unit that checks for the profitability
+// of vectorization. It decides on the optimal vector width, which
+// can be one, if vectorization is not profitable.
+//
+//===----------------------------------------------------------------------===//
+//
+// The reduction-variable vectorization is based on the paper:
+// D. Nuzman and R. Henderson. Multi-platform Auto-vectorization.
+//
+// Variable uniformity checks are inspired by:
+// Karrenberg, R. and Hack, S. Whole Function Vectorization.
+//
+// The interleaved access vectorization is based on the paper:
+// Dorit Nuzman, Ira Rosen and Ayal Zaks. Auto-Vectorization of Interleaved
+// Data for SIMD
+//
+// Other ideas/concepts are from:
+// A. Zaks and D. Nuzman. Autovectorization in GCC-two years later.
+//
+// S. Maleki, Y. Gao, M. Garzaran, T. Wong and D. Padua. An Evaluation of
+// Vectorizing Compilers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_VECTORIZE_LOOPVECTORIZE_H
+#define LLVM_TRANSFORMS_VECTORIZE_LOOPVECTORIZE_H
+
+#include "llvm/ADT/MapVector.h"
+#include "llvm/Analysis/AliasAnalysis.h"
+#include "llvm/Analysis/AssumptionCache.h"
+#include "llvm/Analysis/BasicAliasAnalysis.h"
+#include "llvm/Analysis/BlockFrequencyInfo.h"
+#include "llvm/Analysis/DemandedBits.h"
+#include "llvm/Analysis/LoopAccessAnalysis.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/LoopPassManager.h"
+#include "llvm/Analysis/ScalarEvolution.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/PassManager.h"
+#include <functional>
+
+namespace llvm {
+
+/// The LoopVectorize Pass.
+struct LoopVectorizePass : public PassInfoMixin<LoopVectorizePass> {
+ bool DisableUnrolling = false;
+ /// If true, consider all loops for vectorization.
+ /// If false, only loops that explicitly request vectorization are
+ /// considered.
+ bool AlwaysVectorize = true;
+
+ ScalarEvolution *SE;
+ LoopInfo *LI;
+ TargetTransformInfo *TTI;
+ DominatorTree *DT;
+ BlockFrequencyInfo *BFI;
+ TargetLibraryInfo *TLI;
+ DemandedBits *DB;
+ AliasAnalysis *AA;
+ AssumptionCache *AC;
+ std::function<const LoopAccessInfo &(Loop &)> *GetLAA;
+
+ BlockFrequency ColdEntryFreq;
+
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+
+ // Shim for old PM.
+ bool runImpl(Function &F, ScalarEvolution &SE_, LoopInfo &LI_,
+ TargetTransformInfo &TTI_, DominatorTree &DT_,
+ BlockFrequencyInfo &BFI_, TargetLibraryInfo *TLI_,
+ DemandedBits &DB_, AliasAnalysis &AA_, AssumptionCache &AC_,
+ std::function<const LoopAccessInfo &(Loop &)> &GetLAA_);
+
+ bool processLoop(Loop *L);
+};
+}
+
+#endif // LLVM_TRANSFORMS_VECTORIZE_LOOPVECTORIZE_H
diff --git a/include/llvm/Transforms/Vectorize/SLPVectorizer.h b/include/llvm/Transforms/Vectorize/SLPVectorizer.h
new file mode 100644
index 000000000000..3a5b42411d35
--- /dev/null
+++ b/include/llvm/Transforms/Vectorize/SLPVectorizer.h
@@ -0,0 +1,113 @@
+//===---- SLPVectorizer.h ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// This pass implements the Bottom Up SLP vectorizer. It detects consecutive
+// stores that can be put together into vector-stores. Next, it attempts to
+// construct vectorizable tree using the use-def chains. If a profitable tree
+// was found, the SLP vectorizer performs vectorization on the tree.
+//
+// The pass is inspired by the work described in the paper:
+// "Loop-Aware SLP in GCC" by Ira Rosen, Dorit Nuzman, Ayal Zaks.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_VECTORIZE_SLPVECTORIZER_H
+#define LLVM_TRANSFORMS_VECTORIZE_SLPVECTORIZER_H
+
+#include "llvm/ADT/MapVector.h"
+#include "llvm/Analysis/AliasAnalysis.h"
+#include "llvm/Analysis/AssumptionCache.h"
+#include "llvm/Analysis/DemandedBits.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/ScalarEvolution.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+/// A private "module" namespace for types and utilities used by this pass.
+/// These are implementation details and should not be used by clients.
+namespace slpvectorizer {
+class BoUpSLP;
+}
+
+struct SLPVectorizerPass : public PassInfoMixin<SLPVectorizerPass> {
+ typedef SmallVector<StoreInst *, 8> StoreList;
+ typedef MapVector<Value *, StoreList> StoreListMap;
+ typedef SmallVector<WeakVH, 8> WeakVHList;
+ typedef MapVector<Value *, WeakVHList> WeakVHListMap;
+
+ ScalarEvolution *SE = nullptr;
+ TargetTransformInfo *TTI = nullptr;
+ TargetLibraryInfo *TLI = nullptr;
+ AliasAnalysis *AA = nullptr;
+ LoopInfo *LI = nullptr;
+ DominatorTree *DT = nullptr;
+ AssumptionCache *AC = nullptr;
+ DemandedBits *DB = nullptr;
+ const DataLayout *DL = nullptr;
+
+public:
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+
+ // Glue for old PM.
+ bool runImpl(Function &F, ScalarEvolution *SE_, TargetTransformInfo *TTI_,
+ TargetLibraryInfo *TLI_, AliasAnalysis *AA_, LoopInfo *LI_,
+ DominatorTree *DT_, AssumptionCache *AC_, DemandedBits *DB_);
+
+private:
+ /// \brief Collect store and getelementptr instructions and organize them
+ /// according to the underlying object of their pointer operands. We sort the
+ /// instructions by their underlying objects to reduce the cost of
+ /// consecutive access queries.
+ ///
+ /// TODO: We can further reduce this cost if we flush the chain creation
+ /// every time we run into a memory barrier.
+ void collectSeedInstructions(BasicBlock *BB);
+
+ /// \brief Try to vectorize a chain that starts at two arithmetic instrs.
+ bool tryToVectorizePair(Value *A, Value *B, slpvectorizer::BoUpSLP &R);
+
+ /// \brief Try to vectorize a list of operands.
+ /// \@param BuildVector A list of users to ignore for the purpose of
+ /// scheduling and that don't need extracting.
+ /// \returns true if a value was vectorized.
+ bool tryToVectorizeList(ArrayRef<Value *> VL, slpvectorizer::BoUpSLP &R,
+ ArrayRef<Value *> BuildVector = None,
+ bool allowReorder = false);
+
+ /// \brief Try to vectorize a chain that may start at the operands of \V;
+ bool tryToVectorize(BinaryOperator *V, slpvectorizer::BoUpSLP &R);
+
+ /// \brief Vectorize the store instructions collected in Stores.
+ bool vectorizeStoreChains(slpvectorizer::BoUpSLP &R);
+
+ /// \brief Vectorize the index computations of the getelementptr instructions
+ /// collected in GEPs.
+ bool vectorizeGEPIndices(BasicBlock *BB, slpvectorizer::BoUpSLP &R);
+
+ /// \brief Scan the basic block and look for patterns that are likely to start
+ /// a vectorization chain.
+ bool vectorizeChainsInBlock(BasicBlock *BB, slpvectorizer::BoUpSLP &R);
+
+ bool vectorizeStoreChain(ArrayRef<Value *> Chain, int CostThreshold,
+ slpvectorizer::BoUpSLP &R, unsigned VecRegSize);
+
+ bool vectorizeStores(ArrayRef<StoreInst *> Stores, int costThreshold,
+ slpvectorizer::BoUpSLP &R);
+
+ /// The store instructions in a basic block organized by base pointer.
+ StoreListMap Stores;
+
+ /// The getelementptr instructions in a basic block organized by base pointer.
+ WeakVHListMap GEPs;
+};
+}
+
+#endif // LLVM_TRANSFORMS_VECTORIZE_SLPVECTORIZER_H
diff --git a/include/llvm/module.modulemap b/include/llvm/module.modulemap
index d74ada6faa61..cc1895011dc3 100644
--- a/include/llvm/module.modulemap
+++ b/include/llvm/module.modulemap
@@ -3,9 +3,6 @@ module LLVM_Analysis {
umbrella "Analysis"
module * { export * }
- // FIXME: Why is this excluded?
- exclude header "Analysis/BlockFrequencyInfoImpl.h"
-
// This is intended for (repeated) textual inclusion.
textual header "Analysis/TargetLibraryInfo.def"
}
@@ -37,12 +34,9 @@ module LLVM_Backend {
module Target {
umbrella "Target"
module * { export * }
- }
- // FIXME: Where should this go?
- module Analysis_BlockFrequencyInfoImpl {
- header "Analysis/BlockFrequencyInfoImpl.h"
- export *
+ // This is intended for (repeated) textual inclusion.
+ textual header "Target/TargetOpcodes.def"
}
}
@@ -90,6 +84,17 @@ module LLVM_DebugInfo_PDB_DIA {
module * { export * }
}
+module LLVM_DebugInfo_CodeView {
+ requires cplusplus
+
+ umbrella "DebugInfo/CodeView"
+ module * { export * }
+
+ // These are intended for (repeated) textual inclusion.
+ textual header "DebugInfo/CodeView/TypeRecords.def"
+ textual header "DebugInfo/CodeView/CVSymbolTypes.def"
+}
+
module LLVM_ExecutionEngine {
requires cplusplus
@@ -101,21 +106,64 @@ module LLVM_ExecutionEngine {
// Exclude these; they're intended to be included into only a single
// translation unit (or none) and aren't part of this module.
- exclude header "ExecutionEngine/JIT.h"
exclude header "ExecutionEngine/MCJIT.h"
exclude header "ExecutionEngine/Interpreter.h"
exclude header "ExecutionEngine/OrcMCJITReplacement.h"
}
-module LLVM_IR {
- requires cplusplus
+module LLVM_Pass {
+ module Pass {
+ // PassSupport.h and PassAnalysisSupport.h are made available only through
+ // Pass.h.
+ header "Pass.h"
+ header "PassSupport.h"
+ header "PassAnalysisSupport.h"
+ export *
+ }
- // FIXME: Is this the right place for these?
- module Pass { header "Pass.h" export * }
- module PassSupport { header "PassSupport.h" export * }
- module PassAnalysisSupport { header "PassAnalysisSupport.h" export * }
module PassRegistry { header "PassRegistry.h" export * }
module InitializePasses { header "InitializePasses.h" export * }
+}
+
+module LLVM_intrinsic_gen {
+ requires cplusplus
+
+ // Delay building the modules containing dependencies to Attributes.h and
+ // Intrinsics.h because they need to be generated by tablegen first.
+
+ // Attributes.h
+ module IR_Argument { header "IR/Argument.h" export * }
+ module IR_Attributes { header "IR/Attributes.h" export * }
+ module IR_CallSite { header "IR/CallSite.h" export * }
+ module IR_ConstantFolder { header "IR/ConstantFolder.h" export * }
+ module IR_NoFolder { header "IR/NoFolder.h" export * }
+ module IR_Module { header "IR/Module.h" export * }
+ module IR_ModuleSummaryIndex { header "IR/ModuleSummaryIndex.h" export * }
+ module IR_Function { header "IR/Function.h" export * }
+ module IR_InstrTypes { header "IR/InstrTypes.h" export * }
+ module IR_Instructions { header "IR/Instructions.h" export * }
+
+
+ // Intrinsics.h
+ module IR_CFG { header "IR/CFG.h" export * }
+ module IR_ConstantRange { header "IR/ConstantRange.h" export * }
+ module IR_Dominators { header "IR/Dominators.h" export * }
+ module IR_IRBuilder { header "IR/IRBuilder.h" export * }
+ module IR_PassManager { header "IR/PassManager.h" export * }
+ module IR_PredIteratorCache { header "IR/PredIteratorCache.h" export * }
+ module IR_Verifier { header "IR/Verifier.h" export * }
+ module IR_InstIterator { header "IR/InstIterator.h" export * }
+ module IR_InstVisitor { header "IR/InstVisitor.h" export * }
+ module IR_Intrinsics { header "IR/Intrinsics.h" export * }
+ module IR_IntrinsicInst { header "IR/IntrinsicInst.h" export * }
+ module IR_PatternMatch { header "IR/PatternMatch.h" export * }
+ module IR_Statepoint { header "IR/Statepoint.h" export * }
+
+ export *
+}
+
+module LLVM_IR {
+ requires cplusplus
umbrella "IR"
module * { export * }
@@ -154,6 +202,16 @@ module LLVM_Object {
}
module LLVM_Option { requires cplusplus umbrella "Option" module * { export * } }
+
+module LLVM_ProfileData {
+ requires cplusplus
+
+ umbrella "ProfileData"
+ module * { export * }
+
+ textual header "ProfileData/InstrProfData.inc"
+}
+
module LLVM_TableGen { requires cplusplus umbrella "TableGen" module * { export * } }
module LLVM_Transforms {
@@ -184,9 +242,6 @@ module LLVM_Utils {
// Exclude this; it's only included on Solaris.
exclude header "Support/Solaris.h"
- // Exclude this; it's only included on AIX and fundamentally non-modular.
- exclude header "Support/AIXDataTypesFix.h"
-
// Exclude this; it's fundamentally non-modular.
exclude header "Support/PluginLoader.h"
@@ -195,12 +250,17 @@ module LLVM_Utils {
// These are intended for textual inclusion.
textual header "Support/ARMTargetParser.def"
+ textual header "Support/AArch64TargetParser.def"
textual header "Support/Dwarf.def"
+ textual header "Support/MachO.def"
textual header "Support/ELFRelocs/AArch64.def"
+ textual header "Support/ELFRelocs/AMDGPU.def"
textual header "Support/ELFRelocs/ARM.def"
textual header "Support/ELFRelocs/AVR.def"
+ textual header "Support/ELFRelocs/BPF.def"
textual header "Support/ELFRelocs/Hexagon.def"
textual header "Support/ELFRelocs/i386.def"
+ textual header "Support/ELFRelocs/Lanai.def"
textual header "Support/ELFRelocs/Mips.def"
textual header "Support/ELFRelocs/PowerPC64.def"
textual header "Support/ELFRelocs/PowerPC.def"