aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-05-22 19:43:28 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-05-22 19:43:28 +0000
commitb5630dbadf9a2a06754194387d6b0fd9962a67f1 (patch)
tree3fe1e2bc0dc2823ab21f06959fbb3eaca317ea29
parent7af96fb3afd6725a2824a0a5ca5dad34e5e0b056 (diff)
downloadsrc-b5630dbadf9a2a06754194387d6b0fd9962a67f1.tar.gz
src-b5630dbadf9a2a06754194387d6b0fd9962a67f1.zip
Vendor import of llvm trunk r303571:vendor/llvm/llvm-trunk-r303571
Notes
Notes: svn path=/vendor/llvm/dist/; revision=318663 svn path=/vendor/llvm/llvm-trunk-r303571/; revision=318664; tag=vendor/llvm/llvm-trunk-r303571
-rw-r--r--docs/CMake.rst4
-rw-r--r--docs/GetElementPtr.rst12
-rw-r--r--docs/LangRef.rst6
-rw-r--r--include/llvm/ADT/APInt.h17
-rw-r--r--include/llvm/ADT/SmallPtrSet.h2
-rw-r--r--include/llvm/ADT/Statistic.h12
-rw-r--r--include/llvm/ADT/Triple.h10
-rw-r--r--include/llvm/Analysis/MemorySSA.h113
-rw-r--r--include/llvm/Analysis/ScalarEvolution.h26
-rw-r--r--include/llvm/Analysis/TargetLibraryInfo.h13
-rw-r--r--include/llvm/Analysis/ValueTracking.h37
-rw-r--r--include/llvm/CodeGen/LiveIntervalAnalysis.h2
-rw-r--r--include/llvm/CodeGen/MachineValueType.h234
-rw-r--r--include/llvm/CodeGen/Passes.h51
-rw-r--r--include/llvm/CodeGen/StackProtector.h12
-rw-r--r--include/llvm/CodeGen/ValueTypes.td220
-rw-r--r--include/llvm/DebugInfo/CodeView/CVRecord.h4
-rw-r--r--include/llvm/DebugInfo/CodeView/CVTypeDumper.h61
-rw-r--r--include/llvm/DebugInfo/CodeView/CVTypeVisitor.h35
-rw-r--r--include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h (renamed from include/llvm/DebugInfo/CodeView/RandomAccessTypeVisitor.h)45
-rw-r--r--include/llvm/DebugInfo/CodeView/SymbolDumper.h8
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeCollection.h38
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeDatabase.h19
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h18
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeIndex.h13
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeSerializer.h2
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeStreamMerger.h5
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeTableCollection.h42
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h2
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h5
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFContext.h8
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFRelocMap.h2
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h5
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFUnit.h16
-rw-r--r--include/llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h1
-rw-r--r--include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h2
-rw-r--r--include/llvm/IR/Argument.h3
-rw-r--r--include/llvm/IR/BasicBlock.h6
-rw-r--r--include/llvm/IR/Constant.h2
-rw-r--r--include/llvm/IR/Constants.h14
-rw-r--r--include/llvm/IR/DerivedUser.h41
-rw-r--r--include/llvm/IR/Function.h2
-rw-r--r--include/llvm/IR/GlobalValue.h8
-rw-r--r--include/llvm/IR/GlobalVariable.h2
-rw-r--r--include/llvm/IR/InlineAsm.h3
-rw-r--r--include/llvm/IR/InstrTypes.h10
-rw-r--r--include/llvm/IR/Instruction.def10
-rw-r--r--include/llvm/IR/Instruction.h14
-rw-r--r--include/llvm/IR/Instructions.h12
-rw-r--r--include/llvm/IR/Metadata.h3
-rw-r--r--include/llvm/IR/OperandTraits.h6
-rw-r--r--include/llvm/IR/Operator.h7
-rw-r--r--include/llvm/IR/PatternMatch.h16
-rw-r--r--include/llvm/IR/User.h6
-rw-r--r--include/llvm/IR/Value.def17
-rw-r--r--include/llvm/IR/Value.h21
-rw-r--r--include/llvm/InitializePasses.h1
-rw-r--r--include/llvm/Object/Binary.h4
-rw-r--r--include/llvm/Object/COFFImportFile.h34
-rw-r--r--include/llvm/Object/COFFModuleDefinition.h49
-rw-r--r--include/llvm/Object/Decompressor.h5
-rw-r--r--include/llvm/Object/ELF.h5
-rw-r--r--include/llvm/Object/RelocVisitor.h231
-rw-r--r--include/llvm/Object/WindowsResource.h82
-rw-r--r--include/llvm/PassInfo.h21
-rw-r--r--include/llvm/PassSupport.h6
-rw-r--r--include/llvm/Support/BinaryStreamReader.h21
-rw-r--r--include/llvm/Support/BinaryStreamRef.h150
-rw-r--r--include/llvm/Support/BinaryStreamWriter.h15
-rw-r--r--include/llvm/Support/FileSystem.h2
-rw-r--r--include/llvm/Target/GlobalISel/SelectionDAGCompat.td1
-rw-r--r--include/llvm/Transforms/IPO/FunctionImport.h3
-rw-r--r--include/llvm/Transforms/Scalar/GVNExpression.h16
-rw-r--r--include/llvm/Transforms/Utils/SimplifyLibCalls.h4
-rw-r--r--lib/Analysis/BasicAliasAnalysis.cpp5
-rw-r--r--lib/Analysis/BranchProbabilityInfo.cpp49
-rw-r--r--lib/Analysis/CallGraphSCCPass.cpp6
-rw-r--r--lib/Analysis/InstructionSimplify.cpp74
-rw-r--r--lib/Analysis/MemorySSA.cpp23
-rw-r--r--lib/Analysis/ScalarEvolution.cpp51
-rw-r--r--lib/Analysis/TargetLibraryInfo.cpp16
-rw-r--r--lib/Analysis/ValueTracking.cpp122
-rw-r--r--lib/AsmParser/LLParser.cpp8
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.cpp4
-rw-r--r--lib/Bitcode/Reader/ValueList.cpp4
-rw-r--r--lib/CodeGen/AsmPrinter/CodeViewDebug.cpp41
-rw-r--r--lib/CodeGen/AtomicExpandPass.cpp22
-rw-r--r--lib/CodeGen/CMakeLists.txt1
-rw-r--r--lib/CodeGen/CodeGen.cpp1
-rw-r--r--lib/CodeGen/CodeGenPrepare.cpp27
-rw-r--r--lib/CodeGen/DwarfEHPrepare.cpp32
-rw-r--r--lib/CodeGen/GlobalISel/IRTranslator.cpp26
-rw-r--r--lib/CodeGen/GlobalISel/InstructionSelector.cpp2
-rw-r--r--lib/CodeGen/InterleavedAccessPass.cpp19
-rw-r--r--lib/CodeGen/LLVMTargetMachine.cpp20
-rw-r--r--lib/CodeGen/LiveRangeShrink.cpp211
-rw-r--r--lib/CodeGen/LowerEmuTLS.cpp22
-rw-r--r--lib/CodeGen/MachineBlockPlacement.cpp45
-rw-r--r--lib/CodeGen/MachineModuleInfo.cpp4
-rw-r--r--lib/CodeGen/PrologEpilogInserter.cpp42
-rw-r--r--lib/CodeGen/RegisterCoalescer.cpp8
-rw-r--r--lib/CodeGen/SafeStack.cpp22
-rw-r--r--lib/CodeGen/SafeStackColoring.cpp3
-rw-r--r--lib/CodeGen/SelectionDAG/DAGCombiner.cpp436
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAG.cpp49
-rw-r--r--lib/CodeGen/SelectionDAG/StatepointLowering.cpp4
-rw-r--r--lib/CodeGen/StackProtector.cpp13
-rw-r--r--lib/CodeGen/TargetPassConfig.cpp21
-rw-r--r--lib/CodeGen/WinEHPrepare.cpp10
-rw-r--r--lib/DebugInfo/CodeView/CMakeLists.txt7
-rw-r--r--lib/DebugInfo/CodeView/CVTypeDumper.cpp61
-rw-r--r--lib/DebugInfo/CodeView/CVTypeVisitor.cpp188
-rw-r--r--lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp229
-rw-r--r--lib/DebugInfo/CodeView/RandomAccessTypeVisitor.cpp89
-rw-r--r--lib/DebugInfo/CodeView/SymbolDumper.cpp13
-rw-r--r--lib/DebugInfo/CodeView/TypeDatabase.cpp75
-rw-r--r--lib/DebugInfo/CodeView/TypeDumpVisitor.cpp13
-rw-r--r--lib/DebugInfo/CodeView/TypeIndex.cpp27
-rw-r--r--lib/DebugInfo/CodeView/TypeSerializer.cpp33
-rw-r--r--lib/DebugInfo/CodeView/TypeStreamMerger.cpp14
-rw-r--r--lib/DebugInfo/CodeView/TypeTableCollection.cpp83
-rw-r--r--lib/DebugInfo/DWARF/DWARFContext.cpp34
-rw-r--r--lib/DebugInfo/DWARF/DWARFUnit.cpp31
-rw-r--r--lib/DebugInfo/PDB/Native/DbiStream.cpp8
-rw-r--r--lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp1
-rw-r--r--lib/DebugInfo/PDB/Native/PDBTypeServerHandler.cpp1
-rw-r--r--lib/DebugInfo/PDB/Native/TpiStream.cpp6
-rw-r--r--lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp2
-rw-r--r--lib/Demangle/ItaniumDemangle.cpp2
-rw-r--r--lib/IR/Attributes.cpp2
-rw-r--r--lib/IR/AutoUpgrade.cpp1
-rw-r--r--lib/IR/Constants.cpp15
-rw-r--r--lib/IR/ConstantsContext.h20
-rw-r--r--lib/IR/DataLayout.cpp2
-rw-r--r--lib/IR/Function.cpp2
-rw-r--r--lib/IR/IRBuilder.cpp5
-rw-r--r--lib/IR/InlineAsm.cpp4
-rw-r--r--lib/IR/Instruction.cpp2
-rw-r--r--lib/IR/Instructions.cpp27
-rw-r--r--lib/IR/LLVMContextImpl.cpp21
-rw-r--r--lib/IR/PassRegistry.cpp2
-rw-r--r--lib/IR/User.cpp10
-rw-r--r--lib/IR/Value.cpp29
-rw-r--r--lib/IR/ValueTypes.cpp2
-rw-r--r--lib/IR/Verifier.cpp6
-rw-r--r--lib/LTO/ThinLTOCodeGenerator.cpp72
-rw-r--r--lib/Linker/IRMover.cpp26
-rw-r--r--lib/Object/Binary.cpp4
-rw-r--r--lib/Object/CMakeLists.txt3
-rw-r--r--lib/Object/COFFImportFile.cpp527
-rw-r--r--lib/Object/COFFModuleDefinition.cpp319
-rw-r--r--lib/Object/Decompressor.cpp5
-rw-r--r--lib/Object/WindowsResource.cpp90
-rw-r--r--lib/Passes/PassBuilder.cpp9
-rw-r--r--lib/Support/APInt.cpp253
-rw-r--r--lib/Support/BinaryStreamReader.cpp18
-rw-r--r--lib/Support/BinaryStreamRef.cpp137
-rw-r--r--lib/Support/BinaryStreamWriter.cpp11
-rw-r--r--lib/Support/CMakeLists.txt1
-rw-r--r--lib/Support/FormattedStream.cpp1
-rw-r--r--lib/Support/Triple.cpp18
-rw-r--r--lib/Target/AArch64/AArch64InstrInfo.td10
-rw-r--r--lib/Target/AArch64/AArch64Subtarget.cpp5
-rw-r--r--lib/Target/AArch64/AArch64Subtarget.h6
-rw-r--r--lib/Target/AArch64/AArch64TargetMachine.cpp11
-rw-r--r--lib/Target/AMDGPU/AMDGPU.h20
-rw-r--r--lib/Target/AMDGPU/AMDGPUAnnotateKernelFeatures.cpp15
-rw-r--r--lib/Target/AMDGPU/AMDGPUCallLowering.h3
-rw-r--r--lib/Target/AMDGPU/AMDGPUCallingConv.td50
-rw-r--r--lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp24
-rw-r--r--lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp120
-rw-r--r--lib/Target/AMDGPU/AMDGPUISelLowering.cpp163
-rw-r--r--lib/Target/AMDGPU/AMDGPUISelLowering.h5
-rw-r--r--lib/Target/AMDGPU/AMDGPUInstrInfo.td2
-rw-r--r--lib/Target/AMDGPU/AMDGPULowerIntrinsics.cpp21
-rw-r--r--lib/Target/AMDGPU/AMDGPUMCInstLower.cpp8
-rw-r--r--lib/Target/AMDGPU/AMDGPUMachineFunction.cpp17
-rw-r--r--lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp31
-rw-r--r--lib/Target/AMDGPU/AMDGPURegisterInfo.cpp45
-rw-r--r--lib/Target/AMDGPU/AMDGPURegisterInfo.h3
-rw-r--r--lib/Target/AMDGPU/AMDGPUTargetMachine.cpp20
-rw-r--r--lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp25
-rw-r--r--lib/Target/AMDGPU/BUFInstructions.td4
-rw-r--r--lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp14
-rw-r--r--lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h2
-rw-r--r--lib/Target/AMDGPU/GCNRegPressure.cpp146
-rw-r--r--lib/Target/AMDGPU/GCNRegPressure.h2
-rw-r--r--lib/Target/AMDGPU/R600ClauseMergePass.cpp6
-rw-r--r--lib/Target/AMDGPU/R600ControlFlowFinalizer.cpp6
-rw-r--r--lib/Target/AMDGPU/R600ExpandSpecialInstrs.cpp6
-rw-r--r--lib/Target/AMDGPU/R600OptimizeVectorRegisters.cpp6
-rw-r--r--lib/Target/AMDGPU/R600Packetizer.cpp6
-rw-r--r--lib/Target/AMDGPU/R600RegisterInfo.cpp12
-rw-r--r--lib/Target/AMDGPU/R600RegisterInfo.h2
-rw-r--r--lib/Target/AMDGPU/SIFrameLowering.cpp20
-rw-r--r--lib/Target/AMDGPU/SIFrameLowering.h2
-rw-r--r--lib/Target/AMDGPU/SIISelLowering.cpp174
-rw-r--r--lib/Target/AMDGPU/SIISelLowering.h11
-rw-r--r--lib/Target/AMDGPU/SIInstrFormats.td16
-rw-r--r--lib/Target/AMDGPU/SILoadStoreOptimizer.cpp8
-rw-r--r--lib/Target/AMDGPU/SIMachineFunctionInfo.cpp19
-rw-r--r--lib/Target/AMDGPU/SIMachineFunctionInfo.h5
-rw-r--r--lib/Target/AMDGPU/SIPeepholeSDWA.cpp45
-rw-r--r--lib/Target/AMDGPU/SIRegisterInfo.cpp120
-rw-r--r--lib/Target/AMDGPU/SIRegisterInfo.h14
-rw-r--r--lib/Target/AMDGPU/SOPInstructions.td18
-rw-r--r--lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp13
-rw-r--r--lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h1
-rw-r--r--lib/Target/ARM/ARMTargetMachine.cpp4
-rw-r--r--lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp2
-rw-r--r--lib/Target/Hexagon/HexagonTargetMachine.cpp2
-rw-r--r--lib/Target/Mips/Mips.h12
-rw-r--r--lib/Target/Mips/Mips16HardFloat.cpp17
-rw-r--r--lib/Target/Mips/MipsDelaySlotFiller.cpp12
-rw-r--r--lib/Target/Mips/MipsISelLowering.cpp87
-rw-r--r--lib/Target/Mips/MipsLongBranch.cpp16
-rw-r--r--lib/Target/Mips/MipsModuleISelDAGToDAG.cpp18
-rw-r--r--lib/Target/Mips/MipsOptimizePICCall.cpp6
-rw-r--r--lib/Target/Mips/MipsOs16.cpp4
-rw-r--r--lib/Target/Mips/MipsTargetMachine.cpp24
-rw-r--r--lib/Target/PowerPC/PPCISelLowering.cpp15
-rw-r--r--lib/Target/PowerPC/PPCInstrAltivec.td8
-rw-r--r--lib/Target/PowerPC/PPCInstrInfo.cpp50
-rw-r--r--lib/Target/PowerPC/PPCTargetMachine.cpp2
-rw-r--r--lib/Target/Sparc/DelaySlotFiller.cpp2
-rwxr-xr-xlib/Target/Sparc/LeonPasses.cpp17
-rwxr-xr-xlib/Target/Sparc/LeonPasses.h11
-rw-r--r--lib/Target/Sparc/Sparc.h2
-rw-r--r--lib/Target/Sparc/SparcTargetMachine.cpp14
-rw-r--r--lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp2
-rw-r--r--lib/Target/X86/X86.td3
-rw-r--r--lib/Target/X86/X86CallingConv.td42
-rw-r--r--lib/Target/X86/X86FastISel.cpp7
-rw-r--r--lib/Target/X86/X86FixupLEAs.cpp269
-rw-r--r--lib/Target/X86/X86ISelLowering.cpp162
-rw-r--r--lib/Target/X86/X86InstrAVX512.td132
-rw-r--r--lib/Target/X86/X86InstrFragmentsSIMD.td6
-rw-r--r--lib/Target/X86/X86InstrInfo.cpp4
-rw-r--r--lib/Target/X86/X86InstrInfo.td13
-rw-r--r--lib/Target/X86/X86InstrTSX.td5
-rw-r--r--lib/Target/X86/X86InstructionSelector.cpp24
-rw-r--r--lib/Target/X86/X86LegalizerInfo.cpp19
-rw-r--r--lib/Target/X86/X86RegisterInfo.td4
-rw-r--r--lib/Target/X86/X86Subtarget.cpp7
-rw-r--r--lib/Target/X86/X86Subtarget.h15
-rw-r--r--lib/Target/X86/X86TargetMachine.cpp15
-rw-r--r--lib/Target/X86/X86TargetTransformInfo.cpp36
-rw-r--r--lib/Target/XCore/XCoreTargetMachine.cpp2
-rw-r--r--lib/Transforms/IPO/PassManagerBuilder.cpp10
-rw-r--r--lib/Transforms/InstCombine/InstCombineAddSub.cpp30
-rw-r--r--lib/Transforms/InstCombine/InstCombineAndOrXor.cpp79
-rw-r--r--lib/Transforms/InstCombine/InstCombineCasts.cpp19
-rw-r--r--lib/Transforms/InstCombine/InstCombineCompares.cpp128
-rw-r--r--lib/Transforms/InstCombine/InstCombineInternal.h54
-rw-r--r--lib/Transforms/InstCombine/InstCombineMulDivRem.cpp11
-rw-r--r--lib/Transforms/Scalar/EarlyCSE.cpp2
-rw-r--r--lib/Transforms/Scalar/GVN.cpp2
-rw-r--r--lib/Transforms/Scalar/JumpThreading.cpp33
-rw-r--r--lib/Transforms/Scalar/LoadCombine.cpp2
-rw-r--r--lib/Transforms/Scalar/LoopIdiomRecognize.cpp71
-rw-r--r--lib/Transforms/Scalar/LoopPredication.cpp86
-rw-r--r--lib/Transforms/Scalar/LoopRotation.cpp2
-rw-r--r--lib/Transforms/Scalar/LoopStrengthReduce.cpp1
-rw-r--r--lib/Transforms/Scalar/NewGVN.cpp815
-rw-r--r--lib/Transforms/Scalar/Reassociate.cpp2
-rw-r--r--lib/Transforms/Scalar/SROA.cpp8
-rw-r--r--lib/Transforms/Scalar/StraightLineStrengthReduce.cpp2
-rw-r--r--lib/Transforms/Utils/CloneFunction.cpp2
-rw-r--r--lib/Transforms/Utils/SimplifyCFG.cpp6
-rw-r--r--lib/Transforms/Utils/SimplifyLibCalls.cpp82
-rw-r--r--lib/Transforms/Vectorize/LoopVectorize.cpp2
-rw-r--r--lib/Transforms/Vectorize/SLPVectorizer.cpp4
-rw-r--r--test/Analysis/BranchProbabilityInfo/basic.ll42
-rw-r--r--test/Analysis/BranchProbabilityInfo/deopt-intrinsic.ll4
-rw-r--r--test/Analysis/BranchProbabilityInfo/noreturn.ll22
-rw-r--r--test/Analysis/CostModel/X86/ctlz.ll156
-rw-r--r--test/Analysis/CostModel/X86/ctpop.ll63
-rw-r--r--test/Analysis/CostModel/X86/cttz.ll131
-rw-r--r--test/Analysis/ScalarEvolution/nsw.ll2
-rw-r--r--test/Analysis/ScalarEvolution/trip-count-pow2.ll10
-rw-r--r--test/CodeGen/AArch64/arm64-ccmp.ll2
-rw-r--r--test/CodeGen/AArch64/arm64-misched-multimmo.ll2
-rw-r--r--test/CodeGen/AMDGPU/GlobalISel/amdgpu-irtranslator.ll5
-rw-r--r--test/CodeGen/AMDGPU/add.i16.ll3
-rw-r--r--test/CodeGen/AMDGPU/add.v2i16.ll8
-rw-r--r--test/CodeGen/AMDGPU/bfe-patterns.ll4
-rw-r--r--test/CodeGen/AMDGPU/coalescer_distribute.ll4
-rw-r--r--test/CodeGen/AMDGPU/ctlz.ll3
-rw-r--r--test/CodeGen/AMDGPU/ctlz_zero_undef.ll3
-rw-r--r--test/CodeGen/AMDGPU/ds_write2.ll4
-rw-r--r--test/CodeGen/AMDGPU/endcf-loop-header.ll8
-rw-r--r--test/CodeGen/AMDGPU/fmed3.ll8
-rw-r--r--test/CodeGen/AMDGPU/frame-index-elimination.ll124
-rw-r--r--test/CodeGen/AMDGPU/function-args.ll734
-rw-r--r--test/CodeGen/AMDGPU/function-returns.ll514
-rw-r--r--test/CodeGen/AMDGPU/hsa-func.ll13
-rw-r--r--test/CodeGen/AMDGPU/i1-copy-phi.ll6
-rw-r--r--test/CodeGen/AMDGPU/inline-asm.ll2
-rw-r--r--test/CodeGen/AMDGPU/llvm.amdgcn.atomic.dec.ll2
-rw-r--r--test/CodeGen/AMDGPU/llvm.amdgcn.atomic.inc.ll2
-rw-r--r--test/CodeGen/AMDGPU/llvm.amdgcn.s.barrier.ll6
-rw-r--r--test/CodeGen/AMDGPU/lshl64-to-32.ll45
-rw-r--r--test/CodeGen/AMDGPU/packed-op-sel.ll431
-rw-r--r--test/CodeGen/AMDGPU/regcoalesce-prune.mir31
-rw-r--r--test/CodeGen/AMDGPU/sdwa-peephole.ll50
-rw-r--r--test/CodeGen/AMDGPU/shift-and-i64-ubfe.ll11
-rw-r--r--test/CodeGen/AMDGPU/srl.ll3
-rw-r--r--test/CodeGen/AMDGPU/sub.i16.ll2
-rw-r--r--test/CodeGen/AMDGPU/subreg_interference.mir8
-rw-r--r--test/CodeGen/AMDGPU/vgpr-spill-emergency-stack-slot-compute.ll4
-rw-r--r--test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll30
-rw-r--r--test/CodeGen/ARM/ifcvt-branch-weight-bug.ll2
-rw-r--r--test/CodeGen/Generic/opt-codegen-no-target-machine.ll3
-rw-r--r--test/CodeGen/Mips/dins.ll70
-rw-r--r--test/CodeGen/Mips/micromips-attr.ll39
-rw-r--r--test/CodeGen/Mips/mips64-f128.ll9
-rw-r--r--test/CodeGen/NVPTX/sched1.ll4
-rw-r--r--test/CodeGen/NVPTX/sched2.ll4
-rw-r--r--test/CodeGen/NVPTX/vec8.ll2
-rw-r--r--test/CodeGen/PowerPC/opt-cmp-inst-cr0-live.ll33
-rw-r--r--test/CodeGen/PowerPC/shift128.ll92
-rw-r--r--test/CodeGen/SPARC/LeonItinerariesUT.ll4
-rw-r--r--test/CodeGen/X86/2007-01-08-InstrSched.ll4
-rw-r--r--test/CodeGen/X86/GlobalISel/add-scalar.ll4
-rw-r--r--test/CodeGen/X86/GlobalISel/add-vec.ll111
-rw-r--r--test/CodeGen/X86/GlobalISel/binop.ll8
-rw-r--r--test/CodeGen/X86/GlobalISel/br.ll2
-rw-r--r--test/CodeGen/X86/GlobalISel/callingconv.ll8
-rw-r--r--test/CodeGen/X86/GlobalISel/cmp.ll2
-rw-r--r--test/CodeGen/X86/GlobalISel/constant.ll2
-rw-r--r--test/CodeGen/X86/GlobalISel/ext-x86-64.ll2
-rw-r--r--test/CodeGen/X86/GlobalISel/ext.ll4
-rw-r--r--test/CodeGen/X86/GlobalISel/frameIndex.ll12
-rw-r--r--test/CodeGen/X86/GlobalISel/gep.ll4
-rw-r--r--test/CodeGen/X86/GlobalISel/legalize-add-v128.mir119
-rw-r--r--test/CodeGen/X86/GlobalISel/legalize-add-v256.mir157
-rw-r--r--test/CodeGen/X86/GlobalISel/legalize-add-v512.mir139
-rw-r--r--test/CodeGen/X86/GlobalISel/legalize-sub-v128.mir119
-rw-r--r--test/CodeGen/X86/GlobalISel/legalize-sub-v256.mir120
-rw-r--r--test/CodeGen/X86/GlobalISel/legalize-sub-v512.mir120
-rw-r--r--test/CodeGen/X86/GlobalISel/memop-scalar-x32.ll4
-rw-r--r--test/CodeGen/X86/GlobalISel/memop-scalar.ll4
-rw-r--r--test/CodeGen/X86/GlobalISel/memop-vec.ll4
-rw-r--r--test/CodeGen/X86/GlobalISel/mul-scalar.ll2
-rw-r--r--test/CodeGen/X86/GlobalISel/mul-vec.ll2
-rw-r--r--test/CodeGen/X86/GlobalISel/regbankselect-AVX2.mir55
-rw-r--r--test/CodeGen/X86/GlobalISel/regbankselect-AVX512.mir54
-rw-r--r--test/CodeGen/X86/GlobalISel/select-add-v128.mir195
-rw-r--r--test/CodeGen/X86/GlobalISel/select-add-v256.mir185
-rw-r--r--test/CodeGen/X86/GlobalISel/select-add-v512.mir130
-rw-r--r--test/CodeGen/X86/GlobalISel/select-br.mir4
-rw-r--r--test/CodeGen/X86/GlobalISel/select-cmp.mir2
-rw-r--r--test/CodeGen/X86/GlobalISel/select-constant.mir2
-rw-r--r--test/CodeGen/X86/GlobalISel/select-ext-x86-64.mir2
-rw-r--r--test/CodeGen/X86/GlobalISel/select-ext.mir4
-rw-r--r--test/CodeGen/X86/GlobalISel/select-frameIndex.mir6
-rw-r--r--test/CodeGen/X86/GlobalISel/select-gep.mir2
-rw-r--r--test/CodeGen/X86/GlobalISel/select-sub-v128.mir195
-rw-r--r--test/CodeGen/X86/GlobalISel/select-sub-v256.mir185
-rw-r--r--test/CodeGen/X86/GlobalISel/select-sub-v512.mir130
-rw-r--r--test/CodeGen/X86/GlobalISel/select-trunc.mir92
-rw-r--r--test/CodeGen/X86/GlobalISel/sub-vec.ll111
-rw-r--r--test/CodeGen/X86/GlobalISel/trunc.ll2
-rw-r--r--test/CodeGen/X86/O0-pipeline.ll2
-rw-r--r--test/CodeGen/X86/addcarry.ll20
-rw-r--r--test/CodeGen/X86/avg.ll833
-rw-r--r--test/CodeGen/X86/avx-intrinsics-fast-isel.ll52
-rw-r--r--test/CodeGen/X86/avx.ll2
-rw-r--r--test/CodeGen/X86/avx512-cmp-kor-sequence.ll6
-rw-r--r--test/CodeGen/X86/avx512-cmp.ll81
-rw-r--r--test/CodeGen/X86/avx512-cvt.ll4
-rw-r--r--test/CodeGen/X86/avx512-ext.ll24
-rw-r--r--test/CodeGen/X86/avx512-fsel.ll24
-rw-r--r--test/CodeGen/X86/avx512-gather-scatter-intrin.ll10
-rwxr-xr-xtest/CodeGen/X86/avx512-i1test.ll5
-rw-r--r--test/CodeGen/X86/avx512-insert-extract.ll220
-rw-r--r--test/CodeGen/X86/avx512-insert-extract_i1.ll5
-rw-r--r--test/CodeGen/X86/avx512-intrinsics-upgrade.ll116
-rw-r--r--test/CodeGen/X86/avx512-intrinsics.ll422
-rw-r--r--test/CodeGen/X86/avx512-load-store.ll8
-rwxr-xr-xtest/CodeGen/X86/avx512-mask-bugfix.ll57
-rw-r--r--test/CodeGen/X86/avx512-mask-op.ll151
-rw-r--r--test/CodeGen/X86/avx512-mask-spills.ll40
-rw-r--r--test/CodeGen/X86/avx512-memfold.ll5
-rw-r--r--test/CodeGen/X86/avx512-regcall-NoMask.ll32
-rw-r--r--test/CodeGen/X86/avx512-scalar_mask.ll14
-rw-r--r--test/CodeGen/X86/avx512-select.ll4
-rw-r--r--test/CodeGen/X86/avx512bw-intrinsics-upgrade.ll12
-rw-r--r--test/CodeGen/X86/avx512bw-intrinsics.ll16
-rw-r--r--test/CodeGen/X86/avx512bwvl-intrinsics-upgrade.ll24
-rw-r--r--test/CodeGen/X86/avx512cdvl-intrinsics-upgrade.ll2
-rw-r--r--test/CodeGen/X86/avx512cdvl-intrinsics.ll2
-rw-r--r--test/CodeGen/X86/avx512dq-intrinsics-upgrade.ll9
-rw-r--r--test/CodeGen/X86/avx512dq-intrinsics.ll14
-rw-r--r--test/CodeGen/X86/avx512dqvl-intrinsics-upgrade.ll10
-rw-r--r--test/CodeGen/X86/avx512dqvl-intrinsics.ll4
-rw-r--r--test/CodeGen/X86/avx512er-intrinsics.ll6
-rw-r--r--test/CodeGen/X86/avx512ifma-intrinsics.ll8
-rw-r--r--test/CodeGen/X86/avx512ifmavl-intrinsics.ll16
-rw-r--r--test/CodeGen/X86/avx512vl-intrinsics-upgrade.ll64
-rw-r--r--test/CodeGen/X86/avx512vl-intrinsics.ll28
-rw-r--r--test/CodeGen/X86/bitcast-setcc-128.ll823
-rw-r--r--test/CodeGen/X86/bitcast-setcc-256.ll363
-rw-r--r--test/CodeGen/X86/bswap_tree2.ll35
-rw-r--r--test/CodeGen/X86/constant-combines.ll16
-rw-r--r--test/CodeGen/X86/fast-isel-load-i1.ll4
-rw-r--r--test/CodeGen/X86/fma-fneg-combine.ll5
-rw-r--r--test/CodeGen/X86/fmsubadd-combine.ll193
-rw-r--r--test/CodeGen/X86/fold-tied-op.ll7
-rw-r--r--test/CodeGen/X86/fp128-i128.ll2
-rw-r--r--test/CodeGen/X86/haddsub-2.ll12
-rw-r--r--test/CodeGen/X86/leaFixup32.mir509
-rw-r--r--test/CodeGen/X86/leaFixup64.mir1041
-rw-r--r--test/CodeGen/X86/lrshrink.ll57
-rw-r--r--test/CodeGen/X86/madd.ll34
-rw-r--r--test/CodeGen/X86/masked_gather_scatter.ll34
-rw-r--r--test/CodeGen/X86/merge-consecutive-loads-128.ll16
-rw-r--r--test/CodeGen/X86/misched-matrix.ll4
-rw-r--r--test/CodeGen/X86/mul-i1024.ll3827
-rw-r--r--test/CodeGen/X86/mul-i256.ll94
-rw-r--r--test/CodeGen/X86/mul-i512.ll705
-rw-r--r--test/CodeGen/X86/oddshuffles.ll34
-rw-r--r--test/CodeGen/X86/overflow.ll8
-rw-r--r--test/CodeGen/X86/pmul.ll55
-rw-r--r--test/CodeGen/X86/pr27591.ll18
-rw-r--r--test/CodeGen/X86/pr28173.ll20
-rw-r--r--test/CodeGen/X86/pr29112.ll8
-rw-r--r--test/CodeGen/X86/pr31088.ll2
-rw-r--r--test/CodeGen/X86/pr32241.ll68
-rw-r--r--test/CodeGen/X86/pr32256.ll36
-rw-r--r--test/CodeGen/X86/pr32284.ll12
-rw-r--r--test/CodeGen/X86/pr32451.ll6
-rw-r--r--test/CodeGen/X86/rotate.ll16
-rw-r--r--test/CodeGen/X86/rtm.ll10
-rw-r--r--test/CodeGen/X86/sad.ll929
-rw-r--r--test/CodeGen/X86/select.ll28
-rw-r--r--test/CodeGen/X86/setcc-wide-types.ll56
-rw-r--r--test/CodeGen/X86/shrink_vmul_sse.ll2
-rw-r--r--test/CodeGen/X86/sse-intrinsics-fast-isel.ll10
-rw-r--r--test/CodeGen/X86/sse-scalar-fp-arith.ll8
-rw-r--r--test/CodeGen/X86/sse1.ll8
-rw-r--r--test/CodeGen/X86/sse3-avx-addsub-2.ll14
-rw-r--r--test/CodeGen/X86/sse41.ll8
-rw-r--r--test/CodeGen/X86/subcarry.ll137
-rw-r--r--test/CodeGen/X86/vec_int_to_fp.ll84
-rw-r--r--test/CodeGen/X86/vector-bitreverse.ll6
-rw-r--r--test/CodeGen/X86/vector-blend.ll4
-rw-r--r--test/CodeGen/X86/vector-sqrt.ll8
-rw-r--r--test/CodeGen/X86/x86-interleaved-access.ll14
-rw-r--r--test/CodeGen/X86/xmulo.ll8
-rw-r--r--test/CodeGen/X86/xor-select-i1-combine.ll6
-rw-r--r--test/DebugInfo/Inputs/split-dwarf-addr-object-relocation.dwobin0 -> 1056 bytes
-rw-r--r--test/DebugInfo/Inputs/split-dwarf-addr-object-relocation.obin0 -> 2968 bytes
-rw-r--r--test/DebugInfo/Inputs/split-dwarf-multiple-cu.dwobin0 -> 1040 bytes
-rw-r--r--test/DebugInfo/Inputs/split-dwarf-multiple-cu.obin0 -> 2992 bytes
-rw-r--r--test/DebugInfo/PDB/Inputs/merge1.yaml52
-rw-r--r--test/DebugInfo/PDB/Inputs/merge2.yaml52
-rw-r--r--test/DebugInfo/PDB/pdbdump-headers.test4
-rw-r--r--test/DebugInfo/PDB/pdbdump-mergetypes.test24
-rw-r--r--test/DebugInfo/llvm-symbolizer.test14
-rw-r--r--test/Instrumentation/MemorySanitizer/csr.ll1
-rw-r--r--test/LTO/X86/Inputs/strip-debug-info-bar.ll15
-rw-r--r--test/LTO/X86/Inputs/strip-debug-info.bcbin852 -> 0 bytes
-rw-r--r--test/LTO/X86/strip-debug-info.ll49
-rw-r--r--test/MC/AMDGPU/exp.s12
-rw-r--r--test/MC/Disassembler/AMDGPU/exp_vi.txt40
-rw-r--r--test/MC/Disassembler/AMDGPU/sopc_vi.txt3
-rw-r--r--test/TableGen/GlobalISelEmitter.td35
-rw-r--r--test/TableGen/intrinsic-varargs.td2
-rw-r--r--test/ThinLTO/X86/Inputs/merge-triple.ll1
-rw-r--r--test/ThinLTO/X86/merge-triple.ll10
-rw-r--r--test/Transforms/InstCombine/2008-09-29-FoldingOr.ll10
-rw-r--r--test/Transforms/InstCombine/AMDGPU/amdgcn-demanded-vector-elts.ll (renamed from test/Transforms/InstCombine/amdgcn-demanded-vector-elts.ll)0
-rw-r--r--test/Transforms/InstCombine/NVPTX/lit.local.cfg2
-rw-r--r--test/Transforms/InstCombine/NVPTX/nvvm-intrins.ll (renamed from test/Transforms/InstCombine/nvvm-intrins.ll)0
-rw-r--r--test/Transforms/InstCombine/cast.ll52
-rw-r--r--test/Transforms/InstCombine/lshr.ll72
-rw-r--r--test/Transforms/InstCombine/memchr.ll9
-rw-r--r--test/Transforms/InstCombine/set.ll94
-rw-r--r--test/Transforms/InstCombine/wcslen-1.ll191
-rw-r--r--test/Transforms/InstCombine/wcslen-2.ll18
-rw-r--r--test/Transforms/InstCombine/wcslen-3.ll197
-rw-r--r--test/Transforms/InstSimplify/AndOrXor.ll76
-rw-r--r--test/Transforms/InstSimplify/icmp-bool-constant.ll171
-rw-r--r--test/Transforms/JumpThreading/assume.ll44
-rw-r--r--test/Transforms/JumpThreading/fold-not-thread.ll4
-rw-r--r--test/Transforms/JumpThreading/guards.ll94
-rw-r--r--test/Transforms/LoopStrengthReduce/X86/canonical-2.ll36
-rw-r--r--test/Transforms/NewGVN/completeness.ll415
-rw-r--r--test/Transforms/NewGVN/pr32838.ll157
-rw-r--r--test/Transforms/NewGVN/pr32845.ll64
-rw-r--r--test/Transforms/NewGVN/pr32897.ll26
-rw-r--r--test/Transforms/NewGVN/pr32945.ll24
-rw-r--r--test/Transforms/NewGVN/pr33014.ll54
-rw-r--r--test/Transforms/NewGVN/pr33086.ll59
-rw-r--r--test/Transforms/NewGVN/pr33116.ll39
-rw-r--r--test/Transforms/NewGVN/storeoverstore.ll20
-rw-r--r--test/Transforms/SafeStack/X86/coloring-ssp.ll2
-rw-r--r--test/Transforms/SafeStack/X86/coloring.ll4
-rw-r--r--test/Transforms/SafeStack/X86/coloring2.ll4
-rw-r--r--test/Transforms/SafeStack/X86/layout-frag.ll2
-rw-r--r--test/tools/llvm-cvtres/Inputs/cursor_small.bmpbin0 -> 822 bytes
-rw-r--r--test/tools/llvm-cvtres/Inputs/okay_small.bmpbin0 -> 822 bytes
-rw-r--r--test/tools/llvm-cvtres/Inputs/test_resource.rc44
-rw-r--r--test/tools/llvm-cvtres/Inputs/test_resource.resbin0 -> 2200 bytes
-rw-r--r--test/tools/llvm-cvtres/resource.test7
-rw-r--r--tools/llc/llc.cpp4
-rw-r--r--tools/llvm-cvtres/CMakeLists.txt1
-rw-r--r--tools/llvm-cvtres/llvm-cvtres.cpp102
-rw-r--r--tools/llvm-cvtres/llvm-cvtres.h6
-rw-r--r--tools/llvm-dwp/llvm-dwp.cpp2
-rw-r--r--tools/llvm-lto/llvm-lto.cpp24
-rw-r--r--tools/llvm-pdbdump/Analyze.cpp1
-rw-r--r--tools/llvm-pdbdump/CompactTypeDumpVisitor.cpp10
-rw-r--r--tools/llvm-pdbdump/CompactTypeDumpVisitor.h8
-rw-r--r--tools/llvm-pdbdump/LLVMOutputStyle.cpp119
-rw-r--r--tools/llvm-pdbdump/LLVMOutputStyle.h12
-rw-r--r--tools/llvm-pdbdump/PdbYaml.cpp2
-rw-r--r--tools/llvm-pdbdump/YAMLOutputStyle.h1
-rw-r--r--tools/llvm-pdbdump/YamlTypeDumper.cpp1
-rw-r--r--tools/llvm-pdbdump/llvm-pdbdump.cpp86
-rw-r--r--tools/llvm-readobj/COFFDumper.cpp99
-rw-r--r--tools/opt/opt.cpp12
-rw-r--r--unittests/ADT/APIntTest.cpp58
-rw-r--r--unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp83
-rw-r--r--unittests/IR/AttributesTest.cpp19
-rw-r--r--unittests/IR/ConstantsTest.cpp17
-rw-r--r--unittests/IR/DominatorTreeTest.cpp4
-rw-r--r--unittests/IR/InstructionsTest.cpp4
-rw-r--r--unittests/IR/MetadataTest.cpp2
-rw-r--r--unittests/Support/BinaryStreamTest.cpp33
-rw-r--r--unittests/Support/CrashRecoveryTest.cpp6
-rw-r--r--unittests/Support/ScaledNumberTest.cpp6
-rw-r--r--unittests/Target/AArch64/InstSizes.cpp3
-rw-r--r--unittests/Transforms/Utils/Cloning.cpp11
-rw-r--r--utils/TableGen/CodeGenTarget.cpp2
-rw-r--r--utils/TableGen/GlobalISelEmitter.cpp25
-rwxr-xr-xutils/git-svn/git-llvm2
-rw-r--r--utils/lit/lit/TestRunner.py8
539 files changed, 21334 insertions, 8359 deletions
diff --git a/docs/CMake.rst b/docs/CMake.rst
index 0a32d3957a53..2deae9361874 100644
--- a/docs/CMake.rst
+++ b/docs/CMake.rst
@@ -186,8 +186,8 @@ CMake manual, or execute ``cmake --help-variable VARIABLE_NAME``.
Sets the build type for ``make``-based generators. Possible values are
Release, Debug, RelWithDebInfo and MinSizeRel. If you are using an IDE such as
Visual Studio, you should use the IDE settings to set the build type.
- Be aware that Release and RelWithDebInfo are not using the same optimization
- level on most platform.
+ Be aware that Release and RelWithDebInfo use different optimization levels on
+ most platforms.
**CMAKE_INSTALL_PREFIX**:PATH
Path where LLVM will be installed if "make install" is invoked or the
diff --git a/docs/GetElementPtr.rst b/docs/GetElementPtr.rst
index f39f1d9207a2..d13479dabca8 100644
--- a/docs/GetElementPtr.rst
+++ b/docs/GetElementPtr.rst
@@ -9,10 +9,11 @@ Introduction
============
This document seeks to dispel the mystery and confusion surrounding LLVM's
-`GetElementPtr <LangRef.html#i_getelementptr>`_ (GEP) instruction. Questions
-about the wily GEP instruction are probably the most frequently occurring
-questions once a developer gets down to coding with LLVM. Here we lay out the
-sources of confusion and show that the GEP instruction is really quite simple.
+`GetElementPtr <LangRef.html#getelementptr-instruction>`_ (GEP) instruction.
+Questions about the wily GEP instruction are probably the most frequently
+occurring questions once a developer gets down to coding with LLVM. Here we lay
+out the sources of confusion and show that the GEP instruction is really quite
+simple.
Address Computation
===================
@@ -429,7 +430,8 @@ because LLVM has no restrictions on mixing types in addressing, loads or stores.
LLVM's type-based alias analysis pass uses metadata to describe a different type
system (such as the C type system), and performs type-based aliasing on top of
-that. Further details are in the `language reference <LangRef.html#tbaa>`_.
+that. Further details are in the
+`language reference <LangRef.html#tbaa-metadata>`_.
What happens if a GEP computation overflows?
--------------------------------------------
diff --git a/docs/LangRef.rst b/docs/LangRef.rst
index 9ff47e8366dc..b205cae9b118 100644
--- a/docs/LangRef.rst
+++ b/docs/LangRef.rst
@@ -161,7 +161,7 @@ symbol table entries. Here is an example of the "hello world" module:
; Definition of main function
define i32 @main() { ; i32()*
- ; Convert [13 x i8]* to i8 *...
+ ; Convert [13 x i8]* to i8*...
%cast210 = getelementptr [13 x i8], [13 x i8]* @.str, i64 0, i64 0
; Call puts function to write out the string to stdout.
@@ -9548,7 +9548,7 @@ Syntax:
::
- declare i8 *@llvm.returnaddress(i32 <level>)
+ declare i8* @llvm.returnaddress(i32 <level>)
Overview:
"""""""""
@@ -9586,7 +9586,7 @@ Syntax:
::
- declare i8 *@llvm.addressofreturnaddress()
+ declare i8* @llvm.addressofreturnaddress()
Overview:
"""""""""
diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h
index 894e5571f8ad..fe75e25bd8d2 100644
--- a/include/llvm/ADT/APInt.h
+++ b/include/llvm/ADT/APInt.h
@@ -182,8 +182,9 @@ private:
/// 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,
- unsigned rhsWords, APInt *Quotient, APInt *Remainder);
+ static void divide(const WordType *LHS, unsigned lhsWords,
+ const WordType *RHS, unsigned rhsWords, WordType *Quotient,
+ WordType *Remainder);
/// out-of-line slow case for inline constructor
void initSlowCase(uint64_t val, bool isSigned);
@@ -1016,11 +1017,13 @@ public:
///
/// \returns a new APInt value containing the division result
APInt udiv(const APInt &RHS) const;
+ APInt udiv(uint64_t RHS) const;
/// \brief Signed division function for APInt.
///
/// Signed divide this APInt by APInt RHS.
APInt sdiv(const APInt &RHS) const;
+ APInt sdiv(int64_t RHS) const;
/// \brief Unsigned remainder operation.
///
@@ -1032,11 +1035,13 @@ public:
///
/// \returns a new APInt value containing the remainder result
APInt urem(const APInt &RHS) const;
+ uint64_t urem(uint64_t RHS) const;
/// \brief Function for signed remainder operation.
///
/// Signed remainder operation on APInt.
APInt srem(const APInt &RHS) const;
+ int64_t srem(int64_t RHS) const;
/// \brief Dual division/remainder interface.
///
@@ -1047,9 +1052,13 @@ public:
/// udivrem(X, Y, X, Y), for example.
static void udivrem(const APInt &LHS, const APInt &RHS, APInt &Quotient,
APInt &Remainder);
+ static void udivrem(const APInt &LHS, uint64_t RHS, APInt &Quotient,
+ uint64_t &Remainder);
static void sdivrem(const APInt &LHS, const APInt &RHS, APInt &Quotient,
APInt &Remainder);
+ static void sdivrem(const APInt &LHS, int64_t RHS, APInt &Quotient,
+ int64_t &Remainder);
// Operations that return overflow indicators.
APInt sadd_ov(const APInt &RHS, bool &Overflow) const;
@@ -2015,7 +2024,7 @@ inline APInt operator-(APInt a, const APInt &b) {
}
inline APInt operator-(const APInt &a, APInt &&b) {
- b = -std::move(b);
+ b.negate();
b += a;
return std::move(b);
}
@@ -2026,7 +2035,7 @@ inline APInt operator-(APInt a, uint64_t RHS) {
}
inline APInt operator-(uint64_t LHS, APInt b) {
- b = -std::move(b);
+ b.negate();
b += LHS;
return b;
}
diff --git a/include/llvm/ADT/SmallPtrSet.h b/include/llvm/ADT/SmallPtrSet.h
index b49d216e0b6e..a0b380b237da 100644
--- a/include/llvm/ADT/SmallPtrSet.h
+++ b/include/llvm/ADT/SmallPtrSet.h
@@ -365,6 +365,8 @@ protected:
public:
using iterator = SmallPtrSetIterator<PtrType>;
using const_iterator = SmallPtrSetIterator<PtrType>;
+ using key_type = ConstPtrType;
+ using value_type = PtrType;
SmallPtrSetImpl(const SmallPtrSetImpl &) = delete;
diff --git a/include/llvm/ADT/Statistic.h b/include/llvm/ADT/Statistic.h
index 53fa2a50fcba..d5ebba409c3d 100644
--- a/include/llvm/ADT/Statistic.h
+++ b/include/llvm/ADT/Statistic.h
@@ -101,6 +101,16 @@ public:
return init();
}
+ void updateMax(unsigned V) {
+ unsigned PrevMax = Value.load(std::memory_order_relaxed);
+ // Keep trying to update max until we succeed or another thread produces
+ // a bigger max than us.
+ while (V > PrevMax && !Value.compare_exchange_weak(
+ PrevMax, V, std::memory_order_relaxed)) {
+ }
+ init();
+ }
+
#else // Statistics are disabled in release builds.
const Statistic &operator=(unsigned Val) {
@@ -131,6 +141,8 @@ public:
return *this;
}
+ void updateMax(unsigned V) {}
+
#endif // !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
protected:
diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h
index e3a8a31ba9bc..3a4a37017d61 100644
--- a/include/llvm/ADT/Triple.h
+++ b/include/llvm/ADT/Triple.h
@@ -252,6 +252,10 @@ public:
ObjectFormat == Other.ObjectFormat;
}
+ bool operator!=(const Triple &Other) const {
+ return !(*this == Other);
+ }
+
/// @}
/// @name Normalization
/// @{
@@ -722,6 +726,12 @@ public:
/// \returns true if the triple is little endian, false otherwise.
bool isLittleEndian() const;
+ /// Test whether target triples are compatible.
+ bool isCompatibleWith(const Triple &Other) const;
+
+ /// Merge target triples.
+ std::string merge(const Triple &Other) const;
+
/// @}
/// @name Static helpers for IDs.
/// @{
diff --git a/include/llvm/Analysis/MemorySSA.h b/include/llvm/Analysis/MemorySSA.h
index db31ae9f4f10..f0bba8c4c020 100644
--- a/include/llvm/Analysis/MemorySSA.h
+++ b/include/llvm/Analysis/MemorySSA.h
@@ -84,6 +84,7 @@
#include "llvm/Analysis/MemoryLocation.h"
#include "llvm/Analysis/PHITransAddr.h"
#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/DerivedUser.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/OperandTraits.h"
@@ -127,7 +128,7 @@ using const_memoryaccess_def_iterator =
// \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 DerivedUser,
public ilist_node<MemoryAccess, ilist_tag<MSSAHelpers::AllAccessTag>>,
public ilist_node<MemoryAccess, ilist_tag<MSSAHelpers::DefsOnlyTag>> {
public:
@@ -145,15 +146,14 @@ public:
MemoryAccess(const MemoryAccess &) = delete;
MemoryAccess &operator=(const MemoryAccess &) = delete;
- ~MemoryAccess() override;
void *operator new(size_t, unsigned) = delete;
void *operator new(size_t) = delete;
BasicBlock *getBlock() const { return Block; }
- virtual void print(raw_ostream &OS) const = 0;
- virtual void dump() const;
+ void print(raw_ostream &OS) const;
+ void dump() const;
/// \brief The user iterators for a memory access
typedef user_iterator iterator;
@@ -207,11 +207,12 @@ protected:
/// \brief Used for debugging and tracking things about MemoryAccesses.
/// Guaranteed unique among MemoryAccesses, no guarantees otherwise.
- virtual unsigned getID() const = 0;
+ inline unsigned getID() const;
- MemoryAccess(LLVMContext &C, unsigned Vty, BasicBlock *BB,
- unsigned NumOperands)
- : User(Type::getVoidTy(C), Vty, nullptr, NumOperands), Block(BB) {}
+ MemoryAccess(LLVMContext &C, unsigned Vty, DeleteValueTy DeleteValue,
+ BasicBlock *BB, unsigned NumOperands)
+ : DerivedUser(Type::getVoidTy(C), Vty, nullptr, NumOperands, DeleteValue),
+ Block(BB) {}
private:
BasicBlock *Block;
@@ -248,21 +249,21 @@ public:
// Sadly, these have to be public because they are needed in some of the
// iterators.
- virtual bool isOptimized() const = 0;
- virtual MemoryAccess *getOptimized() const = 0;
- virtual void setOptimized(MemoryAccess *) = 0;
+ inline bool isOptimized() const;
+ inline MemoryAccess *getOptimized() const;
+ inline void setOptimized(MemoryAccess *);
/// \brief Reset the ID of what this MemoryUse was optimized to, causing it to
/// be rewalked by the walker if necessary.
/// This really should only be called by tests.
- virtual void resetOptimized() = 0;
+ inline void resetOptimized();
protected:
friend class MemorySSA;
friend class MemorySSAUpdater;
MemoryUseOrDef(LLVMContext &C, MemoryAccess *DMA, unsigned Vty,
- Instruction *MI, BasicBlock *BB)
- : MemoryAccess(C, Vty, BB, 1), MemoryInst(MI) {
+ DeleteValueTy DeleteValue, Instruction *MI, BasicBlock *BB)
+ : MemoryAccess(C, Vty, DeleteValue, BB, 1), MemoryInst(MI) {
setDefiningAccess(DMA);
}
void setDefiningAccess(MemoryAccess *DMA, bool Optimized = false) {
@@ -292,7 +293,8 @@ public:
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess);
MemoryUse(LLVMContext &C, MemoryAccess *DMA, Instruction *MI, BasicBlock *BB)
- : MemoryUseOrDef(C, DMA, MemoryUseVal, MI, BB), OptimizedID(0) {}
+ : MemoryUseOrDef(C, DMA, MemoryUseVal, deleteMe, MI, BB),
+ OptimizedID(0) {}
// allocate space for exactly one operand
void *operator new(size_t s) { return User::operator new(s, 1); }
@@ -302,32 +304,30 @@ public:
return MA->getValueID() == MemoryUseVal;
}
- void print(raw_ostream &OS) const override;
+ void print(raw_ostream &OS) const;
- virtual void setOptimized(MemoryAccess *DMA) override {
+ void setOptimized(MemoryAccess *DMA) {
OptimizedID = DMA->getID();
setOperand(0, DMA);
}
- virtual bool isOptimized() const override {
+ bool isOptimized() const {
return getDefiningAccess() && OptimizedID == getDefiningAccess()->getID();
}
- virtual MemoryAccess *getOptimized() const override {
+ MemoryAccess *getOptimized() const {
return getDefiningAccess();
}
- virtual void resetOptimized() override {
+ void resetOptimized() {
OptimizedID = INVALID_MEMORYACCESS_ID;
}
protected:
friend class MemorySSA;
- unsigned getID() const override {
- llvm_unreachable("MemoryUses do not have IDs");
- }
-
private:
+ static void deleteMe(DerivedUser *Self);
+
unsigned int OptimizedID;
};
@@ -350,8 +350,8 @@ public:
MemoryDef(LLVMContext &C, MemoryAccess *DMA, Instruction *MI, BasicBlock *BB,
unsigned Ver)
- : MemoryUseOrDef(C, DMA, MemoryDefVal, MI, BB), ID(Ver),
- Optimized(nullptr), OptimizedID(INVALID_MEMORYACCESS_ID) {}
+ : MemoryUseOrDef(C, DMA, MemoryDefVal, deleteMe, MI, BB),
+ ID(Ver), Optimized(nullptr), OptimizedID(INVALID_MEMORYACCESS_ID) {}
// allocate space for exactly one operand
void *operator new(size_t s) { return User::operator new(s, 1); }
@@ -361,27 +361,28 @@ public:
return MA->getValueID() == MemoryDefVal;
}
- virtual void setOptimized(MemoryAccess *MA) override {
+ void setOptimized(MemoryAccess *MA) {
Optimized = MA;
OptimizedID = getDefiningAccess()->getID();
}
- virtual MemoryAccess *getOptimized() const override { return Optimized; }
- virtual bool isOptimized() const override {
+ MemoryAccess *getOptimized() const { return Optimized; }
+ bool isOptimized() const {
return getOptimized() && getDefiningAccess() &&
OptimizedID == getDefiningAccess()->getID();
}
- virtual void resetOptimized() override {
+ void resetOptimized() {
OptimizedID = INVALID_MEMORYACCESS_ID;
}
- void print(raw_ostream &OS) const override;
+ void print(raw_ostream &OS) const;
-protected:
friend class MemorySSA;
- unsigned getID() const override { return ID; }
+ unsigned getID() const { return ID; }
private:
+ static void deleteMe(DerivedUser *Self);
+
const unsigned ID;
MemoryAccess *Optimized;
unsigned int OptimizedID;
@@ -432,7 +433,8 @@ public:
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess);
MemoryPhi(LLVMContext &C, BasicBlock *BB, unsigned Ver, unsigned NumPreds = 0)
- : MemoryAccess(C, MemoryPhiVal, BB, 0), ID(Ver), ReservedSpace(NumPreds) {
+ : MemoryAccess(C, MemoryPhiVal, deleteMe, BB, 0), ID(Ver),
+ ReservedSpace(NumPreds) {
allocHungoffUses(ReservedSpace);
}
@@ -534,7 +536,9 @@ public:
return V->getValueID() == MemoryPhiVal;
}
- void print(raw_ostream &OS) const override;
+ void print(raw_ostream &OS) const;
+
+ unsigned getID() const { return ID; }
protected:
friend class MemorySSA;
@@ -546,8 +550,6 @@ protected:
User::allocHungoffUses(N, /* IsPhi */ true);
}
- unsigned getID() const final { return ID; }
-
private:
// For debugging only
const unsigned ID;
@@ -561,8 +563,45 @@ private:
ReservedSpace = std::max(E + E / 2, 2u);
growHungoffUses(ReservedSpace, /* IsPhi */ true);
}
+
+ static void deleteMe(DerivedUser *Self);
};
+inline unsigned MemoryAccess::getID() const {
+ assert((isa<MemoryDef>(this) || isa<MemoryPhi>(this)) &&
+ "only memory defs and phis have ids");
+ if (const auto *MD = dyn_cast<MemoryDef>(this))
+ return MD->getID();
+ return cast<MemoryPhi>(this)->getID();
+}
+
+inline bool MemoryUseOrDef::isOptimized() const {
+ if (const auto *MD = dyn_cast<MemoryDef>(this))
+ return MD->isOptimized();
+ return cast<MemoryUse>(this)->isOptimized();
+}
+
+inline MemoryAccess *MemoryUseOrDef::getOptimized() const {
+ if (const auto *MD = dyn_cast<MemoryDef>(this))
+ return MD->getOptimized();
+ return cast<MemoryUse>(this)->getOptimized();
+}
+
+inline void MemoryUseOrDef::setOptimized(MemoryAccess *MA) {
+ if (auto *MD = dyn_cast<MemoryDef>(this))
+ MD->setOptimized(MA);
+ else
+ cast<MemoryUse>(this)->setOptimized(MA);
+}
+
+inline void MemoryUseOrDef::resetOptimized() {
+ if (auto *MD = dyn_cast<MemoryDef>(this))
+ MD->resetOptimized();
+ else
+ cast<MemoryUse>(this)->resetOptimized();
+}
+
+
template <> struct OperandTraits<MemoryPhi> : public HungoffOperandTraits<2> {};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryPhi, MemoryAccess)
diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h
index ceca6cb389a1..ac54bd4cfffb 100644
--- a/include/llvm/Analysis/ScalarEvolution.h
+++ b/include/llvm/Analysis/ScalarEvolution.h
@@ -656,10 +656,12 @@ private:
/// Test whether this BackedgeTakenInfo contains complete information.
bool hasFullInfo() const { return isComplete(); }
- /// Return an expression indicating the exact backedge-taken count of 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.
+ /// Return an expression indicating the exact *backedge-taken*
+ /// count of the loop if it is known or SCEVCouldNotCompute
+ /// otherwise. If execution makes it to the backedge on every
+ /// iteration (i.e. there are no abnormal exists like exception
+ /// throws and thread exits) then this is the number of times the
+ /// loop header will execute minus one.
///
/// If the SCEV predicate associated with the answer can be different
/// from AlwaysTrue, we must add a (non null) Predicates argument.
@@ -1398,11 +1400,11 @@ public:
const SCEV *getExitCount(const Loop *L, BasicBlock *ExitingBlock);
/// If the specified loop has a predictable backedge-taken count, return it,
- /// otherwise return a SCEVCouldNotCompute object. The backedge-taken count
- /// is the number of times the loop header will be branched to from within
- /// the loop. This is one less than the trip count of the loop, since it
- /// doesn't count the first iteration, when the header is branched to from
- /// outside the loop.
+ /// otherwise return a SCEVCouldNotCompute object. The backedge-taken count is
+ /// the number of times the loop header will be branched to from within the
+ /// loop, assuming there are no abnormal exists like exception throws. This is
+ /// one less than the trip count of the loop, since it doesn't count the first
+ /// iteration, when the header is branched to from outside the loop.
///
/// Note that it is not valid to call this method on a loop without a
/// loop-invariant backedge-taken count (see
@@ -1417,8 +1419,10 @@ public:
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.
+ /// When successful, this returns a SCEVConstant that is greater than or equal
+ /// to (i.e. a "conservative over-approximation") of the value returend by
+ /// getBackedgeTakenCount. If such a value cannot be computed, it returns the
+ /// SCEVCouldNotCompute object.
const SCEV *getMaxBackedgeTakenCount(const Loop *L);
/// Return true if the backedge taken count is either the value returned by
diff --git a/include/llvm/Analysis/TargetLibraryInfo.h b/include/llvm/Analysis/TargetLibraryInfo.h
index 944250cfd6ac..0e3bdaa11c9a 100644
--- a/include/llvm/Analysis/TargetLibraryInfo.h
+++ b/include/llvm/Analysis/TargetLibraryInfo.h
@@ -191,6 +191,14 @@ public:
void setShouldSignExtI32Param(bool Val) {
ShouldSignExtI32Param = Val;
}
+
+ /// Returns the size of the wchar_t type in bytes.
+ unsigned getWCharSize(const Module &M) const;
+
+ /// Returns size of the default wchar_t type on target \p T. This is mostly
+ /// intended to verify that the size in the frontend matches LLVM. All other
+ /// queries should use getWCharSize() instead.
+ static unsigned getTargetWCharSize(const Triple &T);
};
/// Provides information about what library functions are available for
@@ -307,6 +315,11 @@ public:
return Attribute::None;
}
+ /// \copydoc TargetLibraryInfoImpl::getWCharSize()
+ unsigned getWCharSize(const Module &M) const {
+ return Impl->getWCharSize(M);
+ }
+
/// Handle invalidation from the pass manager.
///
/// If we try to invalidate this info, just return false. It cannot become
diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h
index f5f323c6b797..cf24062e46f8 100644
--- a/include/llvm/Analysis/ValueTracking.h
+++ b/include/llvm/Analysis/ValueTracking.h
@@ -218,9 +218,38 @@ template <typename T> class ArrayRef;
DL);
}
- /// 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);
+ /// Returns true if the GEP is based on a pointer to a string (array of
+ // \p CharSize integers) and is indexing into this string.
+ bool isGEPBasedOnPointerToString(const GEPOperator *GEP,
+ unsigned CharSize = 8);
+
+ /// Represents offset+length into a ConstantDataArray.
+ struct ConstantDataArraySlice {
+ /// ConstantDataArray pointer. nullptr indicates a zeroinitializer (a valid
+ /// initializer, it just doesn't fit the ConstantDataArray interface).
+ const ConstantDataArray *Array;
+ /// Slice starts at this Offset.
+ uint64_t Offset;
+ /// Length of the slice.
+ uint64_t Length;
+
+ /// Moves the Offset and adjusts Length accordingly.
+ void move(uint64_t Delta) {
+ assert(Delta < Length);
+ Offset += Delta;
+ Length -= Delta;
+ }
+ /// Convenience accessor for elements in the slice.
+ uint64_t operator[](unsigned I) const {
+ return Array==nullptr ? 0 : Array->getElementAsInteger(I + Offset);
+ }
+ };
+
+ /// Returns true if the value \p V is a pointer into a ContantDataArray.
+ /// If successfull \p Index will point to a ConstantDataArray info object
+ /// with an apropriate offset.
+ bool getConstantDataArrayInfo(const Value *V, ConstantDataArraySlice &Slice,
+ unsigned ElementSize, uint64_t Offset = 0);
/// 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
@@ -233,7 +262,7 @@ template <typename T> class ArrayRef;
/// 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(const Value *V);
+ uint64_t GetStringLength(const Value *V, unsigned CharSize = 8);
/// This method strips off any GEP address adjustments and pointer casts from
/// the specified value, returning the original object being addressed. Note
diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h
index f5b1f87720ad..181cb375de86 100644
--- a/include/llvm/CodeGen/LiveIntervalAnalysis.h
+++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h
@@ -189,7 +189,7 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
void pruneValue(LiveRange &LR, SlotIndex Kill,
SmallVectorImpl<SlotIndex> *EndPoints);
- /// This function should be used. Its intend is to tell you that
+ /// This function should not be used. Its intend is to tell you that
/// you are doing something wrong if you call pruveValue directly on a
/// LiveInterval. Indeed, you are supposed to call pruneValue on the main
/// LiveRange and all the LiveRange of the subranges if any.
diff --git a/include/llvm/CodeGen/MachineValueType.h b/include/llvm/CodeGen/MachineValueType.h
index a90fe96227b9..e92bb7f74967 100644
--- a/include/llvm/CodeGen/MachineValueType.h
+++ b/include/llvm/CodeGen/MachineValueType.h
@@ -56,117 +56,119 @@ class MVT {
FIRST_FP_VALUETYPE = f16,
LAST_FP_VALUETYPE = ppcf128,
- v2i1 = 14, // 2 x i1
- v4i1 = 15, // 4 x i1
- v8i1 = 16, // 8 x i1
- v16i1 = 17, // 16 x i1
- v32i1 = 18, // 32 x i1
- v64i1 = 19, // 64 x i1
- v512i1 = 20, // 512 x i1
- v1024i1 = 21, // 1024 x i1
-
- v1i8 = 22, // 1 x i8
- v2i8 = 23, // 2 x i8
- v4i8 = 24, // 4 x i8
- v8i8 = 25, // 8 x i8
- v16i8 = 26, // 16 x i8
- v32i8 = 27, // 32 x i8
- v64i8 = 28, // 64 x i8
- v128i8 = 29, //128 x i8
- v256i8 = 30, //256 x i8
-
- v1i16 = 31, // 1 x i16
- v2i16 = 32, // 2 x i16
- v4i16 = 33, // 4 x i16
- v8i16 = 34, // 8 x i16
- v16i16 = 35, // 16 x i16
- v32i16 = 36, // 32 x i16
- v64i16 = 37, // 64 x i16
- v128i16 = 38, //128 x i16
-
- v1i32 = 39, // 1 x i32
- v2i32 = 40, // 2 x i32
- v4i32 = 41, // 4 x i32
- v8i32 = 42, // 8 x i32
- v16i32 = 43, // 16 x i32
- v32i32 = 44, // 32 x i32
- v64i32 = 45, // 64 x i32
-
- v1i64 = 46, // 1 x i64
- v2i64 = 47, // 2 x i64
- v4i64 = 48, // 4 x i64
- v8i64 = 49, // 8 x i64
- v16i64 = 50, // 16 x i64
- v32i64 = 51, // 32 x i64
-
- v1i128 = 52, // 1 x i128
+ v1i1 = 14, // 1 x i1
+ v2i1 = 15, // 2 x i1
+ v4i1 = 16, // 4 x i1
+ v8i1 = 17, // 8 x i1
+ v16i1 = 18, // 16 x i1
+ v32i1 = 19, // 32 x i1
+ v64i1 = 20, // 64 x i1
+ v512i1 = 21, // 512 x i1
+ v1024i1 = 22, // 1024 x i1
+
+ v1i8 = 23, // 1 x i8
+ v2i8 = 24, // 2 x i8
+ v4i8 = 25, // 4 x i8
+ v8i8 = 26, // 8 x i8
+ v16i8 = 27, // 16 x i8
+ v32i8 = 28, // 32 x i8
+ v64i8 = 29, // 64 x i8
+ v128i8 = 30, //128 x i8
+ v256i8 = 31, //256 x i8
+
+ v1i16 = 32, // 1 x i16
+ v2i16 = 33, // 2 x i16
+ v4i16 = 34, // 4 x i16
+ v8i16 = 35, // 8 x i16
+ v16i16 = 36, // 16 x i16
+ v32i16 = 37, // 32 x i16
+ v64i16 = 38, // 64 x i16
+ v128i16 = 39, //128 x i16
+
+ v1i32 = 40, // 1 x i32
+ v2i32 = 41, // 2 x i32
+ v4i32 = 42, // 4 x i32
+ v8i32 = 43, // 8 x i32
+ v16i32 = 44, // 16 x i32
+ v32i32 = 45, // 32 x i32
+ v64i32 = 46, // 64 x i32
+
+ v1i64 = 47, // 1 x i64
+ v2i64 = 48, // 2 x i64
+ v4i64 = 49, // 4 x i64
+ v8i64 = 50, // 8 x i64
+ v16i64 = 51, // 16 x i64
+ v32i64 = 52, // 32 x i64
+
+ v1i128 = 53, // 1 x i128
// Scalable integer types
- nxv2i1 = 53, // n x 2 x i1
- nxv4i1 = 54, // n x 4 x i1
- nxv8i1 = 55, // n x 8 x i1
- nxv16i1 = 56, // n x 16 x i1
- nxv32i1 = 57, // n x 32 x i1
-
- nxv1i8 = 58, // n x 1 x i8
- nxv2i8 = 59, // n x 2 x i8
- nxv4i8 = 60, // n x 4 x i8
- nxv8i8 = 61, // n x 8 x i8
- nxv16i8 = 62, // n x 16 x i8
- nxv32i8 = 63, // n x 32 x i8
-
- nxv1i16 = 64, // n x 1 x i16
- nxv2i16 = 65, // n x 2 x i16
- nxv4i16 = 66, // n x 4 x i16
- nxv8i16 = 67, // n x 8 x i16
- nxv16i16 = 68, // n x 16 x i16
- nxv32i16 = 69, // n x 32 x i16
-
- nxv1i32 = 70, // n x 1 x i32
- nxv2i32 = 71, // n x 2 x i32
- nxv4i32 = 72, // n x 4 x i32
- nxv8i32 = 73, // n x 8 x i32
- nxv16i32 = 74, // n x 16 x i32
- nxv32i32 = 75, // n x 32 x i32
-
- nxv1i64 = 76, // n x 1 x i64
- nxv2i64 = 77, // n x 2 x i64
- nxv4i64 = 78, // n x 4 x i64
- nxv8i64 = 79, // n x 8 x i64
- nxv16i64 = 80, // n x 16 x i64
- nxv32i64 = 81, // n x 32 x i64
-
- FIRST_INTEGER_VECTOR_VALUETYPE = v2i1,
+ nxv1i1 = 54, // n x 1 x i1
+ nxv2i1 = 55, // n x 2 x i1
+ nxv4i1 = 56, // n x 4 x i1
+ nxv8i1 = 57, // n x 8 x i1
+ nxv16i1 = 58, // n x 16 x i1
+ nxv32i1 = 59, // n x 32 x i1
+
+ nxv1i8 = 60, // n x 1 x i8
+ nxv2i8 = 61, // n x 2 x i8
+ nxv4i8 = 62, // n x 4 x i8
+ nxv8i8 = 63, // n x 8 x i8
+ nxv16i8 = 64, // n x 16 x i8
+ nxv32i8 = 65, // n x 32 x i8
+
+ nxv1i16 = 66, // n x 1 x i16
+ nxv2i16 = 67, // n x 2 x i16
+ nxv4i16 = 68, // n x 4 x i16
+ nxv8i16 = 69, // n x 8 x i16
+ nxv16i16 = 70, // n x 16 x i16
+ nxv32i16 = 71, // n x 32 x i16
+
+ nxv1i32 = 72, // n x 1 x i32
+ nxv2i32 = 73, // n x 2 x i32
+ nxv4i32 = 74, // n x 4 x i32
+ nxv8i32 = 75, // n x 8 x i32
+ nxv16i32 = 76, // n x 16 x i32
+ nxv32i32 = 77, // n x 32 x i32
+
+ nxv1i64 = 78, // n x 1 x i64
+ nxv2i64 = 79, // n x 2 x i64
+ nxv4i64 = 80, // n x 4 x i64
+ nxv8i64 = 81, // n x 8 x i64
+ nxv16i64 = 82, // n x 16 x i64
+ nxv32i64 = 83, // n x 32 x i64
+
+ FIRST_INTEGER_VECTOR_VALUETYPE = v1i1,
LAST_INTEGER_VECTOR_VALUETYPE = nxv32i64,
- FIRST_INTEGER_SCALABLE_VALUETYPE = nxv2i1,
+ FIRST_INTEGER_SCALABLE_VALUETYPE = nxv1i1,
LAST_INTEGER_SCALABLE_VALUETYPE = nxv32i64,
- v2f16 = 82, // 2 x f16
- v4f16 = 83, // 4 x f16
- v8f16 = 84, // 8 x f16
- v1f32 = 85, // 1 x f32
- v2f32 = 86, // 2 x f32
- v4f32 = 87, // 4 x f32
- v8f32 = 88, // 8 x f32
- v16f32 = 89, // 16 x f32
- v1f64 = 90, // 1 x f64
- v2f64 = 91, // 2 x f64
- v4f64 = 92, // 4 x f64
- v8f64 = 93, // 8 x f64
-
- nxv2f16 = 94, // n x 2 x f16
- nxv4f16 = 95, // n x 4 x f16
- nxv8f16 = 96, // n x 8 x f16
- nxv1f32 = 97, // n x 1 x f32
- nxv2f32 = 98, // n x 2 x f32
- nxv4f32 = 99, // n x 4 x f32
- nxv8f32 = 100, // n x 8 x f32
- nxv16f32 = 101, // n x 16 x f32
- nxv1f64 = 102, // n x 1 x f64
- nxv2f64 = 103, // n x 2 x f64
- nxv4f64 = 104, // n x 4 x f64
- nxv8f64 = 105, // n x 8 x f64
+ v2f16 = 84, // 2 x f16
+ v4f16 = 85, // 4 x f16
+ v8f16 = 86, // 8 x f16
+ v1f32 = 87, // 1 x f32
+ v2f32 = 88, // 2 x f32
+ v4f32 = 89, // 4 x f32
+ v8f32 = 90, // 8 x f32
+ v16f32 = 91, // 16 x f32
+ v1f64 = 92, // 1 x f64
+ v2f64 = 93, // 2 x f64
+ v4f64 = 94, // 4 x f64
+ v8f64 = 95, // 8 x f64
+
+ nxv2f16 = 96, // n x 2 x f16
+ nxv4f16 = 97, // n x 4 x f16
+ nxv8f16 = 98, // n x 8 x f16
+ nxv1f32 = 99, // n x 1 x f32
+ nxv2f32 = 100, // n x 2 x f32
+ nxv4f32 = 101, // n x 4 x f32
+ nxv8f32 = 102, // n x 8 x f32
+ nxv16f32 = 103, // n x 16 x f32
+ nxv1f64 = 104, // n x 1 x f64
+ nxv2f64 = 105, // n x 2 x f64
+ nxv4f64 = 106, // n x 4 x f64
+ nxv8f64 = 107, // n x 8 x f64
FIRST_FP_VECTOR_VALUETYPE = v2f16,
LAST_FP_VECTOR_VALUETYPE = nxv8f64,
@@ -174,21 +176,21 @@ class MVT {
FIRST_FP_SCALABLE_VALUETYPE = nxv2f16,
LAST_FP_SCALABLE_VALUETYPE = nxv8f64,
- FIRST_VECTOR_VALUETYPE = v2i1,
+ FIRST_VECTOR_VALUETYPE = v1i1,
LAST_VECTOR_VALUETYPE = nxv8f64,
- x86mmx = 106, // This is an X86 MMX value
+ x86mmx = 108, // This is an X86 MMX value
- Glue = 107, // This glues nodes together during pre-RA sched
+ Glue = 109, // This glues nodes together during pre-RA sched
- isVoid = 108, // This has no value
+ isVoid = 110, // This has no value
- Untyped = 109, // This value takes a register, but has
+ Untyped = 111, // This value takes a register, but has
// unspecified type. The register class
// will be determined by the opcode.
FIRST_VALUETYPE = 1, // This is always the beginning of the list.
- LAST_VALUETYPE = 110, // This always remains at the end of the list.
+ LAST_VALUETYPE = 112, // This always remains at the end of the list.
// This is the current maximum for LAST_VALUETYPE.
// MVT::MAX_ALLOWED_VALUETYPE is used for asserts and to size bit vectors
@@ -411,6 +413,7 @@ class MVT {
switch (SimpleTy) {
default:
llvm_unreachable("Not a vector MVT!");
+ case v1i1:
case v2i1:
case v4i1:
case v8i1:
@@ -419,6 +422,7 @@ class MVT {
case v64i1:
case v512i1:
case v1024i1:
+ case nxv1i1:
case nxv2i1:
case nxv4i1:
case nxv8i1:
@@ -589,6 +593,7 @@ class MVT {
case nxv2f16:
case nxv2f32:
case nxv2f64: return 2;
+ case v1i1:
case v1i8:
case v1i16:
case v1i32:
@@ -596,6 +601,7 @@ class MVT {
case v1i128:
case v1f32:
case v1f64:
+ case nxv1i1:
case nxv1i8:
case nxv1i16:
case nxv1i32:
@@ -628,7 +634,9 @@ class MVT {
"in codegen and has no size");
case Metadata:
llvm_unreachable("Value type is metadata.");
- case i1 : return 1;
+ case i1:
+ case v1i1:
+ case nxv1i1: return 1;
case v2i1:
case nxv2i1: return 2;
case v4i1:
@@ -814,6 +822,7 @@ class MVT {
default:
break;
case MVT::i1:
+ if (NumElements == 1) return MVT::v1i1;
if (NumElements == 2) return MVT::v2i1;
if (NumElements == 4) return MVT::v4i1;
if (NumElements == 8) return MVT::v8i1;
@@ -891,6 +900,7 @@ class MVT {
default:
break;
case MVT::i1:
+ if (NumElements == 1) return MVT::nxv1i1;
if (NumElements == 2) return MVT::nxv2i1;
if (NumElements == 4) return MVT::nxv4i1;
if (NumElements == 8) return MVT::nxv8i1;
diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h
index 8a5a1997386f..f3e04cffcda6 100644
--- a/include/llvm/CodeGen/Passes.h
+++ b/include/llvm/CodeGen/Passes.h
@@ -33,7 +33,7 @@ class raw_ostream;
/// List of target independent CodeGen pass IDs.
namespace llvm {
- FunctionPass *createAtomicExpandPass(const TargetMachine *TM);
+ FunctionPass *createAtomicExpandPass();
/// createUnreachableBlockEliminationPass - The LLVM code generator does not
/// work well with unreachable basic blocks (what live ranges make sense for a
@@ -66,7 +66,7 @@ namespace llvm {
/// createCodeGenPreparePass - Transform the code to expose more pattern
/// matching during instruction selection.
- FunctionPass *createCodeGenPreparePass(const TargetMachine *TM = nullptr);
+ FunctionPass *createCodeGenPreparePass();
/// createScalarizeMaskedMemIntrinPass - Replace masked load, store, gather
/// and scatter intrinsics with scalar code when target doesn't support them.
@@ -133,10 +133,6 @@ namespace llvm {
// instruction and update the MachineFunctionInfo with that information.
extern char &ShrinkWrapID;
- /// LiveRangeShrink pass. Move instruction close to its definition to shrink
- /// the definition's live range.
- extern char &LiveRangeShrinkID;
-
/// Greedy register allocator.
extern char &RAGreedyID;
@@ -177,7 +173,7 @@ namespace llvm {
/// PrologEpilogCodeInserter - This pass inserts prolog and epilog code,
/// and eliminates abstract frame references.
extern char &PrologEpilogCodeInserterID;
- MachineFunctionPass *createPrologEpilogInserterPass(const TargetMachine *TM);
+ MachineFunctionPass *createPrologEpilogInserterPass();
/// ExpandPostRAPseudos - This pass expands pseudo instructions after
/// register allocation.
@@ -305,7 +301,7 @@ namespace llvm {
/// createStackProtectorPass - This pass adds stack protectors to functions.
///
- FunctionPass *createStackProtectorPass(const TargetMachine *TM);
+ FunctionPass *createStackProtectorPass();
/// createMachineVerifierPass - This pass verifies cenerated machine code
/// instructions for correctness.
@@ -314,11 +310,11 @@ namespace llvm {
/// createDwarfEHPass - This pass mulches exception handling code into a form
/// adapted to code generation. Required if using dwarf exception handling.
- FunctionPass *createDwarfEHPass(const TargetMachine *TM);
+ FunctionPass *createDwarfEHPass();
/// createWinEHPass - Prepares personality functions used by MSVC on Windows,
/// in addition to the Itanium LSDA based personalities.
- FunctionPass *createWinEHPass(const TargetMachine *TM);
+ FunctionPass *createWinEHPass();
/// createSjLjEHPreparePass - This pass adapts exception handling code to use
/// the GCC-style builtin setjmp/longjmp (sjlj) to handling EH control flow.
@@ -362,12 +358,12 @@ namespace llvm {
/// InterleavedAccess Pass - This pass identifies and matches interleaved
/// memory accesses to target specific intrinsics.
///
- FunctionPass *createInterleavedAccessPass(const TargetMachine *TM);
+ FunctionPass *createInterleavedAccessPass();
/// LowerEmuTLS - This pass generates __emutls_[vt].xyz variables for all
/// TLS variables for the emulated TLS model.
///
- ModulePass *createLowerEmuTLSPass(const TargetMachine *TM);
+ ModulePass *createLowerEmuTLSPass();
/// This pass lowers the @llvm.load.relative intrinsic to instructions.
/// This is unsafe to do earlier because a pass may combine the constant
@@ -384,7 +380,7 @@ namespace llvm {
/// 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);
+ FunctionPass *createSafeStackPass();
/// This pass detects subregister lanes in a virtual register that are used
/// independently of other lanes and splits them into separate virtual
@@ -419,33 +415,4 @@ namespace llvm {
} // End llvm namespace
-/// Target machine pass initializer for passes with dependencies. Use with
-/// INITIALIZE_TM_PASS_END.
-#define INITIALIZE_TM_PASS_BEGIN INITIALIZE_PASS_BEGIN
-
-/// 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; \
- } \
- static llvm::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
-/// initialized can use target dependent interfaces. Please do not move this
-/// 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)
-
#endif
diff --git a/include/llvm/CodeGen/StackProtector.h b/include/llvm/CodeGen/StackProtector.h
index 0655f19a323e..b970de71f862 100644
--- a/include/llvm/CodeGen/StackProtector.h
+++ b/include/llvm/CodeGen/StackProtector.h
@@ -19,6 +19,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/ValueMap.h"
#include "llvm/Pass.h"
@@ -55,7 +56,7 @@ private:
/// TLI - Keep a pointer of a TargetLowering to consult for determining
/// target type sizes.
const TargetLoweringBase *TLI = nullptr;
- const Triple Trip;
+ Triple Trip;
Function *F;
Module *M;
@@ -114,17 +115,12 @@ private:
public:
static char ID; // Pass identification, replacement for typeid.
- StackProtector() : FunctionPass(ID) {
- initializeStackProtectorPass(*PassRegistry::getPassRegistry());
- }
-
- StackProtector(const TargetMachine *TM)
- : FunctionPass(ID), TM(TM), Trip(TM->getTargetTriple()),
- SSPBufferSize(8) {
+ StackProtector() : FunctionPass(ID), SSPBufferSize(8) {
initializeStackProtectorPass(*PassRegistry::getPassRegistry());
}
void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.addRequired<TargetPassConfig>();
AU.addPreserved<DominatorTreeWrapperPass>();
}
diff --git a/include/llvm/CodeGen/ValueTypes.td b/include/llvm/CodeGen/ValueTypes.td
index b87a5e56699e..b1e62daa5aae 100644
--- a/include/llvm/CodeGen/ValueTypes.td
+++ b/include/llvm/CodeGen/ValueTypes.td
@@ -33,115 +33,117 @@ def f80 : ValueType<80 , 11>; // 80-bit floating point value
def f128 : ValueType<128, 12>; // 128-bit floating point value
def ppcf128: ValueType<128, 13>; // PPC 128-bit floating point value
-def v2i1 : ValueType<2 , 14>; // 2 x i1 vector value
-def v4i1 : ValueType<4 , 15>; // 4 x i1 vector value
-def v8i1 : ValueType<8 , 16>; // 8 x i1 vector value
-def v16i1 : ValueType<16, 17>; // 16 x i1 vector value
-def v32i1 : ValueType<32 , 18>; // 32 x i1 vector value
-def v64i1 : ValueType<64 , 19>; // 64 x i1 vector value
-def v512i1 : ValueType<512, 20>; // 512 x i1 vector value
-def v1024i1: ValueType<1024,21>; //1024 x i1 vector value
-
-def v1i8 : ValueType<8, 22>; // 1 x i8 vector value
-def v2i8 : ValueType<16 , 23>; // 2 x i8 vector value
-def v4i8 : ValueType<32 , 24>; // 4 x i8 vector value
-def v8i8 : ValueType<64 , 25>; // 8 x i8 vector value
-def v16i8 : ValueType<128, 26>; // 16 x i8 vector value
-def v32i8 : ValueType<256, 27>; // 32 x i8 vector value
-def v64i8 : ValueType<512, 28>; // 64 x i8 vector value
-def v128i8 : ValueType<1024,29>; //128 x i8 vector value
-def v256i8 : ValueType<2048,30>; //256 x i8 vector value
-
-def v1i16 : ValueType<16 , 31>; // 1 x i16 vector value
-def v2i16 : ValueType<32 , 32>; // 2 x i16 vector value
-def v4i16 : ValueType<64 , 33>; // 4 x i16 vector value
-def v8i16 : ValueType<128, 34>; // 8 x i16 vector value
-def v16i16 : ValueType<256, 35>; // 16 x i16 vector value
-def v32i16 : ValueType<512, 36>; // 32 x i16 vector value
-def v64i16 : ValueType<1024,37>; // 64 x i16 vector value
-def v128i16: ValueType<2048,38>; //128 x i16 vector value
-
-def v1i32 : ValueType<32 , 39>; // 1 x i32 vector value
-def v2i32 : ValueType<64 , 40>; // 2 x i32 vector value
-def v4i32 : ValueType<128, 41>; // 4 x i32 vector value
-def v8i32 : ValueType<256, 42>; // 8 x i32 vector value
-def v16i32 : ValueType<512, 43>; // 16 x i32 vector value
-def v32i32 : ValueType<1024,44>; // 32 x i32 vector value
-def v64i32 : ValueType<2048,45>; // 32 x i32 vector value
-
-def v1i64 : ValueType<64 , 46>; // 1 x i64 vector value
-def v2i64 : ValueType<128, 47>; // 2 x i64 vector value
-def v4i64 : ValueType<256, 48>; // 4 x i64 vector value
-def v8i64 : ValueType<512, 49>; // 8 x i64 vector value
-def v16i64 : ValueType<1024,50>; // 16 x i64 vector value
-def v32i64 : ValueType<2048,51>; // 32 x i64 vector value
-
-def v1i128 : ValueType<128, 52>; // 1 x i128 vector value
-
-def nxv2i1 : ValueType<2, 53>; // n x 2 x i1 vector value
-def nxv4i1 : ValueType<4, 54>; // n x 4 x i1 vector value
-def nxv8i1 : ValueType<8, 55>; // n x 8 x i1 vector value
-def nxv16i1 : ValueType<16, 56>; // n x 16 x i1 vector value
-def nxv32i1 : ValueType<32, 57>; // n x 32 x i1 vector value
-
-def nxv1i8 : ValueType<8, 58>; // n x 1 x i8 vector value
-def nxv2i8 : ValueType<16, 59>; // n x 2 x i8 vector value
-def nxv4i8 : ValueType<32, 60>; // n x 4 x i8 vector value
-def nxv8i8 : ValueType<64, 61>; // n x 8 x i8 vector value
-def nxv16i8 : ValueType<128, 62>; // n x 16 x i8 vector value
-def nxv32i8 : ValueType<256, 63>; // n x 32 x i8 vector value
-
-def nxv1i16 : ValueType<16, 64>; // n x 1 x i16 vector value
-def nxv2i16 : ValueType<32, 65>; // n x 2 x i16 vector value
-def nxv4i16 : ValueType<64, 66>; // n x 4 x i16 vector value
-def nxv8i16 : ValueType<128, 67>; // n x 8 x i16 vector value
-def nxv16i16: ValueType<256, 68>; // n x 16 x i16 vector value
-def nxv32i16: ValueType<512, 69>; // n x 32 x i16 vector value
-
-def nxv1i32 : ValueType<32, 70>; // n x 1 x i32 vector value
-def nxv2i32 : ValueType<64, 71>; // n x 2 x i32 vector value
-def nxv4i32 : ValueType<128, 72>; // n x 4 x i32 vector value
-def nxv8i32 : ValueType<256, 73>; // n x 8 x i32 vector value
-def nxv16i32: ValueType<512, 74>; // n x 16 x i32 vector value
-def nxv32i32: ValueType<1024,75>; // n x 32 x i32 vector value
-
-def nxv1i64 : ValueType<64, 76>; // n x 1 x i64 vector value
-def nxv2i64 : ValueType<128, 77>; // n x 2 x i64 vector value
-def nxv4i64 : ValueType<256, 78>; // n x 4 x i64 vector value
-def nxv8i64 : ValueType<512, 79>; // n x 8 x i64 vector value
-def nxv16i64: ValueType<1024,80>; // n x 16 x i64 vector value
-def nxv32i64: ValueType<2048,81>; // n x 32 x i64 vector value
-
-def v2f16 : ValueType<32 , 82>; // 2 x f16 vector value
-def v4f16 : ValueType<64 , 83>; // 4 x f16 vector value
-def v8f16 : ValueType<128, 84>; // 8 x f16 vector value
-def v1f32 : ValueType<32 , 85>; // 1 x f32 vector value
-def v2f32 : ValueType<64 , 86>; // 2 x f32 vector value
-def v4f32 : ValueType<128, 87>; // 4 x f32 vector value
-def v8f32 : ValueType<256, 88>; // 8 x f32 vector value
-def v16f32 : ValueType<512, 89>; // 16 x f32 vector value
-def v1f64 : ValueType<64, 90>; // 1 x f64 vector value
-def v2f64 : ValueType<128, 91>; // 2 x f64 vector value
-def v4f64 : ValueType<256, 92>; // 4 x f64 vector value
-def v8f64 : ValueType<512, 93>; // 8 x f64 vector value
-
-def nxv2f16 : ValueType<32 , 94>; // n x 2 x f16 vector value
-def nxv4f16 : ValueType<64 , 95>; // n x 4 x f16 vector value
-def nxv8f16 : ValueType<128, 96>; // n x 8 x f16 vector value
-def nxv1f32 : ValueType<32 , 97>; // n x 1 x f32 vector value
-def nxv2f32 : ValueType<64 , 98>; // n x 2 x f32 vector value
-def nxv4f32 : ValueType<128, 99>; // n x 4 x f32 vector value
-def nxv8f32 : ValueType<256, 100>; // n x 8 x f32 vector value
-def nxv16f32 : ValueType<512, 101>; // n x 16 x f32 vector value
-def nxv1f64 : ValueType<64, 102>; // n x 1 x f64 vector value
-def nxv2f64 : ValueType<128, 103>; // n x 2 x f64 vector value
-def nxv4f64 : ValueType<256, 104>; // n x 4 x f64 vector value
-def nxv8f64 : ValueType<512, 105>; // n x 8 x f64 vector value
-
-def x86mmx : ValueType<64 , 106>; // X86 MMX value
-def FlagVT : ValueType<0 , 107>; // Pre-RA sched glue
-def isVoid : ValueType<0 , 108>; // Produces no value
-def untyped: ValueType<8 , 109>; // Produces an untyped value
+def v1i1 : ValueType<1 , 14>; // 1 x i1 vector value
+def v2i1 : ValueType<2 , 15>; // 2 x i1 vector value
+def v4i1 : ValueType<4 , 16>; // 4 x i1 vector value
+def v8i1 : ValueType<8 , 17>; // 8 x i1 vector value
+def v16i1 : ValueType<16, 18>; // 16 x i1 vector value
+def v32i1 : ValueType<32 , 19>; // 32 x i1 vector value
+def v64i1 : ValueType<64 , 20>; // 64 x i1 vector value
+def v512i1 : ValueType<512, 21>; // 512 x i1 vector value
+def v1024i1: ValueType<1024,22>; //1024 x i1 vector value
+
+def v1i8 : ValueType<8, 23>; // 1 x i8 vector value
+def v2i8 : ValueType<16 , 24>; // 2 x i8 vector value
+def v4i8 : ValueType<32 , 25>; // 4 x i8 vector value
+def v8i8 : ValueType<64 , 26>; // 8 x i8 vector value
+def v16i8 : ValueType<128, 27>; // 16 x i8 vector value
+def v32i8 : ValueType<256, 28>; // 32 x i8 vector value
+def v64i8 : ValueType<512, 29>; // 64 x i8 vector value
+def v128i8 : ValueType<1024,30>; //128 x i8 vector value
+def v256i8 : ValueType<2048,31>; //256 x i8 vector value
+
+def v1i16 : ValueType<16 , 32>; // 1 x i16 vector value
+def v2i16 : ValueType<32 , 33>; // 2 x i16 vector value
+def v4i16 : ValueType<64 , 34>; // 4 x i16 vector value
+def v8i16 : ValueType<128, 35>; // 8 x i16 vector value
+def v16i16 : ValueType<256, 36>; // 16 x i16 vector value
+def v32i16 : ValueType<512, 37>; // 32 x i16 vector value
+def v64i16 : ValueType<1024,38>; // 64 x i16 vector value
+def v128i16: ValueType<2048,39>; //128 x i16 vector value
+
+def v1i32 : ValueType<32 , 40>; // 1 x i32 vector value
+def v2i32 : ValueType<64 , 41>; // 2 x i32 vector value
+def v4i32 : ValueType<128, 42>; // 4 x i32 vector value
+def v8i32 : ValueType<256, 43>; // 8 x i32 vector value
+def v16i32 : ValueType<512, 44>; // 16 x i32 vector value
+def v32i32 : ValueType<1024,45>; // 32 x i32 vector value
+def v64i32 : ValueType<2048,46>; // 32 x i32 vector value
+
+def v1i64 : ValueType<64 , 47>; // 1 x i64 vector value
+def v2i64 : ValueType<128, 48>; // 2 x i64 vector value
+def v4i64 : ValueType<256, 49>; // 4 x i64 vector value
+def v8i64 : ValueType<512, 50>; // 8 x i64 vector value
+def v16i64 : ValueType<1024,51>; // 16 x i64 vector value
+def v32i64 : ValueType<2048,52>; // 32 x i64 vector value
+
+def v1i128 : ValueType<128, 53>; // 1 x i128 vector value
+
+def nxv1i1 : ValueType<1, 54>; // n x 1 x i1 vector value
+def nxv2i1 : ValueType<2, 55>; // n x 2 x i1 vector value
+def nxv4i1 : ValueType<4, 56>; // n x 4 x i1 vector value
+def nxv8i1 : ValueType<8, 57>; // n x 8 x i1 vector value
+def nxv16i1 : ValueType<16, 58>; // n x 16 x i1 vector value
+def nxv32i1 : ValueType<32, 59>; // n x 32 x i1 vector value
+
+def nxv1i8 : ValueType<8, 60>; // n x 1 x i8 vector value
+def nxv2i8 : ValueType<16, 61>; // n x 2 x i8 vector value
+def nxv4i8 : ValueType<32, 62>; // n x 4 x i8 vector value
+def nxv8i8 : ValueType<64, 63>; // n x 8 x i8 vector value
+def nxv16i8 : ValueType<128, 64>; // n x 16 x i8 vector value
+def nxv32i8 : ValueType<256, 65>; // n x 32 x i8 vector value
+
+def nxv1i16 : ValueType<16, 66>; // n x 1 x i16 vector value
+def nxv2i16 : ValueType<32, 67>; // n x 2 x i16 vector value
+def nxv4i16 : ValueType<64, 68>; // n x 4 x i16 vector value
+def nxv8i16 : ValueType<128, 69>; // n x 8 x i16 vector value
+def nxv16i16: ValueType<256, 70>; // n x 16 x i16 vector value
+def nxv32i16: ValueType<512, 71>; // n x 32 x i16 vector value
+
+def nxv1i32 : ValueType<32, 72>; // n x 1 x i32 vector value
+def nxv2i32 : ValueType<64, 73>; // n x 2 x i32 vector value
+def nxv4i32 : ValueType<128, 74>; // n x 4 x i32 vector value
+def nxv8i32 : ValueType<256, 75>; // n x 8 x i32 vector value
+def nxv16i32: ValueType<512, 76>; // n x 16 x i32 vector value
+def nxv32i32: ValueType<1024,77>; // n x 32 x i32 vector value
+
+def nxv1i64 : ValueType<64, 78>; // n x 1 x i64 vector value
+def nxv2i64 : ValueType<128, 79>; // n x 2 x i64 vector value
+def nxv4i64 : ValueType<256, 80>; // n x 4 x i64 vector value
+def nxv8i64 : ValueType<512, 81>; // n x 8 x i64 vector value
+def nxv16i64: ValueType<1024,82>; // n x 16 x i64 vector value
+def nxv32i64: ValueType<2048,83>; // n x 32 x i64 vector value
+
+def v2f16 : ValueType<32 , 84>; // 2 x f16 vector value
+def v4f16 : ValueType<64 , 85>; // 4 x f16 vector value
+def v8f16 : ValueType<128, 86>; // 8 x f16 vector value
+def v1f32 : ValueType<32 , 87>; // 1 x f32 vector value
+def v2f32 : ValueType<64 , 88>; // 2 x f32 vector value
+def v4f32 : ValueType<128, 89>; // 4 x f32 vector value
+def v8f32 : ValueType<256, 90>; // 8 x f32 vector value
+def v16f32 : ValueType<512, 91>; // 16 x f32 vector value
+def v1f64 : ValueType<64, 92>; // 1 x f64 vector value
+def v2f64 : ValueType<128, 93>; // 2 x f64 vector value
+def v4f64 : ValueType<256, 94>; // 4 x f64 vector value
+def v8f64 : ValueType<512, 95>; // 8 x f64 vector value
+
+def nxv2f16 : ValueType<32 , 96>; // n x 2 x f16 vector value
+def nxv4f16 : ValueType<64 , 97>; // n x 4 x f16 vector value
+def nxv8f16 : ValueType<128, 98>; // n x 8 x f16 vector value
+def nxv1f32 : ValueType<32 , 99>; // n x 1 x f32 vector value
+def nxv2f32 : ValueType<64 , 100>; // n x 2 x f32 vector value
+def nxv4f32 : ValueType<128, 101>; // n x 4 x f32 vector value
+def nxv8f32 : ValueType<256, 102>; // n x 8 x f32 vector value
+def nxv16f32 : ValueType<512, 103>; // n x 16 x f32 vector value
+def nxv1f64 : ValueType<64, 104>; // n x 1 x f64 vector value
+def nxv2f64 : ValueType<128, 105>; // n x 2 x f64 vector value
+def nxv4f64 : ValueType<256, 106>; // n x 4 x f64 vector value
+def nxv8f64 : ValueType<512, 107>; // n x 8 x f64 vector value
+
+def x86mmx : ValueType<64 , 108>; // X86 MMX value
+def FlagVT : ValueType<0 , 109>; // Pre-RA sched glue
+def isVoid : ValueType<0 , 110>; // Produces no value
+def untyped: ValueType<8 , 111>; // Produces an untyped value
def token : ValueType<0 , 248>; // TokenTy
def MetadataVT: ValueType<0, 249>; // Metadata
diff --git a/include/llvm/DebugInfo/CodeView/CVRecord.h b/include/llvm/DebugInfo/CodeView/CVRecord.h
index ac8aaafeadc1..71ea82b6a9ab 100644
--- a/include/llvm/DebugInfo/CodeView/CVRecord.h
+++ b/include/llvm/DebugInfo/CodeView/CVRecord.h
@@ -32,6 +32,10 @@ public:
uint32_t length() const { return RecordData.size(); }
Kind kind() const { return Type; }
ArrayRef<uint8_t> data() const { return RecordData; }
+ StringRef str_data() const {
+ return StringRef(reinterpret_cast<const char *>(RecordData.data()),
+ RecordData.size());
+ }
ArrayRef<uint8_t> content() const {
return RecordData.drop_front(sizeof(RecordPrefix));
diff --git a/include/llvm/DebugInfo/CodeView/CVTypeDumper.h b/include/llvm/DebugInfo/CodeView/CVTypeDumper.h
deleted file mode 100644
index 02f14ea2107b..000000000000
--- a/include/llvm/DebugInfo/CodeView/CVTypeDumper.h
+++ /dev/null
@@ -1,61 +0,0 @@
-//===-- CVTypeDumper.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_CVTYPEDUMPER_H
-#define LLVM_DEBUGINFO_CODEVIEW_CVTYPEDUMPER_H
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringSet.h"
-#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
-#include "llvm/DebugInfo/CodeView/TypeIndex.h"
-#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
-#include "llvm/Support/ScopedPrinter.h"
-
-namespace llvm {
-
-namespace codeview {
-
-class TypeServerHandler;
-
-/// Dumper for CodeView type streams found in COFF object files and PDB files.
-class CVTypeDumper {
-public:
- explicit CVTypeDumper(TypeDatabase &TypeDB,
- TypeServerHandler *Handler = nullptr)
- : TypeDB(TypeDB), Handler(Handler) {}
-
- /// 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 CVType &Record, TypeVisitorCallbacks &Dumper);
-
- /// Dumps the type records in Types. Returns false if there was a type stream
- /// parse error, and true otherwise.
- Error dump(const CVTypeArray &Types, TypeVisitorCallbacks &Dumper);
-
- /// 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, TypeVisitorCallbacks &Dumper);
-
- static void printTypeIndex(ScopedPrinter &Printer, StringRef FieldName,
- TypeIndex TI, TypeDatabase &DB);
-
-private:
- TypeDatabase &TypeDB;
- TypeServerHandler *Handler;
-};
-
-} // end namespace codeview
-} // end namespace llvm
-
-#endif // LLVM_DEBUGINFO_CODEVIEW_TYPEDUMPER_H
diff --git a/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h b/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
index 6d9f345755ab..4bc8fbefd5d8 100644
--- a/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
+++ b/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
@@ -10,42 +10,15 @@
#ifndef LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H
#define LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H
-#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/DebugInfo/CodeView/CVRecord.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/CodeView/TypeServerHandler.h"
-#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
#include "llvm/Support/Error.h"
namespace llvm {
namespace codeview {
-
-class CVTypeVisitor {
-public:
- explicit CVTypeVisitor(TypeVisitorCallbacks &Callbacks);
-
- void addTypeServerHandler(TypeServerHandler &Handler);
-
- Error visitTypeRecord(CVType &Record, TypeIndex Index);
- Error visitTypeRecord(CVType &Record);
- Error visitMemberRecord(CVMemberRecord Record);
-
- /// Visits the type records in Data. Sets the error flag on parse failures.
- Error visitTypeStream(const CVTypeArray &Types);
- Error visitTypeStream(CVTypeRange Types);
-
- Error visitFieldListMemberStream(ArrayRef<uint8_t> FieldList);
- Error visitFieldListMemberStream(BinaryStreamReader Reader);
-
-private:
- Expected<bool> handleTypeServer(CVType &Record);
- Error finishVisitation(CVType &Record);
-
- /// The interface to the class that gets notified of each visitation.
- TypeVisitorCallbacks &Callbacks;
-
- TinyPtrVector<TypeServerHandler *> Handlers;
-};
+class TypeCollection;
+class TypeServerHandler;
+class TypeVisitorCallbacks;
enum VisitorDataSource {
VDS_BytesPresent, // The record bytes are passed into the the visitation
@@ -76,6 +49,8 @@ Error visitTypeStream(const CVTypeArray &Types, TypeVisitorCallbacks &Callbacks,
TypeServerHandler *TS = nullptr);
Error visitTypeStream(CVTypeRange Types, TypeVisitorCallbacks &Callbacks,
TypeServerHandler *TS = nullptr);
+Error visitTypeStream(TypeCollection &Types, TypeVisitorCallbacks &Callbacks,
+ TypeServerHandler *TS = nullptr);
} // end namespace codeview
} // end namespace llvm
diff --git a/include/llvm/DebugInfo/CodeView/RandomAccessTypeVisitor.h b/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h
index 21288df89be2..0d056e42b45f 100644
--- a/include/llvm/DebugInfo/CodeView/RandomAccessTypeVisitor.h
+++ b/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h
@@ -1,4 +1,4 @@
-//===- RandomAccessTypeVisitor.h ------------------------------ *- C++ --*-===//
+//===- LazyRandomTypeCollection.h ---------------------------- *- C++ --*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,10 +7,10 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_DEBUGINFO_CODEVIEW_RANDOMACCESSTYPEVISITOR_H
-#define LLVM_DEBUGINFO_CODEVIEW_RANDOMACCESSTYPEVISITOR_H
+#ifndef LLVM_DEBUGINFO_CODEVIEW_LAZYRANDOMTYPECOLLECTION_H
+#define LLVM_DEBUGINFO_CODEVIEW_LAZYRANDOMTYPECOLLECTION_H
-#include "llvm/ADT/TinyPtrVector.h"
+#include "llvm/DebugInfo/CodeView/TypeCollection.h"
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
@@ -21,7 +21,6 @@ namespace llvm {
namespace codeview {
class TypeDatabase;
-class TypeServerHandler;
class TypeVisitorCallbacks;
/// \brief Provides amortized O(1) random access to a CodeView type stream.
@@ -40,32 +39,48 @@ class TypeVisitorCallbacks;
/// consumer much better access time, because the consumer can find the nearest
/// index in this array, and do a linear scan forward only from there.
///
-/// RandomAccessTypeVisitor implements this algorithm, but additionally goes one
-/// step further by caching offsets of every record that has been visited at
+/// LazyRandomTypeCollection implements this algorithm, but additionally goes
+/// one step further by caching offsets of every record that has been visited at
/// least once. This way, even repeated visits of the same record will never
/// require more than one linear scan. For a type stream of N elements divided
/// into M chunks of roughly equal size, this yields a worst case lookup time
/// of O(N/M) and an amortized time of O(1).
-class RandomAccessTypeVisitor {
+class LazyRandomTypeCollection : public TypeCollection {
typedef FixedStreamArray<TypeIndexOffset> PartialOffsetArray;
public:
- RandomAccessTypeVisitor(const CVTypeArray &Types, uint32_t NumRecords,
- PartialOffsetArray PartialOffsets);
-
- Error visitTypeIndex(TypeIndex Index, TypeVisitorCallbacks &Callbacks);
+ explicit LazyRandomTypeCollection(uint32_t RecordCountHint);
+ LazyRandomTypeCollection(StringRef Data, uint32_t RecordCountHint);
+ LazyRandomTypeCollection(ArrayRef<uint8_t> Data, uint32_t RecordCountHint);
+ LazyRandomTypeCollection(const CVTypeArray &Types, uint32_t RecordCountHint,
+ PartialOffsetArray PartialOffsets);
+ LazyRandomTypeCollection(const CVTypeArray &Types, uint32_t RecordCountHint);
+
+ void reset(ArrayRef<uint8_t> Data);
+ void reset(StringRef Data);
+
+ CVType getType(TypeIndex Index) override;
+ StringRef getTypeName(TypeIndex Index) override;
+ bool contains(TypeIndex Index) override;
+ uint32_t size() override;
+ uint32_t capacity() override;
+ Optional<TypeIndex> getFirst() override;
+ Optional<TypeIndex> getNext(TypeIndex Prev) override;
+private:
const TypeDatabase &database() const { return Database; }
+ Error ensureTypeExists(TypeIndex Index);
-private:
Error visitRangeForType(TypeIndex TI);
+ Error fullScanForType(TypeIndex TI);
Error visitRange(TypeIndex Begin, uint32_t BeginOffset, TypeIndex End);
+ Error visitOneRecord(TypeIndex TI, uint32_t Offset, CVType &Record);
/// Visited records get automatically added to the type database.
TypeDatabase Database;
/// The type array to allow random access visitation of.
- const CVTypeArray &Types;
+ CVTypeArray Types;
/// The database visitor which adds new records to the database.
TypeDatabaseVisitor DatabaseVisitor;
@@ -85,4 +100,4 @@ private:
} // end namespace codeview
} // end namespace llvm
-#endif // LLVM_DEBUGINFO_CODEVIEW_RANDOMACCESSTYPEVISITOR_H
+#endif // LLVM_DEBUGINFO_CODEVIEW_LAZYRANDOMTYPECOLLECTION_H
diff --git a/include/llvm/DebugInfo/CodeView/SymbolDumper.h b/include/llvm/DebugInfo/CodeView/SymbolDumper.h
index a5419b37e776..e91065dcf87e 100644
--- a/include/llvm/DebugInfo/CodeView/SymbolDumper.h
+++ b/include/llvm/DebugInfo/CodeView/SymbolDumper.h
@@ -20,15 +20,15 @@ namespace llvm {
class ScopedPrinter;
namespace codeview {
-class TypeDatabase;
+class TypeCollection;
/// Dumper for CodeView symbol streams found in COFF object files and PDB files.
class CVSymbolDumper {
public:
- CVSymbolDumper(ScopedPrinter &W, TypeDatabase &TypeDB,
+ CVSymbolDumper(ScopedPrinter &W, TypeCollection &Types,
std::unique_ptr<SymbolDumpDelegate> ObjDelegate,
bool PrintRecordBytes)
- : W(W), TypeDB(TypeDB), ObjDelegate(std::move(ObjDelegate)),
+ : W(W), Types(Types), ObjDelegate(std::move(ObjDelegate)),
PrintRecordBytes(PrintRecordBytes) {}
/// Dumps one type record. Returns false if there was a type parsing error,
@@ -43,7 +43,7 @@ public:
private:
ScopedPrinter &W;
- TypeDatabase &TypeDB;
+ TypeCollection &Types;
std::unique_ptr<SymbolDumpDelegate> ObjDelegate;
bool PrintRecordBytes;
diff --git a/include/llvm/DebugInfo/CodeView/TypeCollection.h b/include/llvm/DebugInfo/CodeView/TypeCollection.h
new file mode 100644
index 000000000000..0f856f57a727
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/TypeCollection.h
@@ -0,0 +1,38 @@
+//===- TypeCollection.h - A collection of CodeView type records -*- 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_TYPECOLLECTION_H
+#define LLVM_DEBUGINFO_CODEVIEW_TYPECOLLECTION_H
+
+#include "llvm/ADT/StringRef.h"
+
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+
+namespace llvm {
+namespace codeview {
+class TypeCollection {
+public:
+ virtual ~TypeCollection() = default;
+
+ bool empty() { return size() == 0; }
+
+ virtual Optional<TypeIndex> getFirst() = 0;
+ virtual Optional<TypeIndex> getNext(TypeIndex Prev) = 0;
+
+ virtual CVType getType(TypeIndex Index) = 0;
+ virtual StringRef getTypeName(TypeIndex Index) = 0;
+ virtual bool contains(TypeIndex Index) = 0;
+ virtual uint32_t size() = 0;
+ virtual uint32_t capacity() = 0;
+};
+}
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/CodeView/TypeDatabase.h b/include/llvm/DebugInfo/CodeView/TypeDatabase.h
index 92c15ebd8b2b..a743e7f70855 100644
--- a/include/llvm/DebugInfo/CodeView/TypeDatabase.h
+++ b/include/llvm/DebugInfo/CodeView/TypeDatabase.h
@@ -13,6 +13,7 @@
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/CodeView/TypeCollection.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/Support/Allocator.h"
@@ -20,7 +21,7 @@
namespace llvm {
namespace codeview {
-class TypeDatabase {
+class TypeDatabase : public TypeCollection {
friend class RandomAccessTypeVisitor;
public:
@@ -41,19 +42,31 @@ public:
CVType &getTypeRecord(TypeIndex Index);
bool contains(TypeIndex Index) const;
-
uint32_t size() const;
uint32_t capacity() const;
bool empty() const;
- TypeIndex getAppendIndex() const;
+ CVType getType(TypeIndex Index) override;
+ StringRef getTypeName(TypeIndex Index) override;
+ bool contains(TypeIndex Index) override;
+ uint32_t size() override;
+ uint32_t capacity() override;
+
+ Optional<TypeIndex> getFirst() override;
+ Optional<TypeIndex> getNext(TypeIndex Prev) override;
+
+ Optional<TypeIndex> largestTypeIndexLessThan(TypeIndex TI) const;
private:
+ TypeIndex getAppendIndex() const;
+
void grow();
+ void grow(TypeIndex Index);
BumpPtrAllocator Allocator;
uint32_t Count = 0;
+ TypeIndex LargestTypeIndex;
/// 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
diff --git a/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h b/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h
index 6f10afb30d60..65b3a33e6548 100644
--- a/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h
+++ b/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h
@@ -12,7 +12,6 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringSet.h"
-#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
@@ -22,17 +21,20 @@ class ScopedPrinter;
namespace codeview {
+class TypeCollection;
+
/// Dumper for CodeView type streams found in COFF object files and PDB files.
class TypeDumpVisitor : public TypeVisitorCallbacks {
public:
- TypeDumpVisitor(TypeDatabase &TypeDB, ScopedPrinter *W, bool PrintRecordBytes)
- : W(W), PrintRecordBytes(PrintRecordBytes), TypeDB(TypeDB) {}
+ TypeDumpVisitor(TypeCollection &TpiTypes, ScopedPrinter *W,
+ bool PrintRecordBytes)
+ : W(W), PrintRecordBytes(PrintRecordBytes), TpiTypes(TpiTypes) {}
/// When dumping types from an IPI stream in a PDB, a type index may refer to
/// a type or an item ID. The dumper will lookup the "name" of the index in
/// the item database if appropriate. If ItemDB is null, it will use TypeDB,
/// which is correct when dumping types from an object file (/Z7).
- void setItemDB(TypeDatabase &DB) { ItemDB = &DB; }
+ void setIpiTypes(TypeCollection &Types) { IpiTypes = &Types; }
void printTypeIndex(StringRef FieldName, TypeIndex TI) const;
@@ -66,14 +68,16 @@ private:
/// Get the database of indices for the stream that we are dumping. If ItemDB
/// is set, then we must be dumping an item (IPI) stream. This will also
/// always get the appropriate DB for printing item names.
- TypeDatabase &getSourceDB() const { return ItemDB ? *ItemDB : TypeDB; }
+ TypeCollection &getSourceTypes() const {
+ return IpiTypes ? *IpiTypes : TpiTypes;
+ }
ScopedPrinter *W;
bool PrintRecordBytes = false;
- TypeDatabase &TypeDB;
- TypeDatabase *ItemDB = nullptr;
+ TypeCollection &TpiTypes;
+ TypeCollection *IpiTypes = nullptr;
};
} // end namespace codeview
diff --git a/include/llvm/DebugInfo/CodeView/TypeIndex.h b/include/llvm/DebugInfo/CodeView/TypeIndex.h
index b5d695fc49d5..31eed7d3e877 100644
--- a/include/llvm/DebugInfo/CodeView/TypeIndex.h
+++ b/include/llvm/DebugInfo/CodeView/TypeIndex.h
@@ -15,8 +15,13 @@
#include <cinttypes>
namespace llvm {
+
+class ScopedPrinter;
+
namespace codeview {
+class TypeCollection;
+
enum class SimpleTypeKind : uint32_t {
None = 0x0000, // uncharacterized type (no type)
Void = 0x0003, // void
@@ -238,6 +243,11 @@ public:
return Result;
}
+ friend inline uint32_t operator-(const TypeIndex &A, const TypeIndex &B) {
+ assert(A >= B);
+ return A.toArrayIndex() - B.toArrayIndex();
+ }
+
private:
support::ulittle32_t Index;
};
@@ -249,6 +259,9 @@ struct TypeIndexOffset {
TypeIndex Type;
support::ulittle32_t Offset;
};
+
+void printTypeIndex(ScopedPrinter &Printer, StringRef FieldName, TypeIndex TI,
+ TypeCollection &Types);
}
}
diff --git a/include/llvm/DebugInfo/CodeView/TypeSerializer.h b/include/llvm/DebugInfo/CodeView/TypeSerializer.h
index 1f4873c4f969..6dad98247136 100644
--- a/include/llvm/DebugInfo/CodeView/TypeSerializer.h
+++ b/include/llvm/DebugInfo/CodeView/TypeSerializer.h
@@ -70,6 +70,8 @@ class TypeSerializer : public TypeVisitorCallbacks {
MutableArrayRef<uint8_t> getCurrentRecordData();
Error writeRecordPrefix(TypeLeafKind Kind);
TypeIndex insertRecordBytesPrivate(MutableArrayRef<uint8_t> Record);
+ TypeIndex insertRecordBytesWithCopy(CVType &Record,
+ MutableArrayRef<uint8_t> Data);
Expected<MutableArrayRef<uint8_t>>
addPadding(MutableArrayRef<uint8_t> Record);
diff --git a/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h b/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
index 2246f197e784..65bcf9812e68 100644
--- a/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
+++ b/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
@@ -12,17 +12,20 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/Support/Error.h"
namespace llvm {
namespace codeview {
+class TypeIndex;
class TypeServerHandler;
+class TypeTableBuilder;
/// Merges one type stream into another. Returns true on success.
Error mergeTypeStreams(TypeTableBuilder &DestIdStream,
TypeTableBuilder &DestTypeStream,
+ SmallVectorImpl<TypeIndex> &SourceToDest,
TypeServerHandler *Handler, const CVTypeArray &Types);
} // end namespace codeview
diff --git a/include/llvm/DebugInfo/CodeView/TypeTableCollection.h b/include/llvm/DebugInfo/CodeView/TypeTableCollection.h
new file mode 100644
index 000000000000..7de562a19a74
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/TypeTableCollection.h
@@ -0,0 +1,42 @@
+//===- TypeTableCollection.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_TYPETABLECOLLECTION_H
+#define LLVM_DEBUGINFO_CODEVIEW_TYPETABLECOLLECTION_H
+
+#include "llvm/DebugInfo/CodeView/TypeCollection.h"
+#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
+
+namespace llvm {
+namespace codeview {
+
+class TypeTableCollection : public TypeCollection {
+public:
+ explicit TypeTableCollection(ArrayRef<MutableArrayRef<uint8_t>> Records);
+
+ Optional<TypeIndex> getFirst() override;
+ Optional<TypeIndex> getNext(TypeIndex Prev) override;
+
+ CVType getType(TypeIndex Index) override;
+ StringRef getTypeName(TypeIndex Index) override;
+ bool contains(TypeIndex Index) override;
+ uint32_t size() override;
+ uint32_t capacity() override;
+
+private:
+ bool hasCapacityFor(TypeIndex Index) const;
+ void ensureTypeExists(TypeIndex Index);
+
+ ArrayRef<MutableArrayRef<uint8_t>> Records;
+ TypeDatabase Database;
+};
+}
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h b/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h
index 2950c7d27cb6..0ea754deb425 100644
--- a/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h
+++ b/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h
@@ -17,8 +17,6 @@ namespace llvm {
namespace codeview {
class TypeVisitorCallbacks {
- friend class CVTypeVisitor;
-
public:
virtual ~TypeVisitorCallbacks() = default;
diff --git a/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h b/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h
index a46d46a5bff3..46c0b7f4ce60 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h
@@ -19,8 +19,9 @@ class DWARFCompileUnit : public DWARFUnit {
public:
DWARFCompileUnit(DWARFContext &Context, const DWARFSection &Section,
const DWARFDebugAbbrev *DA, const DWARFSection *RS,
- StringRef SS, StringRef SOS, StringRef AOS, StringRef LS,
- bool LE, bool IsDWO, const DWARFUnitSectionBase &UnitSection,
+ StringRef SS, StringRef SOS, const DWARFSection *AOS,
+ StringRef LS, bool LE, bool IsDWO,
+ const DWARFUnitSectionBase &UnitSection,
const DWARFUnitIndex::Entry *Entry)
: DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LS, LE, IsDWO,
UnitSection, Entry) {}
diff --git a/include/llvm/DebugInfo/DWARF/DWARFContext.h b/include/llvm/DebugInfo/DWARF/DWARFContext.h
index ca82a68ead31..d3a63edf10ff 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFContext.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFContext.h
@@ -235,7 +235,7 @@ public:
virtual StringRef getStringDWOSection() = 0;
virtual StringRef getStringOffsetDWOSection() = 0;
virtual const DWARFSection &getRangeDWOSection() = 0;
- virtual StringRef getAddrSection() = 0;
+ virtual const DWARFSection &getAddrSection() = 0;
virtual const DWARFSection& getAppleNamesSection() = 0;
virtual const DWARFSection& getAppleTypesSection() = 0;
virtual const DWARFSection& getAppleNamespacesSection() = 0;
@@ -290,7 +290,7 @@ class DWARFContextInMemory : public DWARFContext {
StringRef StringDWOSection;
StringRef StringOffsetDWOSection;
DWARFSection RangeDWOSection;
- StringRef AddrSection;
+ DWARFSection AddrSection;
DWARFSection AppleNamesSection;
DWARFSection AppleTypesSection;
DWARFSection AppleNamespacesSection;
@@ -356,9 +356,7 @@ public:
const DWARFSection &getRangeDWOSection() override { return RangeDWOSection; }
- StringRef getAddrSection() override {
- return AddrSection;
- }
+ const DWARFSection &getAddrSection() override { return AddrSection; }
StringRef getCUIndexSection() override { return CUIndexSection; }
StringRef getGdbIndexSection() override { return GdbIndexSection; }
diff --git a/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h b/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h
index ec0397a0fb09..fabacc0abcea 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h
@@ -17,7 +17,7 @@
namespace llvm {
struct RelocAddrEntry {
- int64_t Value;
+ uint64_t Value;
};
/// In place of applying the relocations to the data we've read from disk we use
diff --git a/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h b/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h
index c9da2c9a3e16..c77d946c070a 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h
@@ -31,8 +31,9 @@ private:
public:
DWARFTypeUnit(DWARFContext &Context, const DWARFSection &Section,
const DWARFDebugAbbrev *DA, const DWARFSection *RS,
- StringRef SS, StringRef SOS, StringRef AOS, StringRef LS,
- bool LE, bool IsDWO, const DWARFUnitSectionBase &UnitSection,
+ StringRef SS, StringRef SOS, const DWARFSection *AOS,
+ StringRef LS, bool LE, bool IsDWO,
+ const DWARFUnitSectionBase &UnitSection,
const DWARFUnitIndex::Entry *Entry)
: DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LS, LE, IsDWO,
UnitSection, Entry) {}
diff --git a/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/include/llvm/DebugInfo/DWARF/DWARFUnit.h
index c15e27f36a8b..ae7fd24ce5bb 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFUnit.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFUnit.h
@@ -57,7 +57,7 @@ protected:
virtual void parseImpl(DWARFContext &Context, const DWARFSection &Section,
const DWARFDebugAbbrev *DA, const DWARFSection *RS,
- StringRef SS, StringRef SOS, StringRef AOS,
+ StringRef SS, StringRef SOS, const DWARFSection *AOS,
StringRef LS, bool isLittleEndian, bool isDWO) = 0;
};
@@ -89,8 +89,8 @@ public:
private:
void parseImpl(DWARFContext &Context, const DWARFSection &Section,
const DWARFDebugAbbrev *DA, const DWARFSection *RS,
- StringRef SS, StringRef SOS, StringRef AOS, StringRef LS,
- bool LE, bool IsDWO) override {
+ StringRef SS, StringRef SOS, const DWARFSection *AOS,
+ StringRef LS, bool LE, bool IsDWO) override {
if (Parsed)
return;
const auto &Index = getDWARFUnitIndex(Context, UnitType::Section);
@@ -120,7 +120,7 @@ class DWARFUnit {
StringRef LineSection;
StringRef StringSection;
StringRef StringOffsetSection;
- StringRef AddrOffsetSection;
+ const DWARFSection *AddrOffsetSection;
uint32_t AddrOffsetSectionBase;
bool isLittleEndian;
bool isDWO;
@@ -149,7 +149,7 @@ class DWARFUnit {
DWARFUnit *DWOU = nullptr;
public:
- DWOHolder(StringRef DWOPath);
+ DWOHolder(StringRef DWOPath, uint64_t DWOId);
DWARFUnit *getUnit() const { return DWOU; }
};
@@ -172,8 +172,8 @@ protected:
public:
DWARFUnit(DWARFContext &Context, const DWARFSection &Section,
const DWARFDebugAbbrev *DA, const DWARFSection *RS, StringRef SS,
- StringRef SOS, StringRef AOS, StringRef LS, bool LE, bool IsDWO,
- const DWARFUnitSectionBase &UnitSection,
+ StringRef SOS, const DWARFSection *AOS, StringRef LS, bool LE,
+ bool IsDWO, const DWARFUnitSectionBase &UnitSection,
const DWARFUnitIndex::Entry *IndexEntry = nullptr);
virtual ~DWARFUnit();
@@ -184,7 +184,7 @@ public:
StringRef getStringSection() const { return StringSection; }
StringRef getStringOffsetSection() const { return StringOffsetSection; }
- void setAddrOffsetSection(StringRef AOS, uint32_t Base) {
+ void setAddrOffsetSection(const DWARFSection *AOS, uint32_t Base) {
AddrOffsetSection = AOS;
AddrOffsetSectionBase = Base;
}
diff --git a/include/llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h b/include/llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h
index d965e1008e95..bfd38b6c80ec 100644
--- a/include/llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h
+++ b/include/llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h
@@ -13,7 +13,6 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
-#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeServerHandler.h"
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
diff --git a/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h b/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h
index 6c609c34665c..21cfa83e6af4 100644
--- a/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h
+++ b/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h
@@ -72,7 +72,7 @@ private:
size_t TypeRecordBytes = 0;
- Optional<PdbRaw_TpiVer> VerHeader;
+ PdbRaw_TpiVer VerHeader = PdbRaw_TpiVer::PdbTpiV80;
std::vector<ArrayRef<uint8_t>> TypeRecords;
std::vector<uint32_t> TypeHashes;
std::vector<codeview::TypeIndexOffset> TypeIndexOffsets;
diff --git a/include/llvm/IR/Argument.h b/include/llvm/IR/Argument.h
index 5ed6d030c984..3efcc637b6ed 100644
--- a/include/llvm/IR/Argument.h
+++ b/include/llvm/IR/Argument.h
@@ -27,8 +27,7 @@ namespace llvm {
/// for a specific function. When used in the body of said function, the
/// argument of course represents the value of the actual argument that the
/// function was called with.
-class Argument : public Value {
- virtual void anchor();
+class Argument final : public Value {
Function *Parent;
unsigned ArgNo;
diff --git a/include/llvm/IR/BasicBlock.h b/include/llvm/IR/BasicBlock.h
index 97989cf5c652..c917b1f2cada 100644
--- a/include/llvm/IR/BasicBlock.h
+++ b/include/llvm/IR/BasicBlock.h
@@ -51,8 +51,8 @@ class ValueSymbolTable;
/// occur because it may be useful in the intermediate stage of constructing or
/// modifying a program. However, the verifier will ensure that basic blocks
/// are "well formed".
-class BasicBlock : public Value, // Basic blocks are data objects also
- public ilist_node_with_parent<BasicBlock, Function> {
+class BasicBlock final : public Value, // Basic blocks are data objects also
+ public ilist_node_with_parent<BasicBlock, Function> {
public:
using InstListType = SymbolTableList<Instruction>;
@@ -77,7 +77,7 @@ private:
public:
BasicBlock(const BasicBlock &) = delete;
BasicBlock &operator=(const BasicBlock &) = delete;
- ~BasicBlock() override;
+ ~BasicBlock();
/// \brief Get the context in which this basic block lives.
LLVMContext &getContext() const;
diff --git a/include/llvm/IR/Constant.h b/include/llvm/IR/Constant.h
index 3b3694e7e60d..82afd9a2691f 100644
--- a/include/llvm/IR/Constant.h
+++ b/include/llvm/IR/Constant.h
@@ -40,8 +40,6 @@ class APInt;
/// don't have to worry about the lifetime of the objects.
/// @brief LLVM Constant Representation
class Constant : public User {
- void anchor() override;
-
protected:
Constant(Type *ty, ValueTy vty, Use *Ops, unsigned NumOps)
: User(ty, vty, Ops, NumOps) {}
diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h
index 5db9b3bb5048..40a8d1eb27d0 100644
--- a/include/llvm/IR/Constants.h
+++ b/include/llvm/IR/Constants.h
@@ -58,8 +58,6 @@ template <class ConstantClass> struct ConstantAggrKeyType;
class ConstantData : public Constant {
friend class Constant;
- void anchor() override;
-
Value *handleOperandChangeImpl(Value *From, Value *To) {
llvm_unreachable("Constant data does not have operands!");
}
@@ -93,7 +91,6 @@ class ConstantInt final : public ConstantData {
ConstantInt(IntegerType *Ty, const APInt& V);
- void anchor() override;
void destroyConstantImpl();
public:
@@ -274,7 +271,6 @@ class ConstantFP final : public ConstantData {
ConstantFP(Type *Ty, const APFloat& V);
- void anchor() override;
void destroyConstantImpl();
public:
@@ -588,7 +584,7 @@ class ConstantDataSequential : public ConstantData {
protected:
explicit ConstantDataSequential(Type *ty, ValueTy VT, const char *Data)
: ConstantData(ty, VT), DataElements(Data), Next(nullptr) {}
- ~ConstantDataSequential() override { delete Next; }
+ ~ConstantDataSequential() { delete Next; }
static Constant *getImpl(StringRef Bytes, Type *Ty);
@@ -638,8 +634,8 @@ public:
/// The size of the elements is known to be a multiple of one byte.
uint64_t getElementByteSize() const;
- /// This method returns true if this is an array of i8.
- bool isString() const;
+ /// This method returns true if this is an array of \p CharSize integers.
+ bool isString(unsigned CharSize = 8) const;
/// This method returns true if the array "isString", ends with a null byte,
/// and does not contains any other null bytes.
@@ -692,8 +688,6 @@ class ConstantDataArray final : public ConstantDataSequential {
return User::operator new(s, 0);
}
- void anchor() override;
-
public:
ConstantDataArray(const ConstantDataArray &) = delete;
@@ -755,8 +749,6 @@ class ConstantDataVector final : public ConstantDataSequential {
return User::operator new(s, 0);
}
- void anchor() override;
-
public:
ConstantDataVector(const ConstantDataVector &) = delete;
diff --git a/include/llvm/IR/DerivedUser.h b/include/llvm/IR/DerivedUser.h
new file mode 100644
index 000000000000..4d681e0db611
--- /dev/null
+++ b/include/llvm/IR/DerivedUser.h
@@ -0,0 +1,41 @@
+//===-- DerivedUser.h - Base for non-IR Users -------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_DERIVEDUSER_H
+#define LLVM_IR_DERIVEDUSER_H
+
+#include "llvm/IR/User.h"
+
+namespace llvm {
+
+/// Extension point for the Value hierarchy. All classes outside of lib/IR
+/// that wish to inherit from User should instead inherit from DerivedUser
+/// instead. Inheriting from this class is discouraged.
+///
+/// Generally speaking, Value is the base of a closed class hierarchy
+/// that can't be extended by code outside of lib/IR. This class creates a
+/// loophole that allows classes outside of lib/IR to extend User to leverage
+/// its use/def list machinery.
+class DerivedUser : public User {
+protected:
+ typedef void (*DeleteValueTy)(DerivedUser *);
+
+private:
+ friend Value;
+ DeleteValueTy DeleteValue;
+
+public:
+ DerivedUser(Type *Ty, unsigned VK, Use *U, unsigned NumOps,
+ DeleteValueTy DeleteValue)
+ : User(Ty, VK, U, NumOps), DeleteValue(DeleteValue) {}
+};
+
+} // namespace llvm
+
+#endif // LLVM_IR_DERIVEDUSER_H
diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h
index 8a2a6ed87eb2..f27e5c50a47f 100644
--- a/include/llvm/IR/Function.h
+++ b/include/llvm/IR/Function.h
@@ -123,7 +123,7 @@ private:
public:
Function(const Function&) = delete;
void operator=(const Function&) = delete;
- ~Function() override;
+ ~Function();
static Function *Create(FunctionType *Ty, LinkageTypes Linkage,
const Twine &N = "", Module *M = nullptr) {
diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h
index 0793a1c0ee2e..20495725f9d0 100644
--- a/include/llvm/IR/GlobalValue.h
+++ b/include/llvm/IR/GlobalValue.h
@@ -161,6 +161,10 @@ protected:
Parent = parent;
}
+ ~GlobalValue() {
+ removeDeadConstantUsers(); // remove any dead constants using this.
+ }
+
public:
enum ThreadLocalMode {
NotThreadLocal = 0,
@@ -172,10 +176,6 @@ public:
GlobalValue(const GlobalValue &) = delete;
- ~GlobalValue() override {
- removeDeadConstantUsers(); // remove any dead constants using this.
- }
-
unsigned getAlignment() const;
enum class UnnamedAddr {
diff --git a/include/llvm/IR/GlobalVariable.h b/include/llvm/IR/GlobalVariable.h
index 21d334c8f01d..3f5d00bd3b3a 100644
--- a/include/llvm/IR/GlobalVariable.h
+++ b/include/llvm/IR/GlobalVariable.h
@@ -66,7 +66,7 @@ public:
GlobalVariable(const GlobalVariable &) = delete;
GlobalVariable &operator=(const GlobalVariable &) = delete;
- ~GlobalVariable() override {
+ ~GlobalVariable() {
dropAllReferences();
// FIXME: needed by operator delete
diff --git a/include/llvm/IR/InlineAsm.h b/include/llvm/IR/InlineAsm.h
index a57e7d63012b..7f03fcd19b65 100644
--- a/include/llvm/IR/InlineAsm.h
+++ b/include/llvm/IR/InlineAsm.h
@@ -28,7 +28,7 @@ class FunctionType;
class PointerType;
template <class ConstantClass> class ConstantUniqueMap;
-class InlineAsm : public Value {
+class InlineAsm final : public Value {
public:
enum AsmDialect {
AD_ATT,
@@ -48,7 +48,6 @@ private:
InlineAsm(FunctionType *Ty, const std::string &AsmString,
const std::string &Constraints, bool hasSideEffects,
bool isAlignStack, AsmDialect asmDialect);
- ~InlineAsm() override;
/// When the ConstantUniqueMap merges two types and makes two InlineAsms
/// identical, it destroys one of them with this method.
diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h
index 61ca90de7393..e850c015d711 100644
--- a/include/llvm/IR/InstrTypes.h
+++ b/include/llvm/IR/InstrTypes.h
@@ -62,9 +62,6 @@ protected:
Use *Ops, unsigned NumOps, BasicBlock *InsertAtEnd)
: Instruction(Ty, iType, Ops, NumOps, InsertAtEnd) {}
- // Out of line virtual method, so the vtable, etc has a home.
- ~TerminatorInst() override;
-
public:
/// Return the number of successors that this terminator has.
unsigned getNumSuccessors() const;
@@ -299,9 +296,6 @@ public:
void *operator new(size_t, unsigned) = delete;
- // Out of line virtual method, so the vtable, etc has a home.
- ~UnaryInstruction() override;
-
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
@@ -568,8 +562,6 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryOperator, Value)
/// if (isa<CastInst>(Instr)) { ... }
/// @brief Base class of casting instructions.
class CastInst : public UnaryInstruction {
- void anchor() override;
-
protected:
/// @brief Constructor with insert-before-instruction semantics for subclasses
CastInst(Type *Ty, unsigned iType, Value *S,
@@ -914,8 +906,6 @@ protected:
Value *LHS, Value *RHS, const Twine &Name,
BasicBlock *InsertAtEnd);
- void anchor() override; // Out of line virtual method.
-
public:
CmpInst() = delete;
diff --git a/include/llvm/IR/Instruction.def b/include/llvm/IR/Instruction.def
index 18711abb8060..86617299c44a 100644
--- a/include/llvm/IR/Instruction.def
+++ b/include/llvm/IR/Instruction.def
@@ -102,6 +102,10 @@
#define LAST_OTHER_INST(num)
#endif
+#ifndef HANDLE_USER_INST
+#define HANDLE_USER_INST(num, opc, Class) HANDLE_OTHER_INST(num, opc, Class)
+#endif
+
// Terminator Instructions - These instructions are used to terminate a basic
// block of the program. Every basic block must end with one of these
// instructions for it to be a well formed basic block.
@@ -185,8 +189,8 @@ HANDLE_OTHER_INST(52, FCmp , FCmpInst ) // Floating point comparison instr.
HANDLE_OTHER_INST(53, PHI , PHINode ) // PHI node instruction
HANDLE_OTHER_INST(54, Call , CallInst ) // Call a function
HANDLE_OTHER_INST(55, Select , SelectInst ) // select instruction
-HANDLE_OTHER_INST(56, UserOp1, Instruction) // May be used internally in a pass
-HANDLE_OTHER_INST(57, UserOp2, Instruction) // Internal to passes only
+HANDLE_USER_INST (56, UserOp1, Instruction) // May be used internally in a pass
+HANDLE_USER_INST (57, UserOp2, Instruction) // Internal to passes only
HANDLE_OTHER_INST(58, VAArg , VAArgInst ) // vaarg instruction
HANDLE_OTHER_INST(59, ExtractElement, ExtractElementInst)// extract from vector
HANDLE_OTHER_INST(60, InsertElement, InsertElementInst) // insert into vector
@@ -220,6 +224,8 @@ HANDLE_OTHER_INST(64, LandingPad, LandingPadInst) // Landing pad instruction.
#undef HANDLE_OTHER_INST
#undef LAST_OTHER_INST
+#undef HANDLE_USER_INST
+
#ifdef HANDLE_INST
#undef HANDLE_INST
#endif
diff --git a/include/llvm/IR/Instruction.h b/include/llvm/IR/Instruction.h
index fca29900f4c2..6e109735ddd3 100644
--- a/include/llvm/IR/Instruction.h
+++ b/include/llvm/IR/Instruction.h
@@ -36,6 +36,10 @@ class FastMathFlags;
class MDNode;
struct AAMDNodes;
+template <> struct ilist_alloc_traits<Instruction> {
+ static inline void deleteNode(Instruction *V);
+};
+
class Instruction : public User,
public ilist_node_with_parent<Instruction, BasicBlock> {
BasicBlock *Parent;
@@ -47,13 +51,13 @@ class Instruction : public User,
HasMetadataBit = 1 << 15
};
+protected:
+ ~Instruction(); // Use deleteValue() to delete a generic Instruction.
+
public:
Instruction(const Instruction &) = delete;
Instruction &operator=(const Instruction &) = delete;
- // Out of line virtual method, so the vtable, etc has a home.
- ~Instruction() override;
-
/// 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());}
@@ -640,6 +644,10 @@ private:
Instruction *cloneImpl() const;
};
+inline void ilist_alloc_traits<Instruction>::deleteNode(Instruction *V) {
+ V->deleteValue();
+}
+
} // end namespace llvm
#endif // LLVM_IR_INSTRUCTION_H
diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h
index c26701af27ce..6fab59613dd6 100644
--- a/include/llvm/IR/Instructions.h
+++ b/include/llvm/IR/Instructions.h
@@ -89,9 +89,6 @@ public:
AllocaInst(Type *Ty, unsigned AddrSpace, Value *ArraySize, unsigned Align,
const Twine &Name, BasicBlock *InsertAtEnd);
- // Out of line virtual method, so the vtable, etc. has a home.
- ~AllocaInst() override;
-
/// Return true if there is an allocation size parameter to the allocation
/// instruction that is not 1.
bool isArrayAllocation() const;
@@ -856,7 +853,6 @@ class GetElementPtrInst : public Instruction {
ArrayRef<Value *> IdxList, unsigned Values,
const Twine &NameStr, BasicBlock *InsertAtEnd);
- void anchor() override;
void init(Value *Ptr, ArrayRef<Value *> IdxList, const Twine &NameStr);
protected:
@@ -1112,8 +1108,6 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrInst, Value)
/// must be identical types.
/// Represent an integer comparison operator.
class ICmpInst: public CmpInst {
- void anchor() override;
-
void AssertOK() {
assert(getPredicate() >= CmpInst::FIRST_ICMP_PREDICATE &&
getPredicate() <= CmpInst::LAST_ICMP_PREDICATE &&
@@ -1426,8 +1420,6 @@ protected:
CallInst *cloneImpl() const;
public:
- ~CallInst() override;
-
static CallInst *Create(Value *Func, ArrayRef<Value *> Args,
ArrayRef<OperandBundleDef> Bundles = None,
const Twine &NameStr = "",
@@ -2592,8 +2584,6 @@ class PHINode : public Instruction {
return User::operator new(s);
}
- void anchor() override;
-
protected:
// Note: Instruction needs to be a friend here to call cloneImpl.
friend class Instruction;
@@ -2927,8 +2917,6 @@ protected:
ReturnInst *cloneImpl() const;
public:
- ~ReturnInst() override;
-
static ReturnInst* Create(LLVMContext &C, Value *retVal = nullptr,
Instruction *InsertBefore = nullptr) {
return new(!!retVal) ReturnInst(C, retVal, InsertBefore);
diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h
index 8f24a6a1d69d..92f701e01ff3 100644
--- a/include/llvm/IR/Metadata.h
+++ b/include/llvm/IR/Metadata.h
@@ -174,12 +174,13 @@ class MetadataAsValue : public Value {
Metadata *MD;
MetadataAsValue(Type *Ty, Metadata *MD);
- ~MetadataAsValue() override;
/// \brief Drop use of metadata (during teardown).
void dropUse() { MD = nullptr; }
public:
+ ~MetadataAsValue();
+
static MetadataAsValue *get(LLVMContext &Context, Metadata *MD);
static MetadataAsValue *getIfExists(LLVMContext &Context, Metadata *MD);
Metadata *getMetadata() const { return MD; }
diff --git a/include/llvm/IR/OperandTraits.h b/include/llvm/IR/OperandTraits.h
index e97a8009ccc0..7b94283856b6 100644
--- a/include/llvm/IR/OperandTraits.h
+++ b/include/llvm/IR/OperandTraits.h
@@ -30,6 +30,9 @@ namespace llvm {
template <typename SubClass, unsigned ARITY>
struct FixedNumOperandTraits {
static Use *op_begin(SubClass* U) {
+ static_assert(
+ !std::is_polymorphic<SubClass>::value,
+ "adding virtual methods to subclasses of User breaks use lists");
return reinterpret_cast<Use*>(U) - ARITY;
}
static Use *op_end(SubClass* U) {
@@ -65,6 +68,9 @@ struct OptionalOperandTraits : public FixedNumOperandTraits<SubClass, ARITY> {
template <typename SubClass, unsigned MINARITY = 0>
struct VariadicOperandTraits {
static Use *op_begin(SubClass* U) {
+ static_assert(
+ !std::is_polymorphic<SubClass>::value,
+ "adding virtual methods to subclasses of User breaks use lists");
return reinterpret_cast<Use*>(U) - static_cast<User*>(U)->getNumOperands();
}
static Use *op_end(SubClass* U) {
diff --git a/include/llvm/IR/Operator.h b/include/llvm/IR/Operator.h
index 997a85340c25..49fa6a6a877a 100644
--- a/include/llvm/IR/Operator.h
+++ b/include/llvm/IR/Operator.h
@@ -29,16 +29,11 @@ namespace llvm {
/// This is a utility class that provides an abstraction for the common
/// functionality between Instructions and ConstantExprs.
class Operator : public User {
-protected:
- // NOTE: Cannot use = delete because it's not legal to delete
- // an overridden method that's not deleted in the base class. Cannot leave
- // this unimplemented because that leads to an ODR-violation.
- ~Operator() override;
-
public:
// The Operator class is intended to be used as a utility, and is never itself
// instantiated.
Operator() = delete;
+ ~Operator() = delete;
void *operator new(size_t, unsigned) = delete;
void *operator new(size_t s) = delete;
diff --git a/include/llvm/IR/PatternMatch.h b/include/llvm/IR/PatternMatch.h
index 6b2b22e82b95..072c6c5ece83 100644
--- a/include/llvm/IR/PatternMatch.h
+++ b/include/llvm/IR/PatternMatch.h
@@ -886,17 +886,21 @@ template <typename LHS_t> struct not_match {
template <typename OpTy> bool match(OpTy *V) {
if (auto *O = dyn_cast<Operator>(V))
- if (O->getOpcode() == Instruction::Xor)
- return matchIfNot(O->getOperand(0), O->getOperand(1));
+ if (O->getOpcode() == Instruction::Xor) {
+ if (isAllOnes(O->getOperand(1)))
+ return L.match(O->getOperand(0));
+ if (isAllOnes(O->getOperand(0)))
+ return L.match(O->getOperand(1));
+ }
return false;
}
private:
- bool matchIfNot(Value *LHS, Value *RHS) {
- return (isa<ConstantInt>(RHS) || isa<ConstantDataVector>(RHS) ||
+ bool isAllOnes(Value *V) {
+ return (isa<ConstantInt>(V) || isa<ConstantDataVector>(V) ||
// FIXME: Remove CV.
- isa<ConstantVector>(RHS)) &&
- cast<Constant>(RHS)->isAllOnesValue() && L.match(LHS);
+ isa<ConstantVector>(V)) &&
+ cast<Constant>(V)->isAllOnesValue();
}
};
diff --git a/include/llvm/IR/User.h b/include/llvm/IR/User.h
index 7b9d451aaf53..109a3d5e7be8 100644
--- a/include/llvm/IR/User.h
+++ b/include/llvm/IR/User.h
@@ -46,8 +46,6 @@ class User : public Value {
template <unsigned>
friend struct HungoffOperandTraits;
- virtual void anchor();
-
LLVM_ATTRIBUTE_ALWAYS_INLINE inline static void *
allocateFixedOperandUser(size_t, unsigned, unsigned);
@@ -93,9 +91,11 @@ protected:
/// should be called if there are no uses.
void growHungoffUses(unsigned N, bool IsPhi = false);
+protected:
+ ~User() = default; // Use deleteValue() to delete a generic Instruction.
+
public:
User(const User &) = delete;
- ~User() override = default;
/// \brief Free memory allocated for User and Use objects.
void operator delete(void *Usr);
diff --git a/include/llvm/IR/Value.def b/include/llvm/IR/Value.def
index 48842d7f9cd5..cebd7f7297ef 100644
--- a/include/llvm/IR/Value.def
+++ b/include/llvm/IR/Value.def
@@ -20,10 +20,14 @@
#if !(defined HANDLE_GLOBAL_VALUE || defined HANDLE_CONSTANT || \
defined HANDLE_INSTRUCTION || defined HANDLE_INLINE_ASM_VALUE || \
defined HANDLE_METADATA_VALUE || defined HANDLE_VALUE || \
- defined HANDLE_CONSTANT_MARKER)
+ defined HANDLE_CONSTANT_MARKER || defined HANDLE_MEMORY_VALUE)
#error "Missing macro definition of HANDLE_VALUE*"
#endif
+#ifndef HANDLE_MEMORY_VALUE
+#define HANDLE_MEMORY_VALUE(ValueName) HANDLE_VALUE(ValueName)
+#endif
+
#ifndef HANDLE_GLOBAL_VALUE
#define HANDLE_GLOBAL_VALUE(ValueName) HANDLE_CONSTANT(ValueName)
#endif
@@ -54,9 +58,13 @@
HANDLE_VALUE(Argument)
HANDLE_VALUE(BasicBlock)
-HANDLE_VALUE(MemoryUse)
-HANDLE_VALUE(MemoryDef)
-HANDLE_VALUE(MemoryPhi)
+
+// FIXME: It's awkward that Value.def knows about classes in Analysis. While
+// this doesn't introduce a strict link or include dependency, we should remove
+// the circular dependency eventually.
+HANDLE_MEMORY_VALUE(MemoryUse)
+HANDLE_MEMORY_VALUE(MemoryDef)
+HANDLE_MEMORY_VALUE(MemoryPhi)
HANDLE_GLOBAL_VALUE(Function)
HANDLE_GLOBAL_VALUE(GlobalAlias)
@@ -94,6 +102,7 @@ HANDLE_CONSTANT_MARKER(ConstantDataLastVal, ConstantTokenNone)
HANDLE_CONSTANT_MARKER(ConstantAggregateFirstVal, ConstantArray)
HANDLE_CONSTANT_MARKER(ConstantAggregateLastVal, ConstantVector)
+#undef HANDLE_MEMORY_VALUE
#undef HANDLE_GLOBAL_VALUE
#undef HANDLE_CONSTANT
#undef HANDLE_INSTRUCTION
diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h
index 96a370dcc35f..d669b1544070 100644
--- a/include/llvm/IR/Value.h
+++ b/include/llvm/IR/Value.h
@@ -21,6 +21,7 @@
#include "llvm-c/Types.h"
#include <cassert>
#include <iterator>
+#include <memory>
namespace llvm {
@@ -69,6 +70,8 @@ using ValueName = StringMapEntry<Value*>;
/// objects that watch it and listen to RAUW and Destroy events. See
/// llvm/IR/ValueHandle.h for details.
class Value {
+ // The least-significant bit of the first word of Value *must* be zero:
+ // http://www.llvm.org/docs/ProgrammersManual.html#the-waymarking-algorithm
Type *VTy;
Use *UseList;
@@ -200,10 +203,19 @@ private:
protected:
Value(Type *Ty, unsigned scid);
+ /// Value's destructor should be virtual by design, but that would require
+ /// that Value and all of its subclasses have a vtable that effectively
+ /// duplicates the information in the value ID. As a size optimization, the
+ /// destructor has been protected, and the caller should manually call
+ /// deleteValue.
+ ~Value(); // Use deleteValue() to delete a generic Value.
+
public:
Value(const Value &) = delete;
void operator=(const Value &) = delete;
- virtual ~Value();
+
+ /// Delete a pointer to a generic Value.
+ void deleteValue();
/// \brief Support for debugging, callable in GDB: V->dump()
void dump() const;
@@ -643,6 +655,13 @@ protected:
void setValueSubclassData(unsigned short D) { SubclassData = D; }
};
+struct ValueDeleter { void operator()(Value *V) { V->deleteValue(); } };
+
+/// Use this instead of std::unique_ptr<Value> or std::unique_ptr<Instruction>.
+/// Those don't work because Value and Instruction's destructors are protected,
+/// aren't virtual, and won't destroy the complete object.
+typedef std::unique_ptr<Value, ValueDeleter> unique_value;
+
inline raw_ostream &operator<<(raw_ostream &OS, const Value &V) {
V.print(OS);
return OS;
diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h
index cf314e19d1ca..3df5244a0bd6 100644
--- a/include/llvm/InitializePasses.h
+++ b/include/llvm/InitializePasses.h
@@ -187,7 +187,6 @@ void initializeLintPass(PassRegistry&);
void initializeLiveDebugValuesPass(PassRegistry&);
void initializeLiveDebugVariablesPass(PassRegistry&);
void initializeLiveIntervalsPass(PassRegistry&);
-void initializeLiveRangeShrinkPass(PassRegistry&);
void initializeLiveRegMatrixPass(PassRegistry&);
void initializeLiveStacksPass(PassRegistry&);
void initializeLiveVariablesPass(PassRegistry&);
diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h
index f42048e48ee3..cf5d93ee9ed7 100644
--- a/include/llvm/Object/Binary.h
+++ b/include/llvm/Object/Binary.h
@@ -57,6 +57,8 @@ protected:
ID_MachO64L, // MachO 64-bit, little endian
ID_MachO64B, // MachO 64-bit, big endian
+ ID_WinRes, // Windows resource (.res) file.
+
ID_Wasm,
ID_EndObjects
@@ -132,6 +134,8 @@ public:
TypeID == ID_MachO32B || TypeID == ID_MachO64B);
}
+ bool isWinRes() const { return TypeID == ID_WinRes; }
+
Triple::ObjectFormatType getTripleObjectFormat() const {
if (isCOFF())
return Triple::COFF;
diff --git a/include/llvm/Object/COFFImportFile.h b/include/llvm/Object/COFFImportFile.h
index 78d9d679acd3..78044a2832fa 100644
--- a/include/llvm/Object/COFFImportFile.h
+++ b/include/llvm/Object/COFFImportFile.h
@@ -9,13 +9,15 @@
//
// COFF short import file is a special kind of file which contains
// only symbol names for DLL-exported symbols. This class implements
-// SymbolicFile interface for the file.
+// exporting of Symbols to create libraries and a SymbolicFile
+// interface for the file type.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_OBJECT_COFF_IMPORT_FILE_H
#define LLVM_OBJECT_COFF_IMPORT_FILE_H
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/Object/COFF.h"
#include "llvm/Object/IRObjectFile.h"
#include "llvm/Object/ObjectFile.h"
@@ -68,6 +70,36 @@ private:
}
};
+struct COFFShortExport {
+ std::string Name;
+ std::string ExtName;
+
+ uint16_t Ordinal = 0;
+ bool Noname = false;
+ bool Data = false;
+ bool Private = false;
+ bool Constant = false;
+
+ bool isWeak() {
+ return ExtName.size() && ExtName != Name;
+ }
+
+ friend bool operator==(const COFFShortExport &L, const COFFShortExport &R) {
+ return L.Name == R.Name && L.ExtName == R.ExtName &&
+ L.Ordinal == R.Ordinal && L.Noname == R.Noname &&
+ L.Data == R.Data && L.Private == R.Private;
+ }
+
+ friend bool operator!=(const COFFShortExport &L, const COFFShortExport &R) {
+ return !(L == R);
+ }
+};
+
+std::error_code writeImportLibrary(StringRef DLLName,
+ StringRef Path,
+ ArrayRef<COFFShortExport> Exports,
+ COFF::MachineTypes Machine);
+
} // namespace object
} // namespace llvm
diff --git a/include/llvm/Object/COFFModuleDefinition.h b/include/llvm/Object/COFFModuleDefinition.h
new file mode 100644
index 000000000000..0428283fdc88
--- /dev/null
+++ b/include/llvm/Object/COFFModuleDefinition.h
@@ -0,0 +1,49 @@
+//===--- COFFModuleDefinition.h ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Windows-specific.
+// A parser for the module-definition file (.def file).
+// Parsed results are directly written to Config global variable.
+//
+// The format of module-definition files are described in this document:
+// https://msdn.microsoft.com/en-us/library/28d6s79h.aspx
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef LLVM_OBJECT_COFF_MODULE_DEFINITION_H
+#define LLVM_OBJECT_COFF_MODULE_DEFINITION_H
+
+#include "llvm/Object/COFFImportFile.h"
+#include "llvm/Object/COFF.h"
+
+namespace llvm {
+namespace object {
+
+struct COFFModuleDefinition {
+ std::vector<COFFShortExport> Exports;
+ std::string OutputFile;
+ uint64_t ImageBase = 0;
+ uint64_t StackReserve = 0;
+ uint64_t StackCommit = 0;
+ uint64_t HeapReserve = 0;
+ uint64_t HeapCommit = 0;
+ uint32_t MajorImageVersion = 0;
+ uint32_t MinorImageVersion = 0;
+ uint32_t MajorOSVersion = 0;
+ uint32_t MinorOSVersion = 0;
+};
+
+Expected<COFFModuleDefinition>
+parseCOFFModuleDefinition(MemoryBufferRef MB, COFF::MachineTypes Machine);
+
+} // End namespace object.
+} // End namespace llvm.
+
+#endif
diff --git a/include/llvm/Object/Decompressor.h b/include/llvm/Object/Decompressor.h
index a11857d546aa..0f63f8b821b7 100644
--- a/include/llvm/Object/Decompressor.h
+++ b/include/llvm/Object/Decompressor.h
@@ -30,7 +30,10 @@ public:
/// @brief Resize the buffer and uncompress section data into it.
/// @param Out Destination buffer.
- Error decompress(SmallString<32> &Out);
+ template <class T> Error resizeAndDecompress(T &Out) {
+ Out.resize(DecompressedSize);
+ return decompress({Out.data(), (size_t)DecompressedSize});
+ }
/// @brief Uncompress section data to raw buffer provided.
/// @param Buffer Destination buffer.
diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h
index 42fdfe3e5a74..a4d431b6cbe7 100644
--- a/include/llvm/Object/ELF.h
+++ b/include/llvm/Object/ELF.h
@@ -235,10 +235,7 @@ ELFFile<ELFT>::getSection(const Elf_Sym *Sym, Elf_Sym_Range Symbols,
uint32_t Index = *IndexOrErr;
if (Index == 0)
return nullptr;
- auto SectionsOrErr = sections();
- if (!SectionsOrErr)
- return SectionsOrErr.takeError();
- return object::getSection<ELFT>(*SectionsOrErr, Index);
+ return getSection(Index);
}
template <class ELFT>
diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h
index 73c7ce367cb0..86579b7c3e3a 100644
--- a/include/llvm/Object/RelocVisitor.h
+++ b/include/llvm/Object/RelocVisitor.h
@@ -32,18 +32,6 @@
namespace llvm {
namespace object {
-struct RelocToApply {
- // The computed value after applying the relevant relocations.
- int64_t Value = 0;
-
- // The width of the value; how many bytes to touch when applying the
- // relocation.
- char Width = 0;
-
- RelocToApply() = default;
- RelocToApply(int64_t Value, char Width) : Value(Value), Width(Width) {}
-};
-
/// @brief Base class for object file relocation visitors.
class RelocVisitor {
public:
@@ -52,7 +40,7 @@ public:
// TODO: Should handle multiple applied relocations via either passing in the
// previously computed value or just count paired relocations as a single
// visit.
- RelocToApply visit(uint32_t RelocType, RelocationRef R, uint64_t Value = 0) {
+ uint64_t visit(uint32_t RelocType, RelocationRef R, uint64_t Value = 0) {
if (isa<ELFObjectFileBase>(ObjToVisit))
return visitELF(RelocType, R, Value);
if (isa<COFFObjectFile>(ObjToVisit))
@@ -61,7 +49,7 @@ public:
return visitMachO(RelocType, R, Value);
HasError = true;
- return RelocToApply();
+ return 0;
}
bool error() { return HasError; }
@@ -70,7 +58,7 @@ private:
const ObjectFile &ObjToVisit;
bool HasError = false;
- RelocToApply visitELF(uint32_t RelocType, RelocationRef R, uint64_t Value) {
+ uint64_t visitELF(uint32_t RelocType, RelocationRef R, uint64_t Value) {
if (ObjToVisit.getBytesInAddress() == 8) { // 64-bit object file
switch (ObjToVisit.getArch()) {
case Triple::x86_64:
@@ -87,7 +75,7 @@ private:
return visitELF_X86_64_32S(R, Value);
default:
HasError = true;
- return RelocToApply();
+ return 0;
}
case Triple::aarch64:
case Triple::aarch64_be:
@@ -98,7 +86,7 @@ private:
return visitELF_AARCH64_ABS64(R, Value);
default:
HasError = true;
- return RelocToApply();
+ return 0;
}
case Triple::bpfel:
case Triple::bpfeb:
@@ -109,7 +97,7 @@ private:
return visitELF_BPF_64_32(R, Value);
default:
HasError = true;
- return RelocToApply();
+ return 0;
}
case Triple::mips64el:
case Triple::mips64:
@@ -120,7 +108,7 @@ private:
return visitELF_MIPS64_64(R, Value);
default:
HasError = true;
- return RelocToApply();
+ return 0;
}
case Triple::ppc64le:
case Triple::ppc64:
@@ -131,7 +119,7 @@ private:
return visitELF_PPC64_ADDR64(R, Value);
default:
HasError = true;
- return RelocToApply();
+ return 0;
}
case Triple::systemz:
switch (RelocType) {
@@ -141,7 +129,7 @@ private:
return visitELF_390_64(R, Value);
default:
HasError = true;
- return RelocToApply();
+ return 0;
}
case Triple::sparcv9:
switch (RelocType) {
@@ -153,7 +141,7 @@ private:
return visitELF_SPARCV9_64(R, Value);
default:
HasError = true;
- return RelocToApply();
+ return 0;
}
case Triple::amdgcn:
switch (RelocType) {
@@ -163,11 +151,11 @@ private:
return visitELF_AMDGPU_ABS64(R, Value);
default:
HasError = true;
- return RelocToApply();
+ return 0;
}
default:
HasError = true;
- return RelocToApply();
+ return 0;
}
} else if (ObjToVisit.getBytesInAddress() == 4) { // 32-bit object file
switch (ObjToVisit.getArch()) {
@@ -181,7 +169,7 @@ private:
return visitELF_386_PC32(R, Value);
default:
HasError = true;
- return RelocToApply();
+ return 0;
}
case Triple::ppc:
switch (RelocType) {
@@ -189,14 +177,14 @@ private:
return visitELF_PPC_ADDR32(R, Value);
default:
HasError = true;
- return RelocToApply();
+ return 0;
}
case Triple::arm:
case Triple::armeb:
switch (RelocType) {
default:
HasError = true;
- return RelocToApply();
+ return 0;
case ELF::R_ARM_ABS32:
return visitELF_ARM_ABS32(R, Value);
}
@@ -206,7 +194,7 @@ private:
return visitELF_Lanai_32(R, Value);
default:
HasError = true;
- return RelocToApply();
+ return 0;
}
case Triple::mipsel:
case Triple::mips:
@@ -215,7 +203,7 @@ private:
return visitELF_MIPS_32(R, Value);
default:
HasError = true;
- return RelocToApply();
+ return 0;
}
case Triple::sparc:
switch (RelocType) {
@@ -224,7 +212,7 @@ private:
return visitELF_SPARC_32(R, Value);
default:
HasError = true;
- return RelocToApply();
+ return 0;
}
case Triple::hexagon:
switch (RelocType) {
@@ -232,18 +220,18 @@ private:
return visitELF_HEX_32(R, Value);
default:
HasError = true;
- return RelocToApply();
+ return 0;
}
default:
HasError = true;
- return RelocToApply();
+ return 0;
}
} else {
report_fatal_error("Invalid word size in object file");
}
}
- RelocToApply visitCOFF(uint32_t RelocType, RelocationRef R, uint64_t Value) {
+ uint64_t visitCOFF(uint32_t RelocType, RelocationRef R, uint64_t Value) {
switch (ObjToVisit.getArch()) {
case Triple::x86:
switch (RelocType) {
@@ -263,10 +251,10 @@ private:
break;
}
HasError = true;
- return RelocToApply();
+ return 0;
}
- RelocToApply visitMachO(uint32_t RelocType, RelocationRef R, uint64_t Value) {
+ uint64_t visitMachO(uint32_t RelocType, RelocationRef R, uint64_t Value) {
switch (ObjToVisit.getArch()) {
default: break;
case Triple::x86_64:
@@ -277,7 +265,7 @@ private:
}
}
HasError = true;
- return RelocToApply();
+ return 0;
}
int64_t getELFAddend(RelocationRef R) {
@@ -287,108 +275,88 @@ private:
return *AddendOrErr;
}
- uint8_t getLengthMachO64(RelocationRef R) {
- const MachOObjectFile *Obj = cast<MachOObjectFile>(R.getObject());
- return Obj->getRelocationLength(R.getRawDataRefImpl());
- }
-
/// Operations
/// 386-ELF
- RelocToApply visitELF_386_NONE(RelocationRef R) {
- return RelocToApply(0, 0);
+ uint64_t visitELF_386_NONE(RelocationRef R) {
+ return 0;
}
// Ideally the Addend here will be the addend in the data for
// the relocation. It's not actually the case for Rel relocations.
- RelocToApply visitELF_386_32(RelocationRef R, uint64_t Value) {
- return RelocToApply(Value, 4);
+ uint64_t visitELF_386_32(RelocationRef R, uint64_t Value) {
+ return Value;
}
- RelocToApply visitELF_386_PC32(RelocationRef R, uint64_t Value) {
- uint64_t Address = R.getOffset();
- return RelocToApply(Value - Address, 4);
+ uint64_t visitELF_386_PC32(RelocationRef R, uint64_t Value) {
+ return Value - R.getOffset();
}
/// X86-64 ELF
- RelocToApply visitELF_X86_64_NONE(RelocationRef R) {
- return RelocToApply(0, 0);
+ uint64_t visitELF_X86_64_NONE(RelocationRef R) {
+ return 0;
}
- RelocToApply visitELF_X86_64_64(RelocationRef R, uint64_t Value) {
- int64_t Addend = getELFAddend(R);
- return RelocToApply(Value + Addend, 8);
+
+ uint64_t visitELF_X86_64_64(RelocationRef R, uint64_t Value) {
+ return Value + getELFAddend(R);
}
- RelocToApply visitELF_X86_64_PC32(RelocationRef R, uint64_t Value) {
- int64_t Addend = getELFAddend(R);
- uint64_t Address = R.getOffset();
- return RelocToApply(Value + Addend - Address, 4);
+
+ uint64_t visitELF_X86_64_PC32(RelocationRef R, uint64_t Value) {
+ return Value + getELFAddend(R) - R.getOffset();
}
- RelocToApply visitELF_X86_64_32(RelocationRef R, uint64_t Value) {
- int64_t Addend = getELFAddend(R);
- uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
- return RelocToApply(Res, 4);
+
+ uint64_t visitELF_X86_64_32(RelocationRef R, uint64_t Value) {
+ return (Value + getELFAddend(R)) & 0xFFFFFFFF;
}
- RelocToApply visitELF_X86_64_32S(RelocationRef R, uint64_t Value) {
- int64_t Addend = getELFAddend(R);
- int32_t Res = (Value + Addend) & 0xFFFFFFFF;
- return RelocToApply(Res, 4);
+
+ uint64_t visitELF_X86_64_32S(RelocationRef R, uint64_t Value) {
+ return (Value + getELFAddend(R)) & 0xFFFFFFFF;
}
/// BPF ELF
- RelocToApply visitELF_BPF_64_32(RelocationRef R, uint64_t Value) {
- uint32_t Res = Value & 0xFFFFFFFF;
- return RelocToApply(Res, 4);
+ uint64_t visitELF_BPF_64_32(RelocationRef R, uint64_t Value) {
+ return Value & 0xFFFFFFFF;
}
- RelocToApply visitELF_BPF_64_64(RelocationRef R, uint64_t Value) {
- return RelocToApply(Value, 8);
+
+ uint64_t visitELF_BPF_64_64(RelocationRef R, uint64_t Value) {
+ return Value;
}
/// PPC64 ELF
- RelocToApply visitELF_PPC64_ADDR32(RelocationRef R, uint64_t Value) {
- int64_t Addend = getELFAddend(R);
- uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
- return RelocToApply(Res, 4);
+ uint64_t visitELF_PPC64_ADDR32(RelocationRef R, uint64_t Value) {
+ return (Value + getELFAddend(R)) & 0xFFFFFFFF;
}
- RelocToApply visitELF_PPC64_ADDR64(RelocationRef R, uint64_t Value) {
- int64_t Addend = getELFAddend(R);
- return RelocToApply(Value + Addend, 8);
+
+ uint64_t visitELF_PPC64_ADDR64(RelocationRef R, uint64_t Value) {
+ return Value + getELFAddend(R);
}
/// PPC32 ELF
- RelocToApply visitELF_PPC_ADDR32(RelocationRef R, uint64_t Value) {
- int64_t Addend = getELFAddend(R);
- uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
- return RelocToApply(Res, 4);
+ uint64_t visitELF_PPC_ADDR32(RelocationRef R, uint64_t Value) {
+ return (Value + getELFAddend(R)) & 0xFFFFFFFF;
}
/// 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);
+ uint64_t visitELF_Lanai_32(RelocationRef R, uint64_t Value) {
+ return (Value + getELFAddend(R)) & 0xFFFFFFFF;
}
/// MIPS ELF
- RelocToApply visitELF_MIPS_32(RelocationRef R, uint64_t Value) {
- uint32_t Res = Value & 0xFFFFFFFF;
- return RelocToApply(Res, 4);
+ uint64_t visitELF_MIPS_32(RelocationRef R, uint64_t Value) {
+ return Value & 0xFFFFFFFF;
}
/// MIPS64 ELF
- RelocToApply visitELF_MIPS64_32(RelocationRef R, uint64_t Value) {
- int64_t Addend = getELFAddend(R);
- uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
- return RelocToApply(Res, 4);
+ uint64_t visitELF_MIPS64_32(RelocationRef R, uint64_t Value) {
+ return (Value + getELFAddend(R)) & 0xFFFFFFFF;
}
- RelocToApply visitELF_MIPS64_64(RelocationRef R, uint64_t Value) {
- int64_t Addend = getELFAddend(R);
- uint64_t Res = (Value + Addend);
- return RelocToApply(Res, 8);
+ uint64_t visitELF_MIPS64_64(RelocationRef R, uint64_t Value) {
+ return Value + getELFAddend(R);
}
// AArch64 ELF
- RelocToApply visitELF_AARCH64_ABS32(RelocationRef R, uint64_t Value) {
+ uint64_t visitELF_AARCH64_ABS32(RelocationRef R, uint64_t Value) {
int64_t Addend = getELFAddend(R);
int64_t Res = Value + Addend;
@@ -396,16 +364,15 @@ private:
if (Res < INT32_MIN || Res > UINT32_MAX)
HasError = true;
- return RelocToApply(static_cast<uint32_t>(Res), 4);
+ return static_cast<uint32_t>(Res);
}
- RelocToApply visitELF_AARCH64_ABS64(RelocationRef R, uint64_t Value) {
- int64_t Addend = getELFAddend(R);
- return RelocToApply(Value + Addend, 8);
+ uint64_t visitELF_AARCH64_ABS64(RelocationRef R, uint64_t Value) {
+ return Value + getELFAddend(R);
}
// SystemZ ELF
- RelocToApply visitELF_390_32(RelocationRef R, uint64_t Value) {
+ uint64_t visitELF_390_32(RelocationRef R, uint64_t Value) {
int64_t Addend = getELFAddend(R);
int64_t Res = Value + Addend;
@@ -413,77 +380,71 @@ private:
if (Res < INT32_MIN || Res > UINT32_MAX)
HasError = true;
- return RelocToApply(static_cast<uint32_t>(Res), 4);
+ return static_cast<uint32_t>(Res);
}
- RelocToApply visitELF_390_64(RelocationRef R, uint64_t Value) {
- int64_t Addend = getELFAddend(R);
- return RelocToApply(Value + Addend, 8);
+ uint64_t visitELF_390_64(RelocationRef R, uint64_t Value) {
+ return Value + getELFAddend(R);
}
- RelocToApply visitELF_SPARC_32(RelocationRef R, uint32_t Value) {
- int32_t Addend = getELFAddend(R);
- return RelocToApply(Value + Addend, 4);
+ uint64_t visitELF_SPARC_32(RelocationRef R, uint32_t Value) {
+ return Value + getELFAddend(R);
}
- RelocToApply visitELF_SPARCV9_32(RelocationRef R, uint64_t Value) {
- int32_t Addend = getELFAddend(R);
- return RelocToApply(Value + Addend, 4);
+ uint64_t visitELF_SPARCV9_32(RelocationRef R, uint64_t Value) {
+ return Value + getELFAddend(R);
}
- RelocToApply visitELF_SPARCV9_64(RelocationRef R, uint64_t Value) {
- int64_t Addend = getELFAddend(R);
- return RelocToApply(Value + Addend, 8);
+ uint64_t visitELF_SPARCV9_64(RelocationRef R, uint64_t Value) {
+ return Value + getELFAddend(R);
}
- RelocToApply visitELF_ARM_ABS32(RelocationRef R, uint64_t Value) {
+ uint64_t visitELF_ARM_ABS32(RelocationRef R, uint64_t Value) {
int64_t Res = Value;
// Overflow check allows for both signed and unsigned interpretation.
if (Res < INT32_MIN || Res > UINT32_MAX)
HasError = true;
- return RelocToApply(static_cast<uint32_t>(Res), 4);
+ return static_cast<uint32_t>(Res);
}
- RelocToApply visitELF_HEX_32(RelocationRef R, uint64_t Value) {
+ uint64_t visitELF_HEX_32(RelocationRef R, uint64_t Value) {
int64_t Addend = getELFAddend(R);
- return RelocToApply(Value + Addend, 4);
+ return Value + Addend;
}
- RelocToApply visitELF_AMDGPU_ABS32(RelocationRef R, uint64_t Value) {
+ uint64_t visitELF_AMDGPU_ABS32(RelocationRef R, uint64_t Value) {
int64_t Addend = getELFAddend(R);
- return RelocToApply(Value + Addend, 4);
+ return Value + Addend;
}
- RelocToApply visitELF_AMDGPU_ABS64(RelocationRef R, uint64_t Value) {
+ uint64_t visitELF_AMDGPU_ABS64(RelocationRef R, uint64_t Value) {
int64_t Addend = getELFAddend(R);
- return RelocToApply(Value + Addend, 8);
+ return Value + Addend;
}
/// I386 COFF
- RelocToApply visitCOFF_I386_SECREL(RelocationRef R, uint64_t Value) {
- return RelocToApply(static_cast<uint32_t>(Value), /*Width=*/4);
+ uint64_t visitCOFF_I386_SECREL(RelocationRef R, uint64_t Value) {
+ return static_cast<uint32_t>(Value);
}
- RelocToApply visitCOFF_I386_DIR32(RelocationRef R, uint64_t Value) {
- return RelocToApply(static_cast<uint32_t>(Value), /*Width=*/4);
+ uint64_t visitCOFF_I386_DIR32(RelocationRef R, uint64_t Value) {
+ return static_cast<uint32_t>(Value);
}
/// AMD64 COFF
- RelocToApply visitCOFF_AMD64_SECREL(RelocationRef R, uint64_t Value) {
- return RelocToApply(static_cast<uint32_t>(Value), /*Width=*/4);
+ uint64_t visitCOFF_AMD64_SECREL(RelocationRef R, uint64_t Value) {
+ return static_cast<uint32_t>(Value);
}
- RelocToApply visitCOFF_AMD64_ADDR64(RelocationRef R, uint64_t Value) {
- return RelocToApply(Value, /*Width=*/8);
+ uint64_t visitCOFF_AMD64_ADDR64(RelocationRef R, uint64_t Value) {
+ return Value;
}
// X86_64 MachO
- RelocToApply visitMACHO_X86_64_UNSIGNED(RelocationRef R, uint64_t Value) {
- uint8_t Length = getLengthMachO64(R);
- Length = 1<<Length;
- return RelocToApply(Value, Length);
+ uint64_t visitMACHO_X86_64_UNSIGNED(RelocationRef R, uint64_t Value) {
+ return Value;
}
};
diff --git a/include/llvm/Object/WindowsResource.h b/include/llvm/Object/WindowsResource.h
new file mode 100644
index 000000000000..f94ad09ce0c6
--- /dev/null
+++ b/include/llvm/Object/WindowsResource.h
@@ -0,0 +1,82 @@
+//===-- WindowsResource.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 declares the .res file class. .res files are intermediate
+// products of the typical resource-compilation process on Windows. This
+// process is as follows:
+//
+// .rc file(s) ---(rc.exe)---> .res file(s) ---(cvtres.exe)---> COFF file
+//
+// .rc files are human-readable scripts that list all resources a program uses.
+//
+// They are compiled into .res files, which are a list of the resources in
+// binary form.
+//
+// Finally the data stored in the .res is compiled into a COFF file, where it
+// is organized in a directory tree structure for optimized access by the
+// program during runtime.
+//
+// Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms648007(v=vs.85).aspx
+//
+//===---------------------------------------------------------------------===//
+
+#ifndef LLVM_INCLUDE_LLVM_OBJECT_RESFILE_H
+#define LLVM_INCLUDE_LLVM_OBJECT_RESFILE_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Object/Binary.h"
+#include "llvm/Support/BinaryByteStream.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace object {
+
+class WindowsResource;
+
+class ResourceEntryRef {
+public:
+ Error moveNext(bool &End);
+
+private:
+ friend class WindowsResource;
+
+ ResourceEntryRef(BinaryStreamRef Ref, const WindowsResource *Owner,
+ Error &Err);
+ Error loadNext();
+
+ BinaryStreamReader Reader;
+ BinaryStreamRef HeaderBytes;
+ BinaryStreamRef DataBytes;
+ const WindowsResource *OwningRes = nullptr;
+};
+
+class WindowsResource : public Binary {
+public:
+ ~WindowsResource() override;
+ Expected<ResourceEntryRef> getHeadEntry();
+
+ static bool classof(const Binary *V) { return V->isWinRes(); }
+
+ static Expected<std::unique_ptr<WindowsResource>>
+ createWindowsResource(MemoryBufferRef Source);
+
+private:
+ friend class ResourceEntryRef;
+
+ WindowsResource(MemoryBufferRef Source);
+
+ BinaryByteStream BBS;
+};
+
+} // namespace object
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/PassInfo.h b/include/llvm/PassInfo.h
index 21ade85b682f..81dface3c9a0 100644
--- a/include/llvm/PassInfo.h
+++ b/include/llvm/PassInfo.h
@@ -32,7 +32,6 @@ class TargetMachine;
class PassInfo {
public:
typedef Pass* (*NormalCtor_t)();
- typedef Pass *(*TargetMachineCtor_t)(TargetMachine *);
private:
StringRef PassName; // Nice name for Pass
@@ -44,24 +43,20 @@ private:
std::vector<const PassInfo *> ItfImpl; // Interfaces implemented by this pass
NormalCtor_t NormalCtor;
- TargetMachineCtor_t TargetMachineCtor;
public:
/// PassInfo ctor - Do not call this directly, this should only be invoked
/// through RegisterPass.
PassInfo(StringRef name, StringRef arg, const void *pi, NormalCtor_t normal,
- bool isCFGOnly, bool is_analysis,
- TargetMachineCtor_t machine = nullptr)
+ bool isCFGOnly, bool is_analysis)
: PassName(name), PassArgument(arg), PassID(pi), IsCFGOnlyPass(isCFGOnly),
- IsAnalysis(is_analysis), IsAnalysisGroup(false), NormalCtor(normal),
- TargetMachineCtor(machine) {}
+ IsAnalysis(is_analysis), IsAnalysisGroup(false), NormalCtor(normal) {}
/// PassInfo ctor - Do not call this directly, this should only be invoked
/// through RegisterPass. This version is for use by analysis groups; it
/// does not auto-register the pass.
PassInfo(StringRef name, const void *pi)
: PassName(name), PassArgument(""), PassID(pi), IsCFGOnlyPass(false),
- IsAnalysis(false), IsAnalysisGroup(true), NormalCtor(nullptr),
- TargetMachineCtor(nullptr) {}
+ IsAnalysis(false), IsAnalysisGroup(true), NormalCtor(nullptr) {}
/// getPassName - Return the friendly name for the pass, never returns null
///
@@ -101,16 +96,6 @@ public:
NormalCtor = Ctor;
}
- /// getTargetMachineCtor - Return a pointer to a function, that when called
- /// with a TargetMachine, creates an instance of the pass and returns it.
- /// This pointer may be null if there is no constructor with a TargetMachine
- /// for the pass.
- ///
- TargetMachineCtor_t getTargetMachineCtor() const { return TargetMachineCtor; }
- void setTargetMachineCtor(TargetMachineCtor_t Ctor) {
- TargetMachineCtor = Ctor;
- }
-
/// createPass() - Use this method to create an instance of this pass.
Pass *createPass() const {
assert((!isAnalysisGroup() || NormalCtor) &&
diff --git a/include/llvm/PassSupport.h b/include/llvm/PassSupport.h
index 50e6b498fb46..602f45ac5178 100644
--- a/include/llvm/PassSupport.h
+++ b/include/llvm/PassSupport.h
@@ -31,8 +31,6 @@
namespace llvm {
-class TargetMachine;
-
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis) \
static void *initialize##passName##PassOnce(PassRegistry &Registry) { \
PassInfo *PI = new PassInfo( \
@@ -78,10 +76,6 @@ class TargetMachine;
template <typename PassName> Pass *callDefaultCtor() { return new PassName(); }
-template <typename PassName> Pass *callTargetMachineCtor(TargetMachine *TM) {
- return new PassName(TM);
-}
-
//===---------------------------------------------------------------------------
/// RegisterPass<t> template - This template class is used to notify the system
/// that a Pass is available for use, and registers it into the internal
diff --git a/include/llvm/Support/BinaryStreamReader.h b/include/llvm/Support/BinaryStreamReader.h
index 77738077f5ff..56375f41d2c0 100644
--- a/include/llvm/Support/BinaryStreamReader.h
+++ b/include/llvm/Support/BinaryStreamReader.h
@@ -16,7 +16,6 @@
#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
-#include "llvm/Support/MathExtras.h"
#include "llvm/Support/type_traits.h"
#include <string>
@@ -32,7 +31,21 @@ namespace llvm {
class BinaryStreamReader {
public:
BinaryStreamReader() = default;
- explicit BinaryStreamReader(BinaryStreamRef Stream);
+ explicit BinaryStreamReader(BinaryStreamRef Ref);
+ explicit BinaryStreamReader(BinaryStream &Stream);
+ explicit BinaryStreamReader(ArrayRef<uint8_t> Data,
+ llvm::support::endianness Endian);
+ explicit BinaryStreamReader(StringRef Data, llvm::support::endianness Endian);
+
+ BinaryStreamReader(const BinaryStreamReader &Other)
+ : Stream(Other.Stream), Offset(Other.Offset) {}
+
+ BinaryStreamReader &operator=(const BinaryStreamReader &Other) {
+ Stream = Other.Stream;
+ Offset = Other.Offset;
+ return *this;
+ }
+
virtual ~BinaryStreamReader() {}
/// Read as much as possible from the underlying string at the current offset
@@ -244,12 +257,14 @@ public:
/// \returns the next byte in the stream.
uint8_t peek() const;
+ Error padToAlignment(uint32_t Align);
+
std::pair<BinaryStreamReader, BinaryStreamReader>
split(uint32_t Offset) const;
private:
BinaryStreamRef Stream;
- uint32_t Offset;
+ uint32_t Offset = 0;
};
} // namespace llvm
diff --git a/include/llvm/Support/BinaryStreamRef.h b/include/llvm/Support/BinaryStreamRef.h
index 465e724a6886..e3bd4bf0860e 100644
--- a/include/llvm/Support/BinaryStreamRef.h
+++ b/include/llvm/Support/BinaryStreamRef.h
@@ -16,36 +16,74 @@
#include "llvm/Support/Error.h"
#include <algorithm>
#include <cstdint>
+#include <memory>
namespace llvm {
/// Common stuff for mutable and immutable StreamRefs.
-template <class StreamType, class RefType> class BinaryStreamRefBase {
-public:
- BinaryStreamRefBase() : Stream(nullptr), ViewOffset(0), Length(0) {}
- BinaryStreamRefBase(StreamType &Stream, uint32_t Offset, uint32_t Length)
- : Stream(&Stream), ViewOffset(Offset), Length(Length) {}
+template <class RefType, class StreamType> class BinaryStreamRefBase {
+protected:
+ BinaryStreamRefBase() = default;
+ BinaryStreamRefBase(std::shared_ptr<StreamType> SharedImpl, uint32_t Offset,
+ uint32_t Length)
+ : SharedImpl(SharedImpl), BorrowedImpl(SharedImpl.get()),
+ ViewOffset(Offset), Length(Length) {}
+ BinaryStreamRefBase(StreamType &BorrowedImpl, uint32_t Offset,
+ uint32_t Length)
+ : BorrowedImpl(&BorrowedImpl), ViewOffset(Offset), Length(Length) {}
+ BinaryStreamRefBase(const BinaryStreamRefBase &Other) {
+ SharedImpl = Other.SharedImpl;
+ BorrowedImpl = Other.BorrowedImpl;
+ ViewOffset = Other.ViewOffset;
+ Length = Other.Length;
+ }
- llvm::support::endianness getEndian() const { return Stream->getEndian(); }
+public:
+ llvm::support::endianness getEndian() const {
+ return BorrowedImpl->getEndian();
+ }
uint32_t getLength() const { return Length; }
- const StreamType *getStream() const { return Stream; }
/// Return a new BinaryStreamRef with the first \p N elements removed.
RefType drop_front(uint32_t N) const {
- if (!Stream)
+ if (!BorrowedImpl)
return RefType();
N = std::min(N, Length);
- return RefType(*Stream, ViewOffset + N, Length - N);
+ RefType Result(static_cast<const RefType &>(*this));
+ Result.ViewOffset += N;
+ Result.Length -= N;
+ return Result;
}
- /// Return a new BinaryStreamRef with only the first \p N elements remaining.
- RefType keep_front(uint32_t N) const {
- if (!Stream)
+ /// Return a new BinaryStreamRef with the first \p N elements removed.
+ RefType drop_back(uint32_t N) const {
+ if (!BorrowedImpl)
return RefType();
+
N = std::min(N, Length);
- return RefType(*Stream, ViewOffset, N);
+ RefType Result(static_cast<const RefType &>(*this));
+ Result.Length -= N;
+ return Result;
+ }
+
+ /// Return a new BinaryStreamRef with only the first \p N elements remaining.
+ RefType keep_front(uint32_t N) const {
+ assert(N <= getLength());
+ return drop_back(getLength() - N);
+ }
+
+ /// Return a new BinaryStreamRef with only the last \p N elements remaining.
+ RefType keep_back(uint32_t N) const {
+ assert(N <= getLength());
+ return drop_front(getLength() - N);
+ }
+
+ /// Return a new BinaryStreamRef with the first and last \p N elements
+ /// removed.
+ RefType drop_symmetric(uint32_t N) const {
+ return drop_front(N).drop_back(N);
}
/// Return a new BinaryStreamRef with the first \p Offset elements removed,
@@ -54,8 +92,10 @@ public:
return drop_front(Offset).keep_front(Len);
}
+ bool valid() const { return BorrowedImpl != nullptr; }
+
bool operator==(const RefType &Other) const {
- if (Stream != Other.Stream)
+ if (BorrowedImpl != Other.BorrowedImpl)
return false;
if (ViewOffset != Other.ViewOffset)
return false;
@@ -73,9 +113,10 @@ protected:
return Error::success();
}
- StreamType *Stream;
- uint32_t ViewOffset;
- uint32_t Length;
+ std::shared_ptr<StreamType> SharedImpl;
+ StreamType *BorrowedImpl = nullptr;
+ uint32_t ViewOffset = 0;
+ uint32_t Length = 0;
};
/// \brief BinaryStreamRef is to BinaryStream what ArrayRef is to an Array. It
@@ -86,21 +127,27 @@ protected:
/// and use inheritance to achieve polymorphism. Instead, you should pass
/// around BinaryStreamRefs by value and achieve polymorphism that way.
class BinaryStreamRef
- : public BinaryStreamRefBase<BinaryStream, BinaryStreamRef> {
+ : public BinaryStreamRefBase<BinaryStreamRef, BinaryStream> {
+ friend BinaryStreamRefBase<BinaryStreamRef, BinaryStream>;
+ friend class WritableBinaryStreamRef;
+ BinaryStreamRef(std::shared_ptr<BinaryStream> Impl, uint32_t ViewOffset,
+ uint32_t Length)
+ : BinaryStreamRefBase(Impl, ViewOffset, Length) {}
+
public:
BinaryStreamRef() = default;
- BinaryStreamRef(BinaryStream &Stream)
- : BinaryStreamRefBase(Stream, 0, Stream.getLength()) {}
- BinaryStreamRef(BinaryStream &Stream, uint32_t Offset, uint32_t Length)
- : BinaryStreamRefBase(Stream, Offset, Length) {}
+ BinaryStreamRef(BinaryStream &Stream);
+ BinaryStreamRef(BinaryStream &Stream, uint32_t Offset, uint32_t Length);
+ explicit BinaryStreamRef(ArrayRef<uint8_t> Data,
+ llvm::support::endianness Endian);
+ explicit BinaryStreamRef(StringRef Data, llvm::support::endianness Endian);
+
+ BinaryStreamRef(const BinaryStreamRef &Other);
// Use BinaryStreamRef.slice() instead.
BinaryStreamRef(BinaryStreamRef &S, uint32_t Offset,
uint32_t Length) = delete;
- /// Check if a Stream is valid.
- bool valid() const { return Stream != nullptr; }
-
/// Given an Offset into this StreamRef and a Size, return a reference to a
/// buffer owned by the stream.
///
@@ -108,12 +155,7 @@ public:
/// bounds of this BinaryStreamRef's view and the implementation could read
/// the data, and an appropriate error code otherwise.
Error readBytes(uint32_t Offset, uint32_t Size,
- ArrayRef<uint8_t> &Buffer) const {
- if (auto EC = checkOffset(Offset, Size))
- return EC;
-
- return Stream->readBytes(ViewOffset + Offset, Size, Buffer);
- }
+ ArrayRef<uint8_t> &Buffer) const;
/// Given an Offset into this BinaryStreamRef, return a reference to the
/// largest buffer the stream could support without necessitating a copy.
@@ -121,33 +163,25 @@ public:
/// \returns a success error code if implementation could read the data,
/// and an appropriate error code otherwise.
Error readLongestContiguousChunk(uint32_t Offset,
- ArrayRef<uint8_t> &Buffer) const {
- if (auto EC = checkOffset(Offset, 1))
- return EC;
-
- if (auto EC =
- Stream->readLongestContiguousChunk(ViewOffset + 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();
- }
+ ArrayRef<uint8_t> &Buffer) const;
};
class WritableBinaryStreamRef
- : public BinaryStreamRefBase<WritableBinaryStream,
- WritableBinaryStreamRef> {
+ : public BinaryStreamRefBase<WritableBinaryStreamRef,
+ WritableBinaryStream> {
+ friend BinaryStreamRefBase<WritableBinaryStreamRef, WritableBinaryStream>;
+ WritableBinaryStreamRef(std::shared_ptr<WritableBinaryStream> Impl,
+ uint32_t ViewOffset, uint32_t Length)
+ : BinaryStreamRefBase(Impl, ViewOffset, Length) {}
+
public:
WritableBinaryStreamRef() = default;
- WritableBinaryStreamRef(WritableBinaryStream &Stream)
- : BinaryStreamRefBase(Stream, 0, Stream.getLength()) {}
+ WritableBinaryStreamRef(WritableBinaryStream &Stream);
WritableBinaryStreamRef(WritableBinaryStream &Stream, uint32_t Offset,
- uint32_t Length)
- : BinaryStreamRefBase(Stream, Offset, Length) {}
+ uint32_t Length);
+ explicit WritableBinaryStreamRef(MutableArrayRef<uint8_t> Data,
+ llvm::support::endianness Endian);
+ WritableBinaryStreamRef(const WritableBinaryStreamRef &Other);
// Use WritableBinaryStreamRef.slice() instead.
WritableBinaryStreamRef(WritableBinaryStreamRef &S, uint32_t Offset,
@@ -159,17 +193,13 @@ public:
/// \returns a success error code if the data could fit within the underlying
/// stream at the specified location and the implementation could write the
/// data, and an appropriate error code otherwise.
- Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) const {
- if (auto EC = checkOffset(Offset, Data.size()))
- return EC;
-
- return Stream->writeBytes(ViewOffset + Offset, Data);
- }
+ Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) const;
- operator BinaryStreamRef() { return BinaryStreamRef(*Stream); }
+ /// Conver this WritableBinaryStreamRef to a read-only BinaryStreamRef.
+ operator BinaryStreamRef() const;
/// \brief For buffered streams, commits changes to the backing store.
- Error commit() { return Stream->commit(); }
+ Error commit();
};
} // end namespace llvm
diff --git a/include/llvm/Support/BinaryStreamWriter.h b/include/llvm/Support/BinaryStreamWriter.h
index 1b61c32a2541..a4495a1ce27d 100644
--- a/include/llvm/Support/BinaryStreamWriter.h
+++ b/include/llvm/Support/BinaryStreamWriter.h
@@ -32,7 +32,20 @@ namespace llvm {
class BinaryStreamWriter {
public:
BinaryStreamWriter() = default;
- explicit BinaryStreamWriter(WritableBinaryStreamRef Stream);
+ explicit BinaryStreamWriter(WritableBinaryStreamRef Ref);
+ explicit BinaryStreamWriter(WritableBinaryStream &Stream);
+ explicit BinaryStreamWriter(MutableArrayRef<uint8_t> Data,
+ llvm::support::endianness Endian);
+
+ BinaryStreamWriter(const BinaryStreamWriter &Other)
+ : Stream(Other.Stream), Offset(Other.Offset) {}
+
+ BinaryStreamWriter &operator=(const BinaryStreamWriter &Other) {
+ Stream = Other.Stream;
+ Offset = Other.Offset;
+ return *this;
+ }
+
virtual ~BinaryStreamWriter() {}
/// Write the bytes specified in \p Buffer to the underlying stream.
diff --git a/include/llvm/Support/FileSystem.h b/include/llvm/Support/FileSystem.h
index e3c5de7fbe64..7caefb5359b8 100644
--- a/include/llvm/Support/FileSystem.h
+++ b/include/llvm/Support/FileSystem.h
@@ -261,7 +261,7 @@ struct file_magic {
coff_object, ///< COFF object file
coff_import_library, ///< COFF import library
pecoff_executable, ///< PECOFF executable file
- windows_resource, ///< Windows compiled resource file (.rc)
+ windows_resource, ///< Windows compiled resource file (.res)
wasm_object ///< WebAssembly Object file
};
diff --git a/include/llvm/Target/GlobalISel/SelectionDAGCompat.td b/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
index 071ec2edb538..a06c67fe814c 100644
--- a/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
+++ b/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
@@ -62,7 +62,6 @@ def : GINodeEquiv<G_FMUL, fmul>;
def : GINodeEquiv<G_FDIV, fdiv>;
def : GINodeEquiv<G_FREM, frem>;
def : GINodeEquiv<G_FPOW, fpow>;
-def : GINodeEquiv<G_INTRINSIC, intrinsic_wo_chain>;
def : GINodeEquiv<G_BR, br>;
// Specifies the GlobalISel equivalents for SelectionDAG's ComplexPattern.
diff --git a/include/llvm/Transforms/IPO/FunctionImport.h b/include/llvm/Transforms/IPO/FunctionImport.h
index ed5742ab8b56..d66b6edc7a4f 100644
--- a/include/llvm/Transforms/IPO/FunctionImport.h
+++ b/include/llvm/Transforms/IPO/FunctionImport.h
@@ -53,8 +53,7 @@ public:
: Index(Index), ModuleLoader(std::move(ModuleLoader)) {}
/// Import functions in Module \p M based on the supplied import list.
- Expected<bool>
- importFunctions(Module &M, const ImportMapTy &ImportList);
+ Expected<bool> importFunctions(Module &M, const ImportMapTy &ImportList);
private:
/// The summaries index used to trigger importing.
diff --git a/include/llvm/Transforms/Scalar/GVNExpression.h b/include/llvm/Transforms/Scalar/GVNExpression.h
index 2670a0c1a533..a971df975b6f 100644
--- a/include/llvm/Transforms/Scalar/GVNExpression.h
+++ b/include/llvm/Transforms/Scalar/GVNExpression.h
@@ -40,6 +40,7 @@ enum ExpressionType {
ET_Base,
ET_Constant,
ET_Variable,
+ ET_Dead,
ET_Unknown,
ET_BasicStart,
ET_Basic,
@@ -380,7 +381,9 @@ public:
OS << "ExpressionTypeStore, ";
this->BasicExpression::printInternal(OS, false);
OS << " represents Store " << *Store;
- OS << " with MemoryLeader " << *getMemoryLeader();
+ OS << " with StoredValue ";
+ StoredValue->printAsOperand(OS);
+ OS << " and MemoryLeader " << *getMemoryLeader();
}
};
@@ -513,6 +516,17 @@ public:
}
};
+class DeadExpression final : public Expression {
+public:
+ DeadExpression() : Expression(ET_Dead) {}
+ DeadExpression(const DeadExpression &) = delete;
+ DeadExpression &operator=(const DeadExpression &) = delete;
+
+ static bool classof(const Expression *E) {
+ return E->getExpressionType() == ET_Dead;
+ }
+};
+
class VariableExpression final : public Expression {
private:
Value *VariableValue;
diff --git a/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/include/llvm/Transforms/Utils/SimplifyLibCalls.h
index 665dd6f4b257..6aba9b2298b1 100644
--- a/include/llvm/Transforms/Utils/SimplifyLibCalls.h
+++ b/include/llvm/Transforms/Utils/SimplifyLibCalls.h
@@ -121,6 +121,7 @@ private:
Value *optimizeMemCpy(CallInst *CI, IRBuilder<> &B);
Value *optimizeMemMove(CallInst *CI, IRBuilder<> &B);
Value *optimizeMemSet(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeWcslen(CallInst *CI, IRBuilder<> &B);
// Wrapper for all String/Memory Library Call Optimizations
Value *optimizeStringMemoryLibCall(CallInst *CI, IRBuilder<> &B);
@@ -165,6 +166,9 @@ private:
/// hasFloatVersion - Checks if there is a float version of the specified
/// function by checking for an existing function with name FuncName + f
bool hasFloatVersion(StringRef FuncName);
+
+ /// Shared code to optimize strlen+wcslen.
+ Value *optimizeStringLength(CallInst *CI, IRBuilder<> &B, unsigned CharSize);
};
} // End llvm namespace
diff --git a/lib/Analysis/BasicAliasAnalysis.cpp b/lib/Analysis/BasicAliasAnalysis.cpp
index a33c01a0e461..f743cb234c45 100644
--- a/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/lib/Analysis/BasicAliasAnalysis.cpp
@@ -683,8 +683,11 @@ static bool isIntrinsicCall(ImmutableCallSite CS, Intrinsic::ID IID) {
#ifndef NDEBUG
static const Function *getParent(const Value *V) {
- if (const Instruction *inst = dyn_cast<Instruction>(V))
+ if (const Instruction *inst = dyn_cast<Instruction>(V)) {
+ if (!inst->getParent())
+ return nullptr;
return inst->getParent()->getParent();
+ }
if (const Argument *arg = dyn_cast<Argument>(V))
return arg->getParent();
diff --git a/lib/Analysis/BranchProbabilityInfo.cpp b/lib/Analysis/BranchProbabilityInfo.cpp
index db87b17c1567..267e19adfe4d 100644
--- a/lib/Analysis/BranchProbabilityInfo.cpp
+++ b/lib/Analysis/BranchProbabilityInfo.cpp
@@ -58,45 +58,12 @@ char BranchProbabilityInfoWrapperPass::ID = 0;
static const uint32_t LBH_TAKEN_WEIGHT = 124;
static const uint32_t LBH_NONTAKEN_WEIGHT = 4;
-/// \brief Unreachable-terminating branch taken weight.
+/// \brief Unreachable-terminating branch taken probability.
///
-/// This is the weight for a branch being taken to a block that terminates
+/// This is the probability for a branch being taken to a block that terminates
/// (eventually) in unreachable. These are predicted as unlikely as possible.
-static const uint32_t UR_TAKEN_WEIGHT = 1;
-
-/// \brief Unreachable-terminating branch not-taken weight.
-///
-/// This is the weight for a branch not being taken toward a block that
-/// terminates (eventually) in unreachable. Such a branch is essentially never
-/// taken. Set the weight to an absurdly high value so that nested loops don't
-/// easily subsume it.
-static const uint32_t UR_NONTAKEN_WEIGHT = 1024*1024 - 1;
-
-/// \brief Returns the branch probability for unreachable edge according to
-/// heuristic.
-///
-/// This is the branch probability being taken to a block that terminates
-/// (eventually) in unreachable. These are predicted as unlikely as possible.
-static BranchProbability getUnreachableProbability(uint64_t UnreachableCount) {
- assert(UnreachableCount > 0 && "UnreachableCount must be > 0");
- return BranchProbability::getBranchProbability(
- UR_TAKEN_WEIGHT,
- (UR_TAKEN_WEIGHT + UR_NONTAKEN_WEIGHT) * UnreachableCount);
-}
-
-/// \brief Returns the branch probability for reachable edge according to
-/// heuristic.
-///
-/// This is the branch probability not being taken toward a block that
-/// terminates (eventually) in unreachable. Such a branch is essentially never
-/// taken. Set the weight to an absurdly high value so that nested loops don't
-/// easily subsume it.
-static BranchProbability getReachableProbability(uint64_t ReachableCount) {
- assert(ReachableCount > 0 && "ReachableCount must be > 0");
- return BranchProbability::getBranchProbability(
- UR_NONTAKEN_WEIGHT,
- (UR_TAKEN_WEIGHT + UR_NONTAKEN_WEIGHT) * ReachableCount);
-}
+/// All reachable probability will equally share the remaining part.
+static const BranchProbability UR_TAKEN_PROB = BranchProbability::getRaw(1);
/// \brief Weight for a branch taken going into a cold block.
///
@@ -232,8 +199,10 @@ bool BranchProbabilityInfo::calcUnreachableHeuristics(const BasicBlock *BB) {
return true;
}
- auto UnreachableProb = getUnreachableProbability(UnreachableEdges.size());
- auto ReachableProb = getReachableProbability(ReachableEdges.size());
+ auto UnreachableProb = UR_TAKEN_PROB;
+ auto ReachableProb =
+ (BranchProbability::getOne() - UR_TAKEN_PROB * UnreachableEdges.size()) /
+ ReachableEdges.size();
for (unsigned SuccIdx : UnreachableEdges)
setEdgeProbability(BB, SuccIdx, UnreachableProb);
@@ -319,7 +288,7 @@ bool BranchProbabilityInfo::calcMetadataWeights(const BasicBlock *BB) {
// If the unreachable heuristic is more strong then we use it for this edge.
if (UnreachableIdxs.size() > 0 && ReachableIdxs.size() > 0) {
auto ToDistribute = BranchProbability::getZero();
- auto UnreachableProb = getUnreachableProbability(UnreachableIdxs.size());
+ auto UnreachableProb = UR_TAKEN_PROB;
for (auto i : UnreachableIdxs)
if (UnreachableProb < BP[i]) {
ToDistribute += BP[i] - UnreachableProb;
diff --git a/lib/Analysis/CallGraphSCCPass.cpp b/lib/Analysis/CallGraphSCCPass.cpp
index 8058e5b1935c..5896e6e0902f 100644
--- a/lib/Analysis/CallGraphSCCPass.cpp
+++ b/lib/Analysis/CallGraphSCCPass.cpp
@@ -477,10 +477,8 @@ bool CGPassManager::runOnModule(Module &M) {
if (DevirtualizedCall)
DEBUG(dbgs() << " CGSCCPASSMGR: Stopped iteration after " << Iteration
<< " times, due to -max-cg-scc-iterations\n");
-
- if (Iteration > MaxSCCIterations)
- MaxSCCIterations = Iteration;
-
+
+ MaxSCCIterations.updateMax(Iteration);
}
Changed |= doFinalization(CG);
return Changed;
diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp
index 5652248a60ce..2e72d5aa8269 100644
--- a/lib/Analysis/InstructionSimplify.cpp
+++ b/lib/Analysis/InstructionSimplify.cpp
@@ -126,8 +126,8 @@ static bool ValueDominatesPHI(Value *V, PHINode *P, const DominatorTree *DT) {
/// Also performs the transform "(A op' B) op C" -> "(A op C) op' (B op C)".
/// Returns the simplified value, or null if no simplification was performed.
static Value *ExpandBinOp(Instruction::BinaryOps Opcode, Value *LHS, Value *RHS,
- Instruction::BinaryOps OpcodeToExpand, const SimplifyQuery &Q,
- unsigned MaxRecurse) {
+ Instruction::BinaryOps OpcodeToExpand,
+ const SimplifyQuery &Q, unsigned MaxRecurse) {
// Recursion is always used, so bail out at once if we already hit the limit.
if (!MaxRecurse--)
return nullptr;
@@ -184,7 +184,8 @@ static Value *ExpandBinOp(Instruction::BinaryOps Opcode, Value *LHS, Value *RHS,
/// Generic simplifications for associative binary operations.
/// Returns the simpler value, or null if none was found.
static Value *SimplifyAssociativeBinOp(Instruction::BinaryOps Opcode,
- Value *LHS, Value *RHS, const SimplifyQuery &Q,
+ Value *LHS, Value *RHS,
+ const SimplifyQuery &Q,
unsigned MaxRecurse) {
assert(Instruction::isAssociative(Opcode) && "Not an associative operation!");
@@ -2260,28 +2261,49 @@ static Value *simplifyICmpOfBools(CmpInst::Predicate Pred, Value *LHS,
if (!OpTy->getScalarType()->isIntegerTy(1))
return nullptr;
- switch (Pred) {
- default:
- break;
- case ICmpInst::ICMP_EQ:
- // X == 1 -> X
- if (match(RHS, m_One()))
- return LHS;
- break;
- case ICmpInst::ICMP_NE:
- // X != 0 -> X
- if (match(RHS, m_Zero()))
+ // A boolean compared to true/false can be simplified in 14 out of the 20
+ // (10 predicates * 2 constants) possible combinations. Cases not handled here
+ // require a 'not' of the LHS, so those must be transformed in InstCombine.
+ if (match(RHS, m_Zero())) {
+ switch (Pred) {
+ case CmpInst::ICMP_NE: // X != 0 -> X
+ case CmpInst::ICMP_UGT: // X >u 0 -> X
+ case CmpInst::ICMP_SLT: // X <s 0 -> X
return LHS;
- break;
- case ICmpInst::ICMP_UGT:
- // X >u 0 -> X
- if (match(RHS, m_Zero()))
+
+ case CmpInst::ICMP_ULT: // X <u 0 -> false
+ case CmpInst::ICMP_SGT: // X >s 0 -> false
+ return getFalse(ITy);
+
+ case CmpInst::ICMP_UGE: // X >=u 0 -> true
+ case CmpInst::ICMP_SLE: // X <=s 0 -> true
+ return getTrue(ITy);
+
+ default: break;
+ }
+ } else if (match(RHS, m_One())) {
+ switch (Pred) {
+ case CmpInst::ICMP_EQ: // X == 1 -> X
+ case CmpInst::ICMP_UGE: // X >=u 1 -> X
+ case CmpInst::ICMP_SLE: // X <=s -1 -> X
return LHS;
+
+ case CmpInst::ICMP_UGT: // X >u 1 -> false
+ case CmpInst::ICMP_SLT: // X <s -1 -> false
+ return getFalse(ITy);
+
+ case CmpInst::ICMP_ULE: // X <=u 1 -> true
+ case CmpInst::ICMP_SGE: // X >=s -1 -> true
+ return getTrue(ITy);
+
+ default: break;
+ }
+ }
+
+ switch (Pred) {
+ default:
break;
case ICmpInst::ICMP_UGE:
- // X >=u 1 -> X
- if (match(RHS, m_One()))
- return LHS;
if (isImpliedCondition(RHS, LHS, Q.DL).getValueOr(false))
return getTrue(ITy);
break;
@@ -2296,16 +2318,6 @@ static Value *simplifyICmpOfBools(CmpInst::Predicate Pred, Value *LHS,
if (isImpliedCondition(LHS, RHS, Q.DL).getValueOr(false))
return getTrue(ITy);
break;
- case ICmpInst::ICMP_SLT:
- // X <s 0 -> X
- if (match(RHS, m_Zero()))
- return LHS;
- break;
- case ICmpInst::ICMP_SLE:
- // X <=s -1 -> X
- if (match(RHS, m_One()))
- return LHS;
- break;
case ICmpInst::ICMP_ULE:
if (isImpliedCondition(LHS, RHS, Q.DL).getValueOr(false))
return getTrue(ITy);
diff --git a/lib/Analysis/MemorySSA.cpp b/lib/Analysis/MemorySSA.cpp
index 2480fe44d5c0..e0e04a91410f 100644
--- a/lib/Analysis/MemorySSA.cpp
+++ b/lib/Analysis/MemorySSA.cpp
@@ -1799,6 +1799,15 @@ bool MemorySSA::dominates(const MemoryAccess *Dominator,
const static char LiveOnEntryStr[] = "liveOnEntry";
+void MemoryAccess::print(raw_ostream &OS) const {
+ switch (getValueID()) {
+ case MemoryPhiVal: return static_cast<const MemoryPhi *>(this)->print(OS);
+ case MemoryDefVal: return static_cast<const MemoryDef *>(this)->print(OS);
+ case MemoryUseVal: return static_cast<const MemoryUse *>(this)->print(OS);
+ }
+ llvm_unreachable("invalid value id");
+}
+
void MemoryDef::print(raw_ostream &OS) const {
MemoryAccess *UO = getDefiningAccess();
@@ -1836,8 +1845,6 @@ void MemoryPhi::print(raw_ostream &OS) const {
OS << ')';
}
-MemoryAccess::~MemoryAccess() {}
-
void MemoryUse::print(raw_ostream &OS) const {
MemoryAccess *UO = getDefiningAccess();
OS << "MemoryUse(";
@@ -2054,3 +2061,15 @@ MemoryAccess *DoNothingMemorySSAWalker::getClobberingMemoryAccess(
return StartingAccess;
}
} // namespace llvm
+
+void MemoryPhi::deleteMe(DerivedUser *Self) {
+ delete static_cast<MemoryPhi *>(Self);
+}
+
+void MemoryDef::deleteMe(DerivedUser *Self) {
+ delete static_cast<MemoryDef *>(Self);
+}
+
+void MemoryUse::deleteMe(DerivedUser *Self) {
+ delete static_cast<MemoryUse *>(Self);
+}
diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp
index a746ddfd7a63..78ded8141c08 100644
--- a/lib/Analysis/ScalarEvolution.cpp
+++ b/lib/Analysis/ScalarEvolution.cpp
@@ -3885,7 +3885,7 @@ public:
: SCEVRewriteVisitor(SE), L(L), Valid(true) {}
const SCEV *visitUnknown(const SCEVUnknown *Expr) {
- if (!(SE.getLoopDisposition(Expr, L) == ScalarEvolution::LoopInvariant))
+ if (!SE.isLoopInvariant(Expr, L))
Valid = false;
return Expr;
}
@@ -3919,7 +3919,7 @@ public:
const SCEV *visitUnknown(const SCEVUnknown *Expr) {
// Only allow AddRecExprs for this loop.
- if (!(SE.getLoopDisposition(Expr, L) == ScalarEvolution::LoopInvariant))
+ if (!SE.isLoopInvariant(Expr, L))
Valid = false;
return Expr;
}
@@ -5947,6 +5947,8 @@ ScalarEvolution::BackedgeTakenInfo::getMax(ScalarEvolution *SE) const {
if (any_of(ExitNotTaken, PredicateNotAlwaysTrue) || !getMax())
return SE->getCouldNotCompute();
+ assert((isa<SCEVCouldNotCompute>(getMax()) || isa<SCEVConstant>(getMax())) &&
+ "No point in having a non-constant max backedge taken count!");
return getMax();
}
@@ -5972,7 +5974,11 @@ bool ScalarEvolution::BackedgeTakenInfo::hasOperand(const SCEV *S,
}
ScalarEvolution::ExitLimit::ExitLimit(const SCEV *E)
- : ExactNotTaken(E), MaxNotTaken(E), MaxOrZero(false) {}
+ : ExactNotTaken(E), MaxNotTaken(E), MaxOrZero(false) {
+ assert((isa<SCEVCouldNotCompute>(MaxNotTaken) ||
+ isa<SCEVConstant>(MaxNotTaken)) &&
+ "No point in having a non-constant max backedge taken count!");
+}
ScalarEvolution::ExitLimit::ExitLimit(
const SCEV *E, const SCEV *M, bool MaxOrZero,
@@ -5981,6 +5987,9 @@ ScalarEvolution::ExitLimit::ExitLimit(
assert((isa<SCEVCouldNotCompute>(ExactNotTaken) ||
!isa<SCEVCouldNotCompute>(MaxNotTaken)) &&
"Exact is not allowed to be less precise than Max");
+ assert((isa<SCEVCouldNotCompute>(MaxNotTaken) ||
+ isa<SCEVConstant>(MaxNotTaken)) &&
+ "No point in having a non-constant max backedge taken count!");
for (auto *PredSet : PredSetList)
for (auto *P : *PredSet)
addPredicate(P);
@@ -5989,11 +5998,19 @@ ScalarEvolution::ExitLimit::ExitLimit(
ScalarEvolution::ExitLimit::ExitLimit(
const SCEV *E, const SCEV *M, bool MaxOrZero,
const SmallPtrSetImpl<const SCEVPredicate *> &PredSet)
- : ExitLimit(E, M, MaxOrZero, {&PredSet}) {}
+ : ExitLimit(E, M, MaxOrZero, {&PredSet}) {
+ assert((isa<SCEVCouldNotCompute>(MaxNotTaken) ||
+ isa<SCEVConstant>(MaxNotTaken)) &&
+ "No point in having a non-constant max backedge taken count!");
+}
ScalarEvolution::ExitLimit::ExitLimit(const SCEV *E, const SCEV *M,
bool MaxOrZero)
- : ExitLimit(E, M, MaxOrZero, None) {}
+ : ExitLimit(E, M, MaxOrZero, None) {
+ assert((isa<SCEVCouldNotCompute>(MaxNotTaken) ||
+ isa<SCEVConstant>(MaxNotTaken)) &&
+ "No point in having a non-constant max backedge taken count!");
+}
/// Allocate memory for BackedgeTakenInfo and copy the not-taken count of each
/// computable exit into a persistent ExitNotTakenInfo array.
@@ -6018,6 +6035,8 @@ ScalarEvolution::BackedgeTakenInfo::BackedgeTakenInfo(
return ExitNotTakenInfo(ExitBB, EL.ExactNotTaken, std::move(Predicate));
});
+ assert((isa<SCEVCouldNotCompute>(MaxCount) || isa<SCEVConstant>(MaxCount)) &&
+ "No point in having a non-constant max backedge taken count!");
}
/// Invalidate this result and free the ExitNotTakenInfo array.
@@ -6279,7 +6298,7 @@ ScalarEvolution::ExitLimit ScalarEvolution::computeExitLimitFromCondImpl(
// to not.
if (isa<SCEVCouldNotCompute>(MaxBECount) &&
!isa<SCEVCouldNotCompute>(BECount))
- MaxBECount = BECount;
+ MaxBECount = getConstant(getUnsignedRange(BECount).getUnsignedMax());
return ExitLimit(BECount, MaxBECount, false,
{&EL0.Predicates, &EL1.Predicates});
@@ -7583,13 +7602,20 @@ ScalarEvolution::howFarToZero(const SCEV *V, const Loop *L, bool ControlsExit,
loopHasNoAbnormalExits(AddRec->getLoop())) {
const SCEV *Exact =
getUDivExpr(Distance, CountDown ? getNegativeSCEV(Step) : Step);
- return ExitLimit(Exact, Exact, false, Predicates);
+ const SCEV *Max =
+ Exact == getCouldNotCompute()
+ ? Exact
+ : getConstant(getUnsignedRange(Exact).getUnsignedMax());
+ return ExitLimit(Exact, Max, false, Predicates);
}
// Solve the general equation.
- const SCEV *E = SolveLinEquationWithOverflow(
- StepC->getAPInt(), getNegativeSCEV(Start), *this);
- return ExitLimit(E, E, false, Predicates);
+ const SCEV *E = SolveLinEquationWithOverflow(StepC->getAPInt(),
+ getNegativeSCEV(Start), *this);
+ const SCEV *M = E == getCouldNotCompute()
+ ? E
+ : getConstant(getUnsignedRange(E).getUnsignedMax());
+ return ExitLimit(E, M, false, Predicates);
}
ScalarEvolution::ExitLimit
@@ -9218,8 +9244,9 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
getConstant(StrideForMaxBECount), false);
}
- if (isa<SCEVCouldNotCompute>(MaxBECount))
- MaxBECount = BECount;
+ if (isa<SCEVCouldNotCompute>(MaxBECount) &&
+ !isa<SCEVCouldNotCompute>(BECount))
+ MaxBECount = getConstant(getUnsignedRange(BECount).getUnsignedMax());
return ExitLimit(BECount, MaxBECount, MaxOrZero, Predicates);
}
diff --git a/lib/Analysis/TargetLibraryInfo.cpp b/lib/Analysis/TargetLibraryInfo.cpp
index 3cf1bbc5daa5..2be5d5caf7c2 100644
--- a/lib/Analysis/TargetLibraryInfo.cpp
+++ b/lib/Analysis/TargetLibraryInfo.cpp
@@ -13,6 +13,7 @@
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/IR/Constants.h"
#include "llvm/Support/CommandLine.h"
using namespace llvm;
@@ -1518,6 +1519,21 @@ TargetLibraryInfoImpl &TargetLibraryAnalysis::lookupInfoImpl(const Triple &T) {
return *Impl;
}
+unsigned TargetLibraryInfoImpl::getTargetWCharSize(const Triple &T) {
+ // See also clang/lib/Basic/Targets.cpp.
+ if (T.isPS4() || T.isOSWindows() || T.isArch16Bit())
+ return 2;
+ if (T.getArch() == Triple::xcore)
+ return 1;
+ return 4;
+}
+
+unsigned TargetLibraryInfoImpl::getWCharSize(const Module &M) const {
+ if (auto *ShortWChar = cast_or_null<ConstantAsMetadata>(
+ M.getModuleFlag("wchar_size")))
+ return cast<ConstantInt>(ShortWChar->getValue())->getZExtValue();
+ return getTargetWCharSize(Triple(M.getTargetTriple()));
+}
TargetLibraryInfoWrapperPass::TargetLibraryInfoWrapperPass()
: ImmutablePass(ID), TLIImpl(), TLI(TLIImpl) {
diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp
index cba7363a0afa..8e6c1096eec8 100644
--- a/lib/Analysis/ValueTracking.cpp
+++ b/lib/Analysis/ValueTracking.cpp
@@ -26,6 +26,7 @@
#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/GetElementPtrTypeIterator.h"
#include "llvm/IR/GlobalAlias.h"
@@ -2953,14 +2954,16 @@ Value *llvm::GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset,
return Ptr;
}
-bool llvm::isGEPBasedOnPointerToString(const GEPOperator *GEP) {
+bool llvm::isGEPBasedOnPointerToString(const GEPOperator *GEP,
+ unsigned CharSize) {
// Make sure the GEP has exactly three arguments.
if (GEP->getNumOperands() != 3)
return false;
- // Make sure the index-ee is a pointer to array of i8.
+ // Make sure the index-ee is a pointer to array of \p CharSize integers.
+ // CharSize.
ArrayType *AT = dyn_cast<ArrayType>(GEP->getSourceElementType());
- if (!AT || !AT->getElementType()->isIntegerTy(8))
+ if (!AT || !AT->getElementType()->isIntegerTy(CharSize))
return false;
// Check to make sure that the first operand of the GEP is an integer and
@@ -2972,11 +2975,9 @@ bool llvm::isGEPBasedOnPointerToString(const GEPOperator *GEP) {
return true;
}
-/// 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.
-bool llvm::getConstantStringInfo(const Value *V, StringRef &Str,
- uint64_t Offset, bool TrimAtNul) {
+bool llvm::getConstantDataArrayInfo(const Value *V,
+ ConstantDataArraySlice &Slice,
+ unsigned ElementSize, uint64_t Offset) {
assert(V);
// Look through bitcast instructions and geps.
@@ -2987,7 +2988,7 @@ bool llvm::getConstantStringInfo(const Value *V, StringRef &Str,
if (const GEPOperator *GEP = dyn_cast<GEPOperator>(V)) {
// The GEP operator should be based on a pointer to string constant, and is
// indexing into the string constant.
- if (!isGEPBasedOnPointerToString(GEP))
+ if (!isGEPBasedOnPointerToString(GEP, ElementSize))
return false;
// If the second index isn't a ConstantInt, then this is a variable index
@@ -2998,8 +2999,8 @@ bool llvm::getConstantStringInfo(const Value *V, StringRef &Str,
StartIdx = CI->getZExtValue();
else
return false;
- return getConstantStringInfo(GEP->getOperand(0), Str, StartIdx + Offset,
- TrimAtNul);
+ return getConstantDataArrayInfo(GEP->getOperand(0), Slice, ElementSize,
+ StartIdx + Offset);
}
// The GEP instruction, constant or instruction, must reference a global
@@ -3009,30 +3010,72 @@ bool llvm::getConstantStringInfo(const Value *V, StringRef &Str,
if (!GV || !GV->isConstant() || !GV->hasDefinitiveInitializer())
return false;
- // Handle the all-zeros case.
+ const ConstantDataArray *Array;
+ ArrayType *ArrayTy;
if (GV->getInitializer()->isNullValue()) {
- // This is a degenerate case. The initializer is constant zero so the
- // length of the string must be zero.
- Str = "";
- return true;
+ Type *GVTy = GV->getValueType();
+ if ( (ArrayTy = dyn_cast<ArrayType>(GVTy)) ) {
+ // A zeroinitializer for the array; There is no ConstantDataArray.
+ Array = nullptr;
+ } else {
+ const DataLayout &DL = GV->getParent()->getDataLayout();
+ uint64_t SizeInBytes = DL.getTypeStoreSize(GVTy);
+ uint64_t Length = SizeInBytes / (ElementSize / 8);
+ if (Length <= Offset)
+ return false;
+
+ Slice.Array = nullptr;
+ Slice.Offset = 0;
+ Slice.Length = Length - Offset;
+ return true;
+ }
+ } else {
+ // This must be a ConstantDataArray.
+ Array = dyn_cast<ConstantDataArray>(GV->getInitializer());
+ if (!Array)
+ return false;
+ ArrayTy = Array->getType();
}
+ if (!ArrayTy->getElementType()->isIntegerTy(ElementSize))
+ return false;
- // This must be a ConstantDataArray.
- const auto *Array = dyn_cast<ConstantDataArray>(GV->getInitializer());
- if (!Array || !Array->isString())
+ uint64_t NumElts = ArrayTy->getArrayNumElements();
+ if (Offset > NumElts)
return false;
- // Get the number of elements in the array.
- uint64_t NumElts = Array->getType()->getArrayNumElements();
+ Slice.Array = Array;
+ Slice.Offset = Offset;
+ Slice.Length = NumElts - Offset;
+ return true;
+}
- // Start out with the entire array in the StringRef.
- Str = Array->getAsString();
+/// 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.
+bool llvm::getConstantStringInfo(const Value *V, StringRef &Str,
+ uint64_t Offset, bool TrimAtNul) {
+ ConstantDataArraySlice Slice;
+ if (!getConstantDataArrayInfo(V, Slice, 8, Offset))
+ return false;
- if (Offset > NumElts)
+ if (Slice.Array == nullptr) {
+ if (TrimAtNul) {
+ Str = StringRef();
+ return true;
+ }
+ if (Slice.Length == 1) {
+ Str = StringRef("", 1);
+ return true;
+ }
+ // We cannot instantiate a StringRef as we do not have an apropriate string
+ // of 0s at hand.
return false;
+ }
+ // Start out with the entire array in the StringRef.
+ Str = Slice.Array->getAsString();
// Skip over 'offset' bytes.
- Str = Str.substr(Offset);
+ Str = Str.substr(Slice.Offset);
if (TrimAtNul) {
// Trim off the \0 and anything after it. If the array is not nul
@@ -3050,7 +3093,8 @@ bool llvm::getConstantStringInfo(const Value *V, StringRef &Str,
/// If we can compute the length of the string pointed to by
/// the specified pointer, return 'len+1'. If we can't, return 0.
static uint64_t GetStringLengthH(const Value *V,
- SmallPtrSetImpl<const PHINode*> &PHIs) {
+ SmallPtrSetImpl<const PHINode*> &PHIs,
+ unsigned CharSize) {
// Look through noop bitcast instructions.
V = V->stripPointerCasts();
@@ -3063,7 +3107,7 @@ static uint64_t GetStringLengthH(const Value *V,
// If it was new, see if all the input strings are the same length.
uint64_t LenSoFar = ~0ULL;
for (Value *IncValue : PN->incoming_values()) {
- uint64_t Len = GetStringLengthH(IncValue, PHIs);
+ uint64_t Len = GetStringLengthH(IncValue, PHIs, CharSize);
if (Len == 0) return 0; // Unknown length -> unknown.
if (Len == ~0ULL) continue;
@@ -3079,9 +3123,9 @@ static uint64_t GetStringLengthH(const Value *V,
// strlen(select(c,x,y)) -> strlen(x) ^ strlen(y)
if (const SelectInst *SI = dyn_cast<SelectInst>(V)) {
- uint64_t Len1 = GetStringLengthH(SI->getTrueValue(), PHIs);
+ uint64_t Len1 = GetStringLengthH(SI->getTrueValue(), PHIs, CharSize);
if (Len1 == 0) return 0;
- uint64_t Len2 = GetStringLengthH(SI->getFalseValue(), PHIs);
+ uint64_t Len2 = GetStringLengthH(SI->getFalseValue(), PHIs, CharSize);
if (Len2 == 0) return 0;
if (Len1 == ~0ULL) return Len2;
if (Len2 == ~0ULL) return Len1;
@@ -3090,20 +3134,30 @@ static uint64_t GetStringLengthH(const Value *V,
}
// Otherwise, see if we can read the string.
- StringRef StrData;
- if (!getConstantStringInfo(V, StrData))
+ ConstantDataArraySlice Slice;
+ if (!getConstantDataArrayInfo(V, Slice, CharSize))
return 0;
- return StrData.size()+1;
+ if (Slice.Array == nullptr)
+ return 1;
+
+ // Search for nul characters
+ unsigned NullIndex = 0;
+ for (unsigned E = Slice.Length; NullIndex < E; ++NullIndex) {
+ if (Slice.Array->getElementAsInteger(Slice.Offset + NullIndex) == 0)
+ break;
+ }
+
+ return NullIndex + 1;
}
/// 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 llvm::GetStringLength(const Value *V) {
+uint64_t llvm::GetStringLength(const Value *V, unsigned CharSize) {
if (!V->getType()->isPointerTy()) return 0;
SmallPtrSet<const PHINode*, 32> PHIs;
- uint64_t Len = GetStringLengthH(V, PHIs);
+ uint64_t Len = GetStringLengthH(V, PHIs, CharSize);
// If Len is ~0ULL, we had an infinite phi cycle: this is dead code, so return
// an empty string as a length.
return Len == ~0ULL ? 1 : Len;
diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp
index d7602c83435c..ff1ea44a18a7 100644
--- a/lib/AsmParser/LLParser.cpp
+++ b/lib/AsmParser/LLParser.cpp
@@ -2502,7 +2502,7 @@ LLParser::PerFunctionState::~PerFunctionState() {
continue;
P.second.first->replaceAllUsesWith(
UndefValue::get(P.second.first->getType()));
- delete P.second.first;
+ P.second.first->deleteValue();
}
for (const auto &P : ForwardRefValIDs) {
@@ -2510,7 +2510,7 @@ LLParser::PerFunctionState::~PerFunctionState() {
continue;
P.second.first->replaceAllUsesWith(
UndefValue::get(P.second.first->getType()));
- delete P.second.first;
+ P.second.first->deleteValue();
}
}
@@ -2642,7 +2642,7 @@ bool LLParser::PerFunctionState::SetInstName(int NameID,
getTypeString(FI->second.first->getType()) + "'");
Sentinel->replaceAllUsesWith(Inst);
- delete Sentinel;
+ Sentinel->deleteValue();
ForwardRefValIDs.erase(FI);
}
@@ -2659,7 +2659,7 @@ bool LLParser::PerFunctionState::SetInstName(int NameID,
getTypeString(FI->second.first->getType()) + "'");
Sentinel->replaceAllUsesWith(Inst);
- delete Sentinel;
+ Sentinel->deleteValue();
ForwardRefVals.erase(FI);
}
diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp
index 76298121566a..686c94687669 100644
--- a/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -4489,11 +4489,11 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
// Add instruction to end of current BB. If there is no current BB, reject
// this file.
if (!CurBB) {
- delete I;
+ I->deleteValue();
return error("Invalid instruction with no BB");
}
if (!OperandBundles.empty()) {
- delete I;
+ I->deleteValue();
return error("Operand bundles found with no consumer");
}
CurBB->getInstList().push_back(I);
diff --git a/lib/Bitcode/Reader/ValueList.cpp b/lib/Bitcode/Reader/ValueList.cpp
index d1a2a11bbfad..f2a3439a87be 100644
--- a/lib/Bitcode/Reader/ValueList.cpp
+++ b/lib/Bitcode/Reader/ValueList.cpp
@@ -73,7 +73,7 @@ void BitcodeReaderValueList::assignValue(Value *V, unsigned Idx) {
// If there was a forward reference to this value, replace it.
Value *PrevVal = OldV;
OldV->replaceAllUsesWith(V);
- delete PrevVal;
+ PrevVal->deleteValue();
}
}
@@ -194,6 +194,6 @@ void BitcodeReaderValueList::resolveConstantForwardRefs() {
// Update all ValueHandles, they should be the only users at this point.
Placeholder->replaceAllUsesWith(RealVal);
- delete Placeholder;
+ Placeholder->deleteValue();
}
}
diff --git a/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index 7d945690e9c3..1b39e46ee466 100644
--- a/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -13,7 +13,6 @@
#include "CodeViewDebug.h"
#include "llvm/ADT/TinyPtrVector.h"
-#include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/Line.h"
@@ -23,6 +22,7 @@
#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeTableCollection.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
#include "llvm/IR/Constants.h"
#include "llvm/MC/MCAsmInfo.h"
@@ -469,17 +469,21 @@ void CodeViewDebug::emitTypeInformation() {
CommentPrefix += ' ';
}
- TypeDatabase TypeDB(TypeTable.records().size());
- CVTypeDumper CVTD(TypeDB);
- TypeTable.ForEachRecord([&](TypeIndex Index, ArrayRef<uint8_t> Record) {
+ TypeTableCollection Table(TypeTable.records());
+ Optional<TypeIndex> B = Table.getFirst();
+ while (B) {
+ // This will fail if the record data is invalid.
+ CVType Record = Table.getType(*B);
+
if (OS.isVerboseAsm()) {
// Emit a block comment describing the type record for readability.
SmallString<512> CommentBlock;
raw_svector_ostream CommentOS(CommentBlock);
ScopedPrinter SP(CommentOS);
SP.setPrefix(CommentPrefix);
- TypeDumpVisitor TDV(TypeDB, &SP, false);
- Error E = CVTD.dump(Record, TDV);
+ TypeDumpVisitor TDV(Table, &SP, false);
+
+ Error E = codeview::visitTypeRecord(Record, *B, TDV);
if (E) {
logAllUnhandledErrors(std::move(E), errs(), "error: ");
llvm_unreachable("produced malformed type record");
@@ -489,29 +493,10 @@ void CodeViewDebug::emitTypeInformation() {
// newline.
OS.emitRawComment(
CommentOS.str().drop_front(CommentPrefix.size() - 1).rtrim());
- } else {
-#ifndef NDEBUG
- // Assert that the type data is valid even if we aren't dumping
- // comments. The MSVC linker doesn't do much type record validation,
- // so the first link of an invalid type record can succeed while
- // subsequent links will fail with LNK1285.
- BinaryByteStream Stream(Record, llvm::support::little);
- CVTypeArray Types;
- BinaryStreamReader Reader(Stream);
- Error E = Reader.readArray(Types, Reader.getLength());
- if (!E) {
- TypeVisitorCallbacks C;
- E = codeview::visitTypeStream(Types, C);
- }
- if (E) {
- logAllUnhandledErrors(std::move(E), errs(), "error: ");
- llvm_unreachable("produced malformed type record");
- }
-#endif
}
- StringRef S(reinterpret_cast<const char *>(Record.data()), Record.size());
- OS.EmitBinaryData(S);
- });
+ OS.EmitBinaryData(Record.str_data());
+ B = Table.getNext(*B);
+ }
}
namespace {
diff --git a/lib/CodeGen/AtomicExpandPass.cpp b/lib/CodeGen/AtomicExpandPass.cpp
index 17e6be05eb42..984973cf3a3b 100644
--- a/lib/CodeGen/AtomicExpandPass.cpp
+++ b/lib/CodeGen/AtomicExpandPass.cpp
@@ -17,6 +17,7 @@
#include "llvm/CodeGen/AtomicExpandUtils.h"
#include "llvm/CodeGen/Passes.h"
+#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstIterator.h"
@@ -35,12 +36,10 @@ using namespace llvm;
namespace {
class AtomicExpand: public FunctionPass {
- const TargetMachine *TM;
const TargetLowering *TLI;
public:
static char ID; // Pass identification, replacement for typeid
- explicit AtomicExpand(const TargetMachine *TM = nullptr)
- : FunctionPass(ID), TM(TM), TLI(nullptr) {
+ AtomicExpand() : FunctionPass(ID), TLI(nullptr) {
initializeAtomicExpandPass(*PassRegistry::getPassRegistry());
}
@@ -97,12 +96,10 @@ namespace {
char AtomicExpand::ID = 0;
char &llvm::AtomicExpandID = AtomicExpand::ID;
-INITIALIZE_TM_PASS(AtomicExpand, "atomic-expand", "Expand Atomic instructions",
- false, false)
+INITIALIZE_PASS(AtomicExpand, "atomic-expand", "Expand Atomic instructions",
+ false, false)
-FunctionPass *llvm::createAtomicExpandPass(const TargetMachine *TM) {
- return new AtomicExpand(TM);
-}
+FunctionPass *llvm::createAtomicExpandPass() { return new AtomicExpand(); }
namespace {
// Helper functions to retrieve the size of atomic instructions.
@@ -172,9 +169,14 @@ bool atomicSizeSupported(const TargetLowering *TLI, Inst *I) {
} // end anonymous namespace
bool AtomicExpand::runOnFunction(Function &F) {
- if (!TM || !TM->getSubtargetImpl(F)->enableAtomicExpand())
+ auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
+ if (!TPC)
+ return false;
+
+ auto &TM = TPC->getTM<TargetMachine>();
+ if (!TM.getSubtargetImpl(F)->enableAtomicExpand())
return false;
- TLI = TM->getSubtargetImpl(F)->getTargetLowering();
+ TLI = TM.getSubtargetImpl(F)->getTargetLowering();
SmallVector<Instruction *, 1> AtomicInsts;
diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt
index 55a27e2fb79e..2b5863aa5800 100644
--- a/lib/CodeGen/CMakeLists.txt
+++ b/lib/CodeGen/CMakeLists.txt
@@ -49,7 +49,6 @@ add_llvm_library(LLVMCodeGen
LivePhysRegs.cpp
LiveRangeCalc.cpp
LiveRangeEdit.cpp
- LiveRangeShrink.cpp
LiveRegMatrix.cpp
LiveRegUnits.cpp
LiveStackAnalysis.cpp
diff --git a/lib/CodeGen/CodeGen.cpp b/lib/CodeGen/CodeGen.cpp
index 4d30c6574b12..2a2715beaadc 100644
--- a/lib/CodeGen/CodeGen.cpp
+++ b/lib/CodeGen/CodeGen.cpp
@@ -43,7 +43,6 @@ void llvm::initializeCodeGen(PassRegistry &Registry) {
initializeLiveDebugValuesPass(Registry);
initializeLiveDebugVariablesPass(Registry);
initializeLiveIntervalsPass(Registry);
- initializeLiveRangeShrinkPass(Registry);
initializeLiveStacksPass(Registry);
initializeLiveVariablesPass(Registry);
initializeLocalStackSlotPassPass(Registry);
diff --git a/lib/CodeGen/CodeGenPrepare.cpp b/lib/CodeGen/CodeGenPrepare.cpp
index f2e024c5e3bd..3a1a3020a8d4 100644
--- a/lib/CodeGen/CodeGenPrepare.cpp
+++ b/lib/CodeGen/CodeGenPrepare.cpp
@@ -14,6 +14,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/Passes.h"
+#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallSet.h"
@@ -197,10 +198,11 @@ class TypePromotionTransaction;
public:
static char ID; // Pass identification, replacement for typeid
- explicit CodeGenPrepare(const TargetMachine *TM = nullptr)
- : FunctionPass(ID), TM(TM), TLI(nullptr), TTI(nullptr), DL(nullptr) {
- initializeCodeGenPreparePass(*PassRegistry::getPassRegistry());
- }
+ CodeGenPrepare()
+ : FunctionPass(ID), TM(nullptr), TLI(nullptr), TTI(nullptr),
+ DL(nullptr) {
+ initializeCodeGenPreparePass(*PassRegistry::getPassRegistry());
+ }
bool runOnFunction(Function &F) override;
StringRef getPassName() const override { return "CodeGen Prepare"; }
@@ -255,15 +257,13 @@ class TypePromotionTransaction;
}
char CodeGenPrepare::ID = 0;
-INITIALIZE_TM_PASS_BEGIN(CodeGenPrepare, "codegenprepare",
- "Optimize for code generation", false, false)
+INITIALIZE_PASS_BEGIN(CodeGenPrepare, "codegenprepare",
+ "Optimize for code generation", false, false)
INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
-INITIALIZE_TM_PASS_END(CodeGenPrepare, "codegenprepare",
- "Optimize for code generation", false, false)
+INITIALIZE_PASS_END(CodeGenPrepare, "codegenprepare",
+ "Optimize for code generation", false, false)
-FunctionPass *llvm::createCodeGenPreparePass(const TargetMachine *TM) {
- return new CodeGenPrepare(TM);
-}
+FunctionPass *llvm::createCodeGenPreparePass() { return new CodeGenPrepare(); }
bool CodeGenPrepare::runOnFunction(Function &F) {
if (skipFunction(F))
@@ -279,7 +279,8 @@ bool CodeGenPrepare::runOnFunction(Function &F) {
BPI.reset();
ModifiedDT = false;
- if (TM) {
+ if (auto *TPC = getAnalysisIfAvailable<TargetPassConfig>()) {
+ TM = &TPC->getTM<TargetMachine>();
SubtargetInfo = TM->getSubtargetImpl(F);
TLI = SubtargetInfo->getTargetLowering();
TRI = SubtargetInfo->getRegisterInfo();
@@ -349,7 +350,7 @@ bool CodeGenPrepare::runOnFunction(Function &F) {
// Really free removed instructions during promotion.
for (Instruction *I : RemovedInsts)
- delete I;
+ I->deleteValue();
EverMadeChange |= MadeChange;
}
diff --git a/lib/CodeGen/DwarfEHPrepare.cpp b/lib/CodeGen/DwarfEHPrepare.cpp
index 38af19a04448..1ef4d8660657 100644
--- a/lib/CodeGen/DwarfEHPrepare.cpp
+++ b/lib/CodeGen/DwarfEHPrepare.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/Passes.h"
+#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/CFG.h"
@@ -34,8 +35,6 @@ STATISTIC(NumResumesLowered, "Number of resume calls lowered");
namespace {
class DwarfEHPrepare : public FunctionPass {
- const TargetMachine *TM;
-
// RewindFunction - _Unwind_Resume or the target equivalent.
Constant *RewindFunction;
@@ -52,15 +51,9 @@ namespace {
public:
static char ID; // Pass identification, replacement for typeid.
- // INITIALIZE_TM_PASS requires a default constructor, but it isn't used in
- // practice.
DwarfEHPrepare()
- : FunctionPass(ID), TM(nullptr), RewindFunction(nullptr), DT(nullptr),
- TLI(nullptr) {}
-
- DwarfEHPrepare(const TargetMachine *TM)
- : FunctionPass(ID), TM(TM), RewindFunction(nullptr), DT(nullptr),
- TLI(nullptr) {}
+ : FunctionPass(ID), RewindFunction(nullptr), DT(nullptr), TLI(nullptr) {
+ }
bool runOnFunction(Function &Fn) override;
@@ -78,18 +71,18 @@ namespace {
} // end anonymous namespace
char DwarfEHPrepare::ID = 0;
-INITIALIZE_TM_PASS_BEGIN(DwarfEHPrepare, "dwarfehprepare",
- "Prepare DWARF exceptions", false, false)
+INITIALIZE_PASS_BEGIN(DwarfEHPrepare, "dwarfehprepare",
+ "Prepare DWARF exceptions", false, false)
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
+INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
-INITIALIZE_TM_PASS_END(DwarfEHPrepare, "dwarfehprepare",
- "Prepare DWARF exceptions", false, false)
+INITIALIZE_PASS_END(DwarfEHPrepare, "dwarfehprepare",
+ "Prepare DWARF exceptions", false, false)
-FunctionPass *llvm::createDwarfEHPass(const TargetMachine *TM) {
- return new DwarfEHPrepare(TM);
-}
+FunctionPass *llvm::createDwarfEHPass() { return new DwarfEHPrepare(); }
void DwarfEHPrepare::getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<TargetPassConfig>();
AU.addRequired<TargetTransformInfoWrapperPass>();
AU.addRequired<DominatorTreeWrapperPass>();
}
@@ -254,9 +247,10 @@ bool DwarfEHPrepare::InsertUnwindResumeCalls(Function &Fn) {
}
bool DwarfEHPrepare::runOnFunction(Function &Fn) {
- assert(TM && "DWARF EH preparation requires a target machine");
+ const TargetMachine &TM =
+ getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
- TLI = TM->getSubtargetImpl(Fn)->getTargetLowering();
+ TLI = TM.getSubtargetImpl(Fn)->getTargetLowering();
bool Changed = InsertUnwindResumeCalls(Fn);
DT = nullptr;
TLI = nullptr;
diff --git a/lib/CodeGen/GlobalISel/IRTranslator.cpp b/lib/CodeGen/GlobalISel/IRTranslator.cpp
index 77dfb13ac1f2..afc18a15aa1c 100644
--- a/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -340,6 +340,15 @@ bool IRTranslator::translateExtractValue(const User &U,
Type *Int32Ty = Type::getInt32Ty(U.getContext());
SmallVector<Value *, 1> Indices;
+ // If Src is a single element ConstantStruct, translate extractvalue
+ // to that element to avoid inserting a cast instruction.
+ if (auto CS = dyn_cast<ConstantStruct>(Src))
+ if (CS->getNumOperands() == 1) {
+ unsigned Res = getOrCreateVReg(*CS->getOperand(0));
+ ValToVReg[&U] = Res;
+ return true;
+ }
+
// getIndexedOffsetInType is designed for GEPs, so the first index is the
// usual array element rather than looking into the actual aggregate.
Indices.push_back(ConstantInt::get(Int32Ty, 0));
@@ -1108,6 +1117,23 @@ bool IRTranslator::translate(const Constant &C, unsigned Reg) {
default:
return false;
}
+ } else if (auto CS = dyn_cast<ConstantStruct>(&C)) {
+ // Return the element if it is a single element ConstantStruct.
+ if (CS->getNumOperands() == 1) {
+ unsigned EltReg = getOrCreateVReg(*CS->getOperand(0));
+ EntryBuilder.buildCast(Reg, EltReg);
+ return true;
+ }
+ SmallVector<unsigned, 4> Ops;
+ SmallVector<uint64_t, 4> Indices;
+ uint64_t Offset = 0;
+ for (unsigned i = 0; i < CS->getNumOperands(); ++i) {
+ unsigned OpReg = getOrCreateVReg(*CS->getOperand(i));
+ Ops.push_back(OpReg);
+ Indices.push_back(Offset);
+ Offset += MRI->getType(OpReg).getSizeInBits();
+ }
+ EntryBuilder.buildSequence(Reg, Ops, Indices);
} else if (auto CV = dyn_cast<ConstantVector>(&C)) {
if (CV->getNumOperands() == 1)
return translate(*CV->getOperand(0), Reg);
diff --git a/lib/CodeGen/GlobalISel/InstructionSelector.cpp b/lib/CodeGen/GlobalISel/InstructionSelector.cpp
index c67da8629a3b..4c0b06dffd21 100644
--- a/lib/CodeGen/GlobalISel/InstructionSelector.cpp
+++ b/lib/CodeGen/GlobalISel/InstructionSelector.cpp
@@ -73,7 +73,7 @@ bool InstructionSelector::isOperandImmEqual(
const MachineOperand &MO, int64_t Value,
const MachineRegisterInfo &MRI) const {
- if (MO.getReg())
+ if (MO.isReg() && MO.getReg())
if (auto VRegVal = getConstantVRegVal(MO.getReg(), MRI))
return *VRegVal == Value;
return false;
diff --git a/lib/CodeGen/InterleavedAccessPass.cpp b/lib/CodeGen/InterleavedAccessPass.cpp
index ec35b3f6449e..bb29db301a95 100644
--- a/lib/CodeGen/InterleavedAccessPass.cpp
+++ b/lib/CodeGen/InterleavedAccessPass.cpp
@@ -45,6 +45,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/Passes.h"
+#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/Support/Debug.h"
@@ -68,8 +69,7 @@ class InterleavedAccess : public FunctionPass {
public:
static char ID;
- InterleavedAccess(const TargetMachine *TM = nullptr)
- : FunctionPass(ID), DT(nullptr), TM(TM), TLI(nullptr) {
+ InterleavedAccess() : FunctionPass(ID), DT(nullptr), TLI(nullptr) {
initializeInterleavedAccessPass(*PassRegistry::getPassRegistry());
}
@@ -84,7 +84,6 @@ public:
private:
DominatorTree *DT;
- const TargetMachine *TM;
const TargetLowering *TLI;
/// The maximum supported interleave factor.
@@ -108,18 +107,18 @@ private:
} // end anonymous namespace.
char InterleavedAccess::ID = 0;
-INITIALIZE_TM_PASS_BEGIN(
+INITIALIZE_PASS_BEGIN(
InterleavedAccess, "interleaved-access",
"Lower interleaved memory accesses to target specific intrinsics", false,
false)
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
-INITIALIZE_TM_PASS_END(
+INITIALIZE_PASS_END(
InterleavedAccess, "interleaved-access",
"Lower interleaved memory accesses to target specific intrinsics", false,
false)
-FunctionPass *llvm::createInterleavedAccessPass(const TargetMachine *TM) {
- return new InterleavedAccess(TM);
+FunctionPass *llvm::createInterleavedAccessPass() {
+ return new InterleavedAccess();
}
/// \brief Check if the mask is a DE-interleave mask of the given factor
@@ -426,13 +425,15 @@ bool InterleavedAccess::lowerInterleavedStore(
}
bool InterleavedAccess::runOnFunction(Function &F) {
- if (!TM || !LowerInterleavedAccesses)
+ auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
+ if (!TPC || !LowerInterleavedAccesses)
return false;
DEBUG(dbgs() << "*** " << getPassName() << ": " << F.getName() << "\n");
DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
- TLI = TM->getSubtargetImpl(F)->getTargetLowering();
+ auto &TM = TPC->getTM<TargetMachine>();
+ TLI = TM.getSubtargetImpl(F)->getTargetLowering();
MaxFactor = TLI->getMaxSupportedInterleaveFactor();
// Holds dead instructions that will be erased later.
diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp
index 7b1706f0f4ba..be3b258315bb 100644
--- a/lib/CodeGen/LLVMTargetMachine.cpp
+++ b/lib/CodeGen/LLVMTargetMachine.cpp
@@ -109,26 +109,24 @@ addPassesToGenerateCode(LLVMTargetMachine *TM, PassManagerBase &PM,
AnalysisID StopAfter,
MachineFunctionInitializer *MFInitializer = nullptr) {
- // When in emulated TLS mode, add the LowerEmuTLS pass.
- if (TM->Options.EmulatedTLS)
- PM.add(createLowerEmuTLSPass(TM));
-
- PM.add(createPreISelIntrinsicLoweringPass());
-
- // Add internal analysis passes from the target machine.
- PM.add(createTargetTransformInfoWrapperPass(TM->getTargetIRAnalysis()));
-
// Targets may override createPassConfig to provide a target-specific
// subclass.
TargetPassConfig *PassConfig = TM->createPassConfig(PM);
PassConfig->setStartStopPasses(StartBefore, StartAfter, StopBefore,
StopAfter);
-
// Set PassConfig options provided by TargetMachine.
PassConfig->setDisableVerify(DisableVerify);
-
PM.add(PassConfig);
+ // When in emulated TLS mode, add the LowerEmuTLS pass.
+ if (TM->Options.EmulatedTLS)
+ PM.add(createLowerEmuTLSPass());
+
+ PM.add(createPreISelIntrinsicLoweringPass());
+
+ // Add internal analysis passes from the target machine.
+ PM.add(createTargetTransformInfoWrapperPass(TM->getTargetIRAnalysis()));
+
PassConfig->addIRPasses();
PassConfig->addCodeGenPrepare();
diff --git a/lib/CodeGen/LiveRangeShrink.cpp b/lib/CodeGen/LiveRangeShrink.cpp
deleted file mode 100644
index 00182e2c779f..000000000000
--- a/lib/CodeGen/LiveRangeShrink.cpp
+++ /dev/null
@@ -1,211 +0,0 @@
-//===-- LiveRangeShrink.cpp - Move instructions to shrink live range ------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-///===---------------------------------------------------------------------===//
-///
-/// \file
-/// This pass moves instructions close to the definition of its operands to
-/// shrink live range of the def instruction. The code motion is limited within
-/// the basic block. The moved instruction should have 1 def, and more than one
-/// uses, all of which are the only use of the def.
-///
-///===---------------------------------------------------------------------===//
-#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/CodeGen/MachineRegisterInfo.h"
-#include "llvm/CodeGen/Passes.h"
-#include "llvm/ADT/Statistic.h"
-#include "llvm/Support/Debug.h"
-
-#define DEBUG_TYPE "lrshrink"
-
-STATISTIC(NumInstrsHoistedToShrinkLiveRange,
- "Number of insructions hoisted to shrink live range.");
-
-using namespace llvm;
-
-namespace {
-class LiveRangeShrink : public MachineFunctionPass {
-public:
- static char ID;
-
- LiveRangeShrink() : MachineFunctionPass(ID) {
- initializeLiveRangeShrinkPass(*PassRegistry::getPassRegistry());
- }
-
- void getAnalysisUsage(AnalysisUsage &AU) const override {
- AU.setPreservesCFG();
- MachineFunctionPass::getAnalysisUsage(AU);
- }
-
- StringRef getPassName() const override { return "Live Range Shrink"; }
-
- bool runOnMachineFunction(MachineFunction &MF) override;
-};
-} // End anonymous namespace.
-
-char LiveRangeShrink::ID = 0;
-char &llvm::LiveRangeShrinkID = LiveRangeShrink::ID;
-
-INITIALIZE_PASS(LiveRangeShrink, "lrshrink", "Live Range Shrink Pass", false,
- false)
-namespace {
-typedef DenseMap<MachineInstr *, unsigned> InstOrderMap;
-
-/// Returns \p New if it's dominated by \p Old, otherwise return \p Old.
-/// \p M maintains a map from instruction to its dominating order that satisfies
-/// M[A] > M[B] guarantees that A is dominated by B.
-/// If \p New is not in \p M, return \p Old. Otherwise if \p Old is null, return
-/// \p New.
-MachineInstr *FindDominatedInstruction(MachineInstr &New, MachineInstr *Old,
- const InstOrderMap &M) {
- auto NewIter = M.find(&New);
- if (NewIter == M.end())
- return Old;
- if (Old == nullptr)
- return &New;
- unsigned OrderOld = M.find(Old)->second;
- unsigned OrderNew = NewIter->second;
- if (OrderOld != OrderNew)
- return OrderOld < OrderNew ? &New : Old;
- // OrderOld == OrderNew, we need to iterate down from Old to see if it
- // can reach New, if yes, New is dominated by Old.
- for (MachineInstr *I = Old->getNextNode(); M.find(I)->second == OrderNew;
- I = I->getNextNode())
- if (I == &New)
- return &New;
- return Old;
-}
-
-/// Builds Instruction to its dominating order number map \p M by traversing
-/// from instruction \p Start.
-void BuildInstOrderMap(MachineBasicBlock::iterator Start, InstOrderMap &M) {
- M.clear();
- unsigned i = 0;
- for (MachineInstr &I : make_range(Start, Start->getParent()->end()))
- M[&I] = i++;
-}
-} // end anonymous namespace
-
-bool LiveRangeShrink::runOnMachineFunction(MachineFunction &MF) {
- if (skipFunction(*MF.getFunction()))
- return false;
-
- MachineRegisterInfo &MRI = MF.getRegInfo();
-
- DEBUG(dbgs() << "**** Analysing " << MF.getName() << '\n');
-
- InstOrderMap IOM;
- // Map from register to instruction order (value of IOM) where the
- // register is used last. When moving instructions up, we need to
- // make sure all its defs (including dead def) will not cross its
- // last use when moving up.
- DenseMap<unsigned, unsigned> UseMap;
-
- for (MachineBasicBlock &MBB : MF) {
- if (MBB.empty())
- continue;
- bool SawStore = false;
- BuildInstOrderMap(MBB.begin(), IOM);
- UseMap.clear();
-
- for (MachineBasicBlock::iterator Next = MBB.begin(); Next != MBB.end();) {
- MachineInstr &MI = *Next;
- ++Next;
- if (MI.isPHI() || MI.isDebugValue())
- continue;
- if (MI.mayStore())
- SawStore = true;
-
- unsigned CurrentOrder = IOM[&MI];
- unsigned Barrier = 0;
- for (const MachineOperand &MO : MI.operands()) {
- if (!MO.isReg() || MO.isDebug())
- continue;
- if (MO.isUse())
- UseMap[MO.getReg()] = CurrentOrder;
- else if (MO.isDead() && UseMap.count(MO.getReg()))
- // Barrier is the last instruction where MO get used. MI should not
- // be moved above Barrier.
- Barrier = std::max(Barrier, UseMap[MO.getReg()]);
- }
-
- if (!MI.isSafeToMove(nullptr, SawStore)) {
- // If MI has side effects, it should become a barrier for code motion.
- // IOM is rebuild from the next instruction to prevent later
- // instructions from being moved before this MI.
- if (MI.hasUnmodeledSideEffects() && Next != MBB.end()) {
- BuildInstOrderMap(Next, IOM);
- SawStore = false;
- }
- continue;
- }
-
- const MachineOperand *DefMO = nullptr;
- MachineInstr *Insert = nullptr;
-
- // Number of live-ranges that will be shortened. We do not count
- // live-ranges that are defined by a COPY as it could be coalesced later.
- unsigned NumEligibleUse = 0;
-
- for (const MachineOperand &MO : MI.operands()) {
- if (!MO.isReg() || MO.isDead() || MO.isDebug())
- continue;
- unsigned Reg = MO.getReg();
- // Do not move the instruction if it def/uses a physical register,
- // unless it is a constant physical register.
- if (TargetRegisterInfo::isPhysicalRegister(Reg) &&
- !MRI.isConstantPhysReg(Reg)) {
- Insert = nullptr;
- break;
- }
- if (MO.isDef()) {
- // Do not move if there is more than one def.
- if (DefMO) {
- Insert = nullptr;
- break;
- }
- DefMO = &MO;
- } else if (MRI.hasOneNonDBGUse(Reg) && MRI.hasOneDef(Reg)) {
- MachineInstr &DefInstr = *MRI.def_instr_begin(Reg);
- if (!DefInstr.isCopy())
- NumEligibleUse++;
- Insert = FindDominatedInstruction(DefInstr, Insert, IOM);
- } else {
- Insert = nullptr;
- break;
- }
- }
- // Move the instruction when # of shrunk live range > 1.
- if (DefMO && Insert && NumEligibleUse > 1 && Barrier <= IOM[Insert]) {
- MachineBasicBlock::iterator I = std::next(Insert->getIterator());
- // Skip all the PHI and debug instructions.
- while (I != MBB.end() && (I->isPHI() || I->isDebugValue()))
- I = std::next(I);
- if (I == MI.getIterator())
- continue;
-
- // Update the dominator order to be the same as the insertion point.
- // We do this to maintain a non-decreasing order without need to update
- // all instruction orders after the insertion point.
- unsigned NewOrder = IOM[&*I];
- IOM[&MI] = NewOrder;
- NumInstrsHoistedToShrinkLiveRange++;
-
- // Find MI's debug value following MI.
- MachineBasicBlock::iterator EndIter = std::next(MI.getIterator());
- if (MI.getOperand(0).isReg())
- for (; EndIter != MBB.end() && EndIter->isDebugValue() &&
- EndIter->getOperand(0).isReg() &&
- EndIter->getOperand(0).getReg() == MI.getOperand(0).getReg();
- ++EndIter, ++Next)
- IOM[&*EndIter] = NewOrder;
- MBB.splice(I, &MBB, MI.getIterator(), EndIter);
- }
- }
- }
- return false;
-}
diff --git a/lib/CodeGen/LowerEmuTLS.cpp b/lib/CodeGen/LowerEmuTLS.cpp
index 6966c8ca4a5f..5fb5b747f471 100644
--- a/lib/CodeGen/LowerEmuTLS.cpp
+++ b/lib/CodeGen/LowerEmuTLS.cpp
@@ -16,6 +16,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/Passes.h"
+#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
@@ -28,14 +29,12 @@ using namespace llvm;
namespace {
class LowerEmuTLS : public ModulePass {
- const TargetMachine *TM;
public:
static char ID; // Pass identification, replacement for typeid
- explicit LowerEmuTLS() : ModulePass(ID), TM(nullptr) { }
- explicit LowerEmuTLS(const TargetMachine *TM)
- : ModulePass(ID), TM(TM) {
+ LowerEmuTLS() : ModulePass(ID) {
initializeLowerEmuTLSPass(*PassRegistry::getPassRegistry());
}
+
bool runOnModule(Module &M) override;
private:
bool addEmuTlsVar(Module &M, const GlobalVariable *GV);
@@ -55,18 +54,21 @@ private:
char LowerEmuTLS::ID = 0;
INITIALIZE_PASS(LowerEmuTLS, "loweremutls",
- "Add __emutls_[vt]. variables for emultated TLS model",
- false, false)
+ "Add __emutls_[vt]. variables for emultated TLS model", false,
+ false)
-ModulePass *llvm::createLowerEmuTLSPass(const TargetMachine *TM) {
- return new LowerEmuTLS(TM);
-}
+ModulePass *llvm::createLowerEmuTLSPass() { return new LowerEmuTLS(); }
bool LowerEmuTLS::runOnModule(Module &M) {
if (skipModule(M))
return false;
- if (!TM || !TM->Options.EmulatedTLS)
+ auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
+ if (!TPC)
+ return false;
+
+ auto &TM = TPC->getTM<TargetMachine>();
+ if (!TM.Options.EmulatedTLS)
return false;
bool Changed = false;
diff --git a/lib/CodeGen/MachineBlockPlacement.cpp b/lib/CodeGen/MachineBlockPlacement.cpp
index 5003115a770f..adfca9a46239 100644
--- a/lib/CodeGen/MachineBlockPlacement.cpp
+++ b/lib/CodeGen/MachineBlockPlacement.cpp
@@ -245,25 +245,26 @@ public:
/// updating the block -> chain mapping. It does not free or tear down the
/// old chain, but the old chain's block list is no longer valid.
void merge(MachineBasicBlock *BB, BlockChain *Chain) {
- assert(BB);
- assert(!Blocks.empty());
+ assert(BB && "Can't merge a null block.");
+ assert(!Blocks.empty() && "Can't merge into an empty chain.");
// Fast path in case we don't have a chain already.
if (!Chain) {
- assert(!BlockToChain[BB]);
+ assert(!BlockToChain[BB] &&
+ "Passed chain is null, but BB has entry in BlockToChain.");
Blocks.push_back(BB);
BlockToChain[BB] = this;
return;
}
- assert(BB == *Chain->begin());
+ assert(BB == *Chain->begin() && "Passed BB is not head of Chain.");
assert(Chain->begin() != Chain->end());
// Update the incoming blocks to point to this chain, and add them to the
// chain structure.
for (MachineBasicBlock *ChainBB : *Chain) {
Blocks.push_back(ChainBB);
- assert(BlockToChain[ChainBB] == Chain && "Incoming blocks not in chain");
+ assert(BlockToChain[ChainBB] == Chain && "Incoming blocks not in chain.");
BlockToChain[ChainBB] = this;
}
}
@@ -1547,13 +1548,15 @@ MachineBasicBlock *MachineBlockPlacement::selectBestCandidateBlock(
MachineBasicBlock *BestBlock = nullptr;
BlockFrequency BestFreq;
for (MachineBasicBlock *MBB : WorkList) {
- assert(MBB->isEHPad() == IsEHPad);
+ assert(MBB->isEHPad() == IsEHPad &&
+ "EHPad mismatch between block and work list.");
BlockChain &SuccChain = *BlockToChain[MBB];
if (&SuccChain == &Chain)
continue;
- assert(SuccChain.UnscheduledPredecessors == 0 && "Found CFG-violating block");
+ assert(SuccChain.UnscheduledPredecessors == 0 &&
+ "Found CFG-violating block");
BlockFrequency CandidateFreq = MBFI->getBlockFreq(MBB);
DEBUG(dbgs() << " " << getBlockName(MBB) << " -> ";
@@ -1621,9 +1624,12 @@ void MachineBlockPlacement::fillWorkLists(
if (!UpdatedPreds.insert(&Chain).second)
return;
- assert(Chain.UnscheduledPredecessors == 0);
+ assert(
+ Chain.UnscheduledPredecessors == 0 &&
+ "Attempting to place block with unscheduled predecessors in worklist.");
for (MachineBasicBlock *ChainBB : Chain) {
- assert(BlockToChain[ChainBB] == &Chain);
+ assert(BlockToChain[ChainBB] == &Chain &&
+ "Block in chain doesn't match BlockToChain map.");
for (MachineBasicBlock *Pred : ChainBB->predecessors()) {
if (BlockFilter && !BlockFilter->count(Pred))
continue;
@@ -2136,8 +2142,10 @@ void MachineBlockPlacement::buildLoopChains(const MachineLoop &L) {
for (const MachineLoop *InnerLoop : L)
buildLoopChains(*InnerLoop);
- assert(BlockWorkList.empty());
- assert(EHPadWorkList.empty());
+ assert(BlockWorkList.empty() &&
+ "BlockWorkList not empty when starting to build loop chains.");
+ assert(EHPadWorkList.empty() &&
+ "EHPadWorkList not empty when starting to build loop chains.");
BlockFilterSet LoopBlockSet = collectLoopBlockSet(L);
// Check if we have profile data for this function. If yes, we will rotate
@@ -2167,7 +2175,8 @@ void MachineBlockPlacement::buildLoopChains(const MachineLoop &L) {
// walk the blocks, and use a set to prevent visiting a particular chain
// twice.
SmallPtrSet<BlockChain *, 4> UpdatedPreds;
- assert(LoopChain.UnscheduledPredecessors == 0);
+ assert(LoopChain.UnscheduledPredecessors == 0 &&
+ "LoopChain should not have unscheduled predecessors.");
UpdatedPreds.insert(&LoopChain);
for (const MachineBasicBlock *LoopBB : LoopBlockSet)
@@ -2256,8 +2265,10 @@ void MachineBlockPlacement::buildCFGChains() {
for (MachineLoop *L : *MLI)
buildLoopChains(*L);
- assert(BlockWorkList.empty());
- assert(EHPadWorkList.empty());
+ assert(BlockWorkList.empty() &&
+ "BlockWorkList should be empty before building final chain.");
+ assert(EHPadWorkList.empty() &&
+ "EHPadWorkList should be empty before building final chain.");
SmallPtrSet<BlockChain *, 4> UpdatedPreds;
for (MachineBasicBlock &MBB : *F)
@@ -2651,8 +2662,10 @@ bool MachineBlockPlacement::runOnMachineFunction(MachineFunction &MF) {
// there are no MachineLoops.
PreferredLoopExit = nullptr;
- assert(BlockToChain.empty());
- assert(ComputedEdges.empty());
+ assert(BlockToChain.empty() &&
+ "BlockToChain map should be empty before starting placement.");
+ assert(ComputedEdges.empty() &&
+ "Computed Edge map should be empty before starting placement.");
unsigned TailDupSize = TailDupPlacementThreshold;
// If only the aggressive threshold is explicitly set, use it.
diff --git a/lib/CodeGen/MachineModuleInfo.cpp b/lib/CodeGen/MachineModuleInfo.cpp
index 2f0f4297ef5c..6cf751d34e26 100644
--- a/lib/CodeGen/MachineModuleInfo.cpp
+++ b/lib/CodeGen/MachineModuleInfo.cpp
@@ -32,8 +32,8 @@ using namespace llvm;
using namespace llvm::dwarf;
// Handle the Pass registration stuff necessary to use DataLayout's.
-INITIALIZE_TM_PASS(MachineModuleInfo, "machinemoduleinfo",
- "Machine Module Information", false, false)
+INITIALIZE_PASS(MachineModuleInfo, "machinemoduleinfo",
+ "Machine Module Information", false, false)
char MachineModuleInfo::ID = 0;
// Out of line virtual method.
diff --git a/lib/CodeGen/PrologEpilogInserter.cpp b/lib/CodeGen/PrologEpilogInserter.cpp
index d2afeae9e70b..aaa253fde494 100644
--- a/lib/CodeGen/PrologEpilogInserter.cpp
+++ b/lib/CodeGen/PrologEpilogInserter.cpp
@@ -60,19 +60,8 @@ namespace {
class PEI : public MachineFunctionPass {
public:
static char ID;
- explicit PEI(const TargetMachine *TM = nullptr) : MachineFunctionPass(ID) {
+ PEI() : MachineFunctionPass(ID) {
initializePEIPass(*PassRegistry::getPassRegistry());
-
- if (TM && (!TM->usesPhysRegsForPEI())) {
- SpillCalleeSavedRegisters = [](MachineFunction &, RegScavenger *,
- unsigned &, unsigned &, const MBBVector &,
- const MBBVector &) {};
- ScavengeFrameVirtualRegs = [](MachineFunction &, RegScavenger *) {};
- } else {
- SpillCalleeSavedRegisters = doSpillCalleeSavedRegs;
- ScavengeFrameVirtualRegs = doScavengeFrameVirtualRegs;
- UsesCalleeSaves = true;
- }
}
void getAnalysisUsage(AnalysisUsage &AU) const override;
@@ -140,18 +129,17 @@ WarnStackSize("warn-stack-size", cl::Hidden, cl::init((unsigned)-1),
cl::desc("Warn for stack size bigger than the given"
" number"));
-INITIALIZE_TM_PASS_BEGIN(PEI, "prologepilog", "Prologue/Epilogue Insertion",
- false, false)
+INITIALIZE_PASS_BEGIN(PEI, "prologepilog", "Prologue/Epilogue Insertion", false,
+ false)
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
INITIALIZE_PASS_DEPENDENCY(StackProtector)
-INITIALIZE_TM_PASS_END(PEI, "prologepilog",
- "Prologue/Epilogue Insertion & Frame Finalization",
- false, false)
+INITIALIZE_PASS_END(PEI, "prologepilog",
+ "Prologue/Epilogue Insertion & Frame Finalization", false,
+ false)
-MachineFunctionPass *
-llvm::createPrologEpilogInserterPass(const TargetMachine *TM) {
- return new PEI(TM);
+MachineFunctionPass *llvm::createPrologEpilogInserterPass() {
+ return new PEI();
}
STATISTIC(NumScavengedRegs, "Number of frame index regs scavenged");
@@ -174,6 +162,20 @@ typedef SmallSetVector<int, 8> StackObjSet;
/// frame indexes with appropriate references.
///
bool PEI::runOnMachineFunction(MachineFunction &Fn) {
+ if (!SpillCalleeSavedRegisters) {
+ const TargetMachine &TM = Fn.getTarget();
+ if (!TM.usesPhysRegsForPEI()) {
+ SpillCalleeSavedRegisters = [](MachineFunction &, RegScavenger *,
+ unsigned &, unsigned &, const MBBVector &,
+ const MBBVector &) {};
+ ScavengeFrameVirtualRegs = [](MachineFunction &, RegScavenger *) {};
+ } else {
+ SpillCalleeSavedRegisters = doSpillCalleeSavedRegs;
+ ScavengeFrameVirtualRegs = doScavengeFrameVirtualRegs;
+ UsesCalleeSaves = true;
+ }
+ }
+
const Function* F = Fn.getFunction();
const TargetRegisterInfo *TRI = Fn.getSubtarget().getRegisterInfo();
const TargetFrameLowering *TFI = Fn.getSubtarget().getFrameLowering();
diff --git a/lib/CodeGen/RegisterCoalescer.cpp b/lib/CodeGen/RegisterCoalescer.cpp
index 1803ea2b9249..7b3a5d5c5ff7 100644
--- a/lib/CodeGen/RegisterCoalescer.cpp
+++ b/lib/CodeGen/RegisterCoalescer.cpp
@@ -2666,11 +2666,17 @@ void JoinVals::pruneSubRegValues(LiveInterval &LI, LaneBitmask &ShrinkMask) {
// Look for values being erased.
bool DidPrune = false;
for (unsigned i = 0, e = LR.getNumValNums(); i != e; ++i) {
- if (Vals[i].Resolution != CR_Erase)
+ // We should trigger in all cases in which eraseInstrs() does something.
+ // match what eraseInstrs() is doing, print a message so
+ if (Vals[i].Resolution != CR_Erase &&
+ (Vals[i].Resolution != CR_Keep || !Vals[i].ErasableImplicitDef ||
+ !Vals[i].Pruned))
continue;
// Check subranges at the point where the copy will be removed.
SlotIndex Def = LR.getValNumInfo(i)->def;
+ // Print message so mismatches with eraseInstrs() can be diagnosed.
+ DEBUG(dbgs() << "\t\tExpecting instruction removal at " << Def << '\n');
for (LiveInterval::SubRange &S : LI.subranges()) {
LiveQueryResult Q = S.Query(Def);
diff --git a/lib/CodeGen/SafeStack.cpp b/lib/CodeGen/SafeStack.cpp
index 08b3d345f689..2771fdbd737a 100644
--- a/lib/CodeGen/SafeStack.cpp
+++ b/lib/CodeGen/SafeStack.cpp
@@ -24,6 +24,7 @@
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
#include "llvm/CodeGen/Passes.h"
+#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/DataLayout.h"
@@ -767,13 +768,12 @@ class SafeStackLegacyPass : public FunctionPass {
public:
static char ID; // Pass identification, replacement for typeid..
- SafeStackLegacyPass(const TargetMachine *TM) : FunctionPass(ID), TM(TM) {
+ SafeStackLegacyPass() : FunctionPass(ID), TM(nullptr) {
initializeSafeStackLegacyPassPass(*PassRegistry::getPassRegistry());
}
- SafeStackLegacyPass() : SafeStackLegacyPass(nullptr) {}
-
void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.addRequired<TargetPassConfig>();
AU.addRequired<TargetLibraryInfoWrapperPass>();
AU.addRequired<AssumptionCacheTracker>();
}
@@ -793,8 +793,7 @@ public:
return false;
}
- if (!TM)
- report_fatal_error("Target machine is required");
+ TM = &getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
auto *TL = TM->getSubtargetImpl(F)->getTargetLowering();
if (!TL)
report_fatal_error("TargetLowering instance is required");
@@ -821,11 +820,10 @@ public:
} // anonymous namespace
char SafeStackLegacyPass::ID = 0;
-INITIALIZE_TM_PASS_BEGIN(SafeStackLegacyPass, "safe-stack",
- "Safe Stack instrumentation pass", false, false)
-INITIALIZE_TM_PASS_END(SafeStackLegacyPass, "safe-stack",
- "Safe Stack instrumentation pass", false, false)
+INITIALIZE_PASS_BEGIN(SafeStackLegacyPass, "safe-stack",
+ "Safe Stack instrumentation pass", false, false)
+INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
+INITIALIZE_PASS_END(SafeStackLegacyPass, "safe-stack",
+ "Safe Stack instrumentation pass", false, false)
-FunctionPass *llvm::createSafeStackPass(const llvm::TargetMachine *TM) {
- return new SafeStackLegacyPass(TM);
-}
+FunctionPass *llvm::createSafeStackPass() { return new SafeStackLegacyPass(); }
diff --git a/lib/CodeGen/SafeStackColoring.cpp b/lib/CodeGen/SafeStackColoring.cpp
index 09289f947dc9..21f2fa497233 100644
--- a/lib/CodeGen/SafeStackColoring.cpp
+++ b/lib/CodeGen/SafeStackColoring.cpp
@@ -20,9 +20,10 @@ using namespace llvm::safestack;
#define DEBUG_TYPE "safestackcoloring"
+// Disabled by default due to PR32143.
static cl::opt<bool> ClColoring("safe-stack-coloring",
cl::desc("enable safe stack coloring"),
- cl::Hidden, cl::init(true));
+ cl::Hidden, cl::init(false));
const StackColoring::LiveRange &StackColoring::getLiveRange(AllocaInst *AI) {
const auto IT = AllocaNumbering.find(AI);
diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 0ccee175abfb..5d450e7e078c 100644
--- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -2138,6 +2138,17 @@ SDValue DAGCombiner::visitADDCARRY(SDNode *N) {
if (isNullConstant(CarryIn))
return DAG.getNode(ISD::UADDO, DL, N->getVTList(), N0, N1);
+ // fold (addcarry 0, 0, X) -> (and (ext/trunc X), 1) and no carry.
+ if (isNullConstant(N0) && isNullConstant(N1)) {
+ EVT VT = N0.getValueType();
+ EVT CarryVT = CarryIn.getValueType();
+ SDValue CarryExt = DAG.getBoolExtOrTrunc(CarryIn, DL, VT, CarryVT);
+ AddToWorklist(CarryExt.getNode());
+ return CombineTo(N, DAG.getNode(ISD::AND, DL, VT, CarryExt,
+ DAG.getConstant(1, DL, VT)),
+ DAG.getConstant(0, DL, CarryVT));
+ }
+
if (SDValue Combined = visitADDCARRYLike(N0, N1, CarryIn, N))
return Combined;
@@ -12533,49 +12544,54 @@ bool DAGCombiner::MergeConsecutiveStores(StoreSDNode *St) {
// mergeable cases. To prevent this, we prune such stores from the
// front of StoreNodes here.
- unsigned StartIdx = 0;
- while ((StartIdx + 1 < StoreNodes.size()) &&
- StoreNodes[StartIdx].OffsetFromBase + ElementSizeBytes !=
- StoreNodes[StartIdx + 1].OffsetFromBase)
- ++StartIdx;
-
- // Bail if we don't have enough candidates to merge.
- if (StartIdx + 1 >= StoreNodes.size())
- return false;
-
- if (StartIdx)
- StoreNodes.erase(StoreNodes.begin(), StoreNodes.begin() + StartIdx);
+ bool RV = false;
+ while (StoreNodes.size() > 1) {
+ unsigned StartIdx = 0;
+ while ((StartIdx + 1 < StoreNodes.size()) &&
+ StoreNodes[StartIdx].OffsetFromBase + ElementSizeBytes !=
+ StoreNodes[StartIdx + 1].OffsetFromBase)
+ ++StartIdx;
- // Scan the memory operations on the chain and find the first non-consecutive
- // store memory address.
- unsigned NumConsecutiveStores = 0;
- int64_t StartAddress = StoreNodes[0].OffsetFromBase;
-
- // Check that the addresses are consecutive starting from the second
- // element in the list of stores.
- for (unsigned i = 1, e = StoreNodes.size(); i < e; ++i) {
- int64_t CurrAddress = StoreNodes[i].OffsetFromBase;
- if (CurrAddress - StartAddress != (ElementSizeBytes * i))
- break;
- NumConsecutiveStores = i + 1;
- }
+ // Bail if we don't have enough candidates to merge.
+ if (StartIdx + 1 >= StoreNodes.size())
+ return RV;
- if (NumConsecutiveStores < 2)
- return false;
+ if (StartIdx)
+ StoreNodes.erase(StoreNodes.begin(), StoreNodes.begin() + StartIdx);
+
+ // Scan the memory operations on the chain and find the first
+ // non-consecutive store memory address.
+ unsigned NumConsecutiveStores = 1;
+ int64_t StartAddress = StoreNodes[0].OffsetFromBase;
+ // Check that the addresses are consecutive starting from the second
+ // element in the list of stores.
+ for (unsigned i = 1, e = StoreNodes.size(); i < e; ++i) {
+ int64_t CurrAddress = StoreNodes[i].OffsetFromBase;
+ if (CurrAddress - StartAddress != (ElementSizeBytes * i))
+ break;
+ NumConsecutiveStores = i + 1;
+ }
- // Check that we can merge these candidates without causing a cycle
- if (!checkMergeStoreCandidatesForDependencies(StoreNodes, NumConsecutiveStores))
- return false;
+ if (NumConsecutiveStores < 2) {
+ StoreNodes.erase(StoreNodes.begin(),
+ StoreNodes.begin() + NumConsecutiveStores);
+ continue;
+ }
+ // Check that we can merge these candidates without causing a cycle
+ if (!checkMergeStoreCandidatesForDependencies(StoreNodes,
+ NumConsecutiveStores)) {
+ StoreNodes.erase(StoreNodes.begin(),
+ StoreNodes.begin() + NumConsecutiveStores);
+ continue;
+ }
- // The node with the lowest store address.
- LLVMContext &Context = *DAG.getContext();
- const DataLayout &DL = DAG.getDataLayout();
+ // The node with the lowest store address.
+ LLVMContext &Context = *DAG.getContext();
+ const DataLayout &DL = DAG.getDataLayout();
- // Store the constants into memory as one consecutive store.
- if (IsConstantSrc) {
- bool RV = false;
- while (NumConsecutiveStores > 1) {
+ // Store the constants into memory as one consecutive store.
+ if (IsConstantSrc) {
LSBaseSDNode *FirstInChain = StoreNodes[0].MemNode;
unsigned FirstStoreAS = FirstInChain->getAddressSpace();
unsigned FirstStoreAlign = FirstInChain->getAlignment();
@@ -12635,33 +12651,33 @@ bool DAGCombiner::MergeConsecutiveStores(StoreSDNode *St) {
}
// Check if we found a legal integer type that creates a meaningful merge.
- if (LastLegalType < 2 && LastLegalVectorType < 2)
- break;
+ if (LastLegalType < 2 && LastLegalVectorType < 2) {
+ StoreNodes.erase(StoreNodes.begin(), StoreNodes.begin() + 1);
+ continue;
+ }
bool UseVector = (LastLegalVectorType > LastLegalType) && !NoVectors;
unsigned NumElem = (UseVector) ? LastLegalVectorType : LastLegalType;
bool Merged = MergeStoresOfConstantsOrVecElts(StoreNodes, MemVT, NumElem,
true, UseVector);
- if (!Merged)
- break;
+ if (!Merged) {
+ StoreNodes.erase(StoreNodes.begin(), StoreNodes.begin() + NumElem);
+ continue;
+ }
// Remove merged stores for next iteration.
- StoreNodes.erase(StoreNodes.begin(), StoreNodes.begin() + NumElem);
RV = true;
- NumConsecutiveStores -= NumElem;
+ StoreNodes.erase(StoreNodes.begin(), StoreNodes.begin() + NumElem);
+ continue;
}
- return RV;
- }
- // When extracting multiple vector elements, try to store them
- // in one vector store rather than a sequence of scalar stores.
- if (IsExtractVecSrc) {
- bool RV = false;
- while (StoreNodes.size() >= 2) {
+ // When extracting multiple vector elements, try to store them
+ // in one vector store rather than a sequence of scalar stores.
+ if (IsExtractVecSrc) {
LSBaseSDNode *FirstInChain = StoreNodes[0].MemNode;
unsigned FirstStoreAS = FirstInChain->getAddressSpace();
unsigned FirstStoreAlign = FirstInChain->getAlignment();
- unsigned NumStoresToMerge = 0;
+ unsigned NumStoresToMerge = 1;
bool IsVec = MemVT.isVector();
for (unsigned i = 0; i < NumConsecutiveStores; ++i) {
StoreSDNode *St = cast<StoreSDNode>(StoreNodes[i].MemNode);
@@ -12673,7 +12689,7 @@ bool DAGCombiner::MergeConsecutiveStores(StoreSDNode *St) {
// handles consecutive loads).
if (StoreValOpcode != ISD::EXTRACT_VECTOR_ELT &&
StoreValOpcode != ISD::EXTRACT_SUBVECTOR)
- return false;
+ return RV;
// Find a legal type for the vector store.
unsigned Elts = i + 1;
@@ -12693,187 +12709,205 @@ bool DAGCombiner::MergeConsecutiveStores(StoreSDNode *St) {
bool Merged = MergeStoresOfConstantsOrVecElts(
StoreNodes, MemVT, NumStoresToMerge, false, true);
- if (!Merged)
- break;
+ if (!Merged) {
+ StoreNodes.erase(StoreNodes.begin(),
+ StoreNodes.begin() + NumStoresToMerge);
+ continue;
+ }
// Remove merged stores for next iteration.
StoreNodes.erase(StoreNodes.begin(),
StoreNodes.begin() + NumStoresToMerge);
RV = true;
- NumConsecutiveStores -= NumStoresToMerge;
+ continue;
}
- return RV;
- }
- // Below we handle the case of multiple consecutive stores that
- // come from multiple consecutive loads. We merge them into a single
- // wide load and a single wide store.
+ // Below we handle the case of multiple consecutive stores that
+ // come from multiple consecutive loads. We merge them into a single
+ // wide load and a single wide store.
- // Look for load nodes which are used by the stored values.
- SmallVector<MemOpLink, 8> LoadNodes;
+ // Look for load nodes which are used by the stored values.
+ SmallVector<MemOpLink, 8> LoadNodes;
- // Find acceptable loads. Loads need to have the same chain (token factor),
- // must not be zext, volatile, indexed, and they must be consecutive.
- BaseIndexOffset LdBasePtr;
- for (unsigned i = 0; i < NumConsecutiveStores; ++i) {
- StoreSDNode *St = cast<StoreSDNode>(StoreNodes[i].MemNode);
- LoadSDNode *Ld = dyn_cast<LoadSDNode>(St->getValue());
- if (!Ld) break;
-
- // Loads must only have one use.
- if (!Ld->hasNUsesOfValue(1, 0))
- break;
+ // Find acceptable loads. Loads need to have the same chain (token factor),
+ // must not be zext, volatile, indexed, and they must be consecutive.
+ BaseIndexOffset LdBasePtr;
+ for (unsigned i = 0; i < NumConsecutiveStores; ++i) {
+ StoreSDNode *St = cast<StoreSDNode>(StoreNodes[i].MemNode);
+ LoadSDNode *Ld = dyn_cast<LoadSDNode>(St->getValue());
+ if (!Ld)
+ break;
- // The memory operands must not be volatile.
- if (Ld->isVolatile() || Ld->isIndexed())
- break;
+ // Loads must only have one use.
+ if (!Ld->hasNUsesOfValue(1, 0))
+ break;
- // We do not accept ext loads.
- if (Ld->getExtensionType() != ISD::NON_EXTLOAD)
- break;
+ // The memory operands must not be volatile.
+ if (Ld->isVolatile() || Ld->isIndexed())
+ break;
- // The stored memory type must be the same.
- if (Ld->getMemoryVT() != MemVT)
- break;
+ // We do not accept ext loads.
+ if (Ld->getExtensionType() != ISD::NON_EXTLOAD)
+ break;
- BaseIndexOffset LdPtr = BaseIndexOffset::match(Ld->getBasePtr(), DAG);
- // If this is not the first ptr that we check.
- if (LdBasePtr.Base.getNode()) {
- // The base ptr must be the same.
- if (!LdPtr.equalBaseIndex(LdBasePtr))
+ // The stored memory type must be the same.
+ if (Ld->getMemoryVT() != MemVT)
break;
- } else {
- // Check that all other base pointers are the same as this one.
- LdBasePtr = LdPtr;
+
+ BaseIndexOffset LdPtr = BaseIndexOffset::match(Ld->getBasePtr(), DAG);
+ // If this is not the first ptr that we check.
+ if (LdBasePtr.Base.getNode()) {
+ // The base ptr must be the same.
+ if (!LdPtr.equalBaseIndex(LdBasePtr))
+ break;
+ } else {
+ // Check that all other base pointers are the same as this one.
+ LdBasePtr = LdPtr;
+ }
+
+ // We found a potential memory operand to merge.
+ LoadNodes.push_back(MemOpLink(Ld, LdPtr.Offset));
}
- // We found a potential memory operand to merge.
- LoadNodes.push_back(MemOpLink(Ld, LdPtr.Offset));
- }
+ if (LoadNodes.size() < 2) {
+ StoreNodes.erase(StoreNodes.begin(), StoreNodes.begin() + 1);
+ continue;
+ }
- if (LoadNodes.size() < 2)
- return false;
+ // If we have load/store pair instructions and we only have two values,
+ // don't bother.
+ unsigned RequiredAlignment;
+ if (LoadNodes.size() == 2 && TLI.hasPairedLoad(MemVT, RequiredAlignment) &&
+ St->getAlignment() >= RequiredAlignment) {
+ StoreNodes.erase(StoreNodes.begin(), StoreNodes.begin() + 2);
+ continue;
+ }
+ LSBaseSDNode *FirstInChain = StoreNodes[0].MemNode;
+ unsigned FirstStoreAS = FirstInChain->getAddressSpace();
+ unsigned FirstStoreAlign = FirstInChain->getAlignment();
+ LoadSDNode *FirstLoad = cast<LoadSDNode>(LoadNodes[0].MemNode);
+ unsigned FirstLoadAS = FirstLoad->getAddressSpace();
+ unsigned FirstLoadAlign = FirstLoad->getAlignment();
+
+ // Scan the memory operations on the chain and find the first
+ // non-consecutive load memory address. These variables hold the index in
+ // the store node array.
+ unsigned LastConsecutiveLoad = 0;
+ // This variable refers to the size and not index in the array.
+ unsigned LastLegalVectorType = 0;
+ unsigned LastLegalIntegerType = 0;
+ StartAddress = LoadNodes[0].OffsetFromBase;
+ SDValue FirstChain = FirstLoad->getChain();
+ for (unsigned i = 1; i < LoadNodes.size(); ++i) {
+ // All loads must share the same chain.
+ if (LoadNodes[i].MemNode->getChain() != FirstChain)
+ break;
- // If we have load/store pair instructions and we only have two values,
- // don't bother.
- unsigned RequiredAlignment;
- if (LoadNodes.size() == 2 && TLI.hasPairedLoad(MemVT, RequiredAlignment) &&
- St->getAlignment() >= RequiredAlignment)
- return false;
- LSBaseSDNode *FirstInChain = StoreNodes[0].MemNode;
- unsigned FirstStoreAS = FirstInChain->getAddressSpace();
- unsigned FirstStoreAlign = FirstInChain->getAlignment();
- LoadSDNode *FirstLoad = cast<LoadSDNode>(LoadNodes[0].MemNode);
- unsigned FirstLoadAS = FirstLoad->getAddressSpace();
- unsigned FirstLoadAlign = FirstLoad->getAlignment();
-
- // Scan the memory operations on the chain and find the first non-consecutive
- // load memory address. These variables hold the index in the store node
- // array.
- unsigned LastConsecutiveLoad = 0;
- // This variable refers to the size and not index in the array.
- unsigned LastLegalVectorType = 0;
- unsigned LastLegalIntegerType = 0;
- StartAddress = LoadNodes[0].OffsetFromBase;
- SDValue FirstChain = FirstLoad->getChain();
- for (unsigned i = 1; i < LoadNodes.size(); ++i) {
- // All loads must share the same chain.
- if (LoadNodes[i].MemNode->getChain() != FirstChain)
- break;
+ int64_t CurrAddress = LoadNodes[i].OffsetFromBase;
+ if (CurrAddress - StartAddress != (ElementSizeBytes * i))
+ break;
+ LastConsecutiveLoad = i;
+ // Find a legal type for the vector store.
+ EVT StoreTy = EVT::getVectorVT(Context, MemVT, i + 1);
+ bool IsFastSt, IsFastLd;
+ if (TLI.isTypeLegal(StoreTy) &&
+ TLI.allowsMemoryAccess(Context, DL, StoreTy, FirstStoreAS,
+ FirstStoreAlign, &IsFastSt) &&
+ IsFastSt &&
+ TLI.allowsMemoryAccess(Context, DL, StoreTy, FirstLoadAS,
+ FirstLoadAlign, &IsFastLd) &&
+ IsFastLd) {
+ LastLegalVectorType = i + 1;
+ }
- int64_t CurrAddress = LoadNodes[i].OffsetFromBase;
- if (CurrAddress - StartAddress != (ElementSizeBytes * i))
- break;
- LastConsecutiveLoad = i;
- // Find a legal type for the vector store.
- EVT StoreTy = EVT::getVectorVT(Context, MemVT, i+1);
- bool IsFastSt, IsFastLd;
- if (TLI.isTypeLegal(StoreTy) &&
- TLI.allowsMemoryAccess(Context, DL, StoreTy, FirstStoreAS,
- FirstStoreAlign, &IsFastSt) && IsFastSt &&
- TLI.allowsMemoryAccess(Context, DL, StoreTy, FirstLoadAS,
- FirstLoadAlign, &IsFastLd) && IsFastLd) {
- LastLegalVectorType = i + 1;
- }
-
- // Find a legal type for the integer store.
- unsigned SizeInBits = (i+1) * ElementSizeBytes * 8;
- StoreTy = EVT::getIntegerVT(Context, SizeInBits);
- if (TLI.isTypeLegal(StoreTy) &&
- TLI.allowsMemoryAccess(Context, DL, StoreTy, FirstStoreAS,
- FirstStoreAlign, &IsFastSt) && IsFastSt &&
- TLI.allowsMemoryAccess(Context, DL, StoreTy, FirstLoadAS,
- FirstLoadAlign, &IsFastLd) && IsFastLd)
- LastLegalIntegerType = i + 1;
- // Or check whether a truncstore and extload is legal.
- else if (TLI.getTypeAction(Context, StoreTy) ==
- TargetLowering::TypePromoteInteger) {
- EVT LegalizedStoredValueTy =
- TLI.getTypeToTransformTo(Context, StoreTy);
- if (TLI.isTruncStoreLegal(LegalizedStoredValueTy, StoreTy) &&
- TLI.isLoadExtLegal(ISD::ZEXTLOAD, LegalizedStoredValueTy, StoreTy) &&
- TLI.isLoadExtLegal(ISD::SEXTLOAD, LegalizedStoredValueTy, StoreTy) &&
- TLI.isLoadExtLegal(ISD::EXTLOAD, LegalizedStoredValueTy, StoreTy) &&
- TLI.allowsMemoryAccess(Context, DL, LegalizedStoredValueTy,
- FirstStoreAS, FirstStoreAlign, &IsFastSt) &&
+ // Find a legal type for the integer store.
+ unsigned SizeInBits = (i + 1) * ElementSizeBytes * 8;
+ StoreTy = EVT::getIntegerVT(Context, SizeInBits);
+ if (TLI.isTypeLegal(StoreTy) &&
+ TLI.allowsMemoryAccess(Context, DL, StoreTy, FirstStoreAS,
+ FirstStoreAlign, &IsFastSt) &&
IsFastSt &&
- TLI.allowsMemoryAccess(Context, DL, LegalizedStoredValueTy,
- FirstLoadAS, FirstLoadAlign, &IsFastLd) &&
+ TLI.allowsMemoryAccess(Context, DL, StoreTy, FirstLoadAS,
+ FirstLoadAlign, &IsFastLd) &&
IsFastLd)
- LastLegalIntegerType = i+1;
+ LastLegalIntegerType = i + 1;
+ // Or check whether a truncstore and extload is legal.
+ else if (TLI.getTypeAction(Context, StoreTy) ==
+ TargetLowering::TypePromoteInteger) {
+ EVT LegalizedStoredValueTy = TLI.getTypeToTransformTo(Context, StoreTy);
+ if (TLI.isTruncStoreLegal(LegalizedStoredValueTy, StoreTy) &&
+ TLI.isLoadExtLegal(ISD::ZEXTLOAD, LegalizedStoredValueTy,
+ StoreTy) &&
+ TLI.isLoadExtLegal(ISD::SEXTLOAD, LegalizedStoredValueTy,
+ StoreTy) &&
+ TLI.isLoadExtLegal(ISD::EXTLOAD, LegalizedStoredValueTy, StoreTy) &&
+ TLI.allowsMemoryAccess(Context, DL, LegalizedStoredValueTy,
+ FirstStoreAS, FirstStoreAlign, &IsFastSt) &&
+ IsFastSt &&
+ TLI.allowsMemoryAccess(Context, DL, LegalizedStoredValueTy,
+ FirstLoadAS, FirstLoadAlign, &IsFastLd) &&
+ IsFastLd)
+ LastLegalIntegerType = i + 1;
+ }
}
- }
- // Only use vector types if the vector type is larger than the integer type.
- // If they are the same, use integers.
- bool UseVectorTy = LastLegalVectorType > LastLegalIntegerType && !NoVectors;
- unsigned LastLegalType = std::max(LastLegalVectorType, LastLegalIntegerType);
+ // Only use vector types if the vector type is larger than the integer type.
+ // If they are the same, use integers.
+ bool UseVectorTy = LastLegalVectorType > LastLegalIntegerType && !NoVectors;
+ unsigned LastLegalType =
+ std::max(LastLegalVectorType, LastLegalIntegerType);
- // We add +1 here because the LastXXX variables refer to location while
- // the NumElem refers to array/index size.
- unsigned NumElem = std::min(NumConsecutiveStores, LastConsecutiveLoad + 1);
- NumElem = std::min(LastLegalType, NumElem);
+ // We add +1 here because the LastXXX variables refer to location while
+ // the NumElem refers to array/index size.
+ unsigned NumElem = std::min(NumConsecutiveStores, LastConsecutiveLoad + 1);
+ NumElem = std::min(LastLegalType, NumElem);
- if (NumElem < 2)
- return false;
+ if (NumElem < 2) {
+ StoreNodes.erase(StoreNodes.begin(), StoreNodes.begin() + 1);
+ continue;
+ }
- // Find if it is better to use vectors or integers to load and store
- // to memory.
- EVT JointMemOpVT;
- if (UseVectorTy) {
- JointMemOpVT = EVT::getVectorVT(Context, MemVT, NumElem);
- } else {
- unsigned SizeInBits = NumElem * ElementSizeBytes * 8;
- JointMemOpVT = EVT::getIntegerVT(Context, SizeInBits);
- }
+ // Find if it is better to use vectors or integers to load and store
+ // to memory.
+ EVT JointMemOpVT;
+ if (UseVectorTy) {
+ JointMemOpVT = EVT::getVectorVT(Context, MemVT, NumElem);
+ } else {
+ unsigned SizeInBits = NumElem * ElementSizeBytes * 8;
+ JointMemOpVT = EVT::getIntegerVT(Context, SizeInBits);
+ }
- SDLoc LoadDL(LoadNodes[0].MemNode);
- SDLoc StoreDL(StoreNodes[0].MemNode);
+ SDLoc LoadDL(LoadNodes[0].MemNode);
+ SDLoc StoreDL(StoreNodes[0].MemNode);
- // The merged loads are required to have the same incoming chain, so
- // using the first's chain is acceptable.
- SDValue NewLoad = DAG.getLoad(JointMemOpVT, LoadDL, FirstLoad->getChain(),
- FirstLoad->getBasePtr(),
- FirstLoad->getPointerInfo(), FirstLoadAlign);
+ // The merged loads are required to have the same incoming chain, so
+ // using the first's chain is acceptable.
+ SDValue NewLoad = DAG.getLoad(JointMemOpVT, LoadDL, FirstLoad->getChain(),
+ FirstLoad->getBasePtr(),
+ FirstLoad->getPointerInfo(), FirstLoadAlign);
- SDValue NewStoreChain = getMergeStoreChains(StoreNodes, NumElem);
+ SDValue NewStoreChain = getMergeStoreChains(StoreNodes, NumElem);
- AddToWorklist(NewStoreChain.getNode());
+ AddToWorklist(NewStoreChain.getNode());
- SDValue NewStore =
- DAG.getStore(NewStoreChain, StoreDL, NewLoad, FirstInChain->getBasePtr(),
- FirstInChain->getPointerInfo(), FirstStoreAlign);
+ SDValue NewStore = DAG.getStore(
+ NewStoreChain, StoreDL, NewLoad, FirstInChain->getBasePtr(),
+ FirstInChain->getPointerInfo(), FirstStoreAlign);
- // Transfer chain users from old loads to the new load.
- for (unsigned i = 0; i < NumElem; ++i) {
- LoadSDNode *Ld = cast<LoadSDNode>(LoadNodes[i].MemNode);
- DAG.ReplaceAllUsesOfValueWith(SDValue(Ld, 1),
- SDValue(NewLoad.getNode(), 1));
- }
+ // Transfer chain users from old loads to the new load.
+ for (unsigned i = 0; i < NumElem; ++i) {
+ LoadSDNode *Ld = cast<LoadSDNode>(LoadNodes[i].MemNode);
+ DAG.ReplaceAllUsesOfValueWith(SDValue(Ld, 1),
+ SDValue(NewLoad.getNode(), 1));
+ }
- // Replace the all stores with the new store.
- for (unsigned i = 0; i < NumElem; ++i)
- CombineTo(StoreNodes[i].MemNode, NewStore);
- return true;
+ // Replace the all stores with the new store.
+ for (unsigned i = 0; i < NumElem; ++i)
+ CombineTo(StoreNodes[i].MemNode, NewStore);
+ RV = true;
+ StoreNodes.erase(StoreNodes.begin(), StoreNodes.begin() + NumElem);
+ continue;
+ }
+ return RV;
}
SDValue DAGCombiner::replaceStoreChain(StoreSDNode *ST, SDValue BetterChain) {
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 057badcd6b74..16c1f78f1b35 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -4685,9 +4685,10 @@ static SDValue getMemsetValue(SDValue Value, EVT VT, SelectionDAG &DAG,
/// used when a memcpy is turned into a memset when the source is a constant
/// string ptr.
static SDValue getMemsetStringVal(EVT VT, const SDLoc &dl, SelectionDAG &DAG,
- const TargetLowering &TLI, StringRef Str) {
+ const TargetLowering &TLI,
+ const ConstantDataArraySlice &Slice) {
// Handle vector with all elements zero.
- if (Str.empty()) {
+ if (Slice.Array == nullptr) {
if (VT.isInteger())
return DAG.getConstant(0, dl, VT);
else if (VT == MVT::f32 || VT == MVT::f64 || VT == MVT::f128)
@@ -4706,15 +4707,15 @@ static SDValue getMemsetStringVal(EVT VT, const SDLoc &dl, SelectionDAG &DAG,
assert(!VT.isVector() && "Can't handle vector type here!");
unsigned NumVTBits = VT.getSizeInBits();
unsigned NumVTBytes = NumVTBits / 8;
- unsigned NumBytes = std::min(NumVTBytes, unsigned(Str.size()));
+ unsigned NumBytes = std::min(NumVTBytes, unsigned(Slice.Length));
APInt Val(NumVTBits, 0);
if (DAG.getDataLayout().isLittleEndian()) {
for (unsigned i = 0; i != NumBytes; ++i)
- Val |= (uint64_t)(unsigned char)Str[i] << i*8;
+ Val |= (uint64_t)(unsigned char)Slice[i] << i*8;
} else {
for (unsigned i = 0; i != NumBytes; ++i)
- Val |= (uint64_t)(unsigned char)Str[i] << (NumVTBytes-i-1)*8;
+ Val |= (uint64_t)(unsigned char)Slice[i] << (NumVTBytes-i-1)*8;
}
// If the "cost" of materializing the integer immediate is less than the cost
@@ -4731,9 +4732,8 @@ SDValue SelectionDAG::getMemBasePlusOffset(SDValue Base, unsigned Offset,
return getNode(ISD::ADD, DL, VT, Base, getConstant(Offset, DL, VT));
}
-/// isMemSrcFromString - Returns true if memcpy source is a string constant.
-///
-static bool isMemSrcFromString(SDValue Src, StringRef &Str) {
+/// Returns true if memcpy source is constant data.
+static bool isMemSrcFromConstant(SDValue Src, ConstantDataArraySlice &Slice) {
uint64_t SrcDelta = 0;
GlobalAddressSDNode *G = nullptr;
if (Src.getOpcode() == ISD::GlobalAddress)
@@ -4747,8 +4747,8 @@ static bool isMemSrcFromString(SDValue Src, StringRef &Str) {
if (!G)
return false;
- return getConstantStringInfo(G->getGlobal(), Str,
- SrcDelta + G->getOffset(), false);
+ return getConstantDataArrayInfo(G->getGlobal(), Slice, 8,
+ SrcDelta + G->getOffset());
}
/// Determines the optimal series of memory ops to replace the memset / memcpy.
@@ -4891,15 +4891,15 @@ static SDValue getMemcpyLoadsAndStores(SelectionDAG &DAG, const SDLoc &dl,
unsigned SrcAlign = DAG.InferPtrAlignment(Src);
if (Align > SrcAlign)
SrcAlign = Align;
- StringRef Str;
- bool CopyFromStr = isMemSrcFromString(Src, Str);
- bool isZeroStr = CopyFromStr && Str.empty();
+ ConstantDataArraySlice Slice;
+ bool CopyFromConstant = isMemSrcFromConstant(Src, Slice);
+ bool isZeroConstant = CopyFromConstant && Slice.Array == nullptr;
unsigned Limit = AlwaysInline ? ~0U : TLI.getMaxStoresPerMemcpy(OptSize);
if (!FindOptimalMemOpLowering(MemOps, Limit, Size,
(DstAlignCanChange ? 0 : Align),
- (isZeroStr ? 0 : SrcAlign),
- false, false, CopyFromStr, true,
+ (isZeroConstant ? 0 : SrcAlign),
+ false, false, CopyFromConstant, true,
DstPtrInfo.getAddrSpace(),
SrcPtrInfo.getAddrSpace(),
DAG, TLI))
@@ -4943,18 +4943,29 @@ static SDValue getMemcpyLoadsAndStores(SelectionDAG &DAG, const SDLoc &dl,
DstOff -= VTSize - Size;
}
- if (CopyFromStr &&
- (isZeroStr || (VT.isInteger() && !VT.isVector()))) {
+ if (CopyFromConstant &&
+ (isZeroConstant || (VT.isInteger() && !VT.isVector()))) {
// It's unlikely a store of a vector immediate can be done in a single
// instruction. It would require a load from a constantpool first.
// We only handle zero vectors here.
// FIXME: Handle other cases where store of vector immediate is done in
// a single instruction.
- Value = getMemsetStringVal(VT, dl, DAG, TLI, Str.substr(SrcOff));
+ ConstantDataArraySlice SubSlice;
+ if (SrcOff < Slice.Length) {
+ SubSlice = Slice;
+ SubSlice.move(SrcOff);
+ } else {
+ // This is an out-of-bounds access and hence UB. Pretend we read zero.
+ SubSlice.Array = nullptr;
+ SubSlice.Offset = 0;
+ SubSlice.Length = VTSize;
+ }
+ Value = getMemsetStringVal(VT, dl, DAG, TLI, SubSlice);
if (Value.getNode())
Store = DAG.getStore(Chain, dl, Value,
DAG.getMemBasePlusOffset(Dst, DstOff, dl),
- DstPtrInfo.getWithOffset(DstOff), Align, MMOFlags);
+ DstPtrInfo.getWithOffset(DstOff), Align,
+ MMOFlags);
}
if (!Store.getNode()) {
diff --git a/lib/CodeGen/SelectionDAG/StatepointLowering.cpp b/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
index c0a5041b1395..1c66649cae01 100644
--- a/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
+++ b/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
@@ -110,8 +110,8 @@ StatepointLoweringState::allocateStackSlot(EVT ValueType,
Builder.FuncInfo.StatepointStackSlots.size() &&
"Broken invariant");
- StatepointMaxSlotsRequired = std::max<unsigned long>(
- StatepointMaxSlotsRequired, Builder.FuncInfo.StatepointStackSlots.size());
+ StatepointMaxSlotsRequired.updateMax(
+ Builder.FuncInfo.StatepointStackSlots.size());
return SpillSlot;
}
diff --git a/lib/CodeGen/StackProtector.cpp b/lib/CodeGen/StackProtector.cpp
index a8aafe78748d..5da77264261b 100644
--- a/lib/CodeGen/StackProtector.cpp
+++ b/lib/CodeGen/StackProtector.cpp
@@ -58,12 +58,13 @@ static cl::opt<bool> EnableSelectionDAGSP("enable-selectiondag-sp",
cl::init(true), cl::Hidden);
char StackProtector::ID = 0;
-INITIALIZE_TM_PASS(StackProtector, "stack-protector", "Insert stack protectors",
- false, true)
+INITIALIZE_PASS_BEGIN(StackProtector, "stack-protector",
+ "Insert stack protectors", false, true)
+INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
+INITIALIZE_PASS_END(StackProtector, "stack-protector",
+ "Insert stack protectors", false, true)
-FunctionPass *llvm::createStackProtectorPass(const TargetMachine *TM) {
- return new StackProtector(TM);
-}
+FunctionPass *llvm::createStackProtectorPass() { return new StackProtector(); }
StackProtector::SSPLayoutKind
StackProtector::getSSPLayout(const AllocaInst *AI) const {
@@ -97,6 +98,8 @@ bool StackProtector::runOnFunction(Function &Fn) {
DominatorTreeWrapperPass *DTWP =
getAnalysisIfAvailable<DominatorTreeWrapperPass>();
DT = DTWP ? &DTWP->getDomTree() : nullptr;
+ TM = &getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
+ Trip = TM->getTargetTriple();
TLI = TM->getSubtargetImpl(Fn)->getTargetLowering();
HasPrologue = false;
HasIRCheck = false;
diff --git a/lib/CodeGen/TargetPassConfig.cpp b/lib/CodeGen/TargetPassConfig.cpp
index 9724cb074584..83348058eca9 100644
--- a/lib/CodeGen/TargetPassConfig.cpp
+++ b/lib/CodeGen/TargetPassConfig.cpp
@@ -315,7 +315,9 @@ TargetPassConfig *LLVMTargetMachine::createPassConfig(PassManagerBase &PM) {
TargetPassConfig::TargetPassConfig()
: ImmutablePass(ID), PM(nullptr) {
- llvm_unreachable("TargetPassConfig should not be constructed on-the-fly");
+ report_fatal_error("Trying to construct TargetPassConfig without a target "
+ "machine. Scheduling a CodeGen pass without a target "
+ "triple set?");
}
// Helper to verify the analysis is really immutable.
@@ -514,14 +516,14 @@ void TargetPassConfig::addPassesToHandleExceptions() {
LLVM_FALLTHROUGH;
case ExceptionHandling::DwarfCFI:
case ExceptionHandling::ARM:
- addPass(createDwarfEHPass(TM));
+ addPass(createDwarfEHPass());
break;
case ExceptionHandling::WinEH:
// We support using both GCC-style and MSVC-style exceptions on Windows, so
// add both preparation passes. Each pass will only actually run if it
// recognizes the personality function.
- addPass(createWinEHPass(TM));
- addPass(createDwarfEHPass(TM));
+ addPass(createWinEHPass());
+ addPass(createDwarfEHPass());
break;
case ExceptionHandling::None:
addPass(createLowerInvokePass());
@@ -536,7 +538,7 @@ void TargetPassConfig::addPassesToHandleExceptions() {
/// before exception handling preparation passes.
void TargetPassConfig::addCodeGenPrepare() {
if (getOptLevel() != CodeGenOpt::None && !DisableCGP)
- addPass(createCodeGenPreparePass(TM));
+ addPass(createCodeGenPreparePass());
addPass(createRewriteSymbolsPass());
}
@@ -551,8 +553,8 @@ void TargetPassConfig::addISelPrepare() {
// Add both the safe stack and the stack protection passes: each of them will
// only protect functions that have corresponding attributes.
- addPass(createSafeStackPass(TM));
- addPass(createStackProtectorPass(TM));
+ addPass(createSafeStackPass());
+ addPass(createStackProtectorPass());
if (PrintISelInput)
addPass(createPrintFunctionPass(
@@ -623,9 +625,6 @@ void TargetPassConfig::addMachinePasses() {
addPass(&LocalStackSlotAllocationID, false);
}
- if (getOptLevel() != CodeGenOpt::None)
- addPass(&LiveRangeShrinkID);
-
// Run pre-ra passes.
addPreRegAlloc();
@@ -650,7 +649,7 @@ void TargetPassConfig::addMachinePasses() {
// Prolog/Epilog inserter needs a TargetMachine to instantiate. But only
// do so if it hasn't been disabled, substituted, or overridden.
if (!isPassSubstitutedOrOverridden(&PrologEpilogCodeInserterID))
- addPass(createPrologEpilogInserterPass(TM));
+ addPass(createPrologEpilogInserterPass());
/// Add passes that optimize machine instructions after register allocation.
if (getOptLevel() != CodeGenOpt::None)
diff --git a/lib/CodeGen/WinEHPrepare.cpp b/lib/CodeGen/WinEHPrepare.cpp
index ae07e8b2fa03..a632b40c20f5 100644
--- a/lib/CodeGen/WinEHPrepare.cpp
+++ b/lib/CodeGen/WinEHPrepare.cpp
@@ -54,7 +54,7 @@ namespace {
class WinEHPrepare : public FunctionPass {
public:
static char ID; // Pass identification, replacement for typeid.
- WinEHPrepare(const TargetMachine *TM = nullptr) : FunctionPass(ID) {}
+ WinEHPrepare() : FunctionPass(ID) {}
bool runOnFunction(Function &Fn) override;
@@ -94,12 +94,10 @@ private:
} // end anonymous namespace
char WinEHPrepare::ID = 0;
-INITIALIZE_TM_PASS(WinEHPrepare, "winehprepare", "Prepare Windows exceptions",
- false, false)
+INITIALIZE_PASS(WinEHPrepare, "winehprepare", "Prepare Windows exceptions",
+ false, false)
-FunctionPass *llvm::createWinEHPass(const TargetMachine *TM) {
- return new WinEHPrepare(TM);
-}
+FunctionPass *llvm::createWinEHPass() { return new WinEHPrepare(); }
bool WinEHPrepare::runOnFunction(Function &Fn) {
if (!Fn.hasPersonalityFn())
diff --git a/lib/DebugInfo/CodeView/CMakeLists.txt b/lib/DebugInfo/CodeView/CMakeLists.txt
index 8d9353ae5f5e..556ebf78622f 100644
--- a/lib/DebugInfo/CodeView/CMakeLists.txt
+++ b/lib/DebugInfo/CodeView/CMakeLists.txt
@@ -2,10 +2,10 @@ add_llvm_library(LLVMDebugInfoCodeView
CodeViewError.cpp
CodeViewRecordIO.cpp
CVSymbolVisitor.cpp
- CVTypeDumper.cpp
CVTypeVisitor.cpp
EnumTables.cpp
Formatters.cpp
+ LazyRandomTypeCollection.cpp
Line.cpp
ModuleDebugFileChecksumFragment.cpp
ModuleDebugFragment.cpp
@@ -13,7 +13,6 @@ add_llvm_library(LLVMDebugInfoCodeView
ModuleDebugFragmentVisitor.cpp
ModuleDebugInlineeLinesFragment.cpp
ModuleDebugLineFragment.cpp
- RandomAccessTypeVisitor.cpp
RecordSerialization.cpp
StringTable.cpp
SymbolRecordMapping.cpp
@@ -22,10 +21,12 @@ add_llvm_library(LLVMDebugInfoCodeView
TypeDatabase.cpp
TypeDatabaseVisitor.cpp
TypeDumpVisitor.cpp
+ TypeIndex.cpp
TypeRecordMapping.cpp
TypeSerializer.cpp
TypeStreamMerger.cpp
-
+ TypeTableCollection.cpp
+
ADDITIONAL_HEADER_DIRS
${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/CodeView
)
diff --git a/lib/DebugInfo/CodeView/CVTypeDumper.cpp b/lib/DebugInfo/CodeView/CVTypeDumper.cpp
deleted file mode 100644
index 02e1682f76e7..000000000000
--- a/lib/DebugInfo/CodeView/CVTypeDumper.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-//===-- CVTypeDumper.cpp - 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.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
-#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
-#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
-#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
-#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
-#include "llvm/Support/BinaryByteStream.h"
-
-using namespace llvm;
-using namespace llvm::codeview;
-
-Error CVTypeDumper::dump(const CVType &Record, TypeVisitorCallbacks &Dumper) {
- TypeDatabaseVisitor DBV(TypeDB);
- TypeVisitorCallbackPipeline Pipeline;
- Pipeline.addCallbackToPipeline(DBV);
- Pipeline.addCallbackToPipeline(Dumper);
-
- CVType RecordCopy = Record;
- return codeview::visitTypeRecord(RecordCopy, Pipeline, VDS_BytesPresent,
- Handler);
-}
-
-Error CVTypeDumper::dump(const CVTypeArray &Types,
- TypeVisitorCallbacks &Dumper) {
- TypeDatabaseVisitor DBV(TypeDB);
- TypeVisitorCallbackPipeline Pipeline;
- Pipeline.addCallbackToPipeline(DBV);
- Pipeline.addCallbackToPipeline(Dumper);
-
- return codeview::visitTypeStream(Types, Pipeline, Handler);
-}
-
-Error CVTypeDumper::dump(ArrayRef<uint8_t> Data, TypeVisitorCallbacks &Dumper) {
- BinaryByteStream Stream(Data, llvm::support::little);
- CVTypeArray Types;
- BinaryStreamReader Reader(Stream);
- if (auto EC = Reader.readArray(Types, Reader.getLength()))
- return EC;
-
- return dump(Types, Dumper);
-}
-
-void CVTypeDumper::printTypeIndex(ScopedPrinter &Printer, StringRef FieldName,
- TypeIndex TI, TypeDatabase &DB) {
- StringRef TypeName;
- if (!TI.isNoneType())
- TypeName = DB.getTypeName(TI);
- if (!TypeName.empty())
- Printer.printHex(FieldName, TypeName, TI.getIndex());
- else
- Printer.printHex(FieldName, TI.getIndex());
-}
diff --git a/lib/DebugInfo/CodeView/CVTypeVisitor.cpp b/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
index 0f7f5f667790..f95c3e79388e 100644
--- a/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
+++ b/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
@@ -9,7 +9,9 @@
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/CodeView/TypeCollection.h"
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
@@ -22,8 +24,6 @@
using namespace llvm;
using namespace llvm::codeview;
-CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
- : Callbacks(Callbacks) {}
template <typename T>
static Error visitKnownRecord(CVType &Record, TypeVisitorCallbacks &Callbacks) {
@@ -66,6 +66,67 @@ static Expected<TypeServer2Record> deserializeTypeServerRecord(CVType &Record) {
return R;
}
+static Error visitMemberRecord(CVMemberRecord &Record,
+ TypeVisitorCallbacks &Callbacks) {
+ if (auto EC = Callbacks.visitMemberBegin(Record))
+ return EC;
+
+ switch (Record.Kind) {
+ default:
+ if (auto EC = Callbacks.visitUnknownMember(Record))
+ return EC;
+ break;
+#define MEMBER_RECORD(EnumName, EnumVal, Name) \
+ case EnumName: { \
+ if (auto EC = visitKnownMember<Name##Record>(Record, Callbacks)) \
+ return EC; \
+ break; \
+ }
+#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
+ MEMBER_RECORD(EnumVal, EnumVal, AliasName)
+#define TYPE_RECORD(EnumName, EnumVal, Name)
+#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#include "llvm/DebugInfo/CodeView/TypeRecords.def"
+ }
+
+ if (auto EC = Callbacks.visitMemberEnd(Record))
+ return EC;
+
+ return Error::success();
+}
+
+namespace {
+
+class CVTypeVisitor {
+public:
+ explicit CVTypeVisitor(TypeVisitorCallbacks &Callbacks);
+
+ void addTypeServerHandler(TypeServerHandler &Handler);
+
+ Error visitTypeRecord(CVType &Record, TypeIndex Index);
+ Error visitTypeRecord(CVType &Record);
+
+ /// Visits the type records in Data. Sets the error flag on parse failures.
+ Error visitTypeStream(const CVTypeArray &Types);
+ Error visitTypeStream(CVTypeRange Types);
+ Error visitTypeStream(TypeCollection &Types);
+
+ Error visitMemberRecord(CVMemberRecord Record);
+ Error visitFieldListMemberStream(BinaryStreamReader &Stream);
+
+private:
+ Expected<bool> handleTypeServer(CVType &Record);
+ Error finishVisitation(CVType &Record);
+
+ /// The interface to the class that gets notified of each visitation.
+ TypeVisitorCallbacks &Callbacks;
+
+ TinyPtrVector<TypeServerHandler *> Handlers;
+};
+
+CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
+ : Callbacks(Callbacks) {}
+
void CVTypeVisitor::addTypeServerHandler(TypeServerHandler &Handler) {
Handlers.push_back(&Handler);
}
@@ -144,35 +205,6 @@ Error CVTypeVisitor::visitTypeRecord(CVType &Record) {
return finishVisitation(Record);
}
-static Error visitMemberRecord(CVMemberRecord &Record,
- TypeVisitorCallbacks &Callbacks) {
- if (auto EC = Callbacks.visitMemberBegin(Record))
- return EC;
-
- switch (Record.Kind) {
- default:
- if (auto EC = Callbacks.visitUnknownMember(Record))
- return EC;
- break;
-#define MEMBER_RECORD(EnumName, EnumVal, Name) \
- case EnumName: { \
- if (auto EC = visitKnownMember<Name##Record>(Record, Callbacks)) \
- return EC; \
- break; \
- }
-#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
- MEMBER_RECORD(EnumVal, EnumVal, AliasName)
-#define TYPE_RECORD(EnumName, EnumVal, Name)
-#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
-#include "llvm/DebugInfo/CodeView/TypeRecords.def"
- }
-
- if (auto EC = Callbacks.visitMemberEnd(Record))
- return EC;
-
- return Error::success();
-}
-
Error CVTypeVisitor::visitMemberRecord(CVMemberRecord Record) {
return ::visitMemberRecord(Record, Callbacks);
}
@@ -194,12 +226,18 @@ Error CVTypeVisitor::visitTypeStream(CVTypeRange Types) {
return Error::success();
}
-Error CVTypeVisitor::visitFieldListMemberStream(BinaryStreamReader Reader) {
- FieldListDeserializer Deserializer(Reader);
- TypeVisitorCallbackPipeline Pipeline;
- Pipeline.addCallbackToPipeline(Deserializer);
- Pipeline.addCallbackToPipeline(Callbacks);
+Error CVTypeVisitor::visitTypeStream(TypeCollection &Types) {
+ Optional<TypeIndex> I = Types.getFirst();
+ while (I) {
+ CVType Type = Types.getType(*I);
+ if (auto EC = visitTypeRecord(Type, *I))
+ return EC;
+ I = Types.getNext(*I);
+ }
+ return Error::success();
+}
+Error CVTypeVisitor::visitFieldListMemberStream(BinaryStreamReader &Reader) {
TypeLeafKind Leaf;
while (!Reader.empty()) {
if (auto EC = Reader.readEnum(Leaf))
@@ -207,20 +245,13 @@ Error CVTypeVisitor::visitFieldListMemberStream(BinaryStreamReader Reader) {
CVMemberRecord Record;
Record.Kind = Leaf;
- if (auto EC = ::visitMemberRecord(Record, Pipeline))
+ if (auto EC = ::visitMemberRecord(Record, Callbacks))
return EC;
}
return Error::success();
}
-Error CVTypeVisitor::visitFieldListMemberStream(ArrayRef<uint8_t> Data) {
- BinaryByteStream S(Data, llvm::support::little);
- BinaryStreamReader SR(S);
- return visitFieldListMemberStream(SR);
-}
-
-namespace {
struct FieldListVisitHelper {
FieldListVisitHelper(TypeVisitorCallbacks &Callbacks, ArrayRef<uint8_t> Data,
VisitorDataSource Source)
@@ -241,11 +272,8 @@ struct FieldListVisitHelper {
};
struct VisitHelper {
- VisitHelper(TypeVisitorCallbacks &Callbacks, VisitorDataSource Source,
- TypeServerHandler *TS)
+ VisitHelper(TypeVisitorCallbacks &Callbacks, VisitorDataSource Source)
: Visitor((Source == VDS_BytesPresent) ? Pipeline : Callbacks) {
- if (TS)
- Visitor.addTypeServerHandler(*TS);
if (Source == VDS_BytesPresent) {
Pipeline.addCallbackToPipeline(Deserializer);
Pipeline.addCallbackToPipeline(Callbacks);
@@ -262,29 +290,57 @@ Error llvm::codeview::visitTypeRecord(CVType &Record, TypeIndex Index,
TypeVisitorCallbacks &Callbacks,
VisitorDataSource Source,
TypeServerHandler *TS) {
- VisitHelper Helper(Callbacks, Source, TS);
- return Helper.Visitor.visitTypeRecord(Record, Index);
+ VisitHelper V(Callbacks, Source);
+ if (TS)
+ V.Visitor.addTypeServerHandler(*TS);
+ return V.Visitor.visitTypeRecord(Record, Index);
}
Error llvm::codeview::visitTypeRecord(CVType &Record,
TypeVisitorCallbacks &Callbacks,
VisitorDataSource Source,
TypeServerHandler *TS) {
- VisitHelper Helper(Callbacks, Source, TS);
- return Helper.Visitor.visitTypeRecord(Record);
+ VisitHelper V(Callbacks, Source);
+ if (TS)
+ V.Visitor.addTypeServerHandler(*TS);
+ return V.Visitor.visitTypeRecord(Record);
}
-Error llvm::codeview::visitMemberRecordStream(ArrayRef<uint8_t> FieldList,
- TypeVisitorCallbacks &Callbacks) {
- CVTypeVisitor Visitor(Callbacks);
- return Visitor.visitFieldListMemberStream(FieldList);
+Error llvm::codeview::visitTypeStream(const CVTypeArray &Types,
+ TypeVisitorCallbacks &Callbacks,
+ TypeServerHandler *TS) {
+ VisitHelper V(Callbacks, VDS_BytesPresent);
+ if (TS)
+ V.Visitor.addTypeServerHandler(*TS);
+ return V.Visitor.visitTypeStream(Types);
+}
+
+Error llvm::codeview::visitTypeStream(CVTypeRange Types,
+ TypeVisitorCallbacks &Callbacks,
+ TypeServerHandler *TS) {
+ VisitHelper V(Callbacks, VDS_BytesPresent);
+ if (TS)
+ V.Visitor.addTypeServerHandler(*TS);
+ return V.Visitor.visitTypeStream(Types);
+}
+
+Error llvm::codeview::visitTypeStream(TypeCollection &Types,
+ TypeVisitorCallbacks &Callbacks,
+ TypeServerHandler *TS) {
+ // When the internal visitor calls Types.getType(Index) the interface is
+ // required to return a CVType with the bytes filled out. So we can assume
+ // that the bytes will be present when individual records are visited.
+ VisitHelper V(Callbacks, VDS_BytesPresent);
+ if (TS)
+ V.Visitor.addTypeServerHandler(*TS);
+ return V.Visitor.visitTypeStream(Types);
}
Error llvm::codeview::visitMemberRecord(CVMemberRecord Record,
TypeVisitorCallbacks &Callbacks,
VisitorDataSource Source) {
- FieldListVisitHelper Helper(Callbacks, Record.Data, Source);
- return Helper.Visitor.visitMemberRecord(Record);
+ FieldListVisitHelper V(Callbacks, Record.Data, Source);
+ return V.Visitor.visitMemberRecord(Record);
}
Error llvm::codeview::visitMemberRecord(TypeLeafKind Kind,
@@ -296,16 +352,8 @@ Error llvm::codeview::visitMemberRecord(TypeLeafKind Kind,
return visitMemberRecord(R, Callbacks, VDS_BytesPresent);
}
-Error llvm::codeview::visitTypeStream(const CVTypeArray &Types,
- TypeVisitorCallbacks &Callbacks,
- TypeServerHandler *TS) {
- VisitHelper Helper(Callbacks, VDS_BytesPresent, TS);
- return Helper.Visitor.visitTypeStream(Types);
-}
-
-Error llvm::codeview::visitTypeStream(CVTypeRange Types,
- TypeVisitorCallbacks &Callbacks,
- TypeServerHandler *TS) {
- VisitHelper Helper(Callbacks, VDS_BytesPresent, TS);
- return Helper.Visitor.visitTypeStream(Types);
+Error llvm::codeview::visitMemberRecordStream(ArrayRef<uint8_t> FieldList,
+ TypeVisitorCallbacks &Callbacks) {
+ FieldListVisitHelper V(Callbacks, FieldList, VDS_BytesPresent);
+ return V.Visitor.visitFieldListMemberStream(V.Reader);
}
diff --git a/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp b/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp
new file mode 100644
index 000000000000..39eb4099ce9e
--- /dev/null
+++ b/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp
@@ -0,0 +1,229 @@
+//===- LazyRandomTypeCollection.cpp ---------------------------- *- C++--*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
+
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
+#include "llvm/DebugInfo/CodeView/TypeServerHandler.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+static void error(Error &&EC) {
+ assert(!static_cast<bool>(EC));
+ if (EC)
+ consumeError(std::move(EC));
+}
+
+LazyRandomTypeCollection::LazyRandomTypeCollection(uint32_t RecordCountHint)
+ : LazyRandomTypeCollection(CVTypeArray(), RecordCountHint,
+ PartialOffsetArray()) {}
+
+LazyRandomTypeCollection::LazyRandomTypeCollection(
+ const CVTypeArray &Types, uint32_t RecordCountHint,
+ PartialOffsetArray PartialOffsets)
+ : Database(RecordCountHint), Types(Types), DatabaseVisitor(Database),
+ PartialOffsets(PartialOffsets) {
+ KnownOffsets.resize(Database.capacity());
+}
+
+LazyRandomTypeCollection::LazyRandomTypeCollection(ArrayRef<uint8_t> Data,
+ uint32_t RecordCountHint)
+ : LazyRandomTypeCollection(RecordCountHint) {
+ reset(Data);
+}
+
+LazyRandomTypeCollection::LazyRandomTypeCollection(StringRef Data,
+ uint32_t RecordCountHint)
+ : LazyRandomTypeCollection(
+ makeArrayRef(Data.bytes_begin(), Data.bytes_end()), RecordCountHint) {
+}
+
+LazyRandomTypeCollection::LazyRandomTypeCollection(const CVTypeArray &Types,
+ uint32_t NumRecords)
+ : LazyRandomTypeCollection(Types, NumRecords, PartialOffsetArray()) {}
+
+void LazyRandomTypeCollection::reset(StringRef Data) {
+ reset(makeArrayRef(Data.bytes_begin(), Data.bytes_end()));
+}
+
+void LazyRandomTypeCollection::reset(ArrayRef<uint8_t> Data) {
+ PartialOffsets = PartialOffsetArray();
+
+ BinaryStreamReader Reader(Data, support::little);
+ error(Reader.readArray(Types, Reader.getLength()));
+
+ KnownOffsets.resize(Database.capacity());
+}
+
+CVType LazyRandomTypeCollection::getType(TypeIndex Index) {
+ error(ensureTypeExists(Index));
+ return Database.getTypeRecord(Index);
+}
+
+StringRef LazyRandomTypeCollection::getTypeName(TypeIndex Index) {
+ if (!Index.isSimple()) {
+ // Try to make sure the type exists. Even if it doesn't though, it may be
+ // because we're dumping a symbol stream with no corresponding type stream
+ // present, in which case we still want to be able to print <unknown UDT>
+ // for the type names.
+ consumeError(ensureTypeExists(Index));
+ }
+
+ return Database.getTypeName(Index);
+}
+
+bool LazyRandomTypeCollection::contains(TypeIndex Index) {
+ return Database.contains(Index);
+}
+
+uint32_t LazyRandomTypeCollection::size() { return Database.size(); }
+
+uint32_t LazyRandomTypeCollection::capacity() { return Database.capacity(); }
+
+Error LazyRandomTypeCollection::ensureTypeExists(TypeIndex TI) {
+ if (!Database.contains(TI)) {
+ if (auto EC = visitRangeForType(TI))
+ return EC;
+ }
+ return Error::success();
+}
+
+Error LazyRandomTypeCollection::visitRangeForType(TypeIndex TI) {
+ if (PartialOffsets.empty())
+ return fullScanForType(TI);
+
+ auto Next = std::upper_bound(PartialOffsets.begin(), PartialOffsets.end(), TI,
+ [](TypeIndex Value, const TypeIndexOffset &IO) {
+ return Value < IO.Type;
+ });
+
+ assert(Next != PartialOffsets.begin());
+ auto Prev = std::prev(Next);
+
+ TypeIndex TIB = Prev->Type;
+ if (Database.contains(TIB)) {
+ // They've asked us to fetch a type index, but the entry we found in the
+ // partial offsets array has already been visited. Since we visit an entire
+ // block every time, that means this record should have been previously
+ // discovered. Ultimately, this means this is a request for a non-existant
+ // type index.
+ return make_error<CodeViewError>("Invalid type index");
+ }
+
+ TypeIndex TIE;
+ if (Next == PartialOffsets.end()) {
+ TIE = TypeIndex::fromArrayIndex(Database.capacity());
+ } else {
+ TIE = Next->Type;
+ }
+
+ if (auto EC = visitRange(TIB, Prev->Offset, TIE))
+ return EC;
+ return Error::success();
+}
+
+Optional<TypeIndex> LazyRandomTypeCollection::getFirst() {
+ TypeIndex TI = TypeIndex::fromArrayIndex(0);
+ if (auto EC = ensureTypeExists(TI)) {
+ consumeError(std::move(EC));
+ return None;
+ }
+ return TI;
+}
+
+Optional<TypeIndex> LazyRandomTypeCollection::getNext(TypeIndex Prev) {
+ // We can't be sure how long this type stream is, given that the initial count
+ // given to the constructor is just a hint. So just try to make sure the next
+ // record exists, and if anything goes wrong, we must be at the end.
+ if (auto EC = ensureTypeExists(Prev + 1)) {
+ consumeError(std::move(EC));
+ return None;
+ }
+
+ return Prev + 1;
+}
+
+Error LazyRandomTypeCollection::fullScanForType(TypeIndex TI) {
+ assert(PartialOffsets.empty());
+
+ TypeIndex CurrentTI = TypeIndex::fromArrayIndex(0);
+ uint32_t Offset = 0;
+ auto Begin = Types.begin();
+
+ if (!Database.empty()) {
+ // In the case of type streams which we don't know the number of records of,
+ // it's possible to search for a type index triggering a full scan, but then
+ // later additional records are added since we didn't know how many there
+ // would be until we did a full visitation, then you try to access the new
+ // type triggering another full scan. To avoid this, we assume that if the
+ // database has some records, this must be what's going on. So we ask the
+ // database for the largest type index less than the one we're searching for
+ // and only do the forward scan from there.
+ auto Prev = Database.largestTypeIndexLessThan(TI);
+ assert(Prev.hasValue() && "Empty database with valid types?");
+ Offset = KnownOffsets[Prev->toArrayIndex()];
+ CurrentTI = *Prev;
+ ++CurrentTI;
+ Begin = Types.at(Offset);
+ ++Begin;
+ Offset = Begin.offset();
+ }
+
+ auto End = Types.end();
+ while (Begin != End) {
+ if (auto EC = visitOneRecord(CurrentTI, Offset, *Begin))
+ return EC;
+
+ Offset += Begin.getRecordLength();
+ ++Begin;
+ ++CurrentTI;
+ }
+ if (CurrentTI <= TI) {
+ return make_error<CodeViewError>("Type Index does not exist!");
+ }
+ return Error::success();
+}
+
+Error LazyRandomTypeCollection::visitRange(TypeIndex Begin,
+ uint32_t BeginOffset,
+ TypeIndex End) {
+
+ auto RI = Types.at(BeginOffset);
+ assert(RI != Types.end());
+
+ while (Begin != End) {
+ if (auto EC = visitOneRecord(Begin, BeginOffset, *RI))
+ return EC;
+
+ BeginOffset += RI.getRecordLength();
+ ++Begin;
+ ++RI;
+ }
+
+ return Error::success();
+}
+
+Error LazyRandomTypeCollection::visitOneRecord(TypeIndex TI, uint32_t Offset,
+ CVType &Record) {
+ assert(!Database.contains(TI));
+ if (auto EC = codeview::visitTypeRecord(Record, TI, DatabaseVisitor))
+ return EC;
+ // Keep the KnownOffsets array the same size as the Database's capacity. Since
+ // we don't always know how many records are in the type stream, we need to be
+ // prepared for the database growing and receicing a type index that can't fit
+ // in our current buffer.
+ if (KnownOffsets.size() < Database.capacity())
+ KnownOffsets.resize(Database.capacity());
+ KnownOffsets[TI.toArrayIndex()] = Offset;
+ return Error::success();
+}
diff --git a/lib/DebugInfo/CodeView/RandomAccessTypeVisitor.cpp b/lib/DebugInfo/CodeView/RandomAccessTypeVisitor.cpp
deleted file mode 100644
index 704d1131108a..000000000000
--- a/lib/DebugInfo/CodeView/RandomAccessTypeVisitor.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-//===- RandomAccessTypeVisitor.cpp ---------------------------- *- C++ --*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/DebugInfo/CodeView/RandomAccessTypeVisitor.h"
-
-#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
-#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
-#include "llvm/DebugInfo/CodeView/TypeServerHandler.h"
-#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
-
-using namespace llvm;
-using namespace llvm::codeview;
-
-RandomAccessTypeVisitor::RandomAccessTypeVisitor(
- const CVTypeArray &Types, uint32_t NumRecords,
- PartialOffsetArray PartialOffsets)
- : Database(NumRecords), Types(Types), DatabaseVisitor(Database),
- PartialOffsets(PartialOffsets) {
-
- KnownOffsets.resize(Database.capacity());
-}
-
-Error RandomAccessTypeVisitor::visitTypeIndex(TypeIndex TI,
- TypeVisitorCallbacks &Callbacks) {
- assert(TI.toArrayIndex() < Database.capacity());
-
- if (!Database.contains(TI)) {
- if (auto EC = visitRangeForType(TI))
- return EC;
- }
-
- assert(Database.contains(TI));
- auto &Record = Database.getTypeRecord(TI);
- return codeview::visitTypeRecord(Record, TI, Callbacks);
-}
-
-Error RandomAccessTypeVisitor::visitRangeForType(TypeIndex TI) {
- if (PartialOffsets.empty()) {
- TypeIndex TIB(TypeIndex::FirstNonSimpleIndex);
- TypeIndex TIE = TIB + Database.capacity();
- return visitRange(TIB, 0, TIE);
- }
-
- auto Next = std::upper_bound(PartialOffsets.begin(), PartialOffsets.end(), TI,
- [](TypeIndex Value, const TypeIndexOffset &IO) {
- return Value < IO.Type;
- });
-
- assert(Next != PartialOffsets.begin());
- auto Prev = std::prev(Next);
-
- TypeIndex TIB = Prev->Type;
- TypeIndex TIE;
- if (Next == PartialOffsets.end()) {
- TIE = TypeIndex::fromArrayIndex(Database.capacity());
- } else {
- TIE = Next->Type;
- }
-
- if (auto EC = visitRange(TIB, Prev->Offset, TIE))
- return EC;
- return Error::success();
-}
-
-Error RandomAccessTypeVisitor::visitRange(TypeIndex Begin, uint32_t BeginOffset,
- TypeIndex End) {
-
- auto RI = Types.at(BeginOffset);
- assert(RI != Types.end());
-
- while (Begin != End) {
- assert(!Database.contains(Begin));
- if (auto EC = codeview::visitTypeRecord(*RI, Begin, DatabaseVisitor))
- return EC;
- KnownOffsets[Begin.toArrayIndex()] = BeginOffset;
-
- BeginOffset += RI.getRecordLength();
- ++Begin;
- ++RI;
- }
-
- return Error::success();
-}
diff --git a/lib/DebugInfo/CodeView/SymbolDumper.cpp b/lib/DebugInfo/CodeView/SymbolDumper.cpp
index 5395e4349b28..7d01c8c5f194 100644
--- a/lib/DebugInfo/CodeView/SymbolDumper.cpp
+++ b/lib/DebugInfo/CodeView/SymbolDumper.cpp
@@ -11,7 +11,6 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
-#include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
#include "llvm/DebugInfo/CodeView/EnumTables.h"
#include "llvm/DebugInfo/CodeView/StringTable.h"
#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
@@ -33,9 +32,9 @@ namespace {
/// the visitor out of SymbolDumper.h.
class CVSymbolDumperImpl : public SymbolVisitorCallbacks {
public:
- CVSymbolDumperImpl(TypeDatabase &TypeDB, SymbolDumpDelegate *ObjDelegate,
+ CVSymbolDumperImpl(TypeCollection &Types, SymbolDumpDelegate *ObjDelegate,
ScopedPrinter &W, bool PrintRecordBytes)
- : TypeDB(TypeDB), ObjDelegate(ObjDelegate), W(W),
+ : Types(Types), ObjDelegate(ObjDelegate), W(W),
PrintRecordBytes(PrintRecordBytes), InFunctionScope(false) {}
/// CVSymbolVisitor overrides.
@@ -54,7 +53,7 @@ private:
void printLocalVariableAddrGap(ArrayRef<LocalVariableAddrGap> Gaps);
void printTypeIndex(StringRef FieldName, TypeIndex TI);
- TypeDatabase &TypeDB;
+ TypeCollection &Types;
SymbolDumpDelegate *ObjDelegate;
ScopedPrinter &W;
@@ -83,7 +82,7 @@ void CVSymbolDumperImpl::printLocalVariableAddrGap(
}
void CVSymbolDumperImpl::printTypeIndex(StringRef FieldName, TypeIndex TI) {
- CVTypeDumper::printTypeIndex(W, FieldName, TI, TypeDB);
+ codeview::printTypeIndex(W, FieldName, TI, Types);
}
Error CVSymbolDumperImpl::visitSymbolBegin(CVSymbol &CVR) {
@@ -670,7 +669,7 @@ Error CVSymbolDumperImpl::visitUnknownSymbol(CVSymbol &CVR) {
Error CVSymbolDumper::dump(CVRecord<SymbolKind> &Record) {
SymbolVisitorCallbackPipeline Pipeline;
SymbolDeserializer Deserializer(ObjDelegate.get());
- CVSymbolDumperImpl Dumper(TypeDB, ObjDelegate.get(), W, PrintRecordBytes);
+ CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, PrintRecordBytes);
Pipeline.addCallbackToPipeline(Deserializer);
Pipeline.addCallbackToPipeline(Dumper);
@@ -681,7 +680,7 @@ Error CVSymbolDumper::dump(CVRecord<SymbolKind> &Record) {
Error CVSymbolDumper::dump(const CVSymbolArray &Symbols) {
SymbolVisitorCallbackPipeline Pipeline;
SymbolDeserializer Deserializer(ObjDelegate.get());
- CVSymbolDumperImpl Dumper(TypeDB, ObjDelegate.get(), W, PrintRecordBytes);
+ CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, PrintRecordBytes);
Pipeline.addCallbackToPipeline(Deserializer);
Pipeline.addCallbackToPipeline(Dumper);
diff --git a/lib/DebugInfo/CodeView/TypeDatabase.cpp b/lib/DebugInfo/CodeView/TypeDatabase.cpp
index 7924440e5e29..af05d2dc294b 100644
--- a/lib/DebugInfo/CodeView/TypeDatabase.cpp
+++ b/lib/DebugInfo/CodeView/TypeDatabase.cpp
@@ -72,16 +72,20 @@ TypeDatabase::TypeDatabase(uint32_t Capacity) : TypeNameStorage(Allocator) {
}
TypeIndex TypeDatabase::appendType(StringRef Name, const CVType &Data) {
- TypeIndex TI;
- TI = getAppendIndex();
- if (TI.toArrayIndex() >= capacity())
+ LargestTypeIndex = getAppendIndex();
+ if (LargestTypeIndex.toArrayIndex() >= capacity())
grow();
- recordType(Name, TI, Data);
- return TI;
+ recordType(Name, LargestTypeIndex, Data);
+ return LargestTypeIndex;
}
void TypeDatabase::recordType(StringRef Name, TypeIndex Index,
const CVType &Data) {
+ LargestTypeIndex = empty() ? Index : std::max(Index, LargestTypeIndex);
+
+ if (LargestTypeIndex.toArrayIndex() >= capacity())
+ grow(Index);
+
uint32_t AI = Index.toArrayIndex();
assert(!contains(Index));
@@ -144,19 +148,66 @@ uint32_t TypeDatabase::size() const { return Count; }
uint32_t TypeDatabase::capacity() const { return TypeRecords.size(); }
-void TypeDatabase::grow() {
- TypeRecords.emplace_back();
- CVUDTNames.emplace_back();
- ValidRecords.resize(ValidRecords.size() + 1);
+CVType TypeDatabase::getType(TypeIndex Index) { return getTypeRecord(Index); }
+
+StringRef TypeDatabase::getTypeName(TypeIndex Index) {
+ return static_cast<const TypeDatabase *>(this)->getTypeName(Index);
+}
+
+bool TypeDatabase::contains(TypeIndex Index) {
+ return static_cast<const TypeDatabase *>(this)->contains(Index);
+}
+
+uint32_t TypeDatabase::size() {
+ return static_cast<const TypeDatabase *>(this)->size();
+}
+
+uint32_t TypeDatabase::capacity() {
+ return static_cast<const TypeDatabase *>(this)->capacity();
+}
+
+void TypeDatabase::grow() { grow(LargestTypeIndex + 1); }
+
+void TypeDatabase::grow(TypeIndex NewIndex) {
+ uint32_t NewSize = NewIndex.toArrayIndex() + 1;
+
+ if (NewSize <= capacity())
+ return;
+
+ uint32_t NewCapacity = NewSize * 3 / 2;
+
+ TypeRecords.resize(NewCapacity);
+ CVUDTNames.resize(NewCapacity);
+ ValidRecords.resize(NewCapacity);
}
bool TypeDatabase::empty() const { return size() == 0; }
+Optional<TypeIndex> TypeDatabase::largestTypeIndexLessThan(TypeIndex TI) const {
+ uint32_t AI = TI.toArrayIndex();
+ int N = ValidRecords.find_prev(AI);
+ if (N == -1)
+ return None;
+ return TypeIndex::fromArrayIndex(N);
+}
+
TypeIndex TypeDatabase::getAppendIndex() const {
if (empty())
return TypeIndex::fromArrayIndex(0);
- int Index = ValidRecords.find_last();
- assert(Index != -1);
- return TypeIndex::fromArrayIndex(Index) + 1;
+ return LargestTypeIndex + 1;
+}
+
+Optional<TypeIndex> TypeDatabase::getFirst() {
+ int N = ValidRecords.find_first();
+ if (N == -1)
+ return None;
+ return TypeIndex::fromArrayIndex(N);
+}
+
+Optional<TypeIndex> TypeDatabase::getNext(TypeIndex Prev) {
+ int N = ValidRecords.find_next(Prev.toArrayIndex());
+ if (N == -1)
+ return None;
+ return TypeIndex::fromArrayIndex(N);
}
diff --git a/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp b/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp
index 9485c9cfedff..84f52a055815 100644
--- a/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp
+++ b/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp
@@ -10,15 +10,13 @@
#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/Formatters.h"
+#include "llvm/DebugInfo/CodeView/TypeCollection.h"
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
-#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/ScopedPrinter.h"
@@ -165,16 +163,15 @@ static StringRef getLeafTypeName(TypeLeafKind LT) {
}
void TypeDumpVisitor::printTypeIndex(StringRef FieldName, TypeIndex TI) const {
- CVTypeDumper::printTypeIndex(*W, FieldName, TI, TypeDB);
+ codeview::printTypeIndex(*W, FieldName, TI, TpiTypes);
}
void TypeDumpVisitor::printItemIndex(StringRef FieldName, TypeIndex TI) const {
- CVTypeDumper::printTypeIndex(*W, FieldName, TI, getSourceDB());
+ codeview::printTypeIndex(*W, FieldName, TI, getSourceTypes());
}
Error TypeDumpVisitor::visitTypeBegin(CVType &Record) {
- TypeIndex TI = getSourceDB().getAppendIndex();
- return visitTypeBegin(Record, TI);
+ return visitTypeBegin(Record, TypeIndex::fromArrayIndex(TpiTypes.size()));
}
Error TypeDumpVisitor::visitTypeBegin(CVType &Record, TypeIndex Index) {
@@ -245,7 +242,7 @@ Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, StringListRecord &Strs) {
W->printNumber("NumStrings", Size);
ListScope Arguments(*W, "Strings");
for (uint32_t I = 0; I < Size; ++I) {
- printTypeIndex("String", Indices[I]);
+ printItemIndex("String", Indices[I]);
}
return Error::success();
}
diff --git a/lib/DebugInfo/CodeView/TypeIndex.cpp b/lib/DebugInfo/CodeView/TypeIndex.cpp
new file mode 100644
index 000000000000..20ba6470cd5b
--- /dev/null
+++ b/lib/DebugInfo/CodeView/TypeIndex.cpp
@@ -0,0 +1,27 @@
+//===-- TypeIndex.cpp - CodeView type index ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+
+#include "llvm/DebugInfo/CodeView/TypeCollection.h"
+#include "llvm/Support/ScopedPrinter.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+void llvm::codeview::printTypeIndex(ScopedPrinter &Printer, StringRef FieldName,
+ TypeIndex TI, TypeCollection &Types) {
+ StringRef TypeName;
+ if (!TI.isNoneType())
+ TypeName = Types.getTypeName(TI);
+ if (!TypeName.empty())
+ Printer.printHex(FieldName, TypeName, TI.getIndex());
+ else
+ Printer.printHex(FieldName, TI.getIndex());
+}
diff --git a/lib/DebugInfo/CodeView/TypeSerializer.cpp b/lib/DebugInfo/CodeView/TypeSerializer.cpp
index fd4d1853fa54..3b061e67e05e 100644
--- a/lib/DebugInfo/CodeView/TypeSerializer.cpp
+++ b/lib/DebugInfo/CodeView/TypeSerializer.cpp
@@ -66,6 +66,31 @@ TypeSerializer::insertRecordBytesPrivate(MutableArrayRef<uint8_t> Record) {
return Result.first->getValue();
}
+TypeIndex
+TypeSerializer::insertRecordBytesWithCopy(CVType &Record,
+ MutableArrayRef<uint8_t> Data) {
+ assert(Data.size() % 4 == 0 && "Record is not aligned to 4 bytes!");
+
+ StringRef S(reinterpret_cast<const char *>(Data.data()), Data.size());
+
+ // Do a two state lookup / insert so that we don't have to allocate unless
+ // we're going
+ // to do an insert. This is a big memory savings.
+ auto Iter = HashedRecords.find(S);
+ if (Iter != HashedRecords.end())
+ return Iter->second;
+
+ LastTypeIndex = calcNextTypeIndex();
+ uint8_t *Copy = RecordStorage.Allocate<uint8_t>(Data.size());
+ ::memcpy(Copy, Data.data(), Data.size());
+ Data = MutableArrayRef<uint8_t>(Copy, Data.size());
+ S = StringRef(reinterpret_cast<const char *>(Data.data()), Data.size());
+ HashedRecords.insert(std::make_pair(S, LastTypeIndex));
+ SeenRecords.push_back(Data);
+ Record.RecordData = Data;
+ return LastTypeIndex;
+}
+
Expected<MutableArrayRef<uint8_t>>
TypeSerializer::addPadding(MutableArrayRef<uint8_t> Record) {
uint32_t Align = Record.size() % 4;
@@ -137,11 +162,9 @@ Expected<TypeIndex> TypeSerializer::visitTypeEndGetIndex(CVType &Record) {
reinterpret_cast<RecordPrefix *>(ThisRecordData.data());
Prefix->RecordLen = ThisRecordData.size() - sizeof(uint16_t);
- uint8_t *Copy = RecordStorage.Allocate<uint8_t>(ThisRecordData.size());
- ::memcpy(Copy, ThisRecordData.data(), ThisRecordData.size());
- ThisRecordData = MutableArrayRef<uint8_t>(Copy, ThisRecordData.size());
- Record = CVType(*TypeKind, ThisRecordData);
- TypeIndex InsertedTypeIndex = insertRecordBytesPrivate(ThisRecordData);
+ Record.Type = *TypeKind;
+ TypeIndex InsertedTypeIndex =
+ insertRecordBytesWithCopy(Record, ThisRecordData);
// Write out each additional segment in reverse order, and update each
// record's continuation index to point to the previous one.
diff --git a/lib/DebugInfo/CodeView/TypeStreamMerger.cpp b/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
index 51f24fa3f135..46747f8eab99 100644
--- a/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
+++ b/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
@@ -11,11 +11,9 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
-#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
-#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ScopedPrinter.h"
@@ -60,9 +58,12 @@ namespace {
class TypeStreamMerger : public TypeVisitorCallbacks {
public:
TypeStreamMerger(TypeTableBuilder &DestIdStream,
- TypeTableBuilder &DestTypeStream, TypeServerHandler *Handler)
+ TypeTableBuilder &DestTypeStream,
+ SmallVectorImpl<TypeIndex> &SourceToDest,
+ TypeServerHandler *Handler)
: DestIdStream(DestIdStream), DestTypeStream(DestTypeStream),
- FieldListBuilder(DestTypeStream), Handler(Handler) {}
+ FieldListBuilder(DestTypeStream), Handler(Handler),
+ IndexMap(SourceToDest) {}
static const TypeIndex Untranslated;
@@ -143,7 +144,7 @@ private:
/// Map from source type index to destination type index. Indexed by source
/// type index minus 0x1000.
- SmallVector<TypeIndex, 0> IndexMap;
+ SmallVectorImpl<TypeIndex> &IndexMap;
};
} // end anonymous namespace
@@ -477,8 +478,9 @@ Error TypeStreamMerger::mergeStream(const CVTypeArray &Types) {
Error llvm::codeview::mergeTypeStreams(TypeTableBuilder &DestIdStream,
TypeTableBuilder &DestTypeStream,
+ SmallVectorImpl<TypeIndex> &SourceToDest,
TypeServerHandler *Handler,
const CVTypeArray &Types) {
- return TypeStreamMerger(DestIdStream, DestTypeStream, Handler)
+ return TypeStreamMerger(DestIdStream, DestTypeStream, SourceToDest, Handler)
.mergeStream(Types);
}
diff --git a/lib/DebugInfo/CodeView/TypeTableCollection.cpp b/lib/DebugInfo/CodeView/TypeTableCollection.cpp
new file mode 100644
index 000000000000..a18710d6ab52
--- /dev/null
+++ b/lib/DebugInfo/CodeView/TypeTableCollection.cpp
@@ -0,0 +1,83 @@
+//===- TypeTableCollection.cpp -------------------------------- *- C++ --*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/TypeTableCollection.h"
+
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
+#include "llvm/Support/BinaryByteStream.h"
+#include "llvm/Support/BinaryStreamReader.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+static void error(Error &&EC) {
+ assert(!static_cast<bool>(EC));
+ if (EC)
+ consumeError(std::move(EC));
+}
+
+TypeTableCollection::TypeTableCollection(
+ ArrayRef<MutableArrayRef<uint8_t>> Records)
+ : Records(Records), Database(Records.size()) {}
+
+Optional<TypeIndex> TypeTableCollection::getFirst() {
+ if (empty())
+ return None;
+ return TypeIndex::fromArrayIndex(0);
+}
+
+Optional<TypeIndex> TypeTableCollection::getNext(TypeIndex Prev) {
+ ++Prev;
+ assert(Prev.toArrayIndex() <= size());
+ if (Prev.toArrayIndex() == size())
+ return None;
+ return Prev;
+}
+
+void TypeTableCollection::ensureTypeExists(TypeIndex Index) {
+ assert(hasCapacityFor(Index));
+
+ if (Database.contains(Index))
+ return;
+
+ BinaryByteStream Bytes(Records[Index.toArrayIndex()], support::little);
+
+ CVType Type;
+ uint32_t Len;
+ error(VarStreamArrayExtractor<CVType>::extract(Bytes, Len, Type));
+
+ TypeDatabaseVisitor DBV(Database);
+ error(codeview::visitTypeRecord(Type, Index, DBV));
+ assert(Database.contains(Index));
+}
+
+CVType TypeTableCollection::getType(TypeIndex Index) {
+ ensureTypeExists(Index);
+ return Database.getTypeRecord(Index);
+}
+
+StringRef TypeTableCollection::getTypeName(TypeIndex Index) {
+ if (!Index.isSimple())
+ ensureTypeExists(Index);
+ return Database.getTypeName(Index);
+}
+
+bool TypeTableCollection::contains(TypeIndex Index) {
+ return Database.contains(Index);
+}
+
+uint32_t TypeTableCollection::size() { return Records.size(); }
+
+uint32_t TypeTableCollection::capacity() { return Records.size(); }
+
+bool TypeTableCollection::hasCapacityFor(TypeIndex Index) const {
+ return Index.toArrayIndex() < Records.size();
+}
diff --git a/lib/DebugInfo/DWARF/DWARFContext.cpp b/lib/DebugInfo/DWARF/DWARFContext.cpp
index 61e75a2b56ab..8e7c6c43d1a2 100644
--- a/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -979,7 +979,7 @@ Error DWARFContextInMemory::maybeDecompress(const SectionRef &Sec,
return Decompressor.takeError();
SmallString<32> Out;
- if (auto Err = Decompressor->decompress(Out))
+ if (auto Err = Decompressor->resizeAndDecompress(Out))
return Err;
UncompressedSections.emplace_back(std::move(Out));
@@ -1063,18 +1063,20 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
// TODO: Add support for relocations in other sections as needed.
// Record relocations for the debug_info and debug_line sections.
- RelocAddrMap *Map = StringSwitch<RelocAddrMap*>(RelSecName)
- .Case("debug_info", &InfoSection.Relocs)
- .Case("debug_loc", &LocSection.Relocs)
- .Case("debug_info.dwo", &InfoDWOSection.Relocs)
- .Case("debug_line", &LineSection.Relocs)
- .Case("debug_ranges", &RangeSection.Relocs)
- .Case("apple_names", &AppleNamesSection.Relocs)
- .Case("apple_types", &AppleTypesSection.Relocs)
- .Case("apple_namespaces", &AppleNamespacesSection.Relocs)
- .Case("apple_namespac", &AppleNamespacesSection.Relocs)
- .Case("apple_objc", &AppleObjCSection.Relocs)
- .Default(nullptr);
+ RelocAddrMap *Map =
+ StringSwitch<RelocAddrMap *>(RelSecName)
+ .Case("debug_info", &InfoSection.Relocs)
+ .Case("debug_loc", &LocSection.Relocs)
+ .Case("debug_info.dwo", &InfoDWOSection.Relocs)
+ .Case("debug_line", &LineSection.Relocs)
+ .Case("debug_ranges", &RangeSection.Relocs)
+ .Case("debug_addr", &AddrSection.Relocs)
+ .Case("apple_names", &AppleNamesSection.Relocs)
+ .Case("apple_types", &AppleTypesSection.Relocs)
+ .Case("apple_namespaces", &AppleNamespacesSection.Relocs)
+ .Case("apple_namespac", &AppleNamespacesSection.Relocs)
+ .Case("apple_objc", &AppleObjCSection.Relocs)
+ .Default(nullptr);
if (!Map) {
// Find debug_types relocs by section rather than name as there are
// multiple, comdat grouped, debug_types sections.
@@ -1104,14 +1106,14 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
}
object::RelocVisitor V(Obj);
- object::RelocToApply R(V.visit(Reloc.getType(), Reloc, *SymAddrOrErr));
+ uint64_t Val = V.visit(Reloc.getType(), Reloc, *SymAddrOrErr);
if (V.error()) {
SmallString<32> Name;
Reloc.getTypeName(Name);
errs() << "error: failed to compute relocation: " << Name << "\n";
continue;
}
- Map->insert({Reloc.getOffset(), {R.Value}});
+ Map->insert({Reloc.getOffset(), {Val}});
}
}
}
@@ -1148,7 +1150,7 @@ StringRef *DWARFContextInMemory::MapSectionToMember(StringRef Name) {
.Case("debug_line.dwo", &LineDWOSection.Data)
.Case("debug_str.dwo", &StringDWOSection)
.Case("debug_str_offsets.dwo", &StringOffsetDWOSection)
- .Case("debug_addr", &AddrSection)
+ .Case("debug_addr", &AddrSection.Data)
.Case("apple_names", &AppleNamesSection.Data)
.Case("apple_types", &AppleTypesSection.Data)
.Case("apple_namespaces", &AppleNamespacesSection.Data)
diff --git a/lib/DebugInfo/DWARF/DWARFUnit.cpp b/lib/DebugInfo/DWARF/DWARFUnit.cpp
index 3835d4da9ae9..c268afc222c3 100644
--- a/lib/DebugInfo/DWARF/DWARFUnit.cpp
+++ b/lib/DebugInfo/DWARF/DWARFUnit.cpp
@@ -33,7 +33,7 @@ using namespace dwarf;
void DWARFUnitSectionBase::parse(DWARFContext &C, const DWARFSection &Section) {
parseImpl(C, Section, C.getDebugAbbrev(), &C.getRangeSection(),
- C.getStringSection(), StringRef(), C.getAddrSection(),
+ C.getStringSection(), StringRef(), &C.getAddrSection(),
C.getLineSection().Data, C.isLittleEndian(), false);
}
@@ -42,14 +42,14 @@ void DWARFUnitSectionBase::parseDWO(DWARFContext &C,
DWARFUnitIndex *Index) {
parseImpl(C, DWOSection, C.getDebugAbbrevDWO(), &C.getRangeDWOSection(),
C.getStringDWOSection(), C.getStringOffsetDWOSection(),
- C.getAddrSection(), C.getLineDWOSection().Data, C.isLittleEndian(),
+ &C.getAddrSection(), C.getLineDWOSection().Data, C.isLittleEndian(),
true);
}
DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section,
const DWARFDebugAbbrev *DA, const DWARFSection *RS,
- StringRef SS, StringRef SOS, StringRef AOS, StringRef LS,
- bool LE, bool IsDWO,
+ StringRef SS, StringRef SOS, const DWARFSection *AOS,
+ StringRef LS, bool LE, bool IsDWO,
const DWARFUnitSectionBase &UnitSection,
const DWARFUnitIndex::Entry *IndexEntry)
: Context(DC), InfoSection(Section), Abbrev(DA), RangeSection(RS),
@@ -69,10 +69,10 @@ DWARFUnit::~DWARFUnit() = default;
bool DWARFUnit::getAddrOffsetSectionItem(uint32_t Index,
uint64_t &Result) const {
uint32_t Offset = AddrOffsetSectionBase + Index * AddrSize;
- if (AddrOffsetSection.size() < Offset + AddrSize)
+ if (AddrOffsetSection->Data.size() < Offset + AddrSize)
return false;
- DataExtractor DA(AddrOffsetSection, isLittleEndian, AddrSize);
- Result = DA.getAddress(&Offset);
+ DataExtractor DA(AddrOffsetSection->Data, isLittleEndian, AddrSize);
+ Result = getRelocatedValue(DA, AddrSize, &Offset, &AddrOffsetSection->Relocs);
return true;
}
@@ -249,7 +249,7 @@ size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) {
return DieArray.size();
}
-DWARFUnit::DWOHolder::DWOHolder(StringRef DWOPath) {
+DWARFUnit::DWOHolder::DWOHolder(StringRef DWOPath, uint64_t DWOId) {
auto Obj = object::ObjectFile::createObjectFile(DWOPath);
if (!Obj) {
// TODO: Actually report errors helpfully.
@@ -259,8 +259,11 @@ DWARFUnit::DWOHolder::DWOHolder(StringRef DWOPath) {
DWOFile = std::move(Obj.get());
DWOContext.reset(
cast<DWARFContext>(new DWARFContextInMemory(*DWOFile.getBinary())));
- if (DWOContext->getNumDWOCompileUnits() > 0)
- DWOU = DWOContext->getDWOCompileUnitAtIndex(0);
+ for (const auto &DWOCU : DWOContext->dwo_compile_units())
+ if (DWOCU->getDWOId() == DWOId) {
+ DWOU = DWOCU.get();
+ return;
+ }
}
bool DWARFUnit::parseDWO() {
@@ -281,10 +284,12 @@ bool DWARFUnit::parseDWO() {
sys::path::append(AbsolutePath, *CompilationDir);
}
sys::path::append(AbsolutePath, *DWOFileName);
- DWO = llvm::make_unique<DWOHolder>(AbsolutePath);
+ auto DWOId = getDWOId();
+ if (!DWOId)
+ return false;
+ DWO = llvm::make_unique<DWOHolder>(AbsolutePath, *DWOId);
DWARFUnit *DWOCU = DWO->getUnit();
- // Verify that compile unit in .dwo file is valid.
- if (!DWOCU || DWOCU->getDWOId() != getDWOId()) {
+ if (!DWOCU) {
DWO.reset();
return false;
}
diff --git a/lib/DebugInfo/PDB/Native/DbiStream.cpp b/lib/DebugInfo/PDB/Native/DbiStream.cpp
index f7538c580ba4..2f4fb6cc295d 100644
--- a/lib/DebugInfo/PDB/Native/DbiStream.cpp
+++ b/lib/DebugInfo/PDB/Native/DbiStream.cpp
@@ -72,14 +72,6 @@ Error DbiStream::reload() {
return make_error<RawError>(raw_error_code::feature_unsupported,
"Unsupported DBI version.");
- auto IS = Pdb.getPDBInfoStream();
- if (!IS)
- return IS.takeError();
-
- if (Header->Age != IS->getAge())
- return make_error<RawError>(raw_error_code::corrupt_file,
- "DBI Age does not match PDB Age.");
-
if (Stream->getLength() !=
sizeof(DbiStreamHeader) + Header->ModiSubstreamSize +
Header->SecContrSubstreamSize + Header->SectionMapSize +
diff --git a/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp b/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
index 4dd965c69071..c6568029ec55 100644
--- a/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
+++ b/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
@@ -117,6 +117,7 @@ Expected<uint32_t> PDBFileBuilder::getNamedStreamIndex(StringRef Name) const {
}
Error PDBFileBuilder::commit(StringRef Filename) {
+ assert(!Filename.empty());
auto ExpectedLayout = finalizeMsfLayout();
if (!ExpectedLayout)
return ExpectedLayout.takeError();
diff --git a/lib/DebugInfo/PDB/Native/PDBTypeServerHandler.cpp b/lib/DebugInfo/PDB/Native/PDBTypeServerHandler.cpp
index cb783cf4fea7..f00567db743e 100644
--- a/lib/DebugInfo/PDB/Native/PDBTypeServerHandler.cpp
+++ b/lib/DebugInfo/PDB/Native/PDBTypeServerHandler.cpp
@@ -21,6 +21,7 @@
#include "llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h"
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
#include "llvm/DebugInfo/PDB/GenericError.h"
#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
diff --git a/lib/DebugInfo/PDB/Native/TpiStream.cpp b/lib/DebugInfo/PDB/Native/TpiStream.cpp
index c0999d93dbb9..8e0065873892 100644
--- a/lib/DebugInfo/PDB/Native/TpiStream.cpp
+++ b/lib/DebugInfo/PDB/Native/TpiStream.cpp
@@ -9,10 +9,7 @@
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
#include "llvm/ADT/iterator_range.h"
-#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
-#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h"
@@ -91,9 +88,6 @@ Error TpiStream::reload() {
HSR.setOffset(Header->HashValueBuffer.Off);
if (auto EC = HSR.readArray(HashValues, NumHashValues))
return EC;
- std::vector<ulittle32_t> HashValueList;
- for (auto I : HashValues)
- HashValueList.push_back(I);
HSR.setOffset(Header->IndexOffsetBuffer.Off);
uint32_t NumTypeIndexOffsets =
diff --git a/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp b/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp
index 701a318511b8..20456cc97823 100644
--- a/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp
+++ b/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp
@@ -69,7 +69,7 @@ Error TpiStreamBuilder::finalize() {
uint32_t Count = TypeRecords.size();
- H->Version = *VerHeader;
+ H->Version = VerHeader;
H->HeaderSize = sizeof(TpiStreamHeader);
H->TypeIndexBegin = codeview::TypeIndex::FirstNonSimpleIndex;
H->TypeIndexEnd = H->TypeIndexBegin + Count;
diff --git a/lib/Demangle/ItaniumDemangle.cpp b/lib/Demangle/ItaniumDemangle.cpp
index 49dbe74d25df..f454ae61d965 100644
--- a/lib/Demangle/ItaniumDemangle.cpp
+++ b/lib/Demangle/ItaniumDemangle.cpp
@@ -1947,7 +1947,7 @@ static const char *parse_type(const char *first, const char *last, C &db) {
break;
}
}
- // drop through
+ // falls through
default:
// must check for builtin-types before class-enum-types to avoid
// ambiguities with operator-names
diff --git a/lib/IR/Attributes.cpp b/lib/IR/Attributes.cpp
index ce60367a6c8b..adb31d127a2e 100644
--- a/lib/IR/Attributes.cpp
+++ b/lib/IR/Attributes.cpp
@@ -1058,7 +1058,7 @@ AttributeList AttributeList::addAttributes(LLVMContext &C, unsigned Index,
#ifndef NDEBUG
// FIXME it is not obvious how this should work for alignment. For now, say
// we can't change a known alignment.
- unsigned OldAlign = getParamAlignment(Index);
+ unsigned OldAlign = getAttributes(Index).getAlignment();
unsigned NewAlign = B.getAlignment();
assert((!OldAlign || !NewAlign || OldAlign == NewAlign) &&
"Attempt to change alignment!");
diff --git a/lib/IR/AutoUpgrade.cpp b/lib/IR/AutoUpgrade.cpp
index 8bcba7672315..06934b365a11 100644
--- a/lib/IR/AutoUpgrade.cpp
+++ b/lib/IR/AutoUpgrade.cpp
@@ -521,6 +521,7 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) {
return true;
}
}
+ break;
}
case 'o':
// We only need to change the name to match the mangling including the
diff --git a/lib/IR/Constants.cpp b/lib/IR/Constants.cpp
index 4b9d89cda539..8b0ff66334a7 100644
--- a/lib/IR/Constants.cpp
+++ b/lib/IR/Constants.cpp
@@ -37,10 +37,6 @@ using namespace llvm;
// Constant Class
//===----------------------------------------------------------------------===//
-void Constant::anchor() { }
-
-void ConstantData::anchor() {}
-
bool Constant::isNegativeZeroValue() const {
// Floating point values have an explicit -0.0 value.
if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this))
@@ -496,8 +492,6 @@ void Constant::removeDeadConstantUsers() const {
// ConstantInt
//===----------------------------------------------------------------------===//
-void ConstantInt::anchor() { }
-
ConstantInt::ConstantInt(IntegerType *Ty, const APInt &V)
: ConstantData(Ty, ConstantIntVal), Val(V) {
assert(V.getBitWidth() == Ty->getBitWidth() && "Invalid constant for type");
@@ -610,8 +604,6 @@ static const fltSemantics *TypeToFloatSemantics(Type *Ty) {
return &APFloat::PPCDoubleDouble();
}
-void ConstantFP::anchor() { }
-
Constant *ConstantFP::get(Type *Ty, double V) {
LLVMContext &Context = Ty->getContext();
@@ -2266,9 +2258,6 @@ Type *GetElementPtrConstantExpr::getResultElementType() const {
//===----------------------------------------------------------------------===//
// ConstantData* implementations
-void ConstantDataArray::anchor() {}
-void ConstantDataVector::anchor() {}
-
Type *ConstantDataSequential::getElementType() const {
return getType()->getElementType();
}
@@ -2627,8 +2616,8 @@ Constant *ConstantDataSequential::getElementAsConstant(unsigned Elt) const {
return ConstantInt::get(getElementType(), getElementAsInteger(Elt));
}
-bool ConstantDataSequential::isString() const {
- return isa<ArrayType>(getType()) && getElementType()->isIntegerTy(8);
+bool ConstantDataSequential::isString(unsigned CharSize) const {
+ return isa<ArrayType>(getType()) && getElementType()->isIntegerTy(CharSize);
}
bool ConstantDataSequential::isCString() const {
diff --git a/lib/IR/ConstantsContext.h b/lib/IR/ConstantsContext.h
index 25eb9452d9d0..6c189cf656de 100644
--- a/lib/IR/ConstantsContext.h
+++ b/lib/IR/ConstantsContext.h
@@ -44,8 +44,6 @@ namespace llvm {
/// UnaryConstantExpr - This class is private to Constants.cpp, and is used
/// behind the scenes to implement unary constant exprs.
class UnaryConstantExpr : public ConstantExpr {
- void anchor() override;
-
public:
UnaryConstantExpr(unsigned Opcode, Constant *C, Type *Ty)
: ConstantExpr(Ty, Opcode, &Op<0>(), 1) {
@@ -65,8 +63,6 @@ public:
/// BinaryConstantExpr - This class is private to Constants.cpp, and is used
/// behind the scenes to implement binary constant exprs.
class BinaryConstantExpr : public ConstantExpr {
- void anchor() override;
-
public:
BinaryConstantExpr(unsigned Opcode, Constant *C1, Constant *C2,
unsigned Flags)
@@ -90,8 +86,6 @@ public:
/// SelectConstantExpr - This class is private to Constants.cpp, and is used
/// behind the scenes to implement select constant exprs.
class SelectConstantExpr : public ConstantExpr {
- void anchor() override;
-
public:
SelectConstantExpr(Constant *C1, Constant *C2, Constant *C3)
: ConstantExpr(C2->getType(), Instruction::Select, &Op<0>(), 3) {
@@ -115,8 +109,6 @@ public:
/// Constants.cpp, and is used behind the scenes to implement
/// extractelement constant exprs.
class ExtractElementConstantExpr : public ConstantExpr {
- void anchor() override;
-
public:
ExtractElementConstantExpr(Constant *C1, Constant *C2)
: ConstantExpr(cast<VectorType>(C1->getType())->getElementType(),
@@ -140,8 +132,6 @@ public:
/// Constants.cpp, and is used behind the scenes to implement
/// insertelement constant exprs.
class InsertElementConstantExpr : public ConstantExpr {
- void anchor() override;
-
public:
InsertElementConstantExpr(Constant *C1, Constant *C2, Constant *C3)
: ConstantExpr(C1->getType(), Instruction::InsertElement,
@@ -166,8 +156,6 @@ public:
/// Constants.cpp, and is used behind the scenes to implement
/// shufflevector constant exprs.
class ShuffleVectorConstantExpr : public ConstantExpr {
- void anchor() override;
-
public:
ShuffleVectorConstantExpr(Constant *C1, Constant *C2, Constant *C3)
: ConstantExpr(VectorType::get(
@@ -195,8 +183,6 @@ public:
/// Constants.cpp, and is used behind the scenes to implement
/// extractvalue constant exprs.
class ExtractValueConstantExpr : public ConstantExpr {
- void anchor() override;
-
public:
ExtractValueConstantExpr(Constant *Agg, ArrayRef<unsigned> IdxList,
Type *DestTy)
@@ -230,8 +216,6 @@ public:
/// Constants.cpp, and is used behind the scenes to implement
/// insertvalue constant exprs.
class InsertValueConstantExpr : public ConstantExpr {
- void anchor() override;
-
public:
InsertValueConstantExpr(Constant *Agg, Constant *Val,
ArrayRef<unsigned> IdxList, Type *DestTy)
@@ -271,8 +255,6 @@ class GetElementPtrConstantExpr : public ConstantExpr {
GetElementPtrConstantExpr(Type *SrcElementTy, Constant *C,
ArrayRef<Constant *> IdxList, Type *DestTy);
- void anchor() override;
-
public:
static GetElementPtrConstantExpr *Create(Type *SrcElementTy, Constant *C,
ArrayRef<Constant *> IdxList,
@@ -301,8 +283,6 @@ public:
// behind the scenes to implement ICmp and FCmp constant expressions. This is
// needed in order to store the predicate value for these instructions.
class CompareConstantExpr : public ConstantExpr {
- void anchor() override;
-
public:
unsigned short predicate;
CompareConstantExpr(Type *ty, Instruction::OtherOps opc,
diff --git a/lib/IR/DataLayout.cpp b/lib/IR/DataLayout.cpp
index c117d29b7f69..d5e29649a237 100644
--- a/lib/IR/DataLayout.cpp
+++ b/lib/IR/DataLayout.cpp
@@ -307,7 +307,7 @@ void DataLayout::parseSpecifier(StringRef Desc) {
case 'a': {
AlignTypeEnum AlignType;
switch (Specifier) {
- default:
+ default: llvm_unreachable("Unexpected specifier!");
case 'i': AlignType = INTEGER_ALIGN; break;
case 'v': AlignType = VECTOR_ALIGN; break;
case 'f': AlignType = FLOAT_ALIGN; break;
diff --git a/lib/IR/Function.cpp b/lib/IR/Function.cpp
index 16a9e51b8306..39de4b0a97fa 100644
--- a/lib/IR/Function.cpp
+++ b/lib/IR/Function.cpp
@@ -66,8 +66,6 @@ template class llvm::SymbolTableListTraits<BasicBlock>;
// Argument Implementation
//===----------------------------------------------------------------------===//
-void Argument::anchor() {}
-
Argument::Argument(Type *Ty, const Twine &Name, Function *Par, unsigned ArgNo)
: Value(Ty, Value::ArgumentVal), Parent(Par), ArgNo(ArgNo) {
setName(Name);
diff --git a/lib/IR/IRBuilder.cpp b/lib/IR/IRBuilder.cpp
index 3477c087967f..7572d0c6b3bc 100644
--- a/lib/IR/IRBuilder.cpp
+++ b/lib/IR/IRBuilder.cpp
@@ -381,8 +381,11 @@ CallInst *IRBuilderBase::CreateMaskedGather(Value *Ptrs, unsigned Align,
Mask = Constant::getAllOnesValue(VectorType::get(Type::getInt1Ty(Context),
NumElts));
+ if (!PassThru)
+ PassThru = UndefValue::get(DataTy);
+
Type *OverloadedTypes[] = {DataTy, PtrsTy};
- Value * Ops[] = {Ptrs, getInt32(Align), Mask, UndefValue::get(DataTy)};
+ Value * Ops[] = {Ptrs, getInt32(Align), Mask, PassThru};
// We specify only one type when we create this intrinsic. Types of other
// arguments are derived from this type.
diff --git a/lib/IR/InlineAsm.cpp b/lib/IR/InlineAsm.cpp
index 8feeeb65d445..6c0c5a267f81 100644
--- a/lib/IR/InlineAsm.cpp
+++ b/lib/IR/InlineAsm.cpp
@@ -40,10 +40,6 @@ InlineAsm::InlineAsm(FunctionType *FTy, const std::string &asmString,
"Function type not legal for constraints!");
}
-// Implement the first virtual method in this class in this file so the
-// InlineAsm vtable is emitted here.
-InlineAsm::~InlineAsm() = default;
-
InlineAsm *InlineAsm::get(FunctionType *FTy, StringRef AsmString,
StringRef Constraints, bool hasSideEffects,
bool isAlignStack, AsmDialect asmDialect) {
diff --git a/lib/IR/Instruction.cpp b/lib/IR/Instruction.cpp
index 91b9d9232b54..828e78b13005 100644
--- a/lib/IR/Instruction.cpp
+++ b/lib/IR/Instruction.cpp
@@ -43,8 +43,6 @@ Instruction::Instruction(Type *ty, unsigned it, Use *Ops, unsigned NumOps,
InsertAtEnd->getInstList().push_back(this);
}
-
-// Out of line virtual method, so the vtable, etc has a home.
Instruction::~Instruction() {
assert(!Parent && "Instruction still linked in the program!");
if (hasMetadataHashEntry())
diff --git a/lib/IR/Instructions.cpp b/lib/IR/Instructions.cpp
index 5a5b9c0d06bb..01d4ed6c8eef 100644
--- a/lib/IR/Instructions.cpp
+++ b/lib/IR/Instructions.cpp
@@ -59,9 +59,6 @@ User::op_iterator CallSite::getCallee() const {
// TerminatorInst Class
//===----------------------------------------------------------------------===//
-// Out of line virtual method, so the vtable, etc has a home.
-TerminatorInst::~TerminatorInst() = default;
-
unsigned TerminatorInst::getNumSuccessors() const {
switch (getOpcode()) {
#define HANDLE_TERM_INST(N, OPC, CLASS) \
@@ -99,13 +96,6 @@ void TerminatorInst::setSuccessor(unsigned idx, BasicBlock *B) {
}
//===----------------------------------------------------------------------===//
-// UnaryInstruction Class
-//===----------------------------------------------------------------------===//
-
-// Out of line virtual method, so the vtable, etc has a home.
-UnaryInstruction::~UnaryInstruction() = default;
-
-//===----------------------------------------------------------------------===//
// SelectInst Class
//===----------------------------------------------------------------------===//
@@ -138,8 +128,6 @@ const char *SelectInst::areInvalidOperands(Value *Op0, Value *Op1, Value *Op2) {
// PHINode Class
//===----------------------------------------------------------------------===//
-void PHINode::anchor() {}
-
PHINode::PHINode(const PHINode &PN)
: Instruction(PN.getType(), Instruction::PHI, nullptr, PN.getNumOperands()),
ReservedSpace(PN.getNumOperands()) {
@@ -293,8 +281,6 @@ void LandingPadInst::addClause(Constant *Val) {
// CallInst Implementation
//===----------------------------------------------------------------------===//
-CallInst::~CallInst() = default;
-
void CallInst::init(FunctionType *FTy, Value *Func, ArrayRef<Value *> Args,
ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr) {
this->FTy = FTy;
@@ -900,8 +886,6 @@ BasicBlock *ReturnInst::getSuccessorV(unsigned idx) const {
llvm_unreachable("ReturnInst has no successors!");
}
-ReturnInst::~ReturnInst() = default;
-
//===----------------------------------------------------------------------===//
// ResumeInst Implementation
//===----------------------------------------------------------------------===//
@@ -1337,9 +1321,6 @@ AllocaInst::AllocaInst(Type *Ty, unsigned AddrSpace, Value *ArraySize,
setName(Name);
}
-// Out of line virtual method, so the vtable, etc has a home.
-AllocaInst::~AllocaInst() = default;
-
void AllocaInst::setAlignment(unsigned Align) {
assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!");
assert(Align <= MaximumAlignment &&
@@ -1689,8 +1670,6 @@ FenceInst::FenceInst(LLVMContext &C, AtomicOrdering Ordering,
// GetElementPtrInst Implementation
//===----------------------------------------------------------------------===//
-void GetElementPtrInst::anchor() {}
-
void GetElementPtrInst::init(Value *Ptr, ArrayRef<Value *> IdxList,
const Twine &Name) {
assert(getNumOperands() == 1 + IdxList.size() &&
@@ -2357,8 +2336,6 @@ float FPMathOperator::getFPAccuracy() const {
// CastInst Class
//===----------------------------------------------------------------------===//
-void CastInst::anchor() {}
-
// Just determine if this cast only deals with integral->integral conversion.
bool CastInst::isIntegerCast() const {
switch (getOpcode()) {
@@ -3387,8 +3364,6 @@ AddrSpaceCastInst::AddrSpaceCastInst(
// CmpInst Classes
//===----------------------------------------------------------------------===//
-void CmpInst::anchor() {}
-
CmpInst::CmpInst(Type *ty, OtherOps op, Predicate predicate, Value *LHS,
Value *RHS, const Twine &Name, Instruction *InsertBefore)
: Instruction(ty, op,
@@ -3528,8 +3503,6 @@ StringRef CmpInst::getPredicateName(Predicate Pred) {
}
}
-void ICmpInst::anchor() {}
-
ICmpInst::Predicate ICmpInst::getSignedPredicate(Predicate pred) {
switch (pred) {
default: llvm_unreachable("Unknown icmp predicate!");
diff --git a/lib/IR/LLVMContextImpl.cpp b/lib/IR/LLVMContextImpl.cpp
index 343722463e5f..4a30d28c3913 100644
--- a/lib/IR/LLVMContextImpl.cpp
+++ b/lib/IR/LLVMContextImpl.cpp
@@ -215,27 +215,6 @@ uint32_t LLVMContextImpl::getOperandBundleTagID(StringRef Tag) const {
return I->second;
}
-// ConstantsContext anchors
-void UnaryConstantExpr::anchor() { }
-
-void BinaryConstantExpr::anchor() { }
-
-void SelectConstantExpr::anchor() { }
-
-void ExtractElementConstantExpr::anchor() { }
-
-void InsertElementConstantExpr::anchor() { }
-
-void ShuffleVectorConstantExpr::anchor() { }
-
-void ExtractValueConstantExpr::anchor() { }
-
-void InsertValueConstantExpr::anchor() { }
-
-void GetElementPtrConstantExpr::anchor() { }
-
-void CompareConstantExpr::anchor() { }
-
/// Singleton instance of the OptBisect class.
///
/// This singleton is accessed via the LLVMContext::getOptBisect() function. It
diff --git a/lib/IR/PassRegistry.cpp b/lib/IR/PassRegistry.cpp
index 584dee2869c1..c0f6f07169ff 100644
--- a/lib/IR/PassRegistry.cpp
+++ b/lib/IR/PassRegistry.cpp
@@ -105,8 +105,6 @@ void PassRegistry::registerAnalysisGroup(const void *InterfaceID,
ImplementationInfo->getNormalCtor() &&
"Cannot specify pass as default if it does not have a default ctor");
InterfaceInfo->setNormalCtor(ImplementationInfo->getNormalCtor());
- InterfaceInfo->setTargetMachineCtor(
- ImplementationInfo->getTargetMachineCtor());
}
}
diff --git a/lib/IR/User.cpp b/lib/IR/User.cpp
index 497b4aa17643..d46039107f33 100644
--- a/lib/IR/User.cpp
+++ b/lib/IR/User.cpp
@@ -19,8 +19,6 @@ class BasicBlock;
// User Class
//===----------------------------------------------------------------------===//
-void User::anchor() {}
-
void User::replaceUsesOfWith(Value *From, Value *To) {
if (From == To) return; // Duh what?
@@ -193,12 +191,4 @@ void User::operator delete(void *Usr) {
}
}
-//===----------------------------------------------------------------------===//
-// Operator Class
-//===----------------------------------------------------------------------===//
-
-Operator::~Operator() {
- llvm_unreachable("should never destroy an Operator");
-}
-
} // End llvm namespace
diff --git a/lib/IR/Value.cpp b/lib/IR/Value.cpp
index 02b40c93b5d8..51a7d424c1f3 100644
--- a/lib/IR/Value.cpp
+++ b/lib/IR/Value.cpp
@@ -20,6 +20,7 @@
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/DerivedUser.h"
#include "llvm/IR/GetElementPtrTypeIterator.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instructions.h"
@@ -59,7 +60,7 @@ Value::Value(Type *ty, unsigned scid)
(SubclassID < ConstantFirstVal || SubclassID > ConstantLastVal))
assert((VTy->isFirstClassType() || VTy->isVoidTy()) &&
"Cannot create non-first-class values except for constants!");
- static_assert(sizeof(Value) == 3 * sizeof(void *) + 2 * sizeof(unsigned),
+ static_assert(sizeof(Value) == 2 * sizeof(void *) + 2 * sizeof(unsigned),
"Value too big");
}
@@ -89,6 +90,32 @@ Value::~Value() {
destroyValueName();
}
+void Value::deleteValue() {
+ switch (getValueID()) {
+#define HANDLE_VALUE(Name) \
+ case Value::Name##Val: \
+ delete static_cast<Name *>(this); \
+ break;
+#define HANDLE_MEMORY_VALUE(Name) \
+ case Value::Name##Val: \
+ static_cast<DerivedUser *>(this)->DeleteValue( \
+ static_cast<DerivedUser *>(this)); \
+ break;
+#define HANDLE_INSTRUCTION(Name) /* nothing */
+#include "llvm/IR/Value.def"
+
+#define HANDLE_INST(N, OPC, CLASS) \
+ case Value::InstructionVal + Instruction::OPC: \
+ delete static_cast<CLASS *>(this); \
+ break;
+#define HANDLE_USER_INST(N, OPC, CLASS)
+#include "llvm/IR/Instruction.def"
+
+ default:
+ llvm_unreachable("attempting to delete unknown value kind");
+ }
+}
+
void Value::destroyValueName() {
ValueName *Name = getValueName();
if (Name)
diff --git a/lib/IR/ValueTypes.cpp b/lib/IR/ValueTypes.cpp
index 2132e1659225..cf6ee063c2d5 100644
--- a/lib/IR/ValueTypes.cpp
+++ b/lib/IR/ValueTypes.cpp
@@ -142,6 +142,7 @@ std::string EVT::getEVTString() const {
case MVT::Other: return "ch";
case MVT::Glue: return "glue";
case MVT::x86mmx: return "x86mmx";
+ case MVT::v1i1: return "v1i1";
case MVT::v2i1: return "v2i1";
case MVT::v4i1: return "v4i1";
case MVT::v8i1: return "v8i1";
@@ -220,6 +221,7 @@ Type *EVT::getTypeForEVT(LLVMContext &Context) const {
case MVT::f128: return Type::getFP128Ty(Context);
case MVT::ppcf128: return Type::getPPC_FP128Ty(Context);
case MVT::x86mmx: return Type::getX86_MMXTy(Context);
+ case MVT::v1i1: return VectorType::get(Type::getInt1Ty(Context), 1);
case MVT::v2i1: return VectorType::get(Type::getInt1Ty(Context), 2);
case MVT::v4i1: return VectorType::get(Type::getInt1Ty(Context), 4);
case MVT::v8i1: return VectorType::get(Type::getInt1Ty(Context), 8);
diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp
index 3b68d6365872..21e8048442be 100644
--- a/lib/IR/Verifier.cpp
+++ b/lib/IR/Verifier.cpp
@@ -1317,6 +1317,12 @@ Verifier::visitModuleFlag(const MDNode *Op,
Assert(Inserted,
"module flag identifiers must be unique (or of 'require' type)", ID);
}
+
+ if (ID->getString() == "wchar_size") {
+ ConstantInt *Value
+ = mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(2));
+ Assert(Value, "wchar_size metadata requires constant integer argument");
+ }
}
/// Return true if this attribute kind only applies to functions.
diff --git a/lib/LTO/ThinLTOCodeGenerator.cpp b/lib/LTO/ThinLTOCodeGenerator.cpp
index 65a7994325bc..ca3fc60f9501 100644
--- a/lib/LTO/ThinLTOCodeGenerator.cpp
+++ b/lib/LTO/ThinLTOCodeGenerator.cpp
@@ -25,9 +25,11 @@
#include "llvm/Bitcode/BitcodeWriterPass.h"
#include "llvm/ExecutionEngine/ObjectMemoryBuffer.h"
#include "llvm/IR/DiagnosticPrinter.h"
+#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Mangler.h"
+#include "llvm/IR/Verifier.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/LTO/LTO.h"
#include "llvm/Linker/Linker.h"
@@ -62,6 +64,7 @@ namespace llvm {
extern cl::opt<bool> LTODiscardValueNames;
extern cl::opt<std::string> LTORemarksFilename;
extern cl::opt<bool> LTOPassRemarksWithHotness;
+extern cl::opt<bool> LTOStripInvalidDebugInfo;
}
namespace {
@@ -142,6 +145,30 @@ static void promoteModule(Module &TheModule, const ModuleSummaryIndex &Index) {
report_fatal_error("renameModuleForThinLTO failed");
}
+namespace {
+class ThinLTODiagnosticInfo : public DiagnosticInfo {
+ const Twine &Msg;
+public:
+ ThinLTODiagnosticInfo(const Twine &DiagMsg,
+ DiagnosticSeverity Severity = DS_Error)
+ : DiagnosticInfo(DK_Linker, Severity), Msg(DiagMsg) {}
+ void print(DiagnosticPrinter &DP) const override { DP << Msg; }
+};
+}
+
+/// Verify the module and strip broken debug info.
+static void verifyLoadedModule(Module &TheModule) {
+ bool BrokenDebugInfo = false;
+ if (verifyModule(TheModule, &dbgs(),
+ LTOStripInvalidDebugInfo ? &BrokenDebugInfo : nullptr))
+ report_fatal_error("Broken module found, compilation aborted!");
+ if (BrokenDebugInfo) {
+ TheModule.getContext().diagnose(ThinLTODiagnosticInfo(
+ "Invalid debug info found, debug info will be stripped", DS_Warning));
+ StripDebugInfo(TheModule);
+ }
+}
+
static std::unique_ptr<Module>
loadModuleFromBuffer(const MemoryBufferRef &Buffer, LLVMContext &Context,
bool Lazy, bool IsImporting) {
@@ -159,6 +186,8 @@ loadModuleFromBuffer(const MemoryBufferRef &Buffer, LLVMContext &Context,
});
report_fatal_error("Can't load module, abort.");
}
+ if (!Lazy)
+ verifyLoadedModule(*ModuleOrErr.get());
return std::move(ModuleOrErr.get());
}
@@ -181,6 +210,8 @@ crossImportIntoModule(Module &TheModule, const ModuleSummaryIndex &Index,
});
report_fatal_error("importFunctions failed");
}
+ // Verify again after cross-importing.
+ verifyLoadedModule(TheModule);
}
static void optimizeModule(Module &TheModule, TargetMachine &TM,
@@ -195,7 +226,8 @@ static void optimizeModule(Module &TheModule, TargetMachine &TM,
PMB.OptLevel = OptLevel;
PMB.LoopVectorize = true;
PMB.SLPVectorize = true;
- PMB.VerifyInput = true;
+ // Already did this in verifyLoadedModule().
+ PMB.VerifyInput = false;
PMB.VerifyOutput = false;
legacy::PassManager PM;
@@ -505,29 +537,25 @@ static void initTMBuilder(TargetMachineBuilder &TMBuilder,
void ThinLTOCodeGenerator::addModule(StringRef Identifier, StringRef Data) {
ThinLTOBuffer Buffer(Data, Identifier);
- if (Modules.empty()) {
- // First module added, so initialize the triple and some options
- LLVMContext Context;
- StringRef TripleStr;
- ErrorOr<std::string> TripleOrErr = expectedToErrorOrAndEmitErrors(
- Context, getBitcodeTargetTriple(Buffer.getMemBuffer()));
- if (TripleOrErr)
- TripleStr = *TripleOrErr;
- Triple TheTriple(TripleStr);
+ LLVMContext Context;
+ StringRef TripleStr;
+ ErrorOr<std::string> TripleOrErr = expectedToErrorOrAndEmitErrors(
+ Context, getBitcodeTargetTriple(Buffer.getMemBuffer()));
+
+ if (TripleOrErr)
+ TripleStr = *TripleOrErr;
+
+ Triple TheTriple(TripleStr);
+
+ if (Modules.empty())
initTMBuilder(TMBuilder, Triple(TheTriple));
+ else if (TMBuilder.TheTriple != TheTriple) {
+ if (!TMBuilder.TheTriple.isCompatibleWith(TheTriple))
+ report_fatal_error("ThinLTO modules with incompatible triples not "
+ "supported");
+ initTMBuilder(TMBuilder, Triple(TMBuilder.TheTriple.merge(TheTriple)));
}
-#ifndef NDEBUG
- else {
- LLVMContext Context;
- StringRef TripleStr;
- ErrorOr<std::string> TripleOrErr = expectedToErrorOrAndEmitErrors(
- Context, getBitcodeTargetTriple(Buffer.getMemBuffer()));
- if (TripleOrErr)
- TripleStr = *TripleOrErr;
- assert(TMBuilder.TheTriple.str() == TripleStr &&
- "ThinLTO modules with different triple not supported");
- }
-#endif
+
Modules.push_back(Buffer);
}
diff --git a/lib/Linker/IRMover.cpp b/lib/Linker/IRMover.cpp
index ecef1efda1a2..c0af21aa148c 100644
--- a/lib/Linker/IRMover.cpp
+++ b/lib/Linker/IRMover.cpp
@@ -1243,27 +1243,6 @@ Error IRLinker::linkModuleFlagsMetadata() {
return Error::success();
}
-// This function returns true if the triples match.
-static bool triplesMatch(const Triple &T0, const Triple &T1) {
- // If vendor is apple, ignore the version number.
- if (T0.getVendor() == Triple::Apple)
- return T0.getArch() == T1.getArch() && T0.getSubArch() == T1.getSubArch() &&
- T0.getVendor() == T1.getVendor() && T0.getOS() == T1.getOS();
-
- return T0 == T1;
-}
-
-// This function returns the merged triple.
-static std::string mergeTriples(const Triple &SrcTriple,
- const Triple &DstTriple) {
- // If vendor is apple, pick the triple with the larger version number.
- if (SrcTriple.getVendor() == Triple::Apple)
- if (DstTriple.isOSVersionLT(SrcTriple))
- return SrcTriple.str();
-
- return DstTriple.str();
-}
-
Error IRLinker::run() {
// Ensure metadata materialized before value mapping.
if (SrcM->getMaterializer())
@@ -1289,14 +1268,15 @@ Error IRLinker::run() {
Triple SrcTriple(SrcM->getTargetTriple()), DstTriple(DstM.getTargetTriple());
- if (!SrcM->getTargetTriple().empty() && !triplesMatch(SrcTriple, DstTriple))
+ if (!SrcM->getTargetTriple().empty()&&
+ !SrcTriple.isCompatibleWith(DstTriple))
emitWarning("Linking two modules of different target triples: " +
SrcM->getModuleIdentifier() + "' is '" +
SrcM->getTargetTriple() + "' whereas '" +
DstM.getModuleIdentifier() + "' is '" + DstM.getTargetTriple() +
"'\n");
- DstM.setTargetTriple(mergeTriples(SrcTriple, DstTriple));
+ DstM.setTargetTriple(SrcTriple.merge(DstTriple));
// Append the module inline asm string.
if (!IsPerformingImport && !SrcM->getModuleInlineAsm().empty()) {
diff --git a/lib/Object/Binary.cpp b/lib/Object/Binary.cpp
index 2b44c4a82d2c..116af3c917be 100644
--- a/lib/Object/Binary.cpp
+++ b/lib/Object/Binary.cpp
@@ -17,6 +17,7 @@
#include "llvm/Object/Error.h"
#include "llvm/Object/MachOUniversal.h"
#include "llvm/Object/ObjectFile.h"
+#include "llvm/Object/WindowsResource.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ErrorOr.h"
@@ -71,9 +72,10 @@ Expected<std::unique_ptr<Binary>> object::createBinary(MemoryBufferRef Buffer,
return ObjectFile::createSymbolicFile(Buffer, Type, Context);
case sys::fs::file_magic::macho_universal_binary:
return MachOUniversalBinary::create(Buffer);
+ case sys::fs::file_magic::windows_resource:
+ return WindowsResource::createWindowsResource(Buffer);
case sys::fs::file_magic::unknown:
case sys::fs::file_magic::coff_cl_gl_object:
- case sys::fs::file_magic::windows_resource:
// Unrecognized object file format.
return errorCodeToError(object_error::invalid_file_type);
}
diff --git a/lib/Object/CMakeLists.txt b/lib/Object/CMakeLists.txt
index 08365e71c2f6..1d08a9efd8b3 100644
--- a/lib/Object/CMakeLists.txt
+++ b/lib/Object/CMakeLists.txt
@@ -2,6 +2,8 @@ add_llvm_library(LLVMObject
Archive.cpp
ArchiveWriter.cpp
Binary.cpp
+ COFFImportFile.cpp
+ COFFModuleDefinition.cpp
COFFObjectFile.cpp
Decompressor.cpp
ELF.cpp
@@ -18,6 +20,7 @@ add_llvm_library(LLVMObject
SymbolicFile.cpp
SymbolSize.cpp
WasmObjectFile.cpp
+ WindowsResource.cpp
ADDITIONAL_HEADER_DIRS
${LLVM_MAIN_INCLUDE_DIR}/llvm/Object
diff --git a/lib/Object/COFFImportFile.cpp b/lib/Object/COFFImportFile.cpp
new file mode 100644
index 000000000000..37962d84d855
--- /dev/null
+++ b/lib/Object/COFFImportFile.cpp
@@ -0,0 +1,527 @@
+//===- COFFImportFile.cpp - COFF short import 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 defines the writeImportLibrary function.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Object/COFFImportFile.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Object/Archive.h"
+#include "llvm/Object/ArchiveWriter.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Path.h"
+
+#include <cstdint>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+using namespace llvm::COFF;
+using namespace llvm::object;
+using namespace llvm;
+
+namespace llvm {
+namespace object {
+
+static bool is32bit(MachineTypes Machine) {
+ switch (Machine) {
+ default:
+ llvm_unreachable("unsupported machine");
+ case IMAGE_FILE_MACHINE_AMD64:
+ return false;
+ case IMAGE_FILE_MACHINE_ARMNT:
+ case IMAGE_FILE_MACHINE_I386:
+ return true;
+ }
+}
+
+static uint16_t getImgRelRelocation(MachineTypes Machine) {
+ switch (Machine) {
+ default:
+ llvm_unreachable("unsupported machine");
+ case IMAGE_FILE_MACHINE_AMD64:
+ return IMAGE_REL_AMD64_ADDR32NB;
+ case IMAGE_FILE_MACHINE_ARMNT:
+ return IMAGE_REL_ARM_ADDR32NB;
+ case IMAGE_FILE_MACHINE_I386:
+ return IMAGE_REL_I386_DIR32NB;
+ }
+}
+
+template <class T> static void append(std::vector<uint8_t> &B, const T &Data) {
+ size_t S = B.size();
+ B.resize(S + sizeof(T));
+ memcpy(&B[S], &Data, sizeof(T));
+}
+
+static void writeStringTable(std::vector<uint8_t> &B,
+ ArrayRef<const std::string> Strings) {
+ // The COFF string table consists of a 4-byte value which is the size of the
+ // table, including the length field itself. This value is followed by the
+ // string content itself, which is an array of null-terminated C-style
+ // strings. The termination is important as they are referenced to by offset
+ // by the symbol entity in the file format.
+
+ size_t Pos = B.size();
+ size_t Offset = B.size();
+
+ // Skip over the length field, we will fill it in later as we will have
+ // computed the length while emitting the string content itself.
+ Pos += sizeof(uint32_t);
+
+ for (const auto &S : Strings) {
+ B.resize(Pos + S.length() + 1);
+ strcpy(reinterpret_cast<char *>(&B[Pos]), S.c_str());
+ Pos += S.length() + 1;
+ }
+
+ // Backfill the length of the table now that it has been computed.
+ support::ulittle32_t Length(B.size() - Offset);
+ support::endian::write32le(&B[Offset], Length);
+}
+
+static ImportNameType getNameType(StringRef Sym, StringRef ExtName,
+ MachineTypes Machine) {
+ if (Sym != ExtName)
+ return IMPORT_NAME_UNDECORATE;
+ if (Machine == IMAGE_FILE_MACHINE_I386 && Sym.startswith("_"))
+ return IMPORT_NAME_NOPREFIX;
+ return IMPORT_NAME;
+}
+
+static Expected<std::string> replace(StringRef S, StringRef From,
+ StringRef To) {
+ size_t Pos = S.find(From);
+
+ // From and To may be mangled, but substrings in S may not.
+ if (Pos == StringRef::npos && From.startswith("_") && To.startswith("_")) {
+ From = From.substr(1);
+ To = To.substr(1);
+ Pos = S.find(From);
+ }
+
+ if (Pos == StringRef::npos) {
+ return make_error<StringError>(
+ StringRef(Twine(S + ": replacing '" + From +
+ "' with '" + To + "' failed").str()), object_error::parse_failed);
+ }
+
+ return (Twine(S.substr(0, Pos)) + To + S.substr(Pos + From.size())).str();
+}
+
+static const std::string NullImportDescriptorSymbolName =
+ "__NULL_IMPORT_DESCRIPTOR";
+
+namespace {
+// This class constructs various small object files necessary to support linking
+// symbols imported from a DLL. The contents are pretty strictly defined and
+// nearly entirely static. The details of the structures files are defined in
+// WINNT.h and the PE/COFF specification.
+class ObjectFactory {
+ using u16 = support::ulittle16_t;
+ using u32 = support::ulittle32_t;
+ MachineTypes Machine;
+ BumpPtrAllocator Alloc;
+ StringRef DLLName;
+ StringRef Library;
+ std::string ImportDescriptorSymbolName;
+ std::string NullThunkSymbolName;
+
+public:
+ ObjectFactory(StringRef S, MachineTypes M)
+ : Machine(M), DLLName(S), Library(S.drop_back(4)),
+ ImportDescriptorSymbolName(("__IMPORT_DESCRIPTOR_" + Library).str()),
+ NullThunkSymbolName(("\x7f" + Library + "_NULL_THUNK_DATA").str()) {}
+
+ // Creates an Import Descriptor. This is a small object file which contains a
+ // reference to the terminators and contains the library name (entry) for the
+ // import name table. It will force the linker to construct the necessary
+ // structure to import symbols from the DLL.
+ NewArchiveMember createImportDescriptor(std::vector<uint8_t> &Buffer);
+
+ // Creates a NULL import descriptor. This is a small object file whcih
+ // contains a NULL import descriptor. It is used to terminate the imports
+ // from a specific DLL.
+ NewArchiveMember createNullImportDescriptor(std::vector<uint8_t> &Buffer);
+
+ // Create a NULL Thunk Entry. This is a small object file which contains a
+ // NULL Import Address Table entry and a NULL Import Lookup Table Entry. It
+ // is used to terminate the IAT and ILT.
+ NewArchiveMember createNullThunk(std::vector<uint8_t> &Buffer);
+
+ // Create a short import file which is described in PE/COFF spec 7. Import
+ // Library Format.
+ NewArchiveMember createShortImport(StringRef Sym, uint16_t Ordinal,
+ ImportType Type, ImportNameType NameType);
+};
+} // namespace
+
+NewArchiveMember
+ObjectFactory::createImportDescriptor(std::vector<uint8_t> &Buffer) {
+ static const uint32_t NumberOfSections = 2;
+ static const uint32_t NumberOfSymbols = 7;
+ static const uint32_t NumberOfRelocations = 3;
+
+ // COFF Header
+ coff_file_header Header{
+ u16(Machine),
+ u16(NumberOfSections),
+ u32(0),
+ u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) +
+ // .idata$2
+ sizeof(coff_import_directory_table_entry) +
+ NumberOfRelocations * sizeof(coff_relocation) +
+ // .idata$4
+ (DLLName.size() + 1)),
+ u32(NumberOfSymbols),
+ u16(0),
+ u16(is32bit(Machine) ? IMAGE_FILE_32BIT_MACHINE : 0),
+ };
+ append(Buffer, Header);
+
+ // Section Header Table
+ static const coff_section SectionTable[NumberOfSections] = {
+ {{'.', 'i', 'd', 'a', 't', 'a', '$', '2'},
+ u32(0),
+ u32(0),
+ u32(sizeof(coff_import_directory_table_entry)),
+ u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section)),
+ u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) +
+ sizeof(coff_import_directory_table_entry)),
+ u32(0),
+ u16(NumberOfRelocations),
+ u16(0),
+ u32(IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_CNT_INITIALIZED_DATA |
+ IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)},
+ {{'.', 'i', 'd', 'a', 't', 'a', '$', '6'},
+ u32(0),
+ u32(0),
+ u32(DLLName.size() + 1),
+ u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) +
+ sizeof(coff_import_directory_table_entry) +
+ NumberOfRelocations * sizeof(coff_relocation)),
+ u32(0),
+ u32(0),
+ u16(0),
+ u16(0),
+ u32(IMAGE_SCN_ALIGN_2BYTES | IMAGE_SCN_CNT_INITIALIZED_DATA |
+ IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)},
+ };
+ append(Buffer, SectionTable);
+
+ // .idata$2
+ static const coff_import_directory_table_entry ImportDescriptor{
+ u32(0), u32(0), u32(0), u32(0), u32(0),
+ };
+ append(Buffer, ImportDescriptor);
+
+ static const coff_relocation RelocationTable[NumberOfRelocations] = {
+ {u32(offsetof(coff_import_directory_table_entry, NameRVA)), u32(2),
+ u16(getImgRelRelocation(Machine))},
+ {u32(offsetof(coff_import_directory_table_entry, ImportLookupTableRVA)),
+ u32(3), u16(getImgRelRelocation(Machine))},
+ {u32(offsetof(coff_import_directory_table_entry, ImportAddressTableRVA)),
+ u32(4), u16(getImgRelRelocation(Machine))},
+ };
+ append(Buffer, RelocationTable);
+
+ // .idata$6
+ auto S = Buffer.size();
+ Buffer.resize(S + DLLName.size() + 1);
+ memcpy(&Buffer[S], DLLName.data(), DLLName.size());
+ Buffer[S + DLLName.size()] = '\0';
+
+ // Symbol Table
+ coff_symbol16 SymbolTable[NumberOfSymbols] = {
+ {{{0, 0, 0, 0, 0, 0, 0, 0}},
+ u32(0),
+ u16(1),
+ u16(0),
+ IMAGE_SYM_CLASS_EXTERNAL,
+ 0},
+ {{{'.', 'i', 'd', 'a', 't', 'a', '$', '2'}},
+ u32(0),
+ u16(1),
+ u16(0),
+ IMAGE_SYM_CLASS_SECTION,
+ 0},
+ {{{'.', 'i', 'd', 'a', 't', 'a', '$', '6'}},
+ u32(0),
+ u16(2),
+ u16(0),
+ IMAGE_SYM_CLASS_STATIC,
+ 0},
+ {{{'.', 'i', 'd', 'a', 't', 'a', '$', '4'}},
+ u32(0),
+ u16(0),
+ u16(0),
+ IMAGE_SYM_CLASS_SECTION,
+ 0},
+ {{{'.', 'i', 'd', 'a', 't', 'a', '$', '5'}},
+ u32(0),
+ u16(0),
+ u16(0),
+ IMAGE_SYM_CLASS_SECTION,
+ 0},
+ {{{0, 0, 0, 0, 0, 0, 0, 0}},
+ u32(0),
+ u16(0),
+ u16(0),
+ IMAGE_SYM_CLASS_EXTERNAL,
+ 0},
+ {{{0, 0, 0, 0, 0, 0, 0, 0}},
+ u32(0),
+ u16(0),
+ u16(0),
+ IMAGE_SYM_CLASS_EXTERNAL,
+ 0},
+ };
+ reinterpret_cast<StringTableOffset &>(SymbolTable[0].Name).Offset =
+ sizeof(uint32_t);
+ reinterpret_cast<StringTableOffset &>(SymbolTable[5].Name).Offset =
+ sizeof(uint32_t) + ImportDescriptorSymbolName.length() + 1;
+ reinterpret_cast<StringTableOffset &>(SymbolTable[6].Name).Offset =
+ sizeof(uint32_t) + ImportDescriptorSymbolName.length() + 1 +
+ NullImportDescriptorSymbolName.length() + 1;
+ append(Buffer, SymbolTable);
+
+ // String Table
+ writeStringTable(Buffer,
+ {ImportDescriptorSymbolName, NullImportDescriptorSymbolName,
+ NullThunkSymbolName});
+
+ StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};
+ return {MemoryBufferRef(F, DLLName)};
+}
+
+NewArchiveMember
+ObjectFactory::createNullImportDescriptor(std::vector<uint8_t> &Buffer) {
+ static const uint32_t NumberOfSections = 1;
+ static const uint32_t NumberOfSymbols = 1;
+
+ // COFF Header
+ coff_file_header Header{
+ u16(Machine),
+ u16(NumberOfSections),
+ u32(0),
+ u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) +
+ // .idata$3
+ sizeof(coff_import_directory_table_entry)),
+ u32(NumberOfSymbols),
+ u16(0),
+ u16(is32bit(Machine) ? IMAGE_FILE_32BIT_MACHINE : 0),
+ };
+ append(Buffer, Header);
+
+ // Section Header Table
+ static const coff_section SectionTable[NumberOfSections] = {
+ {{'.', 'i', 'd', 'a', 't', 'a', '$', '3'},
+ u32(0),
+ u32(0),
+ u32(sizeof(coff_import_directory_table_entry)),
+ u32(sizeof(coff_file_header) +
+ (NumberOfSections * sizeof(coff_section))),
+ u32(0),
+ u32(0),
+ u16(0),
+ u16(0),
+ u32(IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_CNT_INITIALIZED_DATA |
+ IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)},
+ };
+ append(Buffer, SectionTable);
+
+ // .idata$3
+ static const coff_import_directory_table_entry ImportDescriptor{
+ u32(0), u32(0), u32(0), u32(0), u32(0),
+ };
+ append(Buffer, ImportDescriptor);
+
+ // Symbol Table
+ coff_symbol16 SymbolTable[NumberOfSymbols] = {
+ {{{0, 0, 0, 0, 0, 0, 0, 0}},
+ u32(0),
+ u16(1),
+ u16(0),
+ IMAGE_SYM_CLASS_EXTERNAL,
+ 0},
+ };
+ reinterpret_cast<StringTableOffset &>(SymbolTable[0].Name).Offset =
+ sizeof(uint32_t);
+ append(Buffer, SymbolTable);
+
+ // String Table
+ writeStringTable(Buffer, {NullImportDescriptorSymbolName});
+
+ StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};
+ return {MemoryBufferRef(F, DLLName)};
+}
+
+NewArchiveMember ObjectFactory::createNullThunk(std::vector<uint8_t> &Buffer) {
+ static const uint32_t NumberOfSections = 2;
+ static const uint32_t NumberOfSymbols = 1;
+ uint32_t VASize = is32bit(Machine) ? 4 : 8;
+
+ // COFF Header
+ coff_file_header Header{
+ u16(Machine),
+ u16(NumberOfSections),
+ u32(0),
+ u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) +
+ // .idata$5
+ VASize +
+ // .idata$4
+ VASize),
+ u32(NumberOfSymbols),
+ u16(0),
+ u16(is32bit(Machine) ? IMAGE_FILE_32BIT_MACHINE : 0),
+ };
+ append(Buffer, Header);
+
+ // Section Header Table
+ static const coff_section SectionTable[NumberOfSections] = {
+ {{'.', 'i', 'd', 'a', 't', 'a', '$', '5'},
+ u32(0),
+ u32(0),
+ u32(VASize),
+ u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section)),
+ u32(0),
+ u32(0),
+ u16(0),
+ u16(0),
+ u32((is32bit(Machine) ? IMAGE_SCN_ALIGN_4BYTES
+ : IMAGE_SCN_ALIGN_8BYTES) |
+ IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |
+ IMAGE_SCN_MEM_WRITE)},
+ {{'.', 'i', 'd', 'a', 't', 'a', '$', '4'},
+ u32(0),
+ u32(0),
+ u32(VASize),
+ u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) +
+ VASize),
+ u32(0),
+ u32(0),
+ u16(0),
+ u16(0),
+ u32((is32bit(Machine) ? IMAGE_SCN_ALIGN_4BYTES
+ : IMAGE_SCN_ALIGN_8BYTES) |
+ IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |
+ IMAGE_SCN_MEM_WRITE)},
+ };
+ append(Buffer, SectionTable);
+
+ // .idata$5, ILT
+ append(Buffer, u32(0));
+ if (!is32bit(Machine))
+ append(Buffer, u32(0));
+
+ // .idata$4, IAT
+ append(Buffer, u32(0));
+ if (!is32bit(Machine))
+ append(Buffer, u32(0));
+
+ // Symbol Table
+ coff_symbol16 SymbolTable[NumberOfSymbols] = {
+ {{{0, 0, 0, 0, 0, 0, 0, 0}},
+ u32(0),
+ u16(1),
+ u16(0),
+ IMAGE_SYM_CLASS_EXTERNAL,
+ 0},
+ };
+ reinterpret_cast<StringTableOffset &>(SymbolTable[0].Name).Offset =
+ sizeof(uint32_t);
+ append(Buffer, SymbolTable);
+
+ // String Table
+ writeStringTable(Buffer, {NullThunkSymbolName});
+
+ StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};
+ return {MemoryBufferRef{F, DLLName}};
+}
+
+NewArchiveMember ObjectFactory::createShortImport(StringRef Sym,
+ uint16_t Ordinal,
+ ImportType ImportType,
+ ImportNameType NameType) {
+ size_t ImpSize = DLLName.size() + Sym.size() + 2; // +2 for NULs
+ size_t Size = sizeof(coff_import_header) + ImpSize;
+ char *Buf = Alloc.Allocate<char>(Size);
+ memset(Buf, 0, Size);
+ char *P = Buf;
+
+ // Write short import library.
+ auto *Imp = reinterpret_cast<coff_import_header *>(P);
+ P += sizeof(*Imp);
+ Imp->Sig2 = 0xFFFF;
+ Imp->Machine = Machine;
+ Imp->SizeOfData = ImpSize;
+ if (Ordinal > 0)
+ Imp->OrdinalHint = Ordinal;
+ Imp->TypeInfo = (NameType << 2) | ImportType;
+
+ // Write symbol name and DLL name.
+ memcpy(P, Sym.data(), Sym.size());
+ P += Sym.size() + 1;
+ memcpy(P, DLLName.data(), DLLName.size());
+
+ return {MemoryBufferRef(StringRef(Buf, Size), DLLName)};
+}
+
+std::error_code writeImportLibrary(StringRef DLLName, StringRef Path,
+ ArrayRef<COFFShortExport> Exports,
+ MachineTypes Machine) {
+
+ std::vector<NewArchiveMember> Members;
+ ObjectFactory OF(llvm::sys::path::filename(DLLName), Machine);
+
+ std::vector<uint8_t> ImportDescriptor;
+ Members.push_back(OF.createImportDescriptor(ImportDescriptor));
+
+ std::vector<uint8_t> NullImportDescriptor;
+ Members.push_back(OF.createNullImportDescriptor(NullImportDescriptor));
+
+ std::vector<uint8_t> NullThunk;
+ Members.push_back(OF.createNullThunk(NullThunk));
+
+ for (COFFShortExport E : Exports) {
+ if (E.Private)
+ continue;
+
+ ImportType ImportType = IMPORT_CODE;
+ if (E.Data)
+ ImportType = IMPORT_DATA;
+ if (E.Constant)
+ ImportType = IMPORT_CONST;
+
+ StringRef SymbolName = E.isWeak() ? E.ExtName : E.Name;
+ ImportNameType NameType = getNameType(SymbolName, E.Name, Machine);
+ Expected<std::string> Name = E.ExtName.empty()
+ ? SymbolName
+ : replace(SymbolName, E.Name, E.ExtName);
+
+ if (!Name) {
+ return errorToErrorCode(Name.takeError());
+ }
+
+ Members.push_back(
+ OF.createShortImport(*Name, E.Ordinal, ImportType, NameType));
+ }
+
+ std::pair<StringRef, std::error_code> Result =
+ writeArchive(Path, Members, /*WriteSymtab*/ true, object::Archive::K_GNU,
+ /*Deterministic*/ true, /*Thin*/ false);
+
+ return Result.second;
+}
+
+} // namespace object
+} // namespace llvm
diff --git a/lib/Object/COFFModuleDefinition.cpp b/lib/Object/COFFModuleDefinition.cpp
new file mode 100644
index 000000000000..0d69cb6b709c
--- /dev/null
+++ b/lib/Object/COFFModuleDefinition.cpp
@@ -0,0 +1,319 @@
+//===--- COFFModuleDefinition.cpp - Simple DEF parser ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Windows-specific.
+// A parser for the module-definition file (.def file).
+//
+// The format of module-definition files are described in this document:
+// https://msdn.microsoft.com/en-us/library/28d6s79h.aspx
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Object/COFFModuleDefinition.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Object/COFFImportFile.h"
+#include "llvm/Object/Error.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm::COFF;
+using namespace llvm;
+
+namespace llvm {
+namespace object {
+
+enum Kind {
+ Unknown,
+ Eof,
+ Identifier,
+ Comma,
+ Equal,
+ KwBase,
+ KwConstant,
+ KwData,
+ KwExports,
+ KwHeapsize,
+ KwLibrary,
+ KwName,
+ KwNoname,
+ KwPrivate,
+ KwStacksize,
+ KwVersion,
+};
+
+struct Token {
+ explicit Token(Kind T = Unknown, StringRef S = "") : K(T), Value(S) {}
+ Kind K;
+ StringRef Value;
+};
+
+static bool isDecorated(StringRef Sym) {
+ return Sym.startswith("_") || Sym.startswith("@") || Sym.startswith("?");
+}
+
+static Error createError(const Twine &Err) {
+ return make_error<StringError>(StringRef(Err.str()),
+ object_error::parse_failed);
+}
+
+class Lexer {
+public:
+ Lexer(StringRef S) : Buf(S) {}
+
+ Token lex() {
+ Buf = Buf.trim();
+ if (Buf.empty())
+ return Token(Eof);
+
+ switch (Buf[0]) {
+ case '\0':
+ return Token(Eof);
+ case ';': {
+ size_t End = Buf.find('\n');
+ Buf = (End == Buf.npos) ? "" : Buf.drop_front(End);
+ return lex();
+ }
+ case '=':
+ Buf = Buf.drop_front();
+ return Token(Equal, "=");
+ case ',':
+ Buf = Buf.drop_front();
+ return Token(Comma, ",");
+ case '"': {
+ StringRef S;
+ std::tie(S, Buf) = Buf.substr(1).split('"');
+ return Token(Identifier, S);
+ }
+ default: {
+ size_t End = Buf.find_first_of("=,\r\n \t\v");
+ StringRef Word = Buf.substr(0, End);
+ Kind K = llvm::StringSwitch<Kind>(Word)
+ .Case("BASE", KwBase)
+ .Case("CONSTANT", KwConstant)
+ .Case("DATA", KwData)
+ .Case("EXPORTS", KwExports)
+ .Case("HEAPSIZE", KwHeapsize)
+ .Case("LIBRARY", KwLibrary)
+ .Case("NAME", KwName)
+ .Case("NONAME", KwNoname)
+ .Case("PRIVATE", KwPrivate)
+ .Case("STACKSIZE", KwStacksize)
+ .Case("VERSION", KwVersion)
+ .Default(Identifier);
+ Buf = (End == Buf.npos) ? "" : Buf.drop_front(End);
+ return Token(K, Word);
+ }
+ }
+ }
+
+private:
+ StringRef Buf;
+};
+
+class Parser {
+public:
+ explicit Parser(StringRef S, MachineTypes M) : Lex(S), Machine(M) {}
+
+ Expected<COFFModuleDefinition> parse() {
+ do {
+ if (Error Err = parseOne())
+ return std::move(Err);
+ } while (Tok.K != Eof);
+ return Info;
+ }
+
+private:
+ void read() {
+ if (Stack.empty()) {
+ Tok = Lex.lex();
+ return;
+ }
+ Tok = Stack.back();
+ Stack.pop_back();
+ }
+
+ Error readAsInt(uint64_t *I) {
+ read();
+ if (Tok.K != Identifier || Tok.Value.getAsInteger(10, *I))
+ return createError("integer expected");
+ return Error::success();
+ }
+
+ Error expect(Kind Expected, StringRef Msg) {
+ read();
+ if (Tok.K != Expected)
+ return createError(Msg);
+ return Error::success();
+ }
+
+ void unget() { Stack.push_back(Tok); }
+
+ Error parseOne() {
+ read();
+ switch (Tok.K) {
+ case Eof:
+ return Error::success();
+ case KwExports:
+ for (;;) {
+ read();
+ if (Tok.K != Identifier) {
+ unget();
+ return Error::success();
+ }
+ if (Error Err = parseExport())
+ return Err;
+ }
+ case KwHeapsize:
+ return parseNumbers(&Info.HeapReserve, &Info.HeapCommit);
+ case KwStacksize:
+ return parseNumbers(&Info.StackReserve, &Info.StackCommit);
+ case KwLibrary:
+ case KwName: {
+ bool IsDll = Tok.K == KwLibrary; // Check before parseName.
+ std::string Name;
+ if (Error Err = parseName(&Name, &Info.ImageBase))
+ return Err;
+ // Append the appropriate file extension if not already present.
+ StringRef Ext = IsDll ? ".dll" : ".exe";
+ if (!StringRef(Name).endswith_lower(Ext))
+ Name += Ext;
+
+ // Set the output file, but don't override /out if it was already passed.
+ if (Info.OutputFile.empty())
+ Info.OutputFile = Name;
+ return Error::success();
+ }
+ case KwVersion:
+ return parseVersion(&Info.MajorImageVersion, &Info.MinorImageVersion);
+ default:
+ return createError("unknown directive: " + Tok.Value);
+ }
+ }
+
+ Error parseExport() {
+ COFFShortExport E;
+ E.Name = Tok.Value;
+ read();
+ if (Tok.K == Equal) {
+ read();
+ if (Tok.K != Identifier)
+ return createError("identifier expected, but got " + Tok.Value);
+ E.ExtName = E.Name;
+ E.Name = Tok.Value;
+ } else {
+ unget();
+ }
+
+ if (Machine == IMAGE_FILE_MACHINE_I386) {
+ if (!isDecorated(E.Name))
+ E.Name = (std::string("_").append(E.Name));
+ if (!E.ExtName.empty() && !isDecorated(E.ExtName))
+ E.ExtName = (std::string("_").append(E.ExtName));
+ }
+
+ for (;;) {
+ read();
+ if (Tok.K == Identifier && Tok.Value[0] == '@') {
+ Tok.Value.drop_front().getAsInteger(10, E.Ordinal);
+ read();
+ if (Tok.K == KwNoname) {
+ E.Noname = true;
+ } else {
+ unget();
+ }
+ continue;
+ }
+ if (Tok.K == KwData) {
+ E.Data = true;
+ continue;
+ }
+ if (Tok.K == KwConstant) {
+ E.Constant = true;
+ continue;
+ }
+ if (Tok.K == KwPrivate) {
+ E.Private = true;
+ continue;
+ }
+ unget();
+ Info.Exports.push_back(E);
+ return Error::success();
+ }
+ }
+
+ // HEAPSIZE/STACKSIZE reserve[,commit]
+ Error parseNumbers(uint64_t *Reserve, uint64_t *Commit) {
+ if (Error Err = readAsInt(Reserve))
+ return Err;
+ read();
+ if (Tok.K != Comma) {
+ unget();
+ Commit = nullptr;
+ return Error::success();
+ }
+ if (Error Err = readAsInt(Commit))
+ return Err;
+ return Error::success();
+ }
+
+ // NAME outputPath [BASE=address]
+ Error parseName(std::string *Out, uint64_t *Baseaddr) {
+ read();
+ if (Tok.K == Identifier) {
+ *Out = Tok.Value;
+ } else {
+ *Out = "";
+ unget();
+ return Error::success();
+ }
+ read();
+ if (Tok.K == KwBase) {
+ if (Error Err = expect(Equal, "'=' expected"))
+ return Err;
+ if (Error Err = readAsInt(Baseaddr))
+ return Err;
+ } else {
+ unget();
+ *Baseaddr = 0;
+ }
+ return Error::success();
+ }
+
+ // VERSION major[.minor]
+ Error parseVersion(uint32_t *Major, uint32_t *Minor) {
+ read();
+ if (Tok.K != Identifier)
+ return createError("identifier expected, but got " + Tok.Value);
+ StringRef V1, V2;
+ std::tie(V1, V2) = Tok.Value.split('.');
+ if (V1.getAsInteger(10, *Major))
+ return createError("integer expected, but got " + Tok.Value);
+ if (V2.empty())
+ *Minor = 0;
+ else if (V2.getAsInteger(10, *Minor))
+ return createError("integer expected, but got " + Tok.Value);
+ return Error::success();
+ }
+
+ Lexer Lex;
+ Token Tok;
+ std::vector<Token> Stack;
+ MachineTypes Machine;
+ COFFModuleDefinition Info;
+};
+
+Expected<COFFModuleDefinition> parseCOFFModuleDefinition(MemoryBufferRef MB,
+ MachineTypes Machine) {
+ return Parser(MB.getBuffer(), Machine).parse();
+}
+
+} // namespace object
+} // namespace llvm
diff --git a/lib/Object/Decompressor.cpp b/lib/Object/Decompressor.cpp
index 0be602b1fc1a..89d199a3f3f6 100644
--- a/lib/Object/Decompressor.cpp
+++ b/lib/Object/Decompressor.cpp
@@ -88,11 +88,6 @@ bool Decompressor::isCompressedELFSection(uint64_t Flags, StringRef Name) {
return (Flags & ELF::SHF_COMPRESSED) || isGnuStyle(Name);
}
-Error Decompressor::decompress(SmallString<32> &Out) {
- Out.resize(DecompressedSize);
- return decompress({Out.data(), (size_t)DecompressedSize});
-}
-
Error Decompressor::decompress(MutableArrayRef<char> Buffer) {
size_t Size = Buffer.size();
return zlib::uncompress(SectionData, Buffer.data(), Size);
diff --git a/lib/Object/WindowsResource.cpp b/lib/Object/WindowsResource.cpp
new file mode 100644
index 000000000000..b52563469094
--- /dev/null
+++ b/lib/Object/WindowsResource.cpp
@@ -0,0 +1,90 @@
+//===-- WindowsResource.cpp -------------------------------------*- 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 .res file class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Object/WindowsResource.h"
+#include "llvm/Object/Error.h"
+#include <system_error>
+
+namespace llvm {
+namespace object {
+
+static const size_t ResourceMagicSize = 16;
+
+static const size_t NullEntrySize = 16;
+
+#define RETURN_IF_ERROR(X) \
+ if (auto EC = X) \
+ return EC;
+
+WindowsResource::WindowsResource(MemoryBufferRef Source)
+ : Binary(Binary::ID_WinRes, Source) {
+ size_t LeadingSize = ResourceMagicSize + NullEntrySize;
+ BBS = BinaryByteStream(Data.getBuffer().drop_front(LeadingSize),
+ support::little);
+}
+
+WindowsResource::~WindowsResource() = default;
+
+Expected<std::unique_ptr<WindowsResource>>
+WindowsResource::createWindowsResource(MemoryBufferRef Source) {
+ if (Source.getBufferSize() < ResourceMagicSize + NullEntrySize)
+ return make_error<GenericBinaryError>(
+ "File too small to be a resource file",
+ object_error::invalid_file_type);
+ std::unique_ptr<WindowsResource> Ret(new WindowsResource(Source));
+ return std::move(Ret);
+}
+
+Expected<ResourceEntryRef> WindowsResource::getHeadEntry() {
+ Error Err = Error::success();
+ auto Ref = ResourceEntryRef(BinaryStreamRef(BBS), this, Err);
+ if (Err)
+ return std::move(Err);
+ return Ref;
+}
+
+ResourceEntryRef::ResourceEntryRef(BinaryStreamRef Ref,
+ const WindowsResource *Owner, Error &Err)
+ : Reader(Ref), OwningRes(Owner) {
+ if (loadNext())
+ Err = make_error<GenericBinaryError>("Could not read first entry.",
+ object_error::unexpected_eof);
+}
+
+Error ResourceEntryRef::moveNext(bool &End) {
+ // Reached end of all the entries.
+ if (Reader.bytesRemaining() == 0) {
+ End = true;
+ return Error::success();
+ }
+ RETURN_IF_ERROR(loadNext());
+
+ return Error::success();
+}
+
+Error ResourceEntryRef::loadNext() {
+ uint32_t DataSize;
+ RETURN_IF_ERROR(Reader.readInteger(DataSize));
+ uint32_t HeaderSize;
+ RETURN_IF_ERROR(Reader.readInteger(HeaderSize));
+ // The data and header size ints are themselves part of the header, so we must
+ // subtract them from the size.
+ RETURN_IF_ERROR(
+ Reader.readStreamRef(HeaderBytes, HeaderSize - 2 * sizeof(uint32_t)));
+ RETURN_IF_ERROR(Reader.readStreamRef(DataBytes, DataSize));
+ RETURN_IF_ERROR(Reader.padToAlignment(sizeof(uint32_t)));
+ return Error::success();
+}
+
+} // namespace object
+} // namespace llvm
diff --git a/lib/Passes/PassBuilder.cpp b/lib/Passes/PassBuilder.cpp
index 7076e751071d..6ece7965ce64 100644
--- a/lib/Passes/PassBuilder.cpp
+++ b/lib/Passes/PassBuilder.cpp
@@ -150,6 +150,10 @@ using namespace llvm;
static cl::opt<unsigned> MaxDevirtIterations("pm-max-devirt-iterations",
cl::ReallyHidden, cl::init(4));
+static cl::opt<bool>
+ RunPartialInlining("enable-npm-partial-inlining", cl::init(false),
+ cl::Hidden, cl::ZeroOrMore,
+ cl::desc("Run Partial inlinining pass"));
static cl::opt<bool> EnableGVNHoist(
"enable-npm-gvn-hoist", cl::init(false), cl::Hidden,
@@ -552,6 +556,11 @@ PassBuilder::buildPerModuleDefaultPipeline(OptimizationLevel Level,
// At this point, we expect to have canonical and simple IR which we begin
// *optimizing* for efficient execution going forward.
+ // Run partial inlining pass to partially inline functions that have
+ // large bodies.
+ if (RunPartialInlining)
+ MPM.addPass(PartialInlinerPass());
+
// Eliminate externally available functions now that inlining is over -- we
// won't emit these anyways.
MPM.addPass(EliminateAvailableExternallyPass());
diff --git a/lib/Support/APInt.cpp b/lib/Support/APInt.cpp
index 17144522db82..2a916b14bc22 100644
--- a/lib/Support/APInt.cpp
+++ b/lib/Support/APInt.cpp
@@ -1398,8 +1398,8 @@ static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r,
DEBUG(dbgs() << '\n');
}
-void APInt::divide(const APInt &LHS, unsigned lhsWords, const APInt &RHS,
- unsigned rhsWords, APInt *Quotient, APInt *Remainder) {
+void APInt::divide(const WordType *LHS, unsigned lhsWords, const WordType *RHS,
+ unsigned rhsWords, WordType *Quotient, WordType *Remainder) {
assert(lhsWords >= rhsWords && "Fractional result");
// First, compose the values into an array of 32-bit words instead of
@@ -1436,7 +1436,7 @@ void APInt::divide(const APInt &LHS, unsigned lhsWords, const APInt &RHS,
// Initialize the dividend
memset(U, 0, (m+n+1)*sizeof(uint32_t));
for (unsigned i = 0; i < lhsWords; ++i) {
- uint64_t tmp = LHS.getRawData()[i];
+ uint64_t tmp = LHS[i];
U[i * 2] = Lo_32(tmp);
U[i * 2 + 1] = Hi_32(tmp);
}
@@ -1445,7 +1445,7 @@ void APInt::divide(const APInt &LHS, unsigned lhsWords, const APInt &RHS,
// Initialize the divisor
memset(V, 0, (n)*sizeof(uint32_t));
for (unsigned i = 0; i < rhsWords; ++i) {
- uint64_t tmp = RHS.getRawData()[i];
+ uint64_t tmp = RHS[i];
V[i * 2] = Lo_32(tmp);
V[i * 2 + 1] = Hi_32(tmp);
}
@@ -1502,48 +1502,14 @@ void APInt::divide(const APInt &LHS, unsigned lhsWords, const APInt &RHS,
// If the caller wants the quotient
if (Quotient) {
- // Set up the Quotient value's memory.
- Quotient->reallocate(LHS.BitWidth);
- // Clear out any previous bits.
- Quotient->clearAllBits();
-
- // The quotient is in Q. Reconstitute the quotient into Quotient's low
- // order words.
- // This case is currently dead as all users of divide() handle trivial cases
- // earlier.
- if (lhsWords == 1) {
- uint64_t tmp = Make_64(Q[1], Q[0]);
- if (Quotient->isSingleWord())
- Quotient->U.VAL = tmp;
- else
- Quotient->U.pVal[0] = tmp;
- } else {
- assert(!Quotient->isSingleWord() && "Quotient APInt not large enough");
- for (unsigned i = 0; i < lhsWords; ++i)
- Quotient->U.pVal[i] = Make_64(Q[i*2+1], Q[i*2]);
- }
+ for (unsigned i = 0; i < lhsWords; ++i)
+ Quotient[i] = Make_64(Q[i*2+1], Q[i*2]);
}
// If the caller wants the remainder
if (Remainder) {
- // Set up the Remainder value's memory.
- Remainder->reallocate(RHS.BitWidth);
- // Clear out any previous bits.
- Remainder->clearAllBits();
-
- // The remainder is in R. Reconstitute the remainder into Remainder's low
- // order words.
- if (rhsWords == 1) {
- uint64_t tmp = Make_64(R[1], R[0]);
- if (Remainder->isSingleWord())
- Remainder->U.VAL = tmp;
- else
- Remainder->U.pVal[0] = tmp;
- } else {
- assert(!Remainder->isSingleWord() && "Remainder APInt not large enough");
- for (unsigned i = 0; i < rhsWords; ++i)
- Remainder->U.pVal[i] = Make_64(R[i*2+1], R[i*2]);
- }
+ for (unsigned i = 0; i < rhsWords; ++i)
+ Remainder[i] = Make_64(R[i*2+1], R[i*2]);
}
// Clean up the memory we allocated.
@@ -1555,7 +1521,7 @@ void APInt::divide(const APInt &LHS, unsigned lhsWords, const APInt &RHS,
}
}
-APInt APInt::udiv(const APInt& RHS) const {
+APInt APInt::udiv(const APInt &RHS) const {
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
// First, deal with the easy case
@@ -1588,8 +1554,41 @@ APInt APInt::udiv(const APInt& RHS) const {
return APInt(BitWidth, this->U.pVal[0] / RHS.U.pVal[0]);
// We have to compute it the hard way. Invoke the Knuth divide algorithm.
- APInt Quotient; // to hold result.
- divide(*this, lhsWords, RHS, rhsWords, &Quotient, nullptr);
+ APInt Quotient(BitWidth, 0); // to hold result.
+ divide(U.pVal, lhsWords, RHS.U.pVal, rhsWords, Quotient.U.pVal, nullptr);
+ return Quotient;
+}
+
+APInt APInt::udiv(uint64_t RHS) const {
+ assert(RHS != 0 && "Divide by zero?");
+
+ // First, deal with the easy case
+ if (isSingleWord())
+ return APInt(BitWidth, U.VAL / RHS);
+
+ // Get some facts about the LHS words.
+ unsigned lhsWords = getNumWords(getActiveBits());
+
+ // Deal with some degenerate cases
+ if (!lhsWords)
+ // 0 / X ===> 0
+ return APInt(BitWidth, 0);
+ if (RHS == 1)
+ // X / 1 ===> X
+ return *this;
+ if (this->ult(RHS))
+ // X / Y ===> 0, iff X < Y
+ return APInt(BitWidth, 0);
+ if (*this == RHS)
+ // X / X ===> 1
+ return APInt(BitWidth, 1);
+ if (lhsWords == 1) // rhsWords is 1 if lhsWords is 1.
+ // All high words are zero, just use native divide
+ return APInt(BitWidth, this->U.pVal[0] / RHS);
+
+ // We have to compute it the hard way. Invoke the Knuth divide algorithm.
+ APInt Quotient(BitWidth, 0); // to hold result.
+ divide(U.pVal, lhsWords, &RHS, 1, Quotient.U.pVal, nullptr);
return Quotient;
}
@@ -1604,7 +1603,18 @@ APInt APInt::sdiv(const APInt &RHS) const {
return this->udiv(RHS);
}
-APInt APInt::urem(const APInt& RHS) const {
+APInt APInt::sdiv(int64_t RHS) const {
+ if (isNegative()) {
+ if (RHS < 0)
+ return (-(*this)).udiv(-RHS);
+ return -((-(*this)).udiv(RHS));
+ }
+ if (RHS < 0)
+ return -(this->udiv(-RHS));
+ return this->udiv(RHS);
+}
+
+APInt APInt::urem(const APInt &RHS) const {
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
if (isSingleWord()) {
assert(RHS.U.VAL != 0 && "Remainder by zero?");
@@ -1637,8 +1647,40 @@ APInt APInt::urem(const APInt& RHS) const {
return APInt(BitWidth, U.pVal[0] % RHS.U.pVal[0]);
// We have to compute it the hard way. Invoke the Knuth divide algorithm.
- APInt Remainder;
- divide(*this, lhsWords, RHS, rhsWords, nullptr, &Remainder);
+ APInt Remainder(BitWidth, 0);
+ divide(U.pVal, lhsWords, RHS.U.pVal, rhsWords, nullptr, Remainder.U.pVal);
+ return Remainder;
+}
+
+uint64_t APInt::urem(uint64_t RHS) const {
+ assert(RHS != 0 && "Remainder by zero?");
+
+ if (isSingleWord())
+ return U.VAL % RHS;
+
+ // Get some facts about the LHS
+ unsigned lhsWords = getNumWords(getActiveBits());
+
+ // Check the degenerate cases
+ if (lhsWords == 0)
+ // 0 % Y ===> 0
+ return 0;
+ if (RHS == 1)
+ // X % 1 ===> 0
+ return 0;
+ if (this->ult(RHS))
+ // X % Y ===> X, iff X < Y
+ return getZExtValue();
+ if (*this == RHS)
+ // X % X == 0;
+ return 0;
+ if (lhsWords == 1)
+ // All high words are zero, just use native remainder
+ return U.pVal[0] % RHS;
+
+ // We have to compute it the hard way. Invoke the Knuth divide algorithm.
+ uint64_t Remainder;
+ divide(U.pVal, lhsWords, &RHS, 1, nullptr, &Remainder);
return Remainder;
}
@@ -1653,6 +1695,17 @@ APInt APInt::srem(const APInt &RHS) const {
return this->urem(RHS);
}
+int64_t APInt::srem(int64_t RHS) const {
+ if (isNegative()) {
+ if (RHS < 0)
+ return -((-(*this)).urem(-RHS));
+ return -((-(*this)).urem(RHS));
+ }
+ if (RHS < 0)
+ return this->urem(-RHS);
+ return this->urem(RHS);
+}
+
void APInt::udivrem(const APInt &LHS, const APInt &RHS,
APInt &Quotient, APInt &Remainder) {
assert(LHS.BitWidth == RHS.BitWidth && "Bit widths must be the same");
@@ -1698,20 +1751,90 @@ void APInt::udivrem(const APInt &LHS, const APInt &RHS,
return;
}
+ // Make sure there is enough space to hold the results.
+ // NOTE: This assumes that reallocate won't affect any bits if it doesn't
+ // change the size. This is necessary if Quotient or Remainder is aliased
+ // with LHS or RHS.
+ Quotient.reallocate(BitWidth);
+ Remainder.reallocate(BitWidth);
+
if (lhsWords == 1) { // rhsWords is 1 if lhsWords is 1.
// There is only one word to consider so use the native versions.
uint64_t lhsValue = LHS.U.pVal[0];
uint64_t rhsValue = RHS.U.pVal[0];
- // Make sure there is enough space to hold the results.
- Quotient.reallocate(BitWidth);
- Remainder.reallocate(BitWidth);
Quotient = lhsValue / rhsValue;
Remainder = lhsValue % rhsValue;
return;
}
// Okay, lets do it the long way
- divide(LHS, lhsWords, RHS, rhsWords, &Quotient, &Remainder);
+ divide(LHS.U.pVal, lhsWords, RHS.U.pVal, rhsWords, Quotient.U.pVal,
+ Remainder.U.pVal);
+ // Clear the rest of the Quotient and Remainder.
+ std::memset(Quotient.U.pVal + lhsWords, 0,
+ (getNumWords(BitWidth) - lhsWords) * APINT_WORD_SIZE);
+ std::memset(Remainder.U.pVal + rhsWords, 0,
+ (getNumWords(BitWidth) - rhsWords) * APINT_WORD_SIZE);
+}
+
+void APInt::udivrem(const APInt &LHS, uint64_t RHS, APInt &Quotient,
+ uint64_t &Remainder) {
+ assert(RHS != 0 && "Divide by zero?");
+ unsigned BitWidth = LHS.BitWidth;
+
+ // First, deal with the easy case
+ if (LHS.isSingleWord()) {
+ uint64_t QuotVal = LHS.U.VAL / RHS;
+ Remainder = LHS.U.VAL % RHS;
+ Quotient = APInt(BitWidth, QuotVal);
+ return;
+ }
+
+ // Get some size facts about the dividend and divisor
+ unsigned lhsWords = getNumWords(LHS.getActiveBits());
+
+ // Check the degenerate cases
+ if (lhsWords == 0) {
+ Quotient = 0; // 0 / Y ===> 0
+ Remainder = 0; // 0 % Y ===> 0
+ return;
+ }
+
+ if (RHS == 1) {
+ Quotient = LHS; // X / 1 ===> X
+ Remainder = 0; // X % 1 ===> 0
+ }
+
+ if (LHS.ult(RHS)) {
+ Remainder = LHS.getZExtValue(); // X % Y ===> X, iff X < Y
+ Quotient = 0; // X / Y ===> 0, iff X < Y
+ return;
+ }
+
+ if (LHS == RHS) {
+ Quotient = 1; // X / X ===> 1
+ Remainder = 0; // X % X ===> 0;
+ return;
+ }
+
+ // Make sure there is enough space to hold the results.
+ // NOTE: This assumes that reallocate won't affect any bits if it doesn't
+ // change the size. This is necessary if Quotient is aliased with LHS.
+ Quotient.reallocate(BitWidth);
+
+ if (lhsWords == 1) { // rhsWords is 1 if lhsWords is 1.
+ // There is only one word to consider so use the native versions.
+ uint64_t lhsValue = LHS.U.pVal[0];
+ Quotient = lhsValue / RHS;
+ Remainder = lhsValue % RHS;
+ return;
+ }
+
+ // Okay, lets do it the long way
+ divide(LHS.U.pVal, lhsWords, &RHS, 1, Quotient.U.pVal, &Remainder);
+ // Clear the rest of the Quotient.
+ std::memset(Quotient.U.pVal + lhsWords, 0,
+ (getNumWords(BitWidth) - lhsWords) * APINT_WORD_SIZE);
}
void APInt::sdivrem(const APInt &LHS, const APInt &RHS,
@@ -1732,6 +1855,26 @@ void APInt::sdivrem(const APInt &LHS, const APInt &RHS,
}
}
+void APInt::sdivrem(const APInt &LHS, int64_t RHS,
+ APInt &Quotient, int64_t &Remainder) {
+ uint64_t R = Remainder;
+ if (LHS.isNegative()) {
+ if (RHS < 0)
+ APInt::udivrem(-LHS, -RHS, Quotient, R);
+ else {
+ APInt::udivrem(-LHS, RHS, Quotient, R);
+ Quotient.negate();
+ }
+ R = -R;
+ } else if (RHS < 0) {
+ APInt::udivrem(LHS, -RHS, Quotient, R);
+ Quotient.negate();
+ } else {
+ APInt::udivrem(LHS, RHS, Quotient, R);
+ }
+ Remainder = R;
+}
+
APInt APInt::sadd_ov(const APInt &RHS, bool &Overflow) const {
APInt Res = *this+RHS;
Overflow = isNonNegative() == RHS.isNonNegative() &&
@@ -1962,11 +2105,9 @@ void APInt::toString(SmallVectorImpl<char> &Str, unsigned Radix,
Tmp.lshrInPlace(ShiftAmt);
}
} else {
- APInt divisor(Tmp.getBitWidth(), Radix);
- APInt APdigit;
while (Tmp.getBoolValue()) {
- udivrem(Tmp, divisor, Tmp, APdigit);
- unsigned Digit = (unsigned)APdigit.getZExtValue();
+ uint64_t Digit;
+ udivrem(Tmp, Radix, Tmp, Digit);
assert(Digit < Radix && "divide failed");
Str.push_back(Digits[Digit]);
}
diff --git a/lib/Support/BinaryStreamReader.cpp b/lib/Support/BinaryStreamReader.cpp
index 702d98770e05..5c277448a765 100644
--- a/lib/Support/BinaryStreamReader.cpp
+++ b/lib/Support/BinaryStreamReader.cpp
@@ -13,9 +13,18 @@
#include "llvm/Support/BinaryStreamRef.h"
using namespace llvm;
+using endianness = llvm::support::endianness;
-BinaryStreamReader::BinaryStreamReader(BinaryStreamRef S)
- : Stream(S), Offset(0) {}
+BinaryStreamReader::BinaryStreamReader(BinaryStreamRef Ref) : Stream(Ref) {}
+
+BinaryStreamReader::BinaryStreamReader(BinaryStream &Stream) : Stream(Stream) {}
+
+BinaryStreamReader::BinaryStreamReader(ArrayRef<uint8_t> Data,
+ endianness Endian)
+ : Stream(Data, Endian) {}
+
+BinaryStreamReader::BinaryStreamReader(StringRef Data, endianness Endian)
+ : Stream(Data, Endian) {}
Error BinaryStreamReader::readLongestContiguousChunk(
ArrayRef<uint8_t> &Buffer) {
@@ -86,6 +95,11 @@ Error BinaryStreamReader::skip(uint32_t Amount) {
return Error::success();
}
+Error BinaryStreamReader::padToAlignment(uint32_t Align) {
+ uint32_t NewOffset = alignTo(Offset, Align);
+ return skip(NewOffset - Offset);
+}
+
uint8_t BinaryStreamReader::peek() const {
ArrayRef<uint8_t> Buffer;
auto EC = Stream.readBytes(Offset, 1, Buffer);
diff --git a/lib/Support/BinaryStreamRef.cpp b/lib/Support/BinaryStreamRef.cpp
new file mode 100644
index 000000000000..fe9a8171e146
--- /dev/null
+++ b/lib/Support/BinaryStreamRef.cpp
@@ -0,0 +1,137 @@
+//===- BinaryStreamRef.cpp - ----------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/BinaryStreamRef.h"
+#include "llvm/Support/BinaryByteStream.h"
+
+using namespace llvm;
+using namespace llvm::support;
+
+namespace {
+
+class ArrayRefImpl : public BinaryStream {
+public:
+ ArrayRefImpl(ArrayRef<uint8_t> Data, endianness Endian) : BBS(Data, Endian) {}
+
+ llvm::support::endianness getEndian() const override {
+ return BBS.getEndian();
+ }
+ Error readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) override {
+ return BBS.readBytes(Offset, Size, Buffer);
+ }
+ Error readLongestContiguousChunk(uint32_t Offset,
+ ArrayRef<uint8_t> &Buffer) override {
+ return BBS.readLongestContiguousChunk(Offset, Buffer);
+ }
+ uint32_t getLength() override { return BBS.getLength(); }
+
+private:
+ BinaryByteStream BBS;
+};
+
+class MutableArrayRefImpl : public WritableBinaryStream {
+public:
+ MutableArrayRefImpl(MutableArrayRef<uint8_t> Data, endianness Endian)
+ : BBS(Data, Endian) {}
+
+ // Inherited via WritableBinaryStream
+ llvm::support::endianness getEndian() const override {
+ return BBS.getEndian();
+ }
+ Error readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) override {
+ return BBS.readBytes(Offset, Size, Buffer);
+ }
+ Error readLongestContiguousChunk(uint32_t Offset,
+ ArrayRef<uint8_t> &Buffer) override {
+ return BBS.readLongestContiguousChunk(Offset, Buffer);
+ }
+ uint32_t getLength() override { return BBS.getLength(); }
+
+ Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) override {
+ return BBS.writeBytes(Offset, Data);
+ }
+ Error commit() override { return BBS.commit(); }
+
+private:
+ MutableBinaryByteStream BBS;
+};
+}
+
+BinaryStreamRef::BinaryStreamRef(BinaryStream &Stream)
+ : BinaryStreamRef(Stream, 0, Stream.getLength()) {}
+BinaryStreamRef::BinaryStreamRef(BinaryStream &Stream, uint32_t Offset,
+ uint32_t Length)
+ : BinaryStreamRefBase(Stream, Offset, Length) {}
+BinaryStreamRef::BinaryStreamRef(ArrayRef<uint8_t> Data, endianness Endian)
+ : BinaryStreamRefBase(std::make_shared<ArrayRefImpl>(Data, Endian), 0,
+ Data.size()) {}
+BinaryStreamRef::BinaryStreamRef(StringRef Data, endianness Endian)
+ : BinaryStreamRef(makeArrayRef(Data.bytes_begin(), Data.bytes_end()),
+ Endian) {}
+
+BinaryStreamRef::BinaryStreamRef(const BinaryStreamRef &Other)
+ : BinaryStreamRefBase(Other) {}
+
+Error BinaryStreamRef::readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) const {
+ if (auto EC = checkOffset(Offset, Size))
+ return EC;
+ return BorrowedImpl->readBytes(ViewOffset + Offset, Size, Buffer);
+}
+
+Error BinaryStreamRef::readLongestContiguousChunk(
+ uint32_t Offset, ArrayRef<uint8_t> &Buffer) const {
+ if (auto EC = checkOffset(Offset, 1))
+ return EC;
+
+ if (auto EC =
+ BorrowedImpl->readLongestContiguousChunk(ViewOffset + 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();
+}
+
+WritableBinaryStreamRef::WritableBinaryStreamRef(WritableBinaryStream &Stream)
+ : WritableBinaryStreamRef(Stream, 0, Stream.getLength()) {}
+
+WritableBinaryStreamRef::WritableBinaryStreamRef(WritableBinaryStream &Stream,
+ uint32_t Offset,
+ uint32_t Length)
+ : BinaryStreamRefBase(Stream, Offset, Length) {}
+
+WritableBinaryStreamRef::WritableBinaryStreamRef(MutableArrayRef<uint8_t> Data,
+ endianness Endian)
+ : BinaryStreamRefBase(std::make_shared<MutableArrayRefImpl>(Data, Endian),
+ 0, Data.size()) {}
+
+WritableBinaryStreamRef::WritableBinaryStreamRef(
+ const WritableBinaryStreamRef &Other)
+ : BinaryStreamRefBase(Other) {}
+
+Error WritableBinaryStreamRef::writeBytes(uint32_t Offset,
+ ArrayRef<uint8_t> Data) const {
+ if (auto EC = checkOffset(Offset, Data.size()))
+ return EC;
+
+ return BorrowedImpl->writeBytes(ViewOffset + Offset, Data);
+}
+
+WritableBinaryStreamRef::operator BinaryStreamRef() const {
+ return BinaryStreamRef(*BorrowedImpl, ViewOffset, Length);
+}
+
+/// \brief For buffered streams, commits changes to the backing store.
+Error WritableBinaryStreamRef::commit() { return BorrowedImpl->commit(); }
diff --git a/lib/Support/BinaryStreamWriter.cpp b/lib/Support/BinaryStreamWriter.cpp
index d78dbc68f593..b22eb1ed12d0 100644
--- a/lib/Support/BinaryStreamWriter.cpp
+++ b/lib/Support/BinaryStreamWriter.cpp
@@ -15,8 +15,15 @@
using namespace llvm;
-BinaryStreamWriter::BinaryStreamWriter(WritableBinaryStreamRef S)
- : Stream(S), Offset(0) {}
+BinaryStreamWriter::BinaryStreamWriter(WritableBinaryStreamRef Ref)
+ : Stream(Ref) {}
+
+BinaryStreamWriter::BinaryStreamWriter(WritableBinaryStream &Stream)
+ : Stream(Stream) {}
+
+BinaryStreamWriter::BinaryStreamWriter(MutableArrayRef<uint8_t> Data,
+ llvm::support::endianness Endian)
+ : Stream(Data, Endian) {}
Error BinaryStreamWriter::writeBytes(ArrayRef<uint8_t> Buffer) {
if (auto EC = Stream.writeBytes(Offset, Buffer))
diff --git a/lib/Support/CMakeLists.txt b/lib/Support/CMakeLists.txt
index 83376284548f..a12ba4fbfda8 100644
--- a/lib/Support/CMakeLists.txt
+++ b/lib/Support/CMakeLists.txt
@@ -39,6 +39,7 @@ add_llvm_library(LLVMSupport
Allocator.cpp
BinaryStreamError.cpp
BinaryStreamReader.cpp
+ BinaryStreamRef.cpp
BinaryStreamWriter.cpp
BlockFrequency.cpp
BranchProbability.cpp
diff --git a/lib/Support/FormattedStream.cpp b/lib/Support/FormattedStream.cpp
index 2ed71c7e4311..c01659604444 100644
--- a/lib/Support/FormattedStream.cpp
+++ b/lib/Support/FormattedStream.cpp
@@ -32,6 +32,7 @@ static void UpdatePosition(std::pair<unsigned, unsigned> &Position, const char *
switch (*Ptr) {
case '\n':
Line += 1;
+ LLVM_FALLTHROUGH;
case '\r':
Column = 0;
break;
diff --git a/lib/Support/Triple.cpp b/lib/Support/Triple.cpp
index eb8108908ac5..b0e3d6898cae 100644
--- a/lib/Support/Triple.cpp
+++ b/lib/Support/Triple.cpp
@@ -1472,6 +1472,24 @@ bool Triple::isLittleEndian() const {
}
}
+bool Triple::isCompatibleWith(const Triple &Other) const {
+ // If vendor is apple, ignore the version number.
+ if (getVendor() == Triple::Apple)
+ return getArch() == Other.getArch() && getSubArch() == Other.getSubArch() &&
+ getVendor() == Other.getVendor() && getOS() == Other.getOS();
+
+ return *this == Other;
+}
+
+std::string Triple::merge(const Triple &Other) const {
+ // If vendor is apple, pick the triple with the larger version number.
+ if (getVendor() == Triple::Apple)
+ if (Other.isOSVersionLT(*this))
+ return str();
+
+ return Other.str();
+}
+
StringRef Triple::getARMCPUForArch(StringRef MArch) const {
if (MArch.empty())
MArch = getArchName();
diff --git a/lib/Target/AArch64/AArch64InstrInfo.td b/lib/Target/AArch64/AArch64InstrInfo.td
index 5ddf66654a67..da68f3165c5e 100644
--- a/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/lib/Target/AArch64/AArch64InstrInfo.td
@@ -315,8 +315,14 @@ def AArch64umaxv : SDNode<"AArch64ISD::UMAXV", SDT_AArch64UnaryVec>;
// AArch64 Instruction Predicate Definitions.
def IsDarwin : Predicate<"Subtarget->isTargetDarwin()">;
def IsNotDarwin: Predicate<"!Subtarget->isTargetDarwin()">;
-def ForCodeSize : Predicate<"Subtarget->getForCodeSize()">;
-def NotForCodeSize : Predicate<"!Subtarget->getForCodeSize()">;
+
+// We could compute these on a per-module basis but doing so requires accessing
+// the Function object through the <Target>Subtarget and objections were raised
+// to that (see post-commit review comments for r301750).
+let RecomputePerFunction = 1 in {
+ def ForCodeSize : Predicate<"MF->getFunction()->optForSize()">;
+ def NotForCodeSize : Predicate<"!MF->getFunction()->optForSize()">;
+}
include "AArch64InstrFormats.td"
diff --git a/lib/Target/AArch64/AArch64Subtarget.cpp b/lib/Target/AArch64/AArch64Subtarget.cpp
index 1c81d34014fd..b369ee7e4ba2 100644
--- a/lib/Target/AArch64/AArch64Subtarget.cpp
+++ b/lib/Target/AArch64/AArch64Subtarget.cpp
@@ -164,12 +164,11 @@ struct AArch64GISelActualAccessor : public GISelAccessor {
AArch64Subtarget::AArch64Subtarget(const Triple &TT, const std::string &CPU,
const std::string &FS,
- const TargetMachine &TM, bool LittleEndian,
- bool ForCodeSize)
+ const TargetMachine &TM, bool LittleEndian)
: AArch64GenSubtargetInfo(TT, CPU, FS), ReserveX18(TT.isOSDarwin()),
IsLittle(LittleEndian), TargetTriple(TT), FrameLowering(),
InstrInfo(initializeSubtargetDependencies(FS, CPU)), TSInfo(),
- TLInfo(TM, *this), GISel(), ForCodeSize(ForCodeSize) {
+ TLInfo(TM, *this), GISel() {
#ifndef LLVM_BUILD_GLOBAL_ISEL
GISelAccessor *AArch64GISel = new GISelAccessor();
#else
diff --git a/lib/Target/AArch64/AArch64Subtarget.h b/lib/Target/AArch64/AArch64Subtarget.h
index df54bf3f48e1..7933e58c49ee 100644
--- a/lib/Target/AArch64/AArch64Subtarget.h
+++ b/lib/Target/AArch64/AArch64Subtarget.h
@@ -128,8 +128,6 @@ protected:
/// an optional library.
std::unique_ptr<GISelAccessor> GISel;
- bool ForCodeSize;
-
private:
/// initializeSubtargetDependencies - Initializes using CPUString and the
/// passed in feature string so that we can use initializer lists for
@@ -145,7 +143,7 @@ public:
/// of the specified triple.
AArch64Subtarget(const Triple &TT, const std::string &CPU,
const std::string &FS, const TargetMachine &TM,
- bool LittleEndian, bool ForCodeSize);
+ bool LittleEndian);
/// This object will take onwership of \p GISelAccessor.
void setGISelAccessor(GISelAccessor &GISel) {
@@ -274,8 +272,6 @@ public:
}
}
- bool getForCodeSize() const { return ForCodeSize; }
-
/// ParseSubtargetFeatures - Parses features string setting specified
/// subtarget options. Definition of function is auto generated by tblgen.
void ParseSubtargetFeatures(StringRef CPU, StringRef FS);
diff --git a/lib/Target/AArch64/AArch64TargetMachine.cpp b/lib/Target/AArch64/AArch64TargetMachine.cpp
index 5a90fd1eb1ba..132f192f2a9a 100644
--- a/lib/Target/AArch64/AArch64TargetMachine.cpp
+++ b/lib/Target/AArch64/AArch64TargetMachine.cpp
@@ -214,7 +214,6 @@ const AArch64Subtarget *
AArch64TargetMachine::getSubtargetImpl(const Function &F) const {
Attribute CPUAttr = F.getFnAttribute("target-cpu");
Attribute FSAttr = F.getFnAttribute("target-features");
- bool ForCodeSize = F.optForSize();
std::string CPU = !CPUAttr.hasAttribute(Attribute::None)
? CPUAttr.getValueAsString().str()
@@ -222,17 +221,15 @@ AArch64TargetMachine::getSubtargetImpl(const Function &F) const {
std::string FS = !FSAttr.hasAttribute(Attribute::None)
? FSAttr.getValueAsString().str()
: TargetFS;
- std::string ForCodeSizeStr =
- std::string(ForCodeSize ? "+" : "-") + "forcodesize";
- auto &I = SubtargetMap[CPU + FS + ForCodeSizeStr];
+ auto &I = SubtargetMap[CPU + FS];
if (!I) {
// This needs to be done before we create a new subtarget since any
// creation will depend on the TM and the code generation flags on the
// function that reside in TargetOptions.
resetTargetOptions(F);
I = llvm::make_unique<AArch64Subtarget>(TargetTriple, CPU, FS, *this,
- isLittle, ForCodeSize);
+ isLittle);
}
return I.get();
}
@@ -324,7 +321,7 @@ TargetPassConfig *AArch64TargetMachine::createPassConfig(PassManagerBase &PM) {
void AArch64PassConfig::addIRPasses() {
// Always expand atomic operations, we don't deal with atomicrmw or cmpxchg
// ourselves.
- addPass(createAtomicExpandPass(TM));
+ addPass(createAtomicExpandPass());
// Cmpxchg instructions are often used with a subsequent comparison to
// determine whether it succeeded. We can exploit existing control-flow in
@@ -343,7 +340,7 @@ void AArch64PassConfig::addIRPasses() {
// Match interleaved memory accesses to ldN/stN intrinsics.
if (TM->getOptLevel() != CodeGenOpt::None)
- addPass(createInterleavedAccessPass(TM));
+ addPass(createInterleavedAccessPass());
if (TM->getOptLevel() == CodeGenOpt::Aggressive && EnableGEPOpt) {
// Call SeparateConstOffsetFromGEP pass to extract constants within indices
diff --git a/lib/Target/AMDGPU/AMDGPU.h b/lib/Target/AMDGPU/AMDGPU.h
index 3f89702bed50..78ff3bbe3d1a 100644
--- a/lib/Target/AMDGPU/AMDGPU.h
+++ b/lib/Target/AMDGPU/AMDGPU.h
@@ -27,12 +27,12 @@ class PassRegistry;
class Module;
// R600 Passes
-FunctionPass *createR600VectorRegMerger(TargetMachine &tm);
-FunctionPass *createR600ExpandSpecialInstrsPass(TargetMachine &tm);
+FunctionPass *createR600VectorRegMerger();
+FunctionPass *createR600ExpandSpecialInstrsPass();
FunctionPass *createR600EmitClauseMarkers();
-FunctionPass *createR600ClauseMergePass(TargetMachine &tm);
-FunctionPass *createR600Packetizer(TargetMachine &tm);
-FunctionPass *createR600ControlFlowFinalizer(TargetMachine &tm);
+FunctionPass *createR600ClauseMergePass();
+FunctionPass *createR600Packetizer();
+FunctionPass *createR600ControlFlowFinalizer();
FunctionPass *createAMDGPUCFGStructurizerPass();
// SI Passes
@@ -42,24 +42,24 @@ FunctionPass *createSIFoldOperandsPass();
FunctionPass *createSIPeepholeSDWAPass();
FunctionPass *createSILowerI1CopiesPass();
FunctionPass *createSIShrinkInstructionsPass();
-FunctionPass *createSILoadStoreOptimizerPass(TargetMachine &tm);
+FunctionPass *createSILoadStoreOptimizerPass();
FunctionPass *createSIWholeQuadModePass();
FunctionPass *createSIFixControlFlowLiveIntervalsPass();
FunctionPass *createSIFixSGPRCopiesPass();
FunctionPass *createSIDebuggerInsertNopsPass();
FunctionPass *createSIInsertWaitsPass();
FunctionPass *createSIInsertWaitcntsPass();
-FunctionPass *createAMDGPUCodeGenPreparePass(const GCNTargetMachine *TM = nullptr);
+FunctionPass *createAMDGPUCodeGenPreparePass();
FunctionPass *createAMDGPUMachineCFGStructurizerPass();
void initializeAMDGPUMachineCFGStructurizerPass(PassRegistry&);
extern char &AMDGPUMachineCFGStructurizerID;
-ModulePass *createAMDGPUAnnotateKernelFeaturesPass(const TargetMachine *TM = nullptr);
+ModulePass *createAMDGPUAnnotateKernelFeaturesPass();
void initializeAMDGPUAnnotateKernelFeaturesPass(PassRegistry &);
extern char &AMDGPUAnnotateKernelFeaturesID;
-ModulePass *createAMDGPULowerIntrinsicsPass(const TargetMachine *TM = nullptr);
+ModulePass *createAMDGPULowerIntrinsicsPass();
void initializeAMDGPULowerIntrinsicsPass(PassRegistry &);
extern char &AMDGPULowerIntrinsicsID;
@@ -97,7 +97,7 @@ void initializeSIOptimizeExecMaskingPass(PassRegistry &);
extern char &SIOptimizeExecMaskingID;
// Passes common to R600 and SI
-FunctionPass *createAMDGPUPromoteAlloca(const TargetMachine *TM = nullptr);
+FunctionPass *createAMDGPUPromoteAlloca();
void initializeAMDGPUPromoteAllocaPass(PassRegistry&);
extern char &AMDGPUPromoteAllocaID;
diff --git a/lib/Target/AMDGPU/AMDGPUAnnotateKernelFeatures.cpp b/lib/Target/AMDGPU/AMDGPUAnnotateKernelFeatures.cpp
index 3d8db7cd8af5..7235d8fae332 100644
--- a/lib/Target/AMDGPU/AMDGPUAnnotateKernelFeatures.cpp
+++ b/lib/Target/AMDGPU/AMDGPUAnnotateKernelFeatures.cpp
@@ -15,6 +15,7 @@
#include "AMDGPU.h"
#include "AMDGPUSubtarget.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
@@ -27,7 +28,6 @@ namespace {
class AMDGPUAnnotateKernelFeatures : public ModulePass {
private:
- const TargetMachine *TM;
AMDGPUAS AS;
static bool hasAddrSpaceCast(const Function &F, AMDGPUAS AS);
@@ -37,8 +37,7 @@ private:
public:
static char ID;
- AMDGPUAnnotateKernelFeatures(const TargetMachine *TM_ = nullptr) :
- ModulePass(ID), TM(TM_) {}
+ AMDGPUAnnotateKernelFeatures() : ModulePass(ID) {}
bool runOnModule(Module &M) override;
StringRef getPassName() const override {
return "AMDGPU Annotate Kernel Features";
@@ -221,8 +220,10 @@ bool AMDGPUAnnotateKernelFeatures::runOnModule(Module &M) {
if (F.hasFnAttribute("amdgpu-queue-ptr"))
continue;
- bool HasApertureRegs =
- TM && TM->getSubtarget<AMDGPUSubtarget>(F).hasApertureRegs();
+ auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
+ bool HasApertureRegs = TPC && TPC->getTM<TargetMachine>()
+ .getSubtarget<AMDGPUSubtarget>(F)
+ .hasApertureRegs();
if (!HasApertureRegs && hasAddrSpaceCast(F, AS))
F.addFnAttr("amdgpu-queue-ptr");
}
@@ -231,6 +232,6 @@ bool AMDGPUAnnotateKernelFeatures::runOnModule(Module &M) {
return Changed;
}
-ModulePass *llvm::createAMDGPUAnnotateKernelFeaturesPass(const TargetMachine *TM) {
- return new AMDGPUAnnotateKernelFeatures(TM);
+ModulePass *llvm::createAMDGPUAnnotateKernelFeaturesPass() {
+ return new AMDGPUAnnotateKernelFeatures();
}
diff --git a/lib/Target/AMDGPU/AMDGPUCallLowering.h b/lib/Target/AMDGPU/AMDGPUCallLowering.h
index 09bdf8ffcde7..251cb7a2c440 100644
--- a/lib/Target/AMDGPU/AMDGPUCallLowering.h
+++ b/lib/Target/AMDGPU/AMDGPUCallLowering.h
@@ -38,7 +38,8 @@ class AMDGPUCallLowering: public CallLowering {
unsigned VReg) const override;
bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F,
ArrayRef<unsigned> VRegs) const override;
- CCAssignFn *CCAssignFnForCall(CallingConv::ID CC, bool IsVarArg) const;
+ static CCAssignFn *CCAssignFnForCall(CallingConv::ID CC, bool IsVarArg);
+ static CCAssignFn *CCAssignFnForReturn(CallingConv::ID CC, bool IsVarArg);
};
} // End of namespace llvm;
#endif
diff --git a/lib/Target/AMDGPU/AMDGPUCallingConv.td b/lib/Target/AMDGPU/AMDGPUCallingConv.td
index d308f718aae1..4bef7a89bfe3 100644
--- a/lib/Target/AMDGPU/AMDGPUCallingConv.td
+++ b/lib/Target/AMDGPU/AMDGPUCallingConv.td
@@ -13,6 +13,8 @@
// Inversion of CCIfInReg
class CCIfNotInReg<CCAction A> : CCIf<"!ArgFlags.isInReg()", A> {}
+class CCIfExtend<CCAction A>
+ : CCIf<"ArgFlags.isSExt() || ArgFlags.isZExt()", A>;
// Calling convention for SI
def CC_SI : CallingConv<[
@@ -52,7 +54,7 @@ def CC_SI : CallingConv<[
]>>>
]>;
-def RetCC_SI : CallingConv<[
+def RetCC_SI_Shader : CallingConv<[
CCIfType<[i32] , CCAssignToReg<[
SGPR0, SGPR1, SGPR2, SGPR3, SGPR4, SGPR5, SGPR6, SGPR7,
SGPR8, SGPR9, SGPR10, SGPR11, SGPR12, SGPR13, SGPR14, SGPR15,
@@ -99,6 +101,52 @@ def CC_AMDGPU_Kernel : CallingConv<[
CCCustom<"allocateKernArg">
]>;
+def CSR_AMDGPU_VGPRs_24_255 : CalleeSavedRegs<
+ (sequence "VGPR%u", 24, 255)
+>;
+
+def CSR_AMDGPU_VGPRs_32_255 : CalleeSavedRegs<
+ (sequence "VGPR%u", 32, 255)
+>;
+
+def CSR_AMDGPU_SGPRs_32_103 : CalleeSavedRegs<
+ (sequence "SGPR%u", 32, 103)
+>;
+
+def CSR_AMDGPU_HighRegs : CalleeSavedRegs<
+ (add CSR_AMDGPU_VGPRs_32_255, CSR_AMDGPU_SGPRs_32_103)
+>;
+
+// Calling convention for leaf functions
+def CC_AMDGPU_Func : CallingConv<[
+ CCIfByVal<CCPassByVal<4, 4>>,
+ CCIfType<[i1], CCPromoteToType<i32>>,
+ CCIfType<[i1, i8, i16], CCIfExtend<CCPromoteToType<i32>>>,
+ CCIfType<[i32, f32, i16, f16, v2i16, v2f16, i1], CCAssignToReg<[
+ VGPR0, VGPR1, VGPR2, VGPR3, VGPR4, VGPR5, VGPR6, VGPR7,
+ VGPR8, VGPR9, VGPR10, VGPR11, VGPR12, VGPR13, VGPR14, VGPR15,
+ VGPR16, VGPR17, VGPR18, VGPR19, VGPR20, VGPR21, VGPR22, VGPR23,
+ VGPR24, VGPR25, VGPR26, VGPR27, VGPR28, VGPR29, VGPR30, VGPR31]>>,
+ CCIfType<[i64, f64, v2i32, v2f32, v4i32, v4f32, v8i32, v8f32, v16i32, v16f32, v2i64, v2f64], CCCustom<"allocateVGPRTuple">>,
+ CCIfType<[i32, f32, v2i16, v2f16, i16, f16, i1], CCAssignToStack<4, 4>>,
+ CCIfType<[i64, f64, v2i32, v2f32], CCAssignToStack<8, 4>>,
+ CCIfType<[v4i32, v4f32, v2i64, v2f64], CCAssignToStack<16, 4>>,
+ CCIfType<[v8i32, v8f32], CCAssignToStack<32, 4>>,
+ CCIfType<[v16i32, v16f32], CCAssignToStack<64, 4>>
+]>;
+
+// Calling convention for leaf functions
+def RetCC_AMDGPU_Func : CallingConv<[
+ CCIfType<[i1], CCPromoteToType<i32>>,
+ CCIfType<[i1, i16], CCIfExtend<CCPromoteToType<i32>>>,
+ CCIfType<[i32, f32, i16, f16, v2i16, v2f16], CCAssignToReg<[
+ VGPR0, VGPR1, VGPR2, VGPR3, VGPR4, VGPR5, VGPR6, VGPR7,
+ VGPR8, VGPR9, VGPR10, VGPR11, VGPR12, VGPR13, VGPR14, VGPR15,
+ VGPR16, VGPR17, VGPR18, VGPR19, VGPR20, VGPR21, VGPR22, VGPR23,
+ VGPR24, VGPR25, VGPR26, VGPR27, VGPR28, VGPR29, VGPR30, VGPR31]>>,
+ CCIfType<[i64, f64, v2i32, v2f32, v4i32, v4f32, v8i32, v8f32, v16i32, v16f32, v2i64, v2f64], CCCustom<"allocateVGPRTuple">>
+]>;
+
def CC_AMDGPU : CallingConv<[
CCIf<"static_cast<const AMDGPUSubtarget&>"
"(State.getMachineFunction().getSubtarget()).getGeneration() >="
diff --git a/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp b/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp
index e19314fe0a6c..d923cb117c12 100644
--- a/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp
+++ b/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp
@@ -19,6 +19,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/DivergenceAnalysis.h"
#include "llvm/CodeGen/Passes.h"
+#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constants.h"
@@ -48,7 +49,6 @@ namespace {
class AMDGPUCodeGenPrepare : public FunctionPass,
public InstVisitor<AMDGPUCodeGenPrepare, bool> {
- const GCNTargetMachine *TM;
const SISubtarget *ST = nullptr;
DivergenceAnalysis *DA = nullptr;
Module *Mod = nullptr;
@@ -127,8 +127,7 @@ class AMDGPUCodeGenPrepare : public FunctionPass,
public:
static char ID;
- AMDGPUCodeGenPrepare(const TargetMachine *TM = nullptr) :
- FunctionPass(ID), TM(static_cast<const GCNTargetMachine *>(TM)) {}
+ AMDGPUCodeGenPrepare() : FunctionPass(ID) {}
bool visitFDiv(BinaryOperator &I);
@@ -487,10 +486,15 @@ bool AMDGPUCodeGenPrepare::doInitialization(Module &M) {
}
bool AMDGPUCodeGenPrepare::runOnFunction(Function &F) {
- if (!TM || skipFunction(F))
+ if (skipFunction(F))
return false;
- ST = &TM->getSubtarget<SISubtarget>(F);
+ auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
+ if (!TPC)
+ return false;
+
+ const TargetMachine &TM = TPC->getTM<TargetMachine>();
+ ST = &TM.getSubtarget<SISubtarget>(F);
DA = &getAnalysis<DivergenceAnalysis>();
HasUnsafeFPMath = hasUnsafeFPMath(F);
@@ -507,14 +511,14 @@ bool AMDGPUCodeGenPrepare::runOnFunction(Function &F) {
return MadeChange;
}
-INITIALIZE_TM_PASS_BEGIN(AMDGPUCodeGenPrepare, DEBUG_TYPE,
+INITIALIZE_PASS_BEGIN(AMDGPUCodeGenPrepare, DEBUG_TYPE,
"AMDGPU IR optimizations", false, false)
INITIALIZE_PASS_DEPENDENCY(DivergenceAnalysis)
-INITIALIZE_TM_PASS_END(AMDGPUCodeGenPrepare, DEBUG_TYPE,
- "AMDGPU IR optimizations", false, false)
+INITIALIZE_PASS_END(AMDGPUCodeGenPrepare, DEBUG_TYPE, "AMDGPU IR optimizations",
+ false, false)
char AMDGPUCodeGenPrepare::ID = 0;
-FunctionPass *llvm::createAMDGPUCodeGenPreparePass(const GCNTargetMachine *TM) {
- return new AMDGPUCodeGenPrepare(TM);
+FunctionPass *llvm::createAMDGPUCodeGenPreparePass() {
+ return new AMDGPUCodeGenPrepare();
}
diff --git a/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp b/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp
index c3ac796a0a44..19fce064783d 100644
--- a/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp
+++ b/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp
@@ -82,7 +82,7 @@ public:
void PostprocessISelDAG() override;
private:
- SDValue foldFrameIndex(SDValue N) const;
+ std::pair<SDValue, SDValue> foldFrameIndex(SDValue N) const;
bool isNoNanSrc(SDValue N) const;
bool isInlineImmediate(const SDNode *N) const;
bool FoldOperand(SDValue &Src, SDValue &Sel, SDValue &Neg, SDValue &Abs,
@@ -116,9 +116,11 @@ private:
bool SelectMUBUFAddr64(SDValue Addr, SDValue &SRsrc,
SDValue &VAddr, SDValue &SOffset, SDValue &Offset,
SDValue &SLC) const;
- bool SelectMUBUFScratchOffen(SDValue Addr, SDValue &RSrc, SDValue &VAddr,
+ bool SelectMUBUFScratchOffen(SDNode *Root,
+ SDValue Addr, SDValue &RSrc, SDValue &VAddr,
SDValue &SOffset, SDValue &ImmOffset) const;
- bool SelectMUBUFScratchOffset(SDValue Addr, SDValue &SRsrc, SDValue &Soffset,
+ bool SelectMUBUFScratchOffset(SDNode *Root,
+ SDValue Addr, SDValue &SRsrc, SDValue &Soffset,
SDValue &Offset) const;
bool SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc, SDValue &SOffset,
@@ -1074,13 +1076,33 @@ bool AMDGPUDAGToDAGISel::SelectMUBUFAddr64(SDValue Addr, SDValue &SRsrc,
return SelectMUBUFAddr64(Addr, SRsrc, VAddr, SOffset, Offset, GLC, SLC, TFE);
}
-SDValue AMDGPUDAGToDAGISel::foldFrameIndex(SDValue N) const {
- if (auto FI = dyn_cast<FrameIndexSDNode>(N))
- return CurDAG->getTargetFrameIndex(FI->getIndex(), FI->getValueType(0));
- return N;
+static bool isStackPtrRelative(const MachinePointerInfo &PtrInfo) {
+ auto PSV = PtrInfo.V.dyn_cast<const PseudoSourceValue *>();
+ return PSV && PSV->isStack();
+}
+
+std::pair<SDValue, SDValue> AMDGPUDAGToDAGISel::foldFrameIndex(SDValue N) const {
+ const MachineFunction &MF = CurDAG->getMachineFunction();
+ const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
+
+ if (auto FI = dyn_cast<FrameIndexSDNode>(N)) {
+ SDValue TFI = CurDAG->getTargetFrameIndex(FI->getIndex(),
+ FI->getValueType(0));
+
+ // If we can resolve this to a frame index access, this is relative to the
+ // frame pointer SGPR.
+ return std::make_pair(TFI, CurDAG->getRegister(Info->getFrameOffsetReg(),
+ MVT::i32));
+ }
+
+ // If we don't know this private access is a local stack object, it needs to
+ // be relative to the entry point's scratch wave offset register.
+ return std::make_pair(N, CurDAG->getRegister(Info->getScratchWaveOffsetReg(),
+ MVT::i32));
}
-bool AMDGPUDAGToDAGISel::SelectMUBUFScratchOffen(SDValue Addr, SDValue &Rsrc,
+bool AMDGPUDAGToDAGISel::SelectMUBUFScratchOffen(SDNode *Root,
+ SDValue Addr, SDValue &Rsrc,
SDValue &VAddr, SDValue &SOffset,
SDValue &ImmOffset) const {
@@ -1089,7 +1111,6 @@ bool AMDGPUDAGToDAGISel::SelectMUBUFScratchOffen(SDValue Addr, SDValue &Rsrc,
const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
Rsrc = CurDAG->getRegister(Info->getScratchRSrcReg(), MVT::v4i32);
- SOffset = CurDAG->getRegister(Info->getScratchWaveOffsetReg(), MVT::i32);
if (ConstantSDNode *CAddr = dyn_cast<ConstantSDNode>(Addr)) {
unsigned Imm = CAddr->getZExtValue();
@@ -1100,6 +1121,14 @@ bool AMDGPUDAGToDAGISel::SelectMUBUFScratchOffen(SDValue Addr, SDValue &Rsrc,
MachineSDNode *MovHighBits = CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32,
DL, MVT::i32, HighBits);
VAddr = SDValue(MovHighBits, 0);
+
+ // In a call sequence, stores to the argument stack area are relative to the
+ // stack pointer.
+ const MachinePointerInfo &PtrInfo = cast<MemSDNode>(Root)->getPointerInfo();
+ unsigned SOffsetReg = isStackPtrRelative(PtrInfo) ?
+ Info->getStackPtrOffsetReg() : Info->getScratchWaveOffsetReg();
+
+ SOffset = CurDAG->getRegister(SOffsetReg, MVT::i32);
ImmOffset = CurDAG->getTargetConstant(Imm & 4095, DL, MVT::i16);
return true;
}
@@ -1113,19 +1142,20 @@ bool AMDGPUDAGToDAGISel::SelectMUBUFScratchOffen(SDValue Addr, SDValue &Rsrc,
// Offsets in vaddr must be positive.
ConstantSDNode *C1 = cast<ConstantSDNode>(N1);
if (isLegalMUBUFImmOffset(C1)) {
- VAddr = foldFrameIndex(N0);
+ std::tie(VAddr, SOffset) = foldFrameIndex(N0);
ImmOffset = CurDAG->getTargetConstant(C1->getZExtValue(), DL, MVT::i16);
return true;
}
}
// (node)
- VAddr = foldFrameIndex(Addr);
+ std::tie(VAddr, SOffset) = foldFrameIndex(Addr);
ImmOffset = CurDAG->getTargetConstant(0, DL, MVT::i16);
return true;
}
-bool AMDGPUDAGToDAGISel::SelectMUBUFScratchOffset(SDValue Addr,
+bool AMDGPUDAGToDAGISel::SelectMUBUFScratchOffset(SDNode *Root,
+ SDValue Addr,
SDValue &SRsrc,
SDValue &SOffset,
SDValue &Offset) const {
@@ -1138,7 +1168,15 @@ bool AMDGPUDAGToDAGISel::SelectMUBUFScratchOffset(SDValue Addr,
const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
SRsrc = CurDAG->getRegister(Info->getScratchRSrcReg(), MVT::v4i32);
- SOffset = CurDAG->getRegister(Info->getScratchWaveOffsetReg(), MVT::i32);
+
+ const MachinePointerInfo &PtrInfo = cast<MemSDNode>(Root)->getPointerInfo();
+ unsigned SOffsetReg = isStackPtrRelative(PtrInfo) ?
+ Info->getStackPtrOffsetReg() : Info->getScratchWaveOffsetReg();
+
+ // FIXME: Get from MachinePointerInfo? We should only be using the frame
+ // offset if we know this is in a call sequence.
+ SOffset = CurDAG->getRegister(SOffsetReg, MVT::i32);
+
Offset = CurDAG->getTargetConstant(CAddr->getZExtValue(), DL, MVT::i16);
return true;
}
@@ -1700,12 +1738,46 @@ bool AMDGPUDAGToDAGISel::SelectVOP3OMods(SDValue In, SDValue &Src,
return true;
}
+static SDValue stripBitcast(SDValue Val) {
+ return Val.getOpcode() == ISD::BITCAST ? Val.getOperand(0) : Val;
+}
+
+// Figure out if this is really an extract of the high 16-bits of a dword.
+static bool isExtractHiElt(SDValue In, SDValue &Out) {
+ In = stripBitcast(In);
+ if (In.getOpcode() != ISD::TRUNCATE)
+ return false;
+
+ SDValue Srl = In.getOperand(0);
+ if (Srl.getOpcode() == ISD::SRL) {
+ if (ConstantSDNode *ShiftAmt = dyn_cast<ConstantSDNode>(Srl.getOperand(1))) {
+ if (ShiftAmt->getZExtValue() == 16) {
+ Out = stripBitcast(Srl.getOperand(0));
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+// Look through operations that obscure just looking at the low 16-bits of the
+// same register.
+static SDValue stripExtractLoElt(SDValue In) {
+ if (In.getOpcode() == ISD::TRUNCATE) {
+ SDValue Src = In.getOperand(0);
+ if (Src.getValueType().getSizeInBits() == 32)
+ return stripBitcast(Src);
+ }
+
+ return In;
+}
+
bool AMDGPUDAGToDAGISel::SelectVOP3PMods(SDValue In, SDValue &Src,
SDValue &SrcMods) const {
unsigned Mods = 0;
Src = In;
- // FIXME: Look for on separate components
if (Src.getOpcode() == ISD::FNEG) {
Mods ^= (SISrcMods::NEG | SISrcMods::NEG_HI);
Src = Src.getOperand(0);
@@ -1714,19 +1786,28 @@ bool AMDGPUDAGToDAGISel::SelectVOP3PMods(SDValue In, SDValue &Src,
if (Src.getOpcode() == ISD::BUILD_VECTOR) {
unsigned VecMods = Mods;
- SDValue Lo = Src.getOperand(0);
- SDValue Hi = Src.getOperand(1);
+ SDValue Lo = stripBitcast(Src.getOperand(0));
+ SDValue Hi = stripBitcast(Src.getOperand(1));
if (Lo.getOpcode() == ISD::FNEG) {
- Lo = Lo.getOperand(0);
+ Lo = stripBitcast(Lo.getOperand(0));
Mods ^= SISrcMods::NEG;
}
if (Hi.getOpcode() == ISD::FNEG) {
- Hi = Hi.getOperand(0);
+ Hi = stripBitcast(Hi.getOperand(0));
Mods ^= SISrcMods::NEG_HI;
}
+ if (isExtractHiElt(Lo, Lo))
+ Mods |= SISrcMods::OP_SEL_0;
+
+ if (isExtractHiElt(Hi, Hi))
+ Mods |= SISrcMods::OP_SEL_1;
+
+ Lo = stripExtractLoElt(Lo);
+ Hi = stripExtractLoElt(Hi);
+
if (Lo == Hi && !isInlineImmediate(Lo.getNode())) {
// Really a scalar input. Just select from the low half of the register to
// avoid packing.
@@ -1740,9 +1821,6 @@ bool AMDGPUDAGToDAGISel::SelectVOP3PMods(SDValue In, SDValue &Src,
}
// Packed instructions do not have abs modifiers.
-
- // FIXME: Handle abs/neg of individual components.
- // FIXME: Handle swizzling with op_sel
Mods |= SISrcMods::OP_SEL_1;
SrcMods = CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
diff --git a/lib/Target/AMDGPU/AMDGPUISelLowering.cpp b/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
index f80652b87373..5ec46a8294c0 100644
--- a/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
+++ b/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
@@ -76,6 +76,45 @@ static bool allocateSGPRTuple(unsigned ValNo, MVT ValVT, MVT LocVT,
}
}
+// Allocate up to VGPR31.
+//
+// TODO: Since there are no VGPR alignent requirements would it be better to
+// split into individual scalar registers?
+static bool allocateVGPRTuple(unsigned ValNo, MVT ValVT, MVT LocVT,
+ CCValAssign::LocInfo LocInfo,
+ ISD::ArgFlagsTy ArgFlags, CCState &State) {
+ switch (LocVT.SimpleTy) {
+ case MVT::i64:
+ case MVT::f64:
+ case MVT::v2i32:
+ case MVT::v2f32: {
+ return allocateCCRegs(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State,
+ &AMDGPU::VReg_64RegClass, 31);
+ }
+ case MVT::v4i32:
+ case MVT::v4f32:
+ case MVT::v2i64:
+ case MVT::v2f64: {
+ return allocateCCRegs(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State,
+ &AMDGPU::VReg_128RegClass, 29);
+ }
+ case MVT::v8i32:
+ case MVT::v8f32: {
+ return allocateCCRegs(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State,
+ &AMDGPU::VReg_256RegClass, 25);
+
+ }
+ case MVT::v16i32:
+ case MVT::v16f32: {
+ return allocateCCRegs(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State,
+ &AMDGPU::VReg_512RegClass, 17);
+
+ }
+ default:
+ return false;
+ }
+}
+
#include "AMDGPUGenCallingConv.inc"
// Find a larger type to do a load / store of a vector with.
@@ -773,8 +812,43 @@ bool AMDGPUTargetLowering::isNarrowingProfitable(EVT SrcVT, EVT DestVT) const {
//===---------------------------------------------------------------------===//
CCAssignFn *AMDGPUCallLowering::CCAssignFnForCall(CallingConv::ID CC,
- bool IsVarArg) const {
- return CC_AMDGPU;
+ bool IsVarArg) {
+ switch (CC) {
+ case CallingConv::AMDGPU_KERNEL:
+ case CallingConv::SPIR_KERNEL:
+ return CC_AMDGPU_Kernel;
+ case CallingConv::AMDGPU_VS:
+ case CallingConv::AMDGPU_GS:
+ case CallingConv::AMDGPU_PS:
+ case CallingConv::AMDGPU_CS:
+ case CallingConv::AMDGPU_HS:
+ return CC_AMDGPU;
+ case CallingConv::C:
+ case CallingConv::Fast:
+ return CC_AMDGPU_Func;
+ default:
+ report_fatal_error("Unsupported calling convention.");
+ }
+}
+
+CCAssignFn *AMDGPUCallLowering::CCAssignFnForReturn(CallingConv::ID CC,
+ bool IsVarArg) {
+ switch (CC) {
+ case CallingConv::AMDGPU_KERNEL:
+ case CallingConv::SPIR_KERNEL:
+ return CC_AMDGPU_Kernel;
+ case CallingConv::AMDGPU_VS:
+ case CallingConv::AMDGPU_GS:
+ case CallingConv::AMDGPU_PS:
+ case CallingConv::AMDGPU_CS:
+ case CallingConv::AMDGPU_HS:
+ return RetCC_SI_Shader;
+ case CallingConv::C:
+ case CallingConv::Fast:
+ return RetCC_AMDGPU_Func;
+ default:
+ report_fatal_error("Unsupported calling convention.");
+ }
}
/// The SelectionDAGBuilder will automatically promote function arguments
@@ -874,18 +948,15 @@ void AMDGPUTargetLowering::analyzeFormalArgumentsCompute(CCState &State,
}
}
-void AMDGPUTargetLowering::AnalyzeReturn(CCState &State,
- const SmallVectorImpl<ISD::OutputArg> &Outs) const {
-
- State.AnalyzeReturn(Outs, RetCC_SI);
-}
-
-SDValue
-AMDGPUTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
- bool isVarArg,
- const SmallVectorImpl<ISD::OutputArg> &Outs,
- const SmallVectorImpl<SDValue> &OutVals,
- const SDLoc &DL, SelectionDAG &DAG) const {
+SDValue AMDGPUTargetLowering::LowerReturn(
+ SDValue Chain, CallingConv::ID CallConv,
+ bool isVarArg,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ const SmallVectorImpl<SDValue> &OutVals,
+ const SDLoc &DL, SelectionDAG &DAG) const {
+ // FIXME: Fails for r600 tests
+ //assert(!isVarArg && Outs.empty() && OutVals.empty() &&
+ // "wave terminate should not have return values");
return DAG.getNode(AMDGPUISD::ENDPGM, DL, MVT::Other, Chain);
}
@@ -896,20 +967,12 @@ AMDGPUTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
/// Selects the correct CCAssignFn for a given CallingConvention value.
CCAssignFn *AMDGPUTargetLowering::CCAssignFnForCall(CallingConv::ID CC,
bool IsVarArg) {
- switch (CC) {
- case CallingConv::C:
- case CallingConv::AMDGPU_KERNEL:
- case CallingConv::SPIR_KERNEL:
- return CC_AMDGPU_Kernel;
- case CallingConv::AMDGPU_VS:
- case CallingConv::AMDGPU_HS:
- case CallingConv::AMDGPU_GS:
- case CallingConv::AMDGPU_PS:
- case CallingConv::AMDGPU_CS:
- return CC_AMDGPU;
- default:
- report_fatal_error("Unsupported calling convention.");
- }
+ return AMDGPUCallLowering::CCAssignFnForCall(CC, IsVarArg);
+}
+
+CCAssignFn *AMDGPUTargetLowering::CCAssignFnForReturn(CallingConv::ID CC,
+ bool IsVarArg) {
+ return AMDGPUCallLowering::CCAssignFnForReturn(CC, IsVarArg);
}
SDValue AMDGPUTargetLowering::LowerCall(CallLoweringInfo &CLI,
@@ -2532,27 +2595,49 @@ SDValue AMDGPUTargetLowering::splitBinaryBitConstantOpImpl(
SDValue AMDGPUTargetLowering::performShlCombine(SDNode *N,
DAGCombinerInfo &DCI) const {
- if (N->getValueType(0) != MVT::i64)
+ EVT VT = N->getValueType(0);
+ if (VT != MVT::i64)
return SDValue();
- // i64 (shl x, C) -> (build_pair 0, (shl x, C -32))
-
- // On some subtargets, 64-bit shift is a quarter rate instruction. In the
- // common case, splitting this into a move and a 32-bit shift is faster and
- // the same code size.
- const ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N->getOperand(1));
+ ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N->getOperand(1));
if (!RHS)
return SDValue();
- unsigned RHSVal = RHS->getZExtValue();
- if (RHSVal < 32)
- return SDValue();
-
SDValue LHS = N->getOperand(0);
+ unsigned RHSVal = RHS->getZExtValue();
+ if (!RHSVal)
+ return LHS;
SDLoc SL(N);
SelectionDAG &DAG = DCI.DAG;
+ switch (LHS->getOpcode()) {
+ default:
+ break;
+ case ISD::ZERO_EXTEND:
+ case ISD::SIGN_EXTEND:
+ case ISD::ANY_EXTEND: {
+ // shl (ext x) => zext (shl x), if shift does not overflow int
+ KnownBits Known;
+ SDValue X = LHS->getOperand(0);
+ DAG.computeKnownBits(X, Known);
+ unsigned LZ = Known.countMinLeadingZeros();
+ if (LZ < RHSVal)
+ break;
+ EVT XVT = X.getValueType();
+ SDValue Shl = DAG.getNode(ISD::SHL, SL, XVT, X, SDValue(RHS, 0));
+ return DAG.getZExtOrTrunc(Shl, SL, VT);
+ }
+ }
+
+ // i64 (shl x, C) -> (build_pair 0, (shl x, C -32))
+
+ // On some subtargets, 64-bit shift is a quarter rate instruction. In the
+ // common case, splitting this into a move and a 32-bit shift is faster and
+ // the same code size.
+ if (RHSVal < 32)
+ return SDValue();
+
SDValue ShiftAmt = DAG.getConstant(RHSVal - 32, SL, MVT::i32);
SDValue Lo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, LHS);
diff --git a/lib/Target/AMDGPU/AMDGPUISelLowering.h b/lib/Target/AMDGPU/AMDGPUISelLowering.h
index 4c588a7bafd0..fb2f15022d25 100644
--- a/lib/Target/AMDGPU/AMDGPUISelLowering.h
+++ b/lib/Target/AMDGPU/AMDGPUISelLowering.h
@@ -115,9 +115,6 @@ protected:
SmallVectorImpl<SDValue> &Results) const;
void analyzeFormalArgumentsCompute(CCState &State,
const SmallVectorImpl<ISD::InputArg> &Ins) const;
- void AnalyzeReturn(CCState &State,
- const SmallVectorImpl<ISD::OutputArg> &Outs) const;
-
public:
AMDGPUTargetLowering(const TargetMachine &TM, const AMDGPUSubtarget &STI);
@@ -164,6 +161,8 @@ public:
bool isCheapToSpeculateCtlz() const override;
static CCAssignFn *CCAssignFnForCall(CallingConv::ID CC, bool IsVarArg);
+ static CCAssignFn *CCAssignFnForReturn(CallingConv::ID CC, bool IsVarArg);
+
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
diff --git a/lib/Target/AMDGPU/AMDGPUInstrInfo.td b/lib/Target/AMDGPU/AMDGPUInstrInfo.td
index 353cc5742791..e286558ce60d 100644
--- a/lib/Target/AMDGPU/AMDGPUInstrInfo.td
+++ b/lib/Target/AMDGPU/AMDGPUInstrInfo.td
@@ -380,6 +380,6 @@ def AMDGPUendpgm : SDNode<"AMDGPUISD::ENDPGM", SDTNone,
def AMDGPUreturn_to_epilog : SDNode<"AMDGPUISD::RETURN_TO_EPILOG", SDTNone,
[SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
-def AMDGPUret_flag : SDNode<"AMDGPUISD::RET_FLAG", SDTNone,
+def AMDGPUret_flag : SDNode<"AMDGPUISD::RET_FLAG", SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>,
[SDNPHasChain, SDNPOptInGlue, SDNPVariadic]
>;
diff --git a/lib/Target/AMDGPU/AMDGPULowerIntrinsics.cpp b/lib/Target/AMDGPU/AMDGPULowerIntrinsics.cpp
index dcb6670621ee..846e7dff5f8c 100644
--- a/lib/Target/AMDGPU/AMDGPULowerIntrinsics.cpp
+++ b/lib/Target/AMDGPU/AMDGPULowerIntrinsics.cpp
@@ -9,6 +9,7 @@
#include "AMDGPU.h"
#include "AMDGPUSubtarget.h"
+#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
@@ -25,15 +26,13 @@ const unsigned MaxStaticSize = 1024;
class AMDGPULowerIntrinsics : public ModulePass {
private:
- const TargetMachine *TM;
-
bool makeLIDRangeMetadata(Function &F) const;
public:
static char ID;
- AMDGPULowerIntrinsics(const TargetMachine *TM = nullptr)
- : ModulePass(ID), TM(TM) { }
+ AMDGPULowerIntrinsics() : ModulePass(ID) {}
+
bool runOnModule(Module &M) override;
StringRef getPassName() const override {
return "AMDGPU Lower Intrinsics";
@@ -46,8 +45,8 @@ char AMDGPULowerIntrinsics::ID = 0;
char &llvm::AMDGPULowerIntrinsicsID = AMDGPULowerIntrinsics::ID;
-INITIALIZE_TM_PASS(AMDGPULowerIntrinsics, DEBUG_TYPE,
- "Lower intrinsics", false, false)
+INITIALIZE_PASS(AMDGPULowerIntrinsics, DEBUG_TYPE, "Lower intrinsics", false,
+ false)
// TODO: Should refine based on estimated number of accesses (e.g. does it
// require splitting based on alignment)
@@ -104,11 +103,13 @@ static bool expandMemIntrinsicUses(Function &F) {
}
bool AMDGPULowerIntrinsics::makeLIDRangeMetadata(Function &F) const {
- if (!TM)
+ auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
+ if (!TPC)
return false;
+ const TargetMachine &TM = TPC->getTM<TargetMachine>();
+ const AMDGPUSubtarget &ST = TM.getSubtarget<AMDGPUSubtarget>(F);
bool Changed = false;
- const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>(F);
for (auto *U : F.users()) {
auto *CI = dyn_cast<CallInst>(U);
@@ -155,6 +156,6 @@ bool AMDGPULowerIntrinsics::runOnModule(Module &M) {
return Changed;
}
-ModulePass *llvm::createAMDGPULowerIntrinsicsPass(const TargetMachine *TM) {
- return new AMDGPULowerIntrinsics(TM);
+ModulePass *llvm::createAMDGPULowerIntrinsicsPass() {
+ return new AMDGPULowerIntrinsics();
}
diff --git a/lib/Target/AMDGPU/AMDGPUMCInstLower.cpp b/lib/Target/AMDGPU/AMDGPUMCInstLower.cpp
index da247fea7de6..f1ef6281c90f 100644
--- a/lib/Target/AMDGPU/AMDGPUMCInstLower.cpp
+++ b/lib/Target/AMDGPU/AMDGPUMCInstLower.cpp
@@ -126,9 +126,15 @@ bool AMDGPUMCInstLower::lowerOperand(const MachineOperand &MO,
}
void AMDGPUMCInstLower::lower(const MachineInstr *MI, MCInst &OutMI) const {
+ unsigned Opcode = MI->getOpcode();
- int MCOpcode = ST.getInstrInfo()->pseudoToMCOpcode(MI->getOpcode());
+ // FIXME: Should be able to handle this with emitPseudoExpansionLowering. We
+ // need to select it to the subtarget specific version, and there's no way to
+ // do that with a single pseudo source operation.
+ if (Opcode == AMDGPU::S_SETPC_B64_return)
+ Opcode = AMDGPU::S_SETPC_B64;
+ int MCOpcode = ST.getInstrInfo()->pseudoToMCOpcode(Opcode);
if (MCOpcode == -1) {
LLVMContext &C = MI->getParent()->getParent()->getFunction()->getContext();
C.emitError("AMDGPUMCInstLower::lower - Pseudo instruction doesn't have "
diff --git a/lib/Target/AMDGPU/AMDGPUMachineFunction.cpp b/lib/Target/AMDGPU/AMDGPUMachineFunction.cpp
index fe7283ccf7d9..9fb7f5f88927 100644
--- a/lib/Target/AMDGPU/AMDGPUMachineFunction.cpp
+++ b/lib/Target/AMDGPU/AMDGPUMachineFunction.cpp
@@ -12,21 +12,6 @@
using namespace llvm;
-static bool isEntryFunctionCC(CallingConv::ID CC) {
- switch (CC) {
- case CallingConv::AMDGPU_KERNEL:
- case CallingConv::SPIR_KERNEL:
- case CallingConv::AMDGPU_VS:
- case CallingConv::AMDGPU_HS:
- case CallingConv::AMDGPU_GS:
- case CallingConv::AMDGPU_PS:
- case CallingConv::AMDGPU_CS:
- return true;
- default:
- return false;
- }
-}
-
AMDGPUMachineFunction::AMDGPUMachineFunction(const MachineFunction &MF) :
MachineFunctionInfo(),
LocalMemoryObjects(),
@@ -34,7 +19,7 @@ AMDGPUMachineFunction::AMDGPUMachineFunction(const MachineFunction &MF) :
MaxKernArgAlign(0),
LDSSize(0),
ABIArgOffset(0),
- IsEntryFunction(isEntryFunctionCC(MF.getFunction()->getCallingConv())),
+ IsEntryFunction(AMDGPU::isEntryFunctionCC(MF.getFunction()->getCallingConv())),
NoSignedZerosFPMath(MF.getTarget().Options.NoSignedZerosFPMath) {
// FIXME: Should initialize KernArgSize based on ExplicitKernelArgOffset,
// except reserved size is not correctly aligned.
diff --git a/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp b/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
index e40f39557747..85184b363905 100644
--- a/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
+++ b/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
@@ -23,6 +23,7 @@
#include "llvm/ADT/Twine.h"
#include "llvm/Analysis/CaptureTracking.h"
#include "llvm/Analysis/ValueTracking.h"
+#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constant.h"
@@ -99,8 +100,7 @@ private:
public:
static char ID;
- AMDGPUPromoteAlloca(const TargetMachine *TM_ = nullptr) :
- FunctionPass(ID), TM(TM_) {}
+ AMDGPUPromoteAlloca() : FunctionPass(ID) {}
bool doInitialization(Module &M) override;
bool runOnFunction(Function &F) override;
@@ -119,30 +119,31 @@ public:
char AMDGPUPromoteAlloca::ID = 0;
-INITIALIZE_TM_PASS(AMDGPUPromoteAlloca, DEBUG_TYPE,
- "AMDGPU promote alloca to vector or LDS", false, false)
+INITIALIZE_PASS(AMDGPUPromoteAlloca, DEBUG_TYPE,
+ "AMDGPU promote alloca to vector or LDS", false, false)
char &llvm::AMDGPUPromoteAllocaID = AMDGPUPromoteAlloca::ID;
bool AMDGPUPromoteAlloca::doInitialization(Module &M) {
- if (!TM)
- return false;
-
Mod = &M;
DL = &Mod->getDataLayout();
- const Triple &TT = TM->getTargetTriple();
-
- IsAMDGCN = TT.getArch() == Triple::amdgcn;
- IsAMDHSA = TT.getOS() == Triple::AMDHSA;
-
return false;
}
bool AMDGPUPromoteAlloca::runOnFunction(Function &F) {
- if (!TM || skipFunction(F))
+ if (skipFunction(F))
return false;
+ if (auto *TPC = getAnalysisIfAvailable<TargetPassConfig>())
+ TM = &TPC->getTM<TargetMachine>();
+ else
+ return false;
+
+ const Triple &TT = TM->getTargetTriple();
+ IsAMDGCN = TT.getArch() == Triple::amdgcn;
+ IsAMDHSA = TT.getOS() == Triple::AMDHSA;
+
const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>(F);
if (!ST.isPromoteAllocaEnabled())
return false;
@@ -874,6 +875,6 @@ void AMDGPUPromoteAlloca::handleAlloca(AllocaInst &I) {
}
}
-FunctionPass *llvm::createAMDGPUPromoteAlloca(const TargetMachine *TM) {
- return new AMDGPUPromoteAlloca(TM);
+FunctionPass *llvm::createAMDGPUPromoteAlloca() {
+ return new AMDGPUPromoteAlloca();
}
diff --git a/lib/Target/AMDGPU/AMDGPURegisterInfo.cpp b/lib/Target/AMDGPU/AMDGPURegisterInfo.cpp
index 941f2d8a468a..b2867fcc49f9 100644
--- a/lib/Target/AMDGPU/AMDGPURegisterInfo.cpp
+++ b/lib/Target/AMDGPU/AMDGPURegisterInfo.cpp
@@ -14,6 +14,7 @@
#include "AMDGPURegisterInfo.h"
#include "AMDGPUTargetMachine.h"
+#include "SIRegisterInfo.h"
using namespace llvm;
@@ -24,18 +25,6 @@ AMDGPURegisterInfo::AMDGPURegisterInfo() : AMDGPUGenRegisterInfo(0) {}
// they are not supported at this time.
//===----------------------------------------------------------------------===//
-// Dummy to not crash RegisterClassInfo.
-static const MCPhysReg CalleeSavedReg = AMDGPU::NoRegister;
-
-const MCPhysReg *AMDGPURegisterInfo::getCalleeSavedRegs(
- const MachineFunction *) const {
- return &CalleeSavedReg;
-}
-
-unsigned AMDGPURegisterInfo::getFrameRegister(const MachineFunction &MF) const {
- return AMDGPU::NoRegister;
-}
-
unsigned AMDGPURegisterInfo::getSubRegFromChannel(unsigned Channel) const {
static const unsigned SubRegs[] = {
AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3, AMDGPU::sub4,
@@ -50,3 +39,35 @@ unsigned AMDGPURegisterInfo::getSubRegFromChannel(unsigned Channel) const {
#define GET_REGINFO_TARGET_DESC
#include "AMDGPUGenRegisterInfo.inc"
+
+
+// Forced to be here by one .inc
+const MCPhysReg *SIRegisterInfo::getCalleeSavedRegs(
+ const MachineFunction *MF) const {
+ CallingConv::ID CC = MF->getFunction()->getCallingConv();
+ switch (CC) {
+ case CallingConv::C:
+ case CallingConv::Fast:
+ return CSR_AMDGPU_HighRegs_SaveList;
+ default: {
+ // Dummy to not crash RegisterClassInfo.
+ static const MCPhysReg NoCalleeSavedReg = AMDGPU::NoRegister;
+ return &NoCalleeSavedReg;
+ }
+ }
+}
+
+const uint32_t *SIRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
+ CallingConv::ID CC) const {
+ switch (CC) {
+ case CallingConv::C:
+ case CallingConv::Fast:
+ return CSR_AMDGPU_HighRegs_RegMask;
+ default:
+ return nullptr;
+ }
+}
+
+unsigned SIRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
+ return AMDGPU::NoRegister;
+}
diff --git a/lib/Target/AMDGPU/AMDGPURegisterInfo.h b/lib/Target/AMDGPU/AMDGPURegisterInfo.h
index 22b1663821d9..d8604d2590f1 100644
--- a/lib/Target/AMDGPU/AMDGPURegisterInfo.h
+++ b/lib/Target/AMDGPU/AMDGPURegisterInfo.h
@@ -30,9 +30,6 @@ struct AMDGPURegisterInfo : public AMDGPUGenRegisterInfo {
/// \returns the sub reg enum value for the given \p Channel
/// (e.g. getSubRegFromChannel(0) -> AMDGPU::sub0)
unsigned getSubRegFromChannel(unsigned Channel) const;
-
- const MCPhysReg* getCalleeSavedRegs(const MachineFunction *MF) const override;
- unsigned getFrameRegister(const MachineFunction &MF) const override;
};
} // End namespace llvm
diff --git a/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp b/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp
index 386a88b0520f..a9d3a31a7240 100644
--- a/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp
+++ b/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp
@@ -570,7 +570,7 @@ void AMDGPUPassConfig::addIRPasses() {
disablePass(&FuncletLayoutID);
disablePass(&PatchableFunctionID);
- addPass(createAMDGPULowerIntrinsicsPass(&TM));
+ addPass(createAMDGPULowerIntrinsicsPass());
// Function calls are not supported, so make sure we inline everything.
addPass(createAMDGPUAlwaysInlinePass());
@@ -585,8 +585,7 @@ void AMDGPUPassConfig::addIRPasses() {
if (TM.getTargetTriple().getArch() == Triple::amdgcn) {
// TODO: May want to move later or split into an early and late one.
- addPass(createAMDGPUCodeGenPreparePass(
- static_cast<const GCNTargetMachine *>(&TM)));
+ addPass(createAMDGPUCodeGenPreparePass());
}
// Handle uses of OpenCL image2d_t, image3d_t and sampler_t arguments.
@@ -594,7 +593,7 @@ void AMDGPUPassConfig::addIRPasses() {
if (TM.getOptLevel() > CodeGenOpt::None) {
addPass(createInferAddressSpacesPass());
- addPass(createAMDGPUPromoteAlloca(&TM));
+ addPass(createAMDGPUPromoteAlloca());
if (EnableSROA)
addPass(createSROAPass());
@@ -664,22 +663,22 @@ bool R600PassConfig::addPreISel() {
}
void R600PassConfig::addPreRegAlloc() {
- addPass(createR600VectorRegMerger(*TM));
+ addPass(createR600VectorRegMerger());
}
void R600PassConfig::addPreSched2() {
addPass(createR600EmitClauseMarkers(), false);
if (EnableR600IfConvert)
addPass(&IfConverterID, false);
- addPass(createR600ClauseMergePass(*TM), false);
+ addPass(createR600ClauseMergePass(), false);
}
void R600PassConfig::addPreEmitPass() {
addPass(createAMDGPUCFGStructurizerPass(), false);
- addPass(createR600ExpandSpecialInstrsPass(*TM), false);
+ addPass(createR600ExpandSpecialInstrsPass(), false);
addPass(&FinalizeMachineBundlesID, false);
- addPass(createR600Packetizer(*TM), false);
- addPass(createR600ControlFlowFinalizer(*TM), false);
+ addPass(createR600Packetizer(), false);
+ addPass(createR600ControlFlowFinalizer(), false);
}
TargetPassConfig *R600TargetMachine::createPassConfig(PassManagerBase &PM) {
@@ -703,8 +702,7 @@ bool GCNPassConfig::addPreISel() {
// FIXME: We need to run a pass to propagate the attributes when calls are
// supported.
- const AMDGPUTargetMachine &TM = getAMDGPUTargetMachine();
- addPass(createAMDGPUAnnotateKernelFeaturesPass(&TM));
+ addPass(createAMDGPUAnnotateKernelFeaturesPass());
// Merge divergent exit nodes. StructurizeCFG won't recognize the multi-exit
// regions formed by them.
diff --git a/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
index 70c848f3c7bd..b52ea2b3a2c6 100644
--- a/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
+++ b/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
@@ -2796,6 +2796,7 @@ void AMDGPUAsmParser::cvtDSImpl(MCInst &Inst, const OperandVector &Operands,
void AMDGPUAsmParser::cvtExp(MCInst &Inst, const OperandVector &Operands) {
OptionalImmIndexMap OptionalIdx;
+ unsigned OperandIdx[4];
unsigned EnMask = 0;
int SrcIdx = 0;
@@ -2804,15 +2805,18 @@ void AMDGPUAsmParser::cvtExp(MCInst &Inst, const OperandVector &Operands) {
// Add the register arguments
if (Op.isReg()) {
- EnMask |= (1 << SrcIdx);
+ assert(SrcIdx < 4);
+ OperandIdx[SrcIdx] = Inst.size();
Op.addRegOperands(Inst, 1);
++SrcIdx;
continue;
}
if (Op.isOff()) {
- ++SrcIdx;
+ assert(SrcIdx < 4);
+ OperandIdx[SrcIdx] = Inst.size();
Inst.addOperand(MCOperand::createReg(AMDGPU::NoRegister));
+ ++SrcIdx;
continue;
}
@@ -2828,6 +2832,22 @@ void AMDGPUAsmParser::cvtExp(MCInst &Inst, const OperandVector &Operands) {
OptionalIdx[Op.getImmTy()] = i;
}
+ assert(SrcIdx == 4);
+
+ bool Compr = false;
+ if (OptionalIdx.find(AMDGPUOperand::ImmTyExpCompr) != OptionalIdx.end()) {
+ Compr = true;
+ Inst.getOperand(OperandIdx[1]) = Inst.getOperand(OperandIdx[2]);
+ Inst.getOperand(OperandIdx[2]).setReg(AMDGPU::NoRegister);
+ Inst.getOperand(OperandIdx[3]).setReg(AMDGPU::NoRegister);
+ }
+
+ for (auto i = 0; i < SrcIdx; ++i) {
+ if (Inst.getOperand(OperandIdx[i]).getReg() != AMDGPU::NoRegister) {
+ EnMask |= Compr? (0x3 << i * 2) : (0x1 << i);
+ }
+ }
+
addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpVM);
addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpCompr);
@@ -3642,6 +3662,7 @@ static const OptionalOperand AMDGPUOptionalOperandTable[] = {
{"src0_sel", AMDGPUOperand::ImmTySdwaSrc0Sel, false, nullptr},
{"src1_sel", AMDGPUOperand::ImmTySdwaSrc1Sel, false, nullptr},
{"dst_unused", AMDGPUOperand::ImmTySdwaDstUnused, false, nullptr},
+ {"compr", AMDGPUOperand::ImmTyExpCompr, true, nullptr },
{"vm", AMDGPUOperand::ImmTyExpVM, true, nullptr},
{"op_sel", AMDGPUOperand::ImmTyOpSel, false, nullptr},
{"op_sel_hi", AMDGPUOperand::ImmTyOpSelHi, false, nullptr},
diff --git a/lib/Target/AMDGPU/BUFInstructions.td b/lib/Target/AMDGPU/BUFInstructions.td
index 89eddb9ce961..2aca65ac8430 100644
--- a/lib/Target/AMDGPU/BUFInstructions.td
+++ b/lib/Target/AMDGPU/BUFInstructions.td
@@ -11,8 +11,8 @@ def MUBUFAddr32 : ComplexPattern<i64, 9, "SelectMUBUFAddr32">;
def MUBUFAddr64 : ComplexPattern<i64, 7, "SelectMUBUFAddr64">;
def MUBUFAddr64Atomic : ComplexPattern<i64, 5, "SelectMUBUFAddr64">;
-def MUBUFScratchOffen : ComplexPattern<i64, 4, "SelectMUBUFScratchOffen">;
-def MUBUFScratchOffset : ComplexPattern<i64, 3, "SelectMUBUFScratchOffset", [], [], 20>;
+def MUBUFScratchOffen : ComplexPattern<i64, 4, "SelectMUBUFScratchOffen", [], [SDNPWantRoot]>;
+def MUBUFScratchOffset : ComplexPattern<i64, 3, "SelectMUBUFScratchOffset", [], [SDNPWantRoot], 20>;
def MUBUFOffset : ComplexPattern<i64, 6, "SelectMUBUFOffset">;
def MUBUFOffsetNoGLC : ComplexPattern<i64, 3, "SelectMUBUFOffset">;
diff --git a/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp b/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
index 4fb03b62bba9..137b5cca96ce 100644
--- a/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
+++ b/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
@@ -126,6 +126,7 @@ DecodeStatus AMDGPUDisassembler::tryDecodeInst(const uint8_t* Table,
assert(MI.getOpcode() == 0);
assert(MI.getNumOperands() == 0);
MCInst TmpInst;
+ HasLiteral = false;
const auto SavedBytes = Bytes;
if (decodeInstruction(Table, TmpInst, Inst, Address, this, STI)) {
MI = TmpInst;
@@ -343,10 +344,15 @@ MCOperand AMDGPUDisassembler::decodeLiteralConstant() const {
// For now all literal constants are supposed to be unsigned integer
// ToDo: deal with signed/unsigned 64-bit integer constants
// ToDo: deal with float/double constants
- if (Bytes.size() < 4)
- return errOperand(0, "cannot read literal, inst bytes left " +
- Twine(Bytes.size()));
- return MCOperand::createImm(eatBytes<uint32_t>(Bytes));
+ if (!HasLiteral) {
+ if (Bytes.size() < 4) {
+ return errOperand(0, "cannot read literal, inst bytes left " +
+ Twine(Bytes.size()));
+ }
+ HasLiteral = true;
+ Literal = eatBytes<uint32_t>(Bytes);
+ }
+ return MCOperand::createImm(Literal);
}
MCOperand AMDGPUDisassembler::decodeIntImmed(unsigned Imm) {
diff --git a/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h b/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h
index d50665187e10..620bae0a6d1a 100644
--- a/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h
+++ b/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h
@@ -39,6 +39,8 @@ class Twine;
class AMDGPUDisassembler : public MCDisassembler {
private:
mutable ArrayRef<uint8_t> Bytes;
+ mutable uint32_t Literal;
+ mutable bool HasLiteral;
public:
AMDGPUDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx) :
diff --git a/lib/Target/AMDGPU/GCNRegPressure.cpp b/lib/Target/AMDGPU/GCNRegPressure.cpp
index 8066428fe44a..18374dca3f84 100644
--- a/lib/Target/AMDGPU/GCNRegPressure.cpp
+++ b/lib/Target/AMDGPU/GCNRegPressure.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "GCNRegPressure.h"
+#include "llvm/CodeGen/RegisterPressure.h"
using namespace llvm;
@@ -63,15 +64,6 @@ static bool isEqual(const GCNRPTracker::LiveRegSet &S1,
return true;
}
-static GCNRPTracker::LiveRegSet
-stripEmpty(const GCNRPTracker::LiveRegSet &LR) {
- GCNRPTracker::LiveRegSet Res;
- for (const auto &P : LR) {
- if (P.second.any())
- Res.insert(P);
- }
- return Res;
-}
#endif
///////////////////////////////////////////////////////////////////////////////
@@ -185,6 +177,64 @@ void GCNRegPressure::print(raw_ostream &OS, const SISubtarget *ST) const {
}
#endif
+
+static LaneBitmask getDefRegMask(const MachineOperand &MO,
+ const MachineRegisterInfo &MRI) {
+ assert(MO.isDef() && MO.isReg() &&
+ TargetRegisterInfo::isVirtualRegister(MO.getReg()));
+
+ // We don't rely on read-undef flag because in case of tentative schedule
+ // tracking it isn't set correctly yet. This works correctly however since
+ // use mask has been tracked before using LIS.
+ return MO.getSubReg() == 0 ?
+ MRI.getMaxLaneMaskForVReg(MO.getReg()) :
+ MRI.getTargetRegisterInfo()->getSubRegIndexLaneMask(MO.getSubReg());
+}
+
+static LaneBitmask getUsedRegMask(const MachineOperand &MO,
+ const MachineRegisterInfo &MRI,
+ const LiveIntervals &LIS) {
+ assert(MO.isUse() && MO.isReg() &&
+ TargetRegisterInfo::isVirtualRegister(MO.getReg()));
+
+ if (auto SubReg = MO.getSubReg())
+ return MRI.getTargetRegisterInfo()->getSubRegIndexLaneMask(SubReg);
+
+ auto MaxMask = MRI.getMaxLaneMaskForVReg(MO.getReg());
+ if (MaxMask.getAsInteger() == 1) // cannot have subregs
+ return MaxMask;
+
+ // For a tentative schedule LIS isn't updated yet but livemask should remain
+ // the same on any schedule. Subreg defs can be reordered but they all must
+ // dominate uses anyway.
+ auto SI = LIS.getInstructionIndex(*MO.getParent()).getBaseIndex();
+ return getLiveLaneMask(MO.getReg(), SI, LIS, MRI);
+}
+
+SmallVector<RegisterMaskPair, 8> collectVirtualRegUses(const MachineInstr &MI,
+ const LiveIntervals &LIS,
+ const MachineRegisterInfo &MRI) {
+ SmallVector<RegisterMaskPair, 8> Res;
+ for (const auto &MO : MI.operands()) {
+ if (!MO.isReg() || !TargetRegisterInfo::isVirtualRegister(MO.getReg()))
+ continue;
+ if (!MO.isUse() || !MO.readsReg())
+ continue;
+
+ auto const UsedMask = getUsedRegMask(MO, MRI, LIS);
+
+ auto Reg = MO.getReg();
+ auto I = std::find_if(Res.begin(), Res.end(), [Reg](const RegisterMaskPair &RM) {
+ return RM.RegUnit == Reg;
+ });
+ if (I != Res.end())
+ I->LaneMask |= UsedMask;
+ else
+ Res.push_back(RegisterMaskPair(Reg, UsedMask));
+ }
+ return Res;
+}
+
///////////////////////////////////////////////////////////////////////////////
// GCNRPTracker
@@ -222,36 +272,6 @@ GCNRPTracker::LiveRegSet llvm::getLiveRegs(SlotIndex SI,
return LiveRegs;
}
-LaneBitmask GCNRPTracker::getDefRegMask(const MachineOperand &MO) const {
- assert(MO.isDef() && MO.isReg() &&
- TargetRegisterInfo::isVirtualRegister(MO.getReg()));
-
- // We don't rely on read-undef flag because in case of tentative schedule
- // tracking it isn't set correctly yet. This works correctly however since
- // use mask has been tracked before using LIS.
- return MO.getSubReg() == 0 ?
- MRI->getMaxLaneMaskForVReg(MO.getReg()) :
- MRI->getTargetRegisterInfo()->getSubRegIndexLaneMask(MO.getSubReg());
-}
-
-LaneBitmask GCNRPTracker::getUsedRegMask(const MachineOperand &MO) const {
- assert(MO.isUse() && MO.isReg() &&
- TargetRegisterInfo::isVirtualRegister(MO.getReg()));
-
- if (auto SubReg = MO.getSubReg())
- return MRI->getTargetRegisterInfo()->getSubRegIndexLaneMask(SubReg);
-
- auto MaxMask = MRI->getMaxLaneMaskForVReg(MO.getReg());
- if (MaxMask.getAsInteger() == 1) // cannot have subregs
- return MaxMask;
-
- // For a tentative schedule LIS isn't updated yet but livemask should remain
- // the same on any schedule. Subreg defs can be reordered but they all must
- // dominate uses anyway.
- auto SI = LIS.getInstructionIndex(*MO.getParent()).getBaseIndex();
- return getLiveLaneMask(MO.getReg(), SI, LIS, *MRI);
-}
-
void GCNUpwardRPTracker::reset(const MachineInstr &MI,
const LiveRegSet *LiveRegsCopy) {
MRI = &MI.getParent()->getParent()->getRegInfo();
@@ -272,34 +292,40 @@ void GCNUpwardRPTracker::recede(const MachineInstr &MI) {
if (MI.isDebugValue())
return;
- // process all defs first to ensure early clobbers are handled correctly
- // iterating over operands() to catch implicit defs
- for (const auto &MO : MI.operands()) {
- if (!MO.isReg() || !MO.isDef() ||
- !TargetRegisterInfo::isVirtualRegister(MO.getReg()))
- continue;
+ auto const RegUses = collectVirtualRegUses(MI, LIS, *MRI);
- auto Reg = MO.getReg();
- auto &LiveMask = LiveRegs[Reg];
- auto PrevMask = LiveMask;
- LiveMask &= ~getDefRegMask(MO);
- CurPressure.inc(Reg, PrevMask, LiveMask, *MRI);
+ // calc pressure at the MI (defs + uses)
+ auto AtMIPressure = CurPressure;
+ for (const auto &U : RegUses) {
+ auto LiveMask = LiveRegs[U.RegUnit];
+ AtMIPressure.inc(U.RegUnit, LiveMask, LiveMask | U.LaneMask, *MRI);
}
+ // update max pressure
+ MaxPressure = max(AtMIPressure, MaxPressure);
- // then all uses
- for (const auto &MO : MI.uses()) {
- if (!MO.isReg() || !MO.readsReg() ||
- !TargetRegisterInfo::isVirtualRegister(MO.getReg()))
+ for (const auto &MO : MI.defs()) {
+ if (!MO.isReg() || !TargetRegisterInfo::isVirtualRegister(MO.getReg()) ||
+ MO.isDead())
continue;
auto Reg = MO.getReg();
- auto &LiveMask = LiveRegs[Reg];
+ auto I = LiveRegs.find(Reg);
+ if (I == LiveRegs.end())
+ continue;
+ auto &LiveMask = I->second;
auto PrevMask = LiveMask;
- LiveMask |= getUsedRegMask(MO);
+ LiveMask &= ~getDefRegMask(MO, *MRI);
CurPressure.inc(Reg, PrevMask, LiveMask, *MRI);
+ if (LiveMask.none())
+ LiveRegs.erase(I);
}
-
- MaxPressure = max(MaxPressure, CurPressure);
+ for (const auto &U : RegUses) {
+ auto &LiveMask = LiveRegs[U.RegUnit];
+ auto PrevMask = LiveMask;
+ LiveMask |= U.LaneMask;
+ CurPressure.inc(U.RegUnit, PrevMask, LiveMask, *MRI);
+ }
+ assert(CurPressure == getRegPressure(*MRI, LiveRegs));
}
bool GCNDownwardRPTracker::reset(const MachineInstr &MI,
@@ -368,7 +394,7 @@ void GCNDownwardRPTracker::advanceToNext() {
continue;
auto &LiveMask = LiveRegs[Reg];
auto PrevMask = LiveMask;
- LiveMask |= getDefRegMask(MO);
+ LiveMask |= getDefRegMask(MO, *MRI);
CurPressure.inc(Reg, PrevMask, LiveMask, *MRI);
}
@@ -430,7 +456,7 @@ static void reportMismatch(const GCNRPTracker::LiveRegSet &LISLR,
bool GCNUpwardRPTracker::isValid() const {
const auto &SI = LIS.getInstructionIndex(*LastTrackedMI).getBaseIndex();
const auto LISLR = llvm::getLiveRegs(SI, LIS, *MRI);
- const auto TrackedLR = stripEmpty(LiveRegs);
+ const auto &TrackedLR = LiveRegs;
if (!isEqual(LISLR, TrackedLR)) {
dbgs() << "\nGCNUpwardRPTracker error: Tracked and"
diff --git a/lib/Target/AMDGPU/GCNRegPressure.h b/lib/Target/AMDGPU/GCNRegPressure.h
index 9875ca6a6d16..5dfe44053e72 100644
--- a/lib/Target/AMDGPU/GCNRegPressure.h
+++ b/lib/Target/AMDGPU/GCNRegPressure.h
@@ -98,8 +98,6 @@ protected:
const MachineInstr *LastTrackedMI = nullptr;
mutable const MachineRegisterInfo *MRI = nullptr;
GCNRPTracker(const LiveIntervals &LIS_) : LIS(LIS_) {}
- LaneBitmask getDefRegMask(const MachineOperand &MO) const;
- LaneBitmask getUsedRegMask(const MachineOperand &MO) const;
public:
// live regs for the current state
const decltype(LiveRegs) &getLiveRegs() const { return LiveRegs; }
diff --git a/lib/Target/AMDGPU/R600ClauseMergePass.cpp b/lib/Target/AMDGPU/R600ClauseMergePass.cpp
index d0aba38f786d..fbe45cb222d9 100644
--- a/lib/Target/AMDGPU/R600ClauseMergePass.cpp
+++ b/lib/Target/AMDGPU/R600ClauseMergePass.cpp
@@ -62,7 +62,7 @@ private:
const MachineInstr &LatrCFAlu) const;
public:
- R600ClauseMergePass(TargetMachine &tm) : MachineFunctionPass(ID) { }
+ R600ClauseMergePass() : MachineFunctionPass(ID) { }
bool runOnMachineFunction(MachineFunction &MF) override;
@@ -208,6 +208,6 @@ StringRef R600ClauseMergePass::getPassName() const {
} // end anonymous namespace
-llvm::FunctionPass *llvm::createR600ClauseMergePass(TargetMachine &TM) {
- return new R600ClauseMergePass(TM);
+llvm::FunctionPass *llvm::createR600ClauseMergePass() {
+ return new R600ClauseMergePass();
}
diff --git a/lib/Target/AMDGPU/R600ControlFlowFinalizer.cpp b/lib/Target/AMDGPU/R600ControlFlowFinalizer.cpp
index 811b905588b4..09b328765604 100644
--- a/lib/Target/AMDGPU/R600ControlFlowFinalizer.cpp
+++ b/lib/Target/AMDGPU/R600ControlFlowFinalizer.cpp
@@ -499,7 +499,7 @@ private:
}
public:
- R600ControlFlowFinalizer(TargetMachine &tm) : MachineFunctionPass(ID) {}
+ R600ControlFlowFinalizer() : MachineFunctionPass(ID) {}
bool runOnMachineFunction(MachineFunction &MF) override {
ST = &MF.getSubtarget<R600Subtarget>();
@@ -706,6 +706,6 @@ char R600ControlFlowFinalizer::ID = 0;
} // end anonymous namespace
-FunctionPass *llvm::createR600ControlFlowFinalizer(TargetMachine &TM) {
- return new R600ControlFlowFinalizer(TM);
+FunctionPass *llvm::createR600ControlFlowFinalizer() {
+ return new R600ControlFlowFinalizer();
}
diff --git a/lib/Target/AMDGPU/R600ExpandSpecialInstrs.cpp b/lib/Target/AMDGPU/R600ExpandSpecialInstrs.cpp
index 3e46e6387614..5c30a0734f0d 100644
--- a/lib/Target/AMDGPU/R600ExpandSpecialInstrs.cpp
+++ b/lib/Target/AMDGPU/R600ExpandSpecialInstrs.cpp
@@ -37,7 +37,7 @@ private:
unsigned Op);
public:
- R600ExpandSpecialInstrsPass(TargetMachine &tm) : MachineFunctionPass(ID),
+ R600ExpandSpecialInstrsPass() : MachineFunctionPass(ID),
TII(nullptr) { }
bool runOnMachineFunction(MachineFunction &MF) override;
@@ -51,8 +51,8 @@ public:
char R600ExpandSpecialInstrsPass::ID = 0;
-FunctionPass *llvm::createR600ExpandSpecialInstrsPass(TargetMachine &TM) {
- return new R600ExpandSpecialInstrsPass(TM);
+FunctionPass *llvm::createR600ExpandSpecialInstrsPass() {
+ return new R600ExpandSpecialInstrsPass();
}
void R600ExpandSpecialInstrsPass::SetFlagInNewMI(MachineInstr *NewMI,
diff --git a/lib/Target/AMDGPU/R600OptimizeVectorRegisters.cpp b/lib/Target/AMDGPU/R600OptimizeVectorRegisters.cpp
index d90008a550ae..502dd3bce97e 100644
--- a/lib/Target/AMDGPU/R600OptimizeVectorRegisters.cpp
+++ b/lib/Target/AMDGPU/R600OptimizeVectorRegisters.cpp
@@ -124,7 +124,7 @@ private:
public:
static char ID;
- R600VectorRegMerger(TargetMachine &tm) : MachineFunctionPass(ID),
+ R600VectorRegMerger() : MachineFunctionPass(ID),
TII(nullptr) { }
void getAnalysisUsage(AnalysisUsage &AU) const override {
@@ -396,6 +396,6 @@ bool R600VectorRegMerger::runOnMachineFunction(MachineFunction &Fn) {
return false;
}
-llvm::FunctionPass *llvm::createR600VectorRegMerger(TargetMachine &tm) {
- return new R600VectorRegMerger(tm);
+llvm::FunctionPass *llvm::createR600VectorRegMerger() {
+ return new R600VectorRegMerger();
}
diff --git a/lib/Target/AMDGPU/R600Packetizer.cpp b/lib/Target/AMDGPU/R600Packetizer.cpp
index 5b6dd1ed128d..3e957126b497 100644
--- a/lib/Target/AMDGPU/R600Packetizer.cpp
+++ b/lib/Target/AMDGPU/R600Packetizer.cpp
@@ -36,7 +36,7 @@ class R600Packetizer : public MachineFunctionPass {
public:
static char ID;
- R600Packetizer(const TargetMachine &TM) : MachineFunctionPass(ID) {}
+ R600Packetizer() : MachineFunctionPass(ID) {}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesCFG();
@@ -404,6 +404,6 @@ bool R600Packetizer::runOnMachineFunction(MachineFunction &Fn) {
} // end anonymous namespace
-llvm::FunctionPass *llvm::createR600Packetizer(TargetMachine &tm) {
- return new R600Packetizer(tm);
+llvm::FunctionPass *llvm::createR600Packetizer() {
+ return new R600Packetizer();
}
diff --git a/lib/Target/AMDGPU/R600RegisterInfo.cpp b/lib/Target/AMDGPU/R600RegisterInfo.cpp
index dfdc602b80cd..7501facb0cba 100644
--- a/lib/Target/AMDGPU/R600RegisterInfo.cpp
+++ b/lib/Target/AMDGPU/R600RegisterInfo.cpp
@@ -56,6 +56,18 @@ BitVector R600RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
return Reserved;
}
+// Dummy to not crash RegisterClassInfo.
+static const MCPhysReg CalleeSavedReg = AMDGPU::NoRegister;
+
+const MCPhysReg *R600RegisterInfo::getCalleeSavedRegs(
+ const MachineFunction *) const {
+ return &CalleeSavedReg;
+}
+
+unsigned R600RegisterInfo::getFrameRegister(const MachineFunction &MF) const {
+ return AMDGPU::NoRegister;
+}
+
unsigned R600RegisterInfo::getHWRegChan(unsigned reg) const {
return this->getEncodingValue(reg) >> HW_CHAN_SHIFT;
}
diff --git a/lib/Target/AMDGPU/R600RegisterInfo.h b/lib/Target/AMDGPU/R600RegisterInfo.h
index 9dfb3106c6cc..f0d9644b02f2 100644
--- a/lib/Target/AMDGPU/R600RegisterInfo.h
+++ b/lib/Target/AMDGPU/R600RegisterInfo.h
@@ -27,6 +27,8 @@ struct R600RegisterInfo final : public AMDGPURegisterInfo {
R600RegisterInfo();
BitVector getReservedRegs(const MachineFunction &MF) const override;
+ const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override;
+ unsigned getFrameRegister(const MachineFunction &MF) const override;
/// \brief get the HW encoding for a register's channel.
unsigned getHWRegChan(unsigned reg) const;
diff --git a/lib/Target/AMDGPU/SIFrameLowering.cpp b/lib/Target/AMDGPU/SIFrameLowering.cpp
index 1279f845de0e..97bb0f0c0656 100644
--- a/lib/Target/AMDGPU/SIFrameLowering.cpp
+++ b/lib/Target/AMDGPU/SIFrameLowering.cpp
@@ -189,8 +189,6 @@ SIFrameLowering::getReservedPrivateSegmentWaveByteOffsetReg(
// ----
// 13 (+1)
unsigned ReservedRegCount = 13;
- if (SPReg != AMDGPU::NoRegister)
- ++ReservedRegCount;
if (AllSGPRs.size() < ReservedRegCount)
return std::make_pair(ScratchWaveOffsetReg, SPReg);
@@ -208,13 +206,6 @@ SIFrameLowering::getReservedPrivateSegmentWaveByteOffsetReg(
MRI.replaceRegWith(ScratchWaveOffsetReg, Reg);
MFI->setScratchWaveOffsetReg(Reg);
ScratchWaveOffsetReg = Reg;
- } else {
- if (SPReg == AMDGPU::NoRegister)
- break;
-
- MRI.replaceRegWith(SPReg, Reg);
- MFI->setStackPtrOffsetReg(Reg);
- SPReg = Reg;
break;
}
}
@@ -223,8 +214,8 @@ SIFrameLowering::getReservedPrivateSegmentWaveByteOffsetReg(
return std::make_pair(ScratchWaveOffsetReg, SPReg);
}
-void SIFrameLowering::emitPrologue(MachineFunction &MF,
- MachineBasicBlock &MBB) const {
+void SIFrameLowering::emitEntryFunctionPrologue(MachineFunction &MF,
+ MachineBasicBlock &MBB) const {
// Emit debugger prologue if "amdgpu-debugger-emit-prologue" attribute was
// specified.
const SISubtarget &ST = MF.getSubtarget<SISubtarget>();
@@ -424,6 +415,13 @@ void SIFrameLowering::emitPrologue(MachineFunction &MF,
}
}
+void SIFrameLowering::emitPrologue(MachineFunction &MF,
+ MachineBasicBlock &MBB) const {
+ const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
+ if (MFI->isEntryFunction())
+ emitEntryFunctionPrologue(MF, MBB);
+}
+
void SIFrameLowering::emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
diff --git a/lib/Target/AMDGPU/SIFrameLowering.h b/lib/Target/AMDGPU/SIFrameLowering.h
index 7ccd02b3c86a..e17adbe27361 100644
--- a/lib/Target/AMDGPU/SIFrameLowering.h
+++ b/lib/Target/AMDGPU/SIFrameLowering.h
@@ -26,6 +26,8 @@ public:
AMDGPUFrameLowering(D, StackAl, LAO, TransAl) {}
~SIFrameLowering() override = default;
+ void emitEntryFunctionPrologue(MachineFunction &MF,
+ MachineBasicBlock &MBB) const;
void emitPrologue(MachineFunction &MF,
MachineBasicBlock &MBB) const override;
void emitEpilogue(MachineFunction &MF,
diff --git a/lib/Target/AMDGPU/SIISelLowering.cpp b/lib/Target/AMDGPU/SIISelLowering.cpp
index 286be355bc14..01c1f78e7ca4 100644
--- a/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -914,6 +914,55 @@ SDValue SITargetLowering::lowerKernargMemParameter(
return DAG.getMergeValues({ Val, Load.getValue(1) }, SL);
}
+SDValue SITargetLowering::lowerStackParameter(SelectionDAG &DAG, CCValAssign &VA,
+ const SDLoc &SL, SDValue Chain,
+ const ISD::InputArg &Arg) const {
+ MachineFunction &MF = DAG.getMachineFunction();
+ MachineFrameInfo &MFI = MF.getFrameInfo();
+
+ if (Arg.Flags.isByVal()) {
+ unsigned Size = Arg.Flags.getByValSize();
+ int FrameIdx = MFI.CreateFixedObject(Size, VA.getLocMemOffset(), false);
+ return DAG.getFrameIndex(FrameIdx, MVT::i32);
+ }
+
+ unsigned ArgOffset = VA.getLocMemOffset();
+ unsigned ArgSize = VA.getValVT().getStoreSize();
+
+ int FI = MFI.CreateFixedObject(ArgSize, ArgOffset, true);
+
+ // Create load nodes to retrieve arguments from the stack.
+ SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
+ SDValue ArgValue;
+
+ // For NON_EXTLOAD, generic code in getLoad assert(ValVT == MemVT)
+ ISD::LoadExtType ExtType = ISD::NON_EXTLOAD;
+ MVT MemVT = VA.getValVT();
+
+ switch (VA.getLocInfo()) {
+ default:
+ break;
+ case CCValAssign::BCvt:
+ MemVT = VA.getLocVT();
+ break;
+ case CCValAssign::SExt:
+ ExtType = ISD::SEXTLOAD;
+ break;
+ case CCValAssign::ZExt:
+ ExtType = ISD::ZEXTLOAD;
+ break;
+ case CCValAssign::AExt:
+ ExtType = ISD::EXTLOAD;
+ break;
+ }
+
+ ArgValue = DAG.getExtLoad(
+ ExtType, SL, VA.getLocVT(), Chain, FIN,
+ MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI),
+ MemVT);
+ return ArgValue;
+}
+
static void processShaderInputArgs(SmallVectorImpl<ISD::InputArg> &Splits,
CallingConv::ID CallConv,
ArrayRef<ISD::InputArg> Ins,
@@ -1094,10 +1143,12 @@ static void allocateSystemSGPRs(CCState &CCInfo,
static void reservePrivateMemoryRegs(const TargetMachine &TM,
MachineFunction &MF,
const SIRegisterInfo &TRI,
- SIMachineFunctionInfo &Info) {
+ SIMachineFunctionInfo &Info,
+ bool NeedSP) {
// Now that we've figured out where the scratch register inputs are, see if
// should reserve the arguments and use them directly.
- bool HasStackObjects = MF.getFrameInfo().hasStackObjects();
+ MachineFrameInfo &MFI = MF.getFrameInfo();
+ bool HasStackObjects = MFI.hasStackObjects();
// Record that we know we have non-spill stack objects so we don't need to
// check all stack objects later.
@@ -1155,6 +1206,15 @@ static void reservePrivateMemoryRegs(const TargetMachine &TM,
Info.setScratchWaveOffsetReg(ReservedOffsetReg);
}
}
+
+ if (NeedSP){
+ unsigned ReservedStackPtrOffsetReg = TRI.reservedStackPtrOffsetReg(MF);
+ Info.setStackPtrOffsetReg(ReservedStackPtrOffsetReg);
+
+ assert(Info.getStackPtrOffsetReg() != Info.getFrameOffsetReg());
+ assert(!TRI.isSubRegister(Info.getScratchRSrcReg(),
+ Info.getStackPtrOffsetReg()));
+ }
}
SDValue SITargetLowering::LowerFormalArguments(
@@ -1223,8 +1283,10 @@ SDValue SITargetLowering::LowerFormalArguments(
!Info->hasWorkGroupIDZ() && !Info->hasWorkGroupInfo() &&
!Info->hasWorkItemIDX() && !Info->hasWorkItemIDY() &&
!Info->hasWorkItemIDZ());
+ } else if (IsKernel) {
+ assert(Info->hasWorkGroupIDX() && Info->hasWorkItemIDX());
} else {
- assert(!IsKernel || (Info->hasWorkGroupIDX() && Info->hasWorkItemIDX()));
+ Splits.append(Ins.begin(), Ins.end());
}
if (IsEntryFunc) {
@@ -1278,11 +1340,14 @@ SDValue SITargetLowering::LowerFormalArguments(
InVals.push_back(Arg);
continue;
+ } else if (!IsEntryFunc && VA.isMemLoc()) {
+ SDValue Val = lowerStackParameter(DAG, VA, DL, Chain, Arg);
+ InVals.push_back(Val);
+ if (!Arg.Flags.isByVal())
+ Chains.push_back(Val.getValue(1));
+ continue;
}
- if (VA.isMemLoc())
- report_fatal_error("memloc not supported with calling convention");
-
assert(VA.isRegLoc() && "Parameter must be in a register!");
unsigned Reg = VA.getLocReg();
@@ -1291,7 +1356,7 @@ SDValue SITargetLowering::LowerFormalArguments(
Reg = MF.addLiveIn(Reg, RC);
SDValue Val = DAG.getCopyFromReg(Chain, DL, Reg, VT);
- if (Arg.VT.isVector()) {
+ if (IsShader && Arg.VT.isVector()) {
// Build a vector from the registers
Type *ParamType = FType->getParamType(Arg.getOrigArgIndex());
unsigned NumElements = ParamType->getVectorNumElements();
@@ -1317,16 +1382,49 @@ SDValue SITargetLowering::LowerFormalArguments(
InVals.push_back(Val);
}
+ const MachineFrameInfo &FrameInfo = MF.getFrameInfo();
+
+ // TODO: Could maybe omit SP if only tail calls?
+ bool NeedSP = FrameInfo.hasCalls() || FrameInfo.hasVarSizedObjects();
+
// Start adding system SGPRs.
- if (IsEntryFunc)
+ if (IsEntryFunc) {
allocateSystemSGPRs(CCInfo, MF, *Info, CallConv, IsShader);
-
- reservePrivateMemoryRegs(getTargetMachine(), MF, *TRI, *Info);
+ reservePrivateMemoryRegs(getTargetMachine(), MF, *TRI, *Info, NeedSP);
+ } else {
+ CCInfo.AllocateReg(Info->getScratchRSrcReg());
+ CCInfo.AllocateReg(Info->getScratchWaveOffsetReg());
+ CCInfo.AllocateReg(Info->getFrameOffsetReg());
+
+ if (NeedSP) {
+ unsigned StackPtrReg = findFirstFreeSGPR(CCInfo);
+ CCInfo.AllocateReg(StackPtrReg);
+ Info->setStackPtrOffsetReg(StackPtrReg);
+ }
+ }
return Chains.empty() ? Chain :
DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chains);
}
+// TODO: If return values can't fit in registers, we should return as many as
+// possible in registers before passing on stack.
+bool SITargetLowering::CanLowerReturn(
+ CallingConv::ID CallConv,
+ MachineFunction &MF, bool IsVarArg,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ LLVMContext &Context) const {
+ // Replacing returns with sret/stack usage doesn't make sense for shaders.
+ // FIXME: Also sort of a